shithub: minivmac

Download patch

ref: d7ad068d56bdec30805a36a9973f5924ad00641b
author: Sigrid Haflínudóttir <[email protected]>
date: Fri Jun 5 12:38:13 EDT 2020

first dirty version of the port

diff: cannot open b/extras/mydriver/disk//null: file does not exist: 'b/extras/mydriver/disk//null' diff: cannot open b/extras/mydriver/video//null: file does not exist: 'b/extras/mydriver/video//null' diff: cannot open b/extras/mydriver//null: file does not exist: 'b/extras/mydriver//null' diff: cannot open b/extras//null: file does not exist: 'b/extras//null' diff: cannot open b/setup//null: file does not exist: 'b/setup//null' diff: cannot open b/src//null: file does not exist: 'b/src//null'
--- /dev/null
+++ b/COPYING.txt
@@ -1,0 +1,345 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null
+++ b/README.md
@@ -1,0 +1,19 @@
+# minivmac
+
+This is a 9front port of minivmac. You can check out https://cancel.fm/hyperjam to see what you can run with it after installing.
+
+## Installing
+
+Clone the repo, run `./install.rc`. That's it. Now you have `games/vmac` and `games/vmac2`.
+
+Currently `vMac.ROM` (or `MacII.ROM`) are required, you can plumb it while the emulator is running.
+
+## Plumbing
+
+```
+type	is	text
+data	matches	'([.a-zA-Z¡-￿0-9_/+\-]*[a-zA-Z¡-￿0-9_/+\-])\.(dsk|rom|ROM|DSK)'
+arg	isfile	$0
+plumb	to	minivmac
+plumb	start	minivmac $file
+```
--- /dev/null
+++ b/README.txt
@@ -1,0 +1,21 @@
+MnvM_b36: README
+Paul C. Pratt
+www.gryphel.com
+July 27, 2005
+
+
+MnvM_b36 is the build system for Mini vMac,
+a miniature Macintosh emulator.
+
+Further information may be found at
+"https://www.gryphel.com/c/minivmac/".
+
+
+You can redistribute MnvM_b36 and/or modify it under the terms
+of version 2 of the GNU General Public License as published by
+the Free Software Foundation.  See the included file COPYING.
+
+MnvM_b36 is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+license for more details.
--- /dev/null
+++ b/extras/mydriver/disk/README.txt
@@ -1,0 +1,32 @@
+Mini vMac: mydriver/README
+Paul C. Pratt
+www.gryphel.com
+February 23, 2002
+
+The mydriver folder contains source code
+for a replacement disk driver that is patched
+into the emulated rom.
+
+The compiled driver is already in ROMEMDEV.c
+(the initialization of sony_driver variable),
+so this source code is not needed for building
+Mini vMac. It is only needed if you want
+to change this driver.
+
+To compile the driver, use MPW commands
+such as:
+
+set srcdir hd4:Topaz:MinivMac:mydriver:
+asm -case on {srcdir}mydriver.a -o {srcdir}mydriver.a.o
+c {srcdir}mydriver.c -r -b -mbg off -opt full -o {srcdir}mydriver.c.o
+link {srcdir}mydriver.a.o {srcdir}mydriver.c.o -rt DRVR=128 -o {srcdir}mydriver
+
+Then you can use ResEdit to copy the hex data out
+of the DRVR 128 resource, format it a bit, and
+replace the initialization data of the variable
+sony_driver in the file ROMEMDEV.c
+
+(note: this is using the old c compiler, to use
+the current c compiler, use:
+SC {srcdir}mydriver.c -w 17 -proto strict -b -mbg off -opt all -o {srcdir}mydriver.c.o
+)
--- /dev/null
+++ b/extras/mydriver/disk/mydriver.a
@@ -1,0 +1,302 @@
+;	mydriver.a
+;
+;	Copyright (C) 2004 Paul C. Pratt
+;
+;	You can redistribute this file and/or modify it under the terms
+;	of version 2 of the GNU General Public License as published by
+;	the Free Software Foundation.  You should have received a copy
+;	of the license along with this file; see the file COPYING.
+;
+;	This file is distributed in the hope that it will be useful,
+;	but WITHOUT ANY WARRANTY; without even the implied warranty of
+;	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;	license for more details.
+
+; most of this is adapted from sample source code from Apple.
+
+FakeSonyDriver MAIN EXPORT
+		BLANKS  ON
+		STRING  ASIS
+
+kqLink        EQU  0
+kqType        EQU  4
+kioTrap       EQU  6
+kioCmdAddr    EQU  8
+kioCompletion EQU 12
+kioResult     EQU 16
+kioNamePtr    EQU 18
+kioVRefNum    EQU 22
+kioRefNum     EQU 24
+kcsCode       EQU 26
+kcsParam      EQU 28
+kioBuffer     EQU 32 ; Buffer to store data into
+kioReqCount   EQU 36 ; Requested Number of Bytes
+kioActCount   EQU 40 ; Actual Number of Bytes obtained
+kioPosMode    EQU 44 ; Positioning Mode
+kioPosOffset  EQU 46 ; Position Offset
+
+killCode   EQU 1 ; KillIO requested
+noQueueBit EQU 9 ; trap word modifier
+JIODone    EQU $08FC
+
+kCmndSonyPrime    EQU $0001
+kCmndSonyControl  EQU $0002
+kCmndSonyStatus   EQU $0003
+kCmndSonyClose    EQU $0004
+kCmndSonyOpenA    EQU $0005
+kCmndSonyOpenB    EQU $0006
+kCmndSonyOpenC    EQU $0007
+kCmndSonyMount    EQU $0008
+
+DHeader
+DFlags   DC.W  $4F00              ; need lock, responds to all requests
+DDelay   DC.W  0                  ; none
+DEMask   DC.W  0                  ; DA event mask
+DMenu    DC.W  0                  ; no menu
+         DC.W  DOpen - DHeader    ; offset to Open
+         DC.W  DPrime - DHeader   ; offset to Prime
+         DC.W  DControl - DHeader ; offset to Control
+         DC.W  DStatus - DHeader  ; offset to Status
+         DC.W  DClose - DHeader   ; offset to Close
+Name     DC.B  5 ; length of name
+         DC.B  '.Sony'
+         ALIGN 2                  ; word alignment
+
+DPrime
+	MOVEM.L    A0-A1, -(SP)    ; push ParmBlkPtr, DCtlPtr for C
+	SUBQ       #2, A7 ; result code
+	MOVE.W     #kCmndSonyPrime, -(A7)
+	BRA.B      DPrimeStatusCommon
+
+DControl
+	MOVEM.L    A0-A1, -(SP)    ; push ParmBlkPtr, DCtlPtr for C
+	SUBQ       #2, A7 ; result code
+	MOVE.W     #kCmndSonyControl, -(A7)
+
+	LEA        TailData, A0
+	MOVE.L     (A0)+, -(A7)
+	MOVEA.L    (A0), A0
+	MOVE.L     A7, (A0)
+
+	ADDA.W     #6, A7
+	MOVE.W     (A7)+, D0 ; save result code
+	MOVEM.L    (SP)+, A0-A1    ; restore ParmBlkPtr, DCtlPtr
+	CMPI.W     #killCode,kcsCode(A0) ; test for KillIO call (special case)
+	BNE.B      IOReturn
+	RTS                     ; KillIO must always return via RTS
+
+DStatus
+	MOVEM.L    A0-A1, -(SP)    ; push ParmBlkPtr, DCtlPtr for C
+	SUBQ       #2, A7 ; result code
+	MOVE.W     #kCmndSonyStatus, -(A7)
+DPrimeStatusCommon
+
+	LEA        TailData, A0
+	MOVE.L     (A0)+, -(A7)
+	MOVEA.L    (A0), A0
+	MOVE.L     A7, (A0)
+
+	ADDA.W     #6, A7
+	MOVE.W     (A7)+, D0 ; save result code
+	MOVEM.L    (SP)+, A0-A1    ; restore ParmBlkPtr, DCtlPtr
+
+IOReturn
+	MOVE.W   kioTrap(A0),D1
+	BTST     #noQueueBit,D1 ; immediate calls are not queued, and must RTS
+	BEQ.B    @Queued        ; branch if queued
+
+@NotQueued
+	TST.W    D0             ; test asynchronous return result
+	BLE.B    @ImmedRTS      ; result must be <= 0
+	CLR.W    D0             ; "in progress" result (> 0) not passed back
+
+@ImmedRTS
+	MOVE.W   D0,kioResult(A0)   ; for immediate calls you must explicitly
+	                            ; place the result in the ioResult field
+	RTS
+
+@Queued
+	TST.W    D0             ; test asynchronous return result
+	BLE.B    @MyIODone      ; I/O is complete if result <= 0
+	CLR.W    D0             ; "in progress" result (> 0) not passed back
+	RTS
+
+@MyIODone
+	MOVE.L   JIODone,-(SP)  ; push IODone jump vector onto stack
+	RTS
+
+DClose
+	MOVEM.L    A0-A1, -(SP)    ; push ParmBlkPtr, DCtlPtr for C
+	SUBQ       #2, A7 ; result code
+	MOVE.W     #kCmndSonyClose, -(A7)
+
+	LEA        TailData, A0
+	MOVE.L     (A0)+, -(A7)
+	MOVEA.L    (A0), A0
+	MOVE.L     A7, (A0)
+
+	ADDA.W     #6, A7
+	MOVE.W     (A7)+, D0 ; save result code
+	MOVEM.L    (SP)+, A0-A1    ; restore ParmBlkPtr, DCtlPtr
+	RTS
+
+DUpdate
+	MOVEM.L    D0-D2/A0-A1,-(SP)
+	MOVE.L     20(A7),D0 ; data = what was on top of stack before 5 registers pushed
+
+	SUBQ       #4, A7 ; room for eventMsg
+	MOVE.L     D0,-(A7) ; data
+	SUBQ       #2, A7 ; room for result code
+	MOVE.W     #kCmndSonyMount, -(A7)
+
+	LEA        TailData, A0
+	MOVE.L     (A0)+, -(A7)
+	MOVEA.L    (A0), A0
+	MOVE.L     A7, (A0)
+
+	ADDA.W     #6, A7
+	MOVE.W     (A7)+, D1 ; result code
+	ADDQ       #4, A7 ; skip over data
+	MOVE.L     (A7)+, D0 ; eventMsg
+	TST.W      D1 ; result code
+	BNE.S      @1
+	MOVEA.W    #$0007,A0
+	DC.W       $A02F ; _PostEvent
+@1
+
+	MOVEM.L    (SP)+,D0-D2/A0-A1
+	ADDA.W     #4,A7          ; remove arguments from stack
+	RTE
+
+MyAddDrive64k
+
+; This is only needed for the 64k ROM.
+
+DrvQHdr EQU 776
+RomBase EQU $00400000
+
+	Move.L    D0,6(A0)
+	Lea.L     (DrvQHdr),A1
+	Jmp       (RomBase + 2848)
+
+
+NullTaskProc
+	RTS
+
+DOpen
+	MOVEM.L    D3-D7/A3,-(A7)
+	MOVEM.L    A0-A1, -(SP)    ; push ParmBlkPtr, DCtlPtr for C
+
+	SUBQ       #6, A7 ; room for result code, L
+	MOVE.W     #kCmndSonyOpenA, -(A7)
+
+	LEA        TailData, A0
+	MOVE.L     (A0)+, -(A7)
+	MOVEA.L    (A0), A0
+	MOVE.L     A7, (A0)
+
+	ADDA.W     #6, A7
+	MOVE.W     (A7)+, D0 ; result code
+	MOVE.L     (A7)+, D7 ; L
+
+	CMPI.W     #$FFCF,D0
+	BNE.S      @1
+	; driver already open, change to no error and leave
+	CLR.W      D0
+	BRA        @2
+@1
+	TST.W      D0
+	BNE        @2
+	MOVE.L     D7,D0
+	DC.W       $A71E ; _NewPtr    ,Sys,Clear
+	MOVEA.L    A0,A3
+	MOVE.L     A3,D0
+	BEQ        @6
+
+	SUBA       #16, A7 ; room for various results
+	MOVE.L     A3, -(A7)
+	MOVE.L     D7, -(A7)
+	SUBQ       #2, A7 ; room for result code
+	MOVE.W     #kCmndSonyOpenB, -(A7)
+
+	LEA        TailData, A0
+	MOVE.L     (A0)+, -(A7)
+	MOVEA.L    (A0), A0
+	MOVE.L     A7, (A0)
+
+	ADDA.W     #6, A7
+	MOVE.W     (A7)+, D0 ; result code
+	ADDA.W     #8, A7
+	MOVE.L     (A7)+, D7 ; dvl
+	MOVEQ      #$00, D3
+	MOVE.W     (A7)+, D3 ; step
+	MOVE.W     (A7)+, D4 ; n
+	MOVE.W     (A7)+, D6 ; i
+	MOVE.W     (A7)+, D5 ; driver
+	MOVEA.L    (A7)+, A3 ; NullTask
+
+	TST.W      D0
+	BNE.S      @2
+
+	MOVE.L     A3,D0
+	BEQ.S      @3
+
+	; There is apparently a bug in the time manager
+	; in System 6.0.8, which will cause a crash
+	; if there are no installed time
+	; tasks. So create a time task, since
+	; real disk driver does.
+
+	LEA        NullTaskProc,A0     ; id: 102
+	MOVE.L     A0,$0006(A3)
+	MOVEA.L    A3,A0
+	DC.W       $A058 ; _InsTime
+	BRA.S      @4
+@3
+	LEA        MyAddDrive64k,A0    ; id: 106
+	MOVE.W     #$A04E,D0
+	DC.W       $A047 ; _SetTrapAddress
+	BRA.S      @4
+@5
+	MOVEA.L    D7,A0
+
+	MOVE.W     D6,D0 ; drive number in high word
+	SWAP       D0
+	MOVE.W     D5,D0 ; driver in low word
+
+	DC.W       $A04E ; _AddDrive
+	ADD.L      D3,D7
+	ADDQ.W     #$1,D6
+@4
+	DBF        D4, @5
+
+	PEA        DUpdate
+	SUBQ       #2, A7 ; room for result code
+	MOVE.W     #kCmndSonyOpenC, -(A7)
+
+	LEA        TailData, A0
+	MOVE.L     (A0)+, -(A7)
+	MOVEA.L    (A0), A0
+	MOVE.L     A7, (A0)
+
+	ADDA.W     #6, A7
+	MOVE.W     (A7)+, D0 ; result code
+	ADDA.W     #4, A7
+
+@2
+	; result code should be in D0 when reach here
+
+	MOVEM.L    (A7)+, A0-A1    ; restore ParmBlkPtr, DCtlPtr
+	MOVEM.L    (A7)+, D3-D7/A3
+
+	RTS                     ; open is always immediate, must return via RTS
+@6
+	; _NewPtr failed
+	MOVE.W     #-1, D0
+	BRA.S      @2
+
+TailData
+
+		ENDMAIN
+
+		END
--- /dev/null
+++ b/extras/mydriver/video/firmware.a
@@ -1,0 +1,277 @@
+	STRING	C
+	MACHINE	MC68020
+	PRINT	OFF
+	INCLUDE	'SlotEqu.a'
+	INCLUDE	'VideoEqu.a'
+	INCLUDE	'Traps.a'
+	INCLUDE	'SysEqu.a'
+	INCLUDE	'SysErr.a'
+	PRINT	ON
+
+VideoDeclROM	MAIN
+
+;========================================================================================
+
+; General Directives
+
+	BLANKS	ON
+	STRING	ASIS
+
+kCmndVideoSetIntEnbl  EQU $0003
+kCmndVideoClearInt    EQU $0004
+kCmndVideoStatus      EQU $0005
+kCmndVideoControl     EQU $0006
+
+;========================================================================================
+;	       Local Vars, definitions, etc...
+;========================================================================================
+
+;This is device storage, a handle to which is stored in the dCtlStorage field of the DCE.
+
+saveSQElPtr EQU 0 ; the SQ element pointer (for
+                    ;   _SIRemove
+dCtlSize    EQU saveSQElPtr+4 ; size of the dCtlStorage
+
+;========================================================================================
+;           Video Driver Header
+;========================================================================================
+
+VidDrvr
+	DC.W    $4C00       ; ctl,status,needsLock
+	DC.W    0, 0, 0     ; not an ornament
+
+;Entry point offset table
+
+	DC.W    VideoOpen - VidDrvr   ; open routine
+	DC.W    VidDrvr - VidDrvr     ; no prime
+	DC.W    VideoCtl - VidDrvr    ; control
+	DC.W    VideoStatus - VidDrvr ; status
+	DC.W    VideoClose - VidDrvr  ; close
+
+VideoTitle
+	STRING  Pascal
+	DC.W    '.Display_Video_Sample'
+	STRING  ASIS
+	ALIGN   2       ; make sure we're aligned
+	DC.W    0       ; version-0
+
+;========================================================================================
+;VideoOpen allocates private storage for the device in the DCE and locks
+;      it down for perpetuity. It installs the interrupt handler and enables
+;      the interrupts. It also sets the default gamma table included in the driver.
+;
+;Entry:
+;   A0 = param block pointer
+;   A1 = DCE pointer
+;
+;Locals:
+;   A2 = Saved param block pointer
+;   A3 = Saved DCE pointer
+;   A4 = Saved interrupt handler ptr
+;========================================================================================
+
+;Save registers
+VideoOpen
+	MOVE.L     A0, A2  ; A2 <- param block pointer
+	MOVE.L     A1, A3  ; A3 <- DCE pointer
+
+;Allocate private storage
+	MOVEQ      #dCtlSize, D0 ; get size of parameters
+	_ResrvMem ,SYS           ; make room as low as possible
+	MOVEQ      #dCtlSize, D0 ; get size of parameters
+	_NewHandle ,SYS,CLEAR    ; get some memory for private
+	                         ; storage
+	BNE        OpError       ;=> return an error in open
+	MOVE.L     A0, dCtlStorage(A3) ; saved returned handle in DCE
+	_HLock                   ; and lock it down
+
+;Get and install the interrupt handler
+	LEA        BeginIH, A4   ; Save point to interrupt handler
+	MOVEQ      #SlotIntQElement.sqHDSize,D0  ; allocate a slot queue element
+	_NewPtr    ,SYS,CLEAR    ; get it from system heap cleared
+	BNE        OpError
+	MOVE.W     #SIQType, SlotIntQElement.sqType(A0) ; setup queue ID
+	MOVE.L     A4, SlotIntQElement.sqAddr(A0)  ; setup int routine address
+	MOVE.L     A3, SlotIntQElement.sqParm(A0)  ; save slot base addr as A3 parm
+	CLR.L      D0
+	MOVE.B     dctlSlot(A3), D0 ; setup slot #
+	_SIntInstall   ; and do install
+	BNE.S      OpError
+
+;Save SQElPtr for removal
+	MOVE.L     dCtlStorage(A3), A1  ; Get point to private storage
+	MOVE.L     (A1), A1
+	MOVE.L     A0, saveSQElPtr(A1)  ; Save the SQ element pointer
+
+;Enable interrupts
+
+	MOVE.W     #1, -(A7) ; enabled
+	SUBQ       #2, A7    ; result code
+	MOVE.W     #kCmndVideoSetIntEnbl, -(A7)
+	LEA        TailData, A0
+	MOVE.L     (A0)+, -(A7)
+	MOVEA.L    (A0), A0
+	MOVE.L     A7, (A0)
+	ADDA.W     #10, A7
+
+	MOVEQ      #0, D0      ; no error
+	BRA.S      EndOpen
+
+; Error
+OpError
+	MOVE.L     #openErr, D0  ; say can't open driver
+EndOpen
+	RTS
+
+;========================================================================================
+;          The interrupt handler for the board
+;========================================================================================
+
+; On entry A1 contains DCE
+
+; wrong! : "D0-D3/A0-A3 have been preserved."
+; (comment from Apples sample code.)
+; must preserve registers except A1/D0
+
+BeginIH
+	MOVE.L     A0, -(A7)
+
+	; clear interrupt from card
+
+	SUBQ       #2, A7    ; result code
+	MOVE.W     #kCmndVideoClearInt, -(A7)
+
+	LEA        TailData, A0
+	MOVE.L     (A0)+, -(A7)
+	MOVEA.L    (A0), A0
+	MOVE.L     A7, (A0)
+
+	ADDQ.W     #8, A7
+
+	MOVE.L     dctlDevBase(A1), D0 ; D0 = $Fsxxxxxx
+	ROL.L      #8, D0              ; D0 <- $xxxxxxFs     Convert the
+	                               ;                     address into
+	AND        #$0F, D0            ; D0 <- $xxxx000x     the slot
+	                               ;                     number
+	MOVE.L     JVBLTask, A0        ; call the VBL task manager
+	JSR        (A0)                ; with slot # in D0
+
+	MOVE.L     (A7)+, A0
+	MOVEQ      #1, D0     ; signal that int was serviced
+	RTS                   ; and return to caller
+
+;========================================================================================
+;
+;VideoClose releases the device's private storage.
+;
+;Entry:
+;   A0 = param block pointer
+;   A1 = DCE pointer
+;
+;Locals:
+;   A2 = Saved param block pointer
+;   A3 = Saved DCE pointer
+;   A4 = Temporary
+;
+;========================================================================================
+
+VideoClose
+
+	MOVE.L     A3, -(A7) ; save
+	MOVE.L     dCtlStorage(A1), A3; Get pointer to private storage
+
+	MOVE.W     #0, -(A7) ; disabled
+	SUBQ       #2, A7 ; result code
+	MOVE.W     #kCmndVideoSetIntEnbl, -(A7)
+	LEA        TailData, A0
+	MOVE.L     (A0)+, -(A7)
+	MOVEA.L    (A0), A0
+	MOVE.L     A7, (A0)
+	ADDA.W     #10, A7
+
+	MOVE.L     (A3), A0
+	MOVE.L     saveSQElPtr(A0), A0 ; Get the SQ element pointer
+	_SIntRemove          ; Remove the interrupt handler
+
+	MOVE.L     A3, A0    ; Dispose of the private storage
+	_DisposHandle
+	MOVEQ      #0, D0    ; get error into D0
+
+	MOVE.L     (A7)+, A3 ; restore A3
+	RTS                  ; return to caller
+
+;========================================================================================
+;
+;Video Driver Control Call Handler.
+;
+;      Entry:
+;   A0    = param block pointer
+;   A1    = DCE pointer
+;      Uses:
+;   A2    = cs paramaters (i.e. A2 <- csParam(A0)) (must be preserved)
+;   A3    = scratch (doesn't need to be preserved)
+;   A4    = scratch (must be preserved)
+;   D0-D3 = scratch (don't need to be preserved)
+;
+;      Exit:  D0    =       error code
+;
+;========================================================================================
+
+;Decode the call
+VideoCtl
+	MOVE.L     A0, -(A7)
+	SUBQ       #2, A7 ; result code
+	MOVE.W     #kCmndVideoControl, -(A7)
+	BRA.S      VideoStatusControlCommon
+
+;========================================================================================
+;
+;Video DriverStatus Call Handler.  Right now there are three calls:
+;
+;      (2)  GetMode
+;      (4)  GetPage
+;      (5)  GetPageBase
+;
+;      Entry:
+;   A0    = param block
+;   A1    = DCE pointer
+;      Uses:
+;   A2    = cs paramaters (i.e. A2 <- csParam(A0)) (must be preserved)
+;   A3    = scratch (doesn't need to be preserved)
+;   D0-D3 = scratch (don't need to be preserved)
+;
+;      Exit:  D0    =       error code
+;
+;========================================================================================
+
+VideoStatus
+	MOVE.L     A0, -(A7)
+	SUBQ       #2, A7 ; result code
+	MOVE.W     #kCmndVideoStatus, -(A7)
+VideoStatusControlCommon
+	LEA        TailData, A0
+	MOVE.L     (A0)+, -(A7)
+	MOVEA.L    (A0), A0
+	MOVE.L     A7, (A0)
+
+	ADDA.W     #6, A7
+	MOVE.W     (A7)+, D0 ; save result code
+	MOVE.L     (A7)+, A0 ; restore A0
+
+;========================================================================================
+;      Exit from control or status
+;========================================================================================
+
+	BTST       #NoQueueBit,ioTrap(A0) ;no queue bit set?
+	BEQ.S      GoIODone     ;=> no, not immediate
+	RTS                     ;otherwise, it was an immediate call
+
+GoIODone
+	MOVE.L     JIODone,A0   ;get the IODone address
+	JMP        (A0)
+
+TailData
+
+	ENDP
+
+	END
--- /dev/null
+++ b/extras/trans.txt
@@ -1,0 +1,32 @@
+# Some source files are simple transformations of other source
+# files. Here are some MPW scripts to help keep them in sync.
+
+Set x "rd:t1.txt"
+
+
+Catenate "{my_project_d}"data:src:VIAEMDEV.c > "{x}"
+Open "{x}"
+Set CaseSensitive 1
+Find � "{x}"
+Replace -c � /'VIA1'/ 'VIA2' "{x}"
+Find � "{x}"
+Replace -c � /'VIAEMDEV'/ 'VIA2EMDV' "{x}"
+Find � "{x}"
+Replace -c � /'0x04'([0-9A-FX][0-9A-FX])�1/ '0x05'�1 "{x}"
+Unset SearchType
+
+Compare "{my_project_d}"data:src:VIA2EMDV.c "{x}"
+
+
+Catenate "{my_project_d}"data:src:VIA2EMDV.c > "{x}"
+Open "{x}"
+Set CaseSensitive 1
+Find � "{x}"
+Replace -c � /'VIA2EMDV'/ 'VIAEMDEV' "{x}"
+Find � "{x}"
+Replace -c � /'VIA2'/ 'VIA1' "{x}"
+Find � "{x}"
+Replace -c � /'0x05'([0-9A-FX][0-9A-FX])�1/ '0x04'�1 "{x}"
+Unset SearchType
+
+Compare "{my_project_d}"data:src:VIAEMDEV.c "{x}"
--- /dev/null
+++ b/install.rc
@@ -1,0 +1,13 @@
+#!/bin/rc
+rfork ne
+
+cd setup
+mk clean
+mk all
+cd ..
+rm -rf bld cfg
+./setup/6.out -t 9x64 -an vmac | my_project_d='' my_obj_d='' rc
+mk install
+rm -rf bld cfg
+./setup/6.out -t 9x64 -an vmac2 -m II | my_project_d='' my_obj_d='' rc
+mk install
--- /dev/null
+++ b/setup/BLDUTIL3.i
@@ -1,0 +1,1252 @@
+/*
+	BLDUTIL3.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	BuiLD system UTILities part 3
+*/
+
+
+#define src_d_name "src"
+#define cfg_d_name "cfg"
+
+#define obj_d_name "bld"
+	/* not "obj", so as to work in freebsd make */
+
+LOCALVAR blnr HaveAltSrc;
+
+LOCALPROC WritepDtString(void)
+{
+	WriteCStrToDestFile((char *)pDt);
+}
+
+LOCALPROC WriteMaintainerName(void)
+{
+	WriteCStrToDestFile(kMaintainerName);
+}
+
+LOCALPROC WriteHomePage(void)
+{
+	WriteCStrToDestFile(kStrHomePage);
+}
+
+/* end of default value of options */
+
+LOCALPROC WriteVersionStr(void)
+{
+	WriteDec2CharToOutput(MajorVersion);
+	WriteCStrToDestFile(".");
+	WriteDec2CharToOutput(MinorVersion);
+}
+
+LOCALPROC WriteAppVariationStr(void)
+{
+	WriteCStrToDestFile(vVariationName);
+}
+
+LOCALPROC WriteAppCopyrightYearStr(void)
+{
+	WriteCStrToDestFile(kStrCopyrightYear);
+}
+
+LOCALPROC WriteGetInfoString(void)
+{
+	WriteAppVariationStr();
+	WriteCStrToDestFile(", Copyright ");
+	WriteAppCopyrightYearStr();
+	WriteCStrToDestFile(" maintained by ");
+	WriteMaintainerName();
+	WriteCStrToDestFile(".");
+}
+
+LOCALPROC WriteLProjName(void)
+{
+	WriteCStrToDestFile(GetLProjName(gbo_lang));
+}
+
+/* --- XML utilities --- */
+
+LOCALPROC WriteXMLtagBegin(char *s)
+{
+	WriteCStrToDestFile("<");
+	WriteCStrToDestFile(s);
+	WriteCStrToDestFile(">");
+}
+
+LOCALPROC WriteXMLtagEnd(char *s)
+{
+	WriteCStrToDestFile("</");
+	WriteCStrToDestFile(s);
+	WriteCStrToDestFile(">");
+}
+
+LOCALPROC WriteBeginXMLtagLine(char *s)
+{
+	WriteBgnDestFileLn();
+	WriteXMLtagBegin(s);
+	WriteEndDestFileLn();
+	++DestFileIndent;
+}
+
+LOCALPROC WriteEndXMLtagLine(char *s)
+{
+	--DestFileIndent;
+	WriteBgnDestFileLn();
+	WriteXMLtagEnd(s);
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteXMLtagBeginValEndLine(char *t, char *v)
+{
+	WriteBgnDestFileLn();
+	WriteXMLtagBegin(t);
+	WriteCStrToDestFile(v);
+	WriteXMLtagEnd(t);
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteXMLtagBeginProcValEndLine(char *t, MyProc v)
+{
+	WriteBgnDestFileLn();
+	WriteXMLtagBegin(t);
+	v();
+	WriteXMLtagEnd(t);
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteXMLtaggedLines(char *s, MyProc p)
+{
+	WriteBeginXMLtagLine(s);
+		if (NULL != p) {
+			p();
+		}
+	WriteEndXMLtagLine(s);
+}
+
+LOCALPROC WriteXMLtaglinewithprops(char *s, MyProc p)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("<");
+	WriteCStrToDestFile(s);
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		if (NULL != p) {
+			p();
+		}
+	--DestFileIndent;
+	WriteDestFileLn("/>");
+}
+
+LOCALPROC WriteXMLtaggedLinesWithProps(char *s, MyProc pp, MyProc p)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("<");
+	WriteCStrToDestFile(s);
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		if (NULL != pp) {
+			pp();
+		}
+		WriteDestFileLn(">");
+		if (NULL != p) {
+			p();
+		}
+	WriteEndXMLtagLine(s);
+}
+
+LOCALPROC WriteXMLtaggedLinesWith1LnProps(char *s, MyProc pp, MyProc p)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("<");
+	WriteCStrToDestFile(s);
+	if (NULL != pp) {
+		pp();
+	}
+	WriteCStrToDestFile(">");
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		if (NULL != p) {
+			p();
+		}
+	WriteEndXMLtagLine(s);
+}
+
+/* --- end XML utilities --- */
+
+/* --- c preprocessor utilities --- */
+
+LOCALPROC WriteCompCondBool(char *s, blnr v)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define ");
+	WriteCStrToDestFile(s);
+	if (v) {
+		WriteCStrToDestFile(" 1");
+	} else {
+		WriteCStrToDestFile(" 0");
+	}
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteDefineUimr(char *s, uimr v)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define ");
+	WriteCStrToDestFile(s);
+	WriteSpaceToDestFile();
+	WriteUnsignedToOutput(v);
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteCDefQuote(char *s, MyProc p)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define ");
+	WriteCStrToDestFile(s);
+	WriteSpaceToDestFile();
+	WriteQuoteToDestFile();
+	p();
+	WriteQuoteToDestFile();
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteWrongCNFGGLOB(void)
+{
+	WriteDestFileLn("#error \"wrong CNFGGLOB.h\"");
+}
+
+LOCALPROC WriteCheckPreDef(char *s)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#ifndef ");
+	WriteCStrToDestFile(s);
+	WriteEndDestFileLn();
+	WriteWrongCNFGGLOB();
+	WriteDestFileLn("#endif");
+}
+
+LOCALPROC WriteCheckPreNDef(char *s)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#ifdef ");
+	WriteCStrToDestFile(s);
+	WriteEndDestFileLn();
+	WriteWrongCNFGGLOB();
+	WriteDestFileLn("#endif");
+}
+
+/* --- end c preprocessor utilities --- */
+
+LOCALPROC WritePathInDirToDestFile0(MyProc p, MyProc ps,
+	blnr isdir)
+{
+	switch (cur_ide) {
+		case gbk_ide_mpw:
+		case gbk_ide_mw8:
+			if (p != NULL) {
+				p();
+			} else {
+				WriteCStrToDestFile(":");
+			}
+			ps();
+			if (isdir) {
+				WriteCStrToDestFile(":");
+			}
+			break;
+		case gbk_ide_bgc:
+		case gbk_ide_mvc:
+		case gbk_ide_cyg:
+		case gbk_ide_xcd:
+		case gbk_ide_snc:
+		case gbk_ide_dkp:
+		case gbk_ide_ccc:
+		case gbk_ide_9pc:
+			if (p != NULL) {
+				p();
+			}
+			ps();
+			if (isdir) {
+				WriteCStrToDestFile("/");
+			}
+			break;
+		case gbk_ide_msv:
+		case gbk_ide_lcc:
+		case gbk_ide_dmc:
+		case gbk_ide_plc:
+			if (p != NULL) {
+				p();
+				WriteBackSlashToDestFile();
+			} else {
+				if (gbk_ide_lcc == cur_ide) {
+					if (! UseCmndLine) {
+						WriteCStrToDestFile("c:\\output\\");
+					}
+				} else if ((gbk_ide_msv == cur_ide)
+					&& (ide_vers >= 7100)
+					&& (ide_vers < 10000))
+				{
+					WriteCStrToDestFile(".\\");
+				}
+			}
+			ps();
+			break;
+		case gbk_ide_mgw:
+			if (p != NULL) {
+				p();
+				WriteCStrToDestFile("/");
+			}
+			ps();
+			break;
+		case gbk_ide_dvc:
+			if (p != NULL) {
+				p();
+				if (UseCmndLine) {
+					WriteCStrToDestFile("/");
+				} else {
+					WriteBackSlashToDestFile();
+				}
+			}
+			ps();
+			break;
+	}
+}
+
+LOCALPROC WriteFileInDirToDestFile0(MyProc p, MyProc ps)
+{
+	WritePathInDirToDestFile0(p, ps, falseblnr);
+}
+
+LOCALPROC WriteSubDirToDestFile(MyProc p, MyProc ps)
+{
+	WritePathInDirToDestFile0(p, ps, trueblnr);
+}
+
+LOCALPROC Write_toplevel_f_ToDestFile(MyProc ps)
+{
+	WritePathInDirToDestFile0(NULL, ps, falseblnr);
+}
+
+LOCALPROC Write_toplevel_d_ToDestFile(MyProc ps)
+{
+	WritePathInDirToDestFile0(NULL, ps, trueblnr);
+}
+
+LOCALPROC Write_src_d_Name(void)
+{
+	WriteCStrToDestFile(src_d_name);
+}
+
+LOCALPROC Write_src_d_ToDestFile(void)
+{
+	Write_toplevel_d_ToDestFile(Write_src_d_Name);
+}
+
+LOCALPROC Write_cfg_d_Name(void)
+{
+	WriteCStrToDestFile(cfg_d_name);
+}
+
+LOCALPROC Write_cfg_d_ToDestFile(void)
+{
+	Write_toplevel_d_ToDestFile(Write_cfg_d_Name);
+}
+
+LOCALPROC Write_obj_d_Name(void)
+{
+	WriteCStrToDestFile(obj_d_name);
+}
+
+LOCALPROC Write_obj_d_ToDestFile(void)
+{
+	Write_toplevel_d_ToDestFile(Write_obj_d_Name);
+}
+
+LOCALPROC WriteLProjFolderName(void)
+{
+	WriteLProjName();
+	WriteCStrToDestFile(".lproj");
+}
+
+LOCALPROC WriteLProjFolderPath(void)
+{
+	WriteSubDirToDestFile(Write_cfg_d_ToDestFile,
+		WriteLProjFolderName);
+}
+
+LOCALPROC WriteStrAppAbbrev(void)
+{
+	WriteCStrToDestFile(vStrAppAbbrev);
+}
+
+LOCALPROC WriteAppNameStr(void)
+{
+	WriteStrAppAbbrev();
+	switch (gbo_targfam) {
+		case gbk_targfam_mach:
+		case gbk_targfam_carb:
+			if (HaveMacBundleApp) {
+				WriteCStrToDestFile(".app");
+			}
+			break;
+		case gbk_targfam_mswn:
+		case gbk_targfam_wnce:
+		case gbk_targfam_cygw:
+			WriteCStrToDestFile(".exe");
+			break;
+		case gbk_targfam_lnds:
+			WriteCStrToDestFile(".nds");
+			break;
+		default:
+			break;
+	}
+}
+
+LOCALPROC WriteAppNamePath(void)
+{
+	if (HaveMacBundleApp) {
+		Write_toplevel_d_ToDestFile(WriteAppNameStr);
+	} else {
+		Write_toplevel_f_ToDestFile(WriteAppNameStr);
+	}
+}
+
+LOCALPROC WriteStrAppUnabrevName(void)
+{
+	WriteCStrToDestFile(kStrAppName);
+}
+
+LOCALPROC Write_contents_d_Name(void)
+{
+	WriteCStrToDestFile("Contents");
+}
+
+LOCALPROC Write_machocontents_d_ToDestFile(void)
+{
+	WriteSubDirToDestFile(WriteAppNamePath,
+		Write_contents_d_Name);
+}
+
+LOCALPROC Write_macos_d_Name(void)
+{
+	WriteCStrToDestFile("MacOS");
+}
+
+LOCALPROC Write_machomac_d_ToDestFile(void)
+{
+	WriteSubDirToDestFile(Write_machocontents_d_ToDestFile,
+		Write_macos_d_Name);
+}
+
+LOCALPROC Write_resources_d_Name(void)
+{
+	WriteCStrToDestFile("Resources");
+}
+
+LOCALPROC Write_machores_d_ToDestFile(void)
+{
+	WriteSubDirToDestFile(Write_machocontents_d_ToDestFile,
+		Write_resources_d_Name);
+}
+
+LOCALPROC WriteBinElfObjName(void)
+{
+	WriteStrAppAbbrev();
+	WriteCStrToDestFile(".elf");
+}
+
+LOCALPROC WriteBinElfObjObjPath(void)
+{
+	WriteFileInDirToDestFile0(Write_obj_d_ToDestFile,
+		WriteBinElfObjName);
+}
+
+LOCALPROC WriteBinArmObjName(void)
+{
+	WriteStrAppAbbrev();
+	WriteCStrToDestFile(".arm9");
+}
+
+LOCALPROC WriteBinArmObjObjPath(void)
+{
+	WriteFileInDirToDestFile0(Write_obj_d_ToDestFile,
+		WriteBinArmObjName);
+}
+
+LOCALPROC Write_machobinpath_ToDestFile(void)
+{
+	if (HaveMacBundleApp) {
+		WriteFileInDirToDestFile0(Write_machomac_d_ToDestFile,
+			WriteStrAppAbbrev);
+	} else {
+		WriteAppNamePath();
+	}
+}
+
+LOCALPROC Write_tmachobun_d_Name(void)
+{
+	WriteCStrToDestFile("AppTemp");
+}
+
+LOCALPROC Write_tmachobun_d_ToDestFile(void)
+{
+	Write_toplevel_d_ToDestFile(Write_tmachobun_d_Name);
+}
+
+LOCALPROC Write_tmachocontents_d_ToDestFile(void)
+{
+	WriteSubDirToDestFile(Write_tmachobun_d_ToDestFile,
+		Write_contents_d_Name);
+}
+
+LOCALPROC Write_tmachomac_d_ToDestFile(void)
+{
+	WriteSubDirToDestFile(Write_tmachocontents_d_ToDestFile,
+		Write_macos_d_Name);
+}
+
+LOCALPROC Write_tmachores_d_ToDestFile(void)
+{
+	WriteSubDirToDestFile(Write_tmachocontents_d_ToDestFile,
+		Write_resources_d_Name);
+}
+
+LOCALPROC Write_tmacholang_d_ToDestFile(void)
+{
+	WriteSubDirToDestFile(Write_tmachores_d_ToDestFile,
+		WriteLProjFolderName);
+}
+
+LOCALPROC Write_tmachobinpath_ToDestFile(void)
+{
+	WriteFileInDirToDestFile0(Write_tmachomac_d_ToDestFile,
+		WriteStrAppAbbrev);
+}
+
+LOCALPROC Write_umachobun_d_Name(void)
+{
+	WriteStrAppAbbrev();
+	WriteCStrToDestFile("_u.app");
+}
+
+LOCALPROC Write_umachobun_d_ToDestFile(void)
+{
+	Write_toplevel_d_ToDestFile(Write_umachobun_d_Name);
+}
+
+LOCALPROC Write_umachocontents_d_ToDestFile(void)
+{
+	WriteSubDirToDestFile(Write_umachobun_d_ToDestFile,
+		Write_contents_d_Name);
+}
+
+LOCALPROC Write_umachomac_d_ToDestFile(void)
+{
+	WriteSubDirToDestFile(Write_umachocontents_d_ToDestFile,
+		Write_macos_d_Name);
+}
+
+LOCALPROC Write_umachobinpath_ToDestFile(void)
+{
+	WriteFileInDirToDestFile0(Write_umachomac_d_ToDestFile,
+		WriteStrAppAbbrev);
+}
+
+LOCALPROC WriteInfoPlistFileName(void)
+{
+	WriteCStrToDestFile("Info.plist");
+}
+
+LOCALPROC WriteInfoPlistFilePath(void)
+{
+	WriteFileInDirToDestFile0(Write_cfg_d_ToDestFile,
+		WriteInfoPlistFileName);
+}
+
+LOCALPROC WriteDummyLangFileName(void)
+{
+	WriteCStrToDestFile("dummy.txt");
+}
+
+LOCALPROC Write_tmachoLangDummyPath(void)
+{
+	WriteFileInDirToDestFile0(Write_tmacholang_d_ToDestFile,
+		WriteDummyLangFileName);
+}
+
+LOCALPROC Write_tmachoLangDummyContents(void)
+{
+	WriteCStrToDestFile("dummy");
+}
+
+LOCALPROC Write_tmachoPkgInfoName(void)
+{
+	WriteCStrToDestFile("PkgInfo");
+}
+
+LOCALPROC Write_tmachoPkgInfoPath(void)
+{
+	WriteFileInDirToDestFile0(Write_tmachocontents_d_ToDestFile,
+		Write_tmachoPkgInfoName);
+}
+
+LOCALPROC Write_MacCreatorSigOrGeneric(void)
+{
+	if (WantIconMaster) {
+		WriteCStrToDestFile(kMacCreatorSig);
+	} else {
+		WriteCStrToDestFile("????");
+	}
+}
+
+LOCALPROC Write_tmachoPkgInfoContents(void)
+{
+	WriteCStrToDestFile("APPL");
+	Write_MacCreatorSigOrGeneric();
+}
+
+LOCALPROC Write_machoRsrcName(void)
+{
+	WriteStrAppAbbrev();
+	WriteCStrToDestFile(".rsrc");
+}
+
+LOCALPROC Write_machoRsrcPath(void)
+{
+	WriteFileInDirToDestFile0(Write_machores_d_ToDestFile,
+		Write_machoRsrcName);
+}
+
+LOCALPROC Write_AppIconName(void)
+{
+	WriteCStrToDestFile("ICONAPPO.icns");
+}
+
+LOCALPROC Write_machoAppIconPath(void)
+{
+	WriteFileInDirToDestFile0(Write_machores_d_ToDestFile,
+		Write_AppIconName);
+}
+
+LOCALPROC Write_srcAppIconPath(void)
+{
+	WriteFileInDirToDestFile0(Write_src_d_ToDestFile,
+		Write_AppIconName);
+}
+
+LOCALPROC WriteMainRsrcName(void)
+{
+	switch (cur_ide) {
+		case gbk_ide_msv:
+		case gbk_ide_dvc:
+		case gbk_ide_cyg:
+		case gbk_ide_mgw:
+		case gbk_ide_lcc:
+		case gbk_ide_dmc:
+		case gbk_ide_dkp:
+		case gbk_ide_plc:
+			WriteCStrToDestFile("main.rc");
+			break;
+		case gbk_ide_mvc:
+			switch (gbo_targfam) {
+				case gbk_targfam_mswn:
+				case gbk_targfam_wnce:
+					WriteCStrToDestFile("main.rc");
+					break;
+				default:
+					WriteCStrToDestFile("main.r");
+					break;
+			}
+			break;
+		default:
+			WriteCStrToDestFile("main.r");
+			break;
+	}
+}
+
+LOCALPROC Write_Rsrc_d_ToDestFile(void)
+{
+	if ((gbk_targfam_mswn == gbo_targfam)
+		|| (gbk_targfam_wnce == gbo_targfam))
+	{
+		Write_cfg_d_ToDestFile();
+	} else
+	{
+		Write_src_d_ToDestFile();
+	}
+}
+
+LOCALPROC WriteMainRsrcSrcPath(void)
+{
+	WriteFileInDirToDestFile0(Write_Rsrc_d_ToDestFile,
+		WriteMainRsrcName);
+}
+
+LOCALPROC WriteMainRsrcObjName(void)
+{
+#if (gbk_ide_msv == cur_ide) \
+	|| (gbk_ide_lcc == cur_ide) \
+	|| (gbk_ide_dvc == cur_ide) \
+	|| (gbk_ide_cyg == cur_ide) \
+	|| (gbk_ide_mgw == cur_ide) \
+	|| (gbk_ide_mvc == cur_ide) \
+	|| (gbk_ide_dmc == cur_ide) \
+	|| (gbk_ide_dkp == cur_ide) \
+	|| (gbk_ide_plc == cur_ide)
+	WriteCStrToDestFile("main.res");
+#endif
+
+#if (gbk_ide_mpw == cur_ide)
+	WriteCStrToDestFile("main.rsrc");
+#endif
+}
+
+LOCALPROC WriteMainRsrcObjPath(void)
+{
+	WriteFileInDirToDestFile0(Write_obj_d_ToDestFile,
+		WriteMainRsrcObjName);
+}
+
+LOCALPROC WriteCNFGGLOBName(void)
+{
+	WriteCStrToDestFile("CNFGGLOB.h");
+}
+
+LOCALPROC WriteCNFGGLOBPath(void)
+{
+	WriteFileInDirToDestFile0(Write_cfg_d_ToDestFile,
+		WriteCNFGGLOBName);
+}
+
+LOCALPROC WriteCNFGRAPIName(void)
+{
+	WriteCStrToDestFile("CNFGRAPI.h");
+}
+
+LOCALPROC WriteCNFGRAPIPath(void)
+{
+	WriteFileInDirToDestFile0(Write_cfg_d_ToDestFile,
+		WriteCNFGRAPIName);
+}
+
+LOCALPROC WritePathArgInMakeCmnd(MyProc p)
+{
+	switch (cur_ide) {
+		case gbk_ide_mpw:
+		case gbk_ide_bgc:
+		case gbk_ide_mvc:
+		case gbk_ide_cyg:
+		case gbk_ide_snc:
+		case gbk_ide_xcd:
+		case gbk_ide_msv:
+		case gbk_ide_dkp:
+		case gbk_ide_ccc:
+			WriteSpaceToDestFile();
+			WriteQuoteToDestFile();
+			p();
+			WriteQuoteToDestFile();
+			break;
+		case gbk_ide_lcc:
+			/* saw some glitches with quotes */
+		case gbk_ide_dmc:
+		case gbk_ide_plc:
+		case gbk_ide_dvc:
+		case gbk_ide_mgw:
+		case gbk_ide_9pc:
+			WriteSpaceToDestFile();
+			p();
+			break;
+		default:
+			break;
+	}
+}
+
+LOCALPROC WriteMakeVar(char *s)
+{
+	switch (cur_ide) {
+		case gbk_ide_mpw:
+			WriteCStrToDestFile("{");
+			WriteCStrToDestFile(s);
+			WriteCStrToDestFile("}");
+			break;
+		case gbk_ide_bgc:
+		case gbk_ide_mvc:
+		case gbk_ide_cyg:
+		case gbk_ide_snc:
+		case gbk_ide_xcd:
+		case gbk_ide_msv:
+		case gbk_ide_lcc:
+		case gbk_ide_dvc:
+		case gbk_ide_mgw:
+		case gbk_ide_dmc:
+		case gbk_ide_plc:
+		case gbk_ide_dkp:
+		case gbk_ide_ccc:
+			WriteCStrToDestFile("$(");
+			WriteCStrToDestFile(s);
+			WriteCStrToDestFile(")");
+			break;
+		case gbk_ide_9pc:
+			WriteCStrToDestFile("$");
+			WriteCStrToDestFile(s);
+			break;
+		default:
+			break;
+	}
+}
+
+LOCALPROC WriteMakeDependFile(MyProc p)
+{
+	switch (cur_ide) {
+		case gbk_ide_msv:
+		case gbk_ide_mpw:
+			WriteSpaceToDestFile();
+			WriteQuoteToDestFile();
+			p();
+			WriteQuoteToDestFile();
+			break;
+		case gbk_ide_bgc:
+		case gbk_ide_mvc:
+		case gbk_ide_cyg:
+		case gbk_ide_snc:
+		case gbk_ide_xcd:
+		case gbk_ide_lcc:
+		case gbk_ide_dvc:
+		case gbk_ide_mgw:
+		case gbk_ide_dmc:
+		case gbk_ide_plc:
+		case gbk_ide_dkp:
+		case gbk_ide_ccc:
+		case gbk_ide_9pc:
+			WriteSpaceToDestFile();
+			p();
+		default:
+			break;
+	}
+}
+
+LOCALPROC WriteMainRsrcObjMSCdeps(void)
+{
+	WriteMakeDependFile(WriteMainRsrcSrcPath);
+}
+
+LOCALPROC WriteMakeRule(MyProc ptarg,
+	MyProc pdeps, MyProc pbody)
+{
+	WriteBgnDestFileLn();
+	switch (cur_ide) {
+		case gbk_ide_mpw:
+			WriteQuoteToDestFile();
+			ptarg();
+			WriteQuoteToDestFile();
+			WriteCStrToDestFile(" \304");
+			pdeps();
+			break;
+		case gbk_ide_bgc:
+		case gbk_ide_mvc:
+		case gbk_ide_cyg:
+		case gbk_ide_snc:
+		case gbk_ide_xcd:
+		case gbk_ide_ccc:
+			ptarg();
+			WriteCStrToDestFile(" :");
+			pdeps();
+			break;
+		case gbk_ide_9pc:
+			ptarg();
+			WriteCStrToDestFile(": ");
+			pdeps();
+			break;
+		case gbk_ide_msv:
+			WriteQuoteToDestFile();
+			ptarg();
+			WriteQuoteToDestFile();
+			WriteCStrToDestFile(" :");
+			pdeps();
+			break;
+		case gbk_ide_lcc:
+		case gbk_ide_dvc:
+		case gbk_ide_mgw:
+		case gbk_ide_dmc:
+		case gbk_ide_plc:
+		case gbk_ide_dkp:
+			ptarg();
+			WriteCStrToDestFile(":");
+			pdeps();
+			break;
+		default:
+			break;
+	}
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		pbody();
+	--DestFileIndent;
+}
+
+LOCALPROC WriteMkDir(MyProc p)
+{
+	WriteBgnDestFileLn();
+	switch (cur_ide) {
+		case gbk_ide_mpw:
+			WriteCStrToDestFile("NewFolder");
+			break;
+		case gbk_ide_bgc:
+		case gbk_ide_mvc:
+		case gbk_ide_cyg:
+		case gbk_ide_snc:
+		case gbk_ide_xcd:
+		case gbk_ide_ccc:
+		case gbk_ide_9pc:
+		case gbk_ide_dkp:
+			WriteCStrToDestFile("mkdir");
+			break;
+		default:
+			break;
+	}
+	WritePathArgInMakeCmnd(p);
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteRmDir(MyProc p)
+{
+	WriteBgnDestFileLn();
+	switch (cur_ide) {
+		case gbk_ide_mpw:
+			WriteCStrToDestFile("Delete -i -y");
+			break;
+		case gbk_ide_bgc:
+		case gbk_ide_mvc:
+		case gbk_ide_cyg:
+		case gbk_ide_snc:
+		case gbk_ide_xcd:
+		case gbk_ide_ccc:
+		case gbk_ide_9pc:
+		case gbk_ide_dkp:
+			WriteCStrToDestFile("rm -fr");
+			break;
+		default:
+			break;
+	}
+	WritePathArgInMakeCmnd(p);
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteRmFile(MyProc p)
+{
+	WriteBgnDestFileLn();
+	switch (cur_ide) {
+		case gbk_ide_mpw:
+			WriteCStrToDestFile("Delete -i");
+			break;
+		case gbk_ide_bgc:
+		case gbk_ide_mvc:
+		case gbk_ide_cyg:
+		case gbk_ide_snc:
+		case gbk_ide_xcd:
+		case gbk_ide_dvc:
+		case gbk_ide_mgw:
+		case gbk_ide_dkp:
+		case gbk_ide_ccc:
+		case gbk_ide_9pc:
+			WriteCStrToDestFile("rm -f");
+			break;
+		case gbk_ide_msv:
+			WriteCStrToDestFile("-@erase");
+			break;
+		case gbk_ide_lcc:
+		case gbk_ide_dmc:
+		case gbk_ide_plc:
+			WriteCStrToDestFile("del");
+			break;
+		default:
+			break;
+	}
+	WritePathArgInMakeCmnd(p);
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteCopyFile(MyProc pfrom, MyProc pto)
+{
+	WriteBgnDestFileLn();
+	switch (cur_ide) {
+		case gbk_ide_mpw:
+			WriteCStrToDestFile("Duplicate");
+			break;
+		case gbk_ide_bgc:
+		case gbk_ide_mvc:
+		case gbk_ide_cyg:
+		case gbk_ide_snc:
+		case gbk_ide_xcd:
+		case gbk_ide_dkp:
+		case gbk_ide_ccc:
+		case gbk_ide_9pc:
+			WriteCStrToDestFile("cp");
+			break;
+		default:
+			break;
+	}
+	WritePathArgInMakeCmnd(pfrom);
+	WritePathArgInMakeCmnd(pto);
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteMoveDir(MyProc pfrom, MyProc pto)
+{
+	WriteBgnDestFileLn();
+	switch (cur_ide) {
+		case gbk_ide_mpw:
+			WriteCStrToDestFile("Move");
+			break;
+		case gbk_ide_bgc:
+		case gbk_ide_mvc:
+		case gbk_ide_cyg:
+		case gbk_ide_snc:
+		case gbk_ide_xcd:
+		case gbk_ide_dkp:
+		case gbk_ide_ccc:
+		case gbk_ide_9pc:
+			WriteCStrToDestFile("mv");
+			break;
+		default:
+			break;
+	}
+	WritePathArgInMakeCmnd(pfrom);
+	WritePathArgInMakeCmnd(pto);
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteEchoToNewFile(MyProc ptext, MyProc pto, blnr newline)
+{
+	WriteBgnDestFileLn();
+	switch (cur_ide) {
+		case gbk_ide_mpw:
+			WriteCStrToDestFile("Echo");
+			if (! newline) {
+				WriteCStrToDestFile(" -n");
+			}
+			WriteCStrToDestFile(" \"");
+			ptext();
+			WriteCStrToDestFile("\" >");
+			WritePathArgInMakeCmnd(pto);
+			break;
+			break;
+		case gbk_ide_cyg:
+		case gbk_ide_snc:
+		case gbk_ide_dkp:
+		case gbk_ide_ccc:
+			WriteCStrToDestFile("echo");
+			if (! newline) {
+				WriteCStrToDestFile(" -n");
+			}
+			WriteCStrToDestFile(" \"");
+			ptext();
+			WriteCStrToDestFile("\" >");
+			WritePathArgInMakeCmnd(pto);
+			break;
+		case gbk_ide_9pc:
+			WriteCStrToDestFile("echo");
+			if (! newline) {
+				WriteCStrToDestFile(" -n");
+			}
+			WriteCStrToDestFile(" '");
+			ptext();
+			WriteCStrToDestFile("' >");
+			WritePathArgInMakeCmnd(pto);
+			break;
+		case gbk_ide_bgc:
+		case gbk_ide_mvc:
+		case gbk_ide_xcd:
+			WriteCStrToDestFile("printf \"");
+			ptext();
+			if (newline) {
+				WriteCStrToDestFile("\\n");
+			}
+			WriteCStrToDestFile("\" >");
+			WritePathArgInMakeCmnd(pto);
+			break;
+		default:
+			break;
+	}
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteCompileCExec(void)
+{
+	switch (cur_ide) {
+		case gbk_ide_9pc:
+			WriteCStrToDestFile("$CC");
+			break;
+		case gbk_ide_mpw:
+			if (gbk_cpufam_68k == gbo_cpufam) {
+				WriteCStrToDestFile("SC");
+			} else if (gbk_cpufam_ppc == gbo_cpufam) {
+				WriteCStrToDestFile("MrC");
+			}
+			break;
+		case gbk_ide_bgc:
+		case gbk_ide_mvc:
+		case gbk_ide_cyg:
+		case gbk_ide_xcd:
+			WriteCStrToDestFile("gcc");
+			break;
+		case gbk_ide_snc:
+		case gbk_ide_ccc:
+			WriteCStrToDestFile("cc");
+			break;
+		case gbk_ide_msv:
+			if (gbk_cpufam_arm == gbo_cpufam) {
+				WriteCStrToDestFile("clarm.exe");
+			} else {
+				WriteCStrToDestFile("cl.exe");
+			}
+			break;
+		case gbk_ide_lcc:
+			WriteCStrToDestFile("lcc.exe");
+			break;
+		case gbk_ide_dvc:
+		case gbk_ide_mgw:
+			WriteCStrToDestFile("gcc.exe");
+			break;
+		case gbk_ide_dkp:
+			WriteCStrToDestFile("$(DEVKITARM)/bin/arm-eabi-gcc.exe");
+			break;
+		case gbk_ide_dmc:
+			WriteCStrToDestFile("dmc.exe");
+			break;
+		case gbk_ide_plc:
+			WriteCStrToDestFile("pocc.exe");
+			break;
+		default:
+			break;
+	}
+}
+
+LOCALPROC WriteCompileC(MyProc psrc, MyProc pobj,
+	blnr UseAPI)
+{
+	WriteBgnDestFileLn();
+	switch (cur_ide) {
+		case gbk_ide_9pc:
+			WriteCompileCExec();
+			WriteCStrToDestFile(" -o");
+			WritePathArgInMakeCmnd(pobj);
+			WriteCStrToDestFile(" $CFLAGS");
+			WritePathArgInMakeCmnd(psrc);
+			break;
+		case gbk_ide_mpw:
+		case gbk_ide_bgc:
+		case gbk_ide_cyg:
+		case gbk_ide_xcd:
+		case gbk_ide_snc:
+		case gbk_ide_dvc:
+		case gbk_ide_mgw:
+		case gbk_ide_dkp:
+		case gbk_ide_ccc:
+			WriteCompileCExec();
+			WritePathArgInMakeCmnd(psrc);
+			WriteCStrToDestFile(" -o");
+			WritePathArgInMakeCmnd(pobj);
+			WriteSpaceToDestFile();
+			if (! UseAPI) {
+				WriteMakeVar("mk_COptions");
+			} else {
+				if (gbk_ide_xcd == cur_ide)
+				{
+					WriteMakeVar("mk_COptionsOSGLU");
+				} else {
+					WriteMakeVar("mk_COptions");
+				}
+				if (gbk_apifam_xwn == gbo_apifam) {
+#if 0
+					if (gbk_targfam_fbsd == gbo_targfam) {
+						WriteCStrToDestFile(" -I/usr/local/include");
+						/*
+							this is location in latest PC-BSD,
+							but in old PC-BSD need
+								/usr/X11R6/include/
+							and in latest PC-BSD
+								/usr/X11R6/ links to /usr/local/
+							so just use old location.
+						*/
+					}
+#endif
+					if ((gbk_ide_xcd == cur_ide)
+						|| (gbk_targfam_fbsd == gbo_targfam)
+						|| (gbk_targfam_obsd == gbo_targfam)
+						|| (gbk_targfam_oind == gbo_targfam))
+					{
+						WriteCStrToDestFile(" -I/usr/X11R6/include/");
+					} else if (gbk_targfam_nbsd == gbo_targfam) {
+						WriteCStrToDestFile(" -I/usr/X11R7/include/");
+					} else if (gbk_targfam_dbsd == gbo_targfam) {
+						WriteCStrToDestFile(" -I/usr/pkg/include/");
+					} else if (gbk_targfam_minx == gbo_targfam) {
+						WriteCStrToDestFile(
+							" -I/usr/pkg/X11R6/include/");
+					}
+				} else if (gbk_apifam_sdl == gbo_apifam) {
+					if (gbk_targfam_mach == gbo_targfam) {
+						WriteCStrToDestFile(" -I/usr/local/include/"
+							" -D_GNU_SOURCE=1 -D_THREAD_SAFE");
+					}
+				} else if (gbk_apifam_sd2 == gbo_apifam) {
+					if (gbk_targfam_mach == gbo_targfam) {
+						WriteCStrToDestFile(
+							" -D_GNU_SOURCE=1 -D_THREAD_SAFE");
+					}
+				} else if (gbk_apifam_nds == gbo_apifam) {
+					WriteCStrToDestFile(
+						" -I$(DEVKITPRO)/libnds/include");
+				} else if (gbk_apifam_gtk == gbo_apifam) {
+					WriteCStrToDestFile(
+						" `pkg-config --cflags gtk+-2.0`");
+				}
+			}
+			break;
+		case gbk_ide_msv:
+			WriteCompileCExec();
+			WritePathArgInMakeCmnd(psrc);
+			WriteSpaceToDestFile();
+			WriteMakeVar("mk_COptions");
+			break;
+		case gbk_ide_lcc:
+			WriteCompileCExec();
+			WritePathArgInMakeCmnd(psrc);
+			WriteCStrToDestFile(" -Fo");
+			pobj();
+			WriteSpaceToDestFile();
+			WriteMakeVar("mk_COptions");
+			break;
+		case gbk_ide_dmc:
+			WriteCompileCExec();
+			WritePathArgInMakeCmnd(psrc);
+			WriteCStrToDestFile(" -o");
+			pobj();
+			WriteSpaceToDestFile();
+			WriteMakeVar("mk_COptions");
+			break;
+		case gbk_ide_plc:
+			WriteCompileCExec();
+			WritePathArgInMakeCmnd(psrc);
+			WriteCStrToDestFile(" -Fo");
+			WriteQuoteToDestFile();
+			pobj();
+			WriteQuoteToDestFile();
+			WriteSpaceToDestFile();
+			WriteMakeVar("mk_COptions");
+			break;
+		default:
+			break;
+	}
+	WriteEndDestFileLn();
+}
--- /dev/null
+++ b/setup/BLDUTIL4.i
@@ -1,0 +1,303 @@
+/*
+	BLDUTIL4.i
+	Copyright (C) 2009 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	BuiLD system UTILities part 4
+*/
+
+LOCALPROC WriteOutDummyContents(void)
+{
+	WriteDestFileLn(
+		"This file is here because some archive extraction");
+	WriteDestFileLn("software will not create an empty directory.");
+}
+
+LOCALPROC WriteMakeOutputDirectories(void)
+{
+	if ((gbk_ide_xcd == cur_ide) && (! UseCmndLine)) {
+	} else
+	if (gbk_ide_mw8 == cur_ide) {
+	} else {
+		WriteSectionCommentDestFile("make output directory");
+
+		MakeSubDirectory("my_obj_d", "my_project_d", obj_d_name, "");
+
+		WriteADstFile1("my_obj_d",
+			"dummy", ".txt", "Dummy",
+			WriteOutDummyContents);
+	}
+}
+
+LOCALPROC WriteIdeSpecificFiles(void)
+{
+#if gbk_ide_mpw == cur_ide
+	WriteMPWSpecificFiles();
+#endif
+
+#if gbk_ide_mvc == cur_ide
+	WriteMVCSpecificFiles();
+#endif
+
+#if (gbk_ide_bgc == cur_ide) \
+	|| (gbk_ide_cyg == cur_ide) \
+	|| (gbk_ide_mgw == cur_ide) \
+	|| (gbk_ide_dkp == cur_ide)
+	WriteBashGccSpecificFiles();
+#endif
+
+#if gbk_ide_mw8 == cur_ide
+	WriteMetrowerksSpecificFiles();
+#endif
+
+#if gbk_ide_snc == cur_ide
+	WriteSncSpecificFiles();
+#endif
+
+#if gbk_ide_msv == cur_ide
+	WriteMsvSpecificFiles();
+#endif
+
+#if gbk_ide_lcc == cur_ide
+	if (UseCmndLine) {
+		WriteLccW32clSpecificFiles();
+	} else {
+		WriteLccW32SpecificFiles();
+	}
+#endif
+
+#if gbk_ide_dvc == cur_ide
+	if (UseCmndLine) {
+		WriteBashGccSpecificFiles();
+	} else {
+		WriteDevCSpecificFiles();
+	}
+#endif
+
+#if gbk_ide_xcd == cur_ide
+	if (UseCmndLine) {
+		WriteBashGccSpecificFiles();
+	} else {
+		WriteXCDSpecificFiles();
+	}
+#endif
+
+#if gbk_ide_dmc == cur_ide
+	WriteDMCSpecificFiles();
+#endif
+
+#if gbk_ide_plc == cur_ide
+	if (UseCmndLine) {
+		WritePLCclSpecificFiles();
+	} else {
+		WritePLCSpecificFiles();
+	}
+#endif
+
+#if gbk_ide_ccc == cur_ide
+	WriteCccSpecificFiles();
+#endif
+
+#if gbk_ide_9pc == cur_ide
+	Write9pcSpecificFiles();
+#endif
+}
+
+LOCALPROC ResetAllCommandLineParameters(void)
+{
+	GNResetCommandLineParameters();
+	GNDevResetCommandLineParameters();
+#ifdef Have_SPBLDOPT
+	SPResetCommandLineParameters();
+#endif
+	olv_cur = 1;
+	OnlyUserOptions = falseblnr;
+}
+
+LOCALFUNC tMyErr TryAsAtOptionNot(void)
+{
+	tMyErr err;
+
+	if (! CurArgIsCStr_v2("@")) {
+		err = kMyErrNoMatch;
+	} else
+	if (OnlyUserOptions) {
+		err = ReportParseFailure("Already have @");
+	} else
+	if (kMyErr_noErr != (err = AdvanceTheArg())) {
+		/* fail */
+	} else
+	{
+		OnlyUserOptions = trueblnr;
+		err = kMyErr_noErr;
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr TryAsXClmOptionNot(void)
+{
+	tMyErr err;
+
+	if (! CurArgIsCStr_v2("!")) {
+		err = kMyErrNoMatch;
+	} else
+	if (kMyErr_noErr != (err = AdvanceTheArg())) {
+		/* fail */
+	} else
+	{
+		err = kMyErr_noErr;
+		++olv_cur;
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr ReportUnknownSwitch(void)
+{
+	MyPStr t0;
+	MyPStr t;
+
+	GetCurArgAsPStr(t0);
+	PStrFromCStr(t, "unknown switch : ");
+	PStrAppend(t, t0);
+
+	return ReportParseFailPStr(t);
+}
+
+LOCALFUNC tMyErr ProcessCommandLineArguments(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+	while ((! The_arg_end) && (kMyErr_noErr == err)) {
+		if (kMyErrNoMatch == (err = TryAsGNOptionNot()))
+		if (kMyErrNoMatch == (err = TryAsGNDevOptionNot()))
+#ifdef Have_SPBLDOPT
+		if (kMyErrNoMatch == (err = TryAsSPOptionNot()))
+#endif
+		if (kMyErrNoMatch == (err = TryAsAtOptionNot()))
+		if (kMyErrNoMatch == (err = TryAsXClmOptionNot()))
+		{
+			err = ReportUnknownSwitch();
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC DoDocTypeAddToMainRC(void)
+{
+	WriteBgnDestFileLn();
+	WriteUnsignedToOutput(256 + DocTypeCounter);
+	WriteCStrToDestFile(
+		"                     ICON    DISCARDABLE     ");
+	WriteQuoteToDestFile();
+	WriteDocTypeIconFileName();
+	WriteQuoteToDestFile();
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteWinMainRCcontents(void)
+{
+	DoAllDocTypesWithSetup(DoDocTypeAddToMainRC);
+}
+
+LOCALPROC WriteWinMainRC(void)
+{
+	WriteADstFile1("my_config_d",
+		"main", ".rc", "Resource Configuration file",
+		WriteWinMainRCcontents);
+}
+
+LOCALPROC WriteConfigFiles(void)
+{
+	WriteAppSpecificConfigFiles();
+
+	if (HaveMacRrscs) {
+		WriteCommonCNFGRSRC();
+	}
+
+	if (gbk_apifam_win == gbo_apifam) {
+		WriteWinMainRC();
+	}
+}
+
+
+LOCALPROC MakeConfigFolder(void)
+{
+	WriteSectionCommentDestFile("make configuration folder");
+
+	MakeSubDirectory("my_config_d", "my_project_d", cfg_d_name, "");
+}
+
+#if WantWriteVarName
+LOCALPROC WriteAppVariationStr1(void)
+{
+	WriteBgnDestFileLn();
+	WriteAppVariationStr();
+	WriteEndDestFileLn();
+}
+#endif
+
+#if WantWriteBldOpts
+LOCALPROC WriteBldOpts1(void)
+{
+	WriteBgnDestFileLn();
+	WriteBldOpts();
+	WriteEndDestFileLn();
+}
+#endif
+
+LOCALFUNC tMyErr DoTheCommand(void)
+{
+	tMyErr err;
+
+	ResetAllCommandLineParameters();
+
+	if (kMyErr_noErr == (err = ProcessCommandLineArguments()))
+	if (kMyErr_noErr == (err = AutoChooseGNSettings()))
+	if (kMyErr_noErr == (err = AutoChooseGNDevSettings()))
+#ifdef Have_SPBLDOPT
+	if (kMyErr_noErr == (err = AutoChooseSPSettings()))
+#endif
+	{
+		WriteScriptLangHeader();
+
+		WriteMakeOutputDirectories();
+
+		MakeConfigFolder();
+
+		WriteConfigFiles();
+
+		if (CurPrintCFiles) {
+			WriteCFilesList();
+		}
+
+#if WantWriteVarName
+		WriteADstFile1("my_project_d",
+			"var_name", "", "variation name",
+			WriteAppVariationStr1);
+#endif
+#if WantWriteBldOpts
+		WriteADstFile1("my_project_d",
+			"bld_opts", "", "build options",
+			WriteBldOpts1);
+#endif
+
+		WriteIdeSpecificFiles();
+	}
+
+	return err;
+}
--- /dev/null
+++ b/setup/CMDARGT1.i
@@ -1,0 +1,101 @@
+/*
+	CMDARGT1.i
+	Copyright (C) 2009 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	CoMmandD ARGument Tool part 1
+
+	allows code used with CMDARGW1 to also be
+	used to make an MPW tool.
+*/
+
+
+LOCALVAR int The_argc;
+LOCALVAR int The_argi;
+typedef char **The_argvt;
+LOCALVAR The_argvt The_argv;
+LOCALVAR char *Cur_args;
+LOCALVAR blnr The_arg_end;
+
+GLOBALFUNC tMyErr AdvanceTheArg(void)
+{
+	++The_argi;
+	if (The_argi < The_argc) {
+		Cur_args = The_argv[The_argi];
+	} else {
+		The_arg_end = trueblnr;
+	}
+
+	return kMyErr_noErr;
+}
+
+GLOBALFUNC blnr CurArgIsCStr_v2(char *s)
+{
+	/* warning : assumes (! The_arg_end) */
+	return CStrEq(Cur_args, s);
+}
+
+GLOBALFUNC tMyErr CurArgIsCStrAdvance_v2(char *s)
+{
+	tMyErr err;
+
+	/* warning : assumes (! The_arg_end) */
+	if (! CurArgIsCStr_v2(s)) {
+		err = kMyErrNoMatch;
+	} else {
+		err = AdvanceTheArg();
+	}
+
+	return err;
+}
+
+GLOBALPROC GetCurArgAsCStr(char *s, uimr MaxN)
+{
+	/* warning : assumes (! The_arg_end) */
+	if (CStrLength(Cur_args) > MaxN) {
+		s[0] = 0;
+	} else {
+		CStrCopy(s, Cur_args);
+	}
+}
+
+GLOBALPROC GetCurArgAsPStr(ps3p s)
+{
+	/* warning : assumes (! The_arg_end) */
+	PStrFromCStr(s, Cur_args);
+}
+
+GLOBALPROC BeginParseCommandLineArguments(int argc, The_argvt argv)
+{
+	The_argi = 0;
+	The_argc = argc;
+	The_argv = argv;
+	The_arg_end = falseblnr;
+	(void) AdvanceTheArg();
+}
+
+GLOBALFUNC tMyErr ReportParseFailure(char *s)
+{
+	fprintf(stderr, "%s\n", s);
+
+	return kMyErrReported;
+}
+
+GLOBALFUNC tMyErr ReportParseFailPStr(ps3p s)
+{
+	char t[256];
+
+	CStrFromPStr(s, t);
+	return ReportParseFailure(t);
+}
--- /dev/null
+++ b/setup/CNFGDLFT.i
@@ -1,0 +1,98 @@
+/*
+	CNFGDLFT.i
+	Copyright (C) 2018 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	CoNFiGuration DeFauLTs
+
+	set default values for things not set in CONFIGUR.i
+*/
+
+
+#ifndef kMaintainerName
+#define kMaintainerName "unknown"
+#endif
+
+
+#ifndef kStrHomePage
+#define kStrHomePage "(unknown)"
+#endif
+
+#ifdef __plan9__
+#define cur_ide gbk_ide_9pc
+#endif
+
+#ifndef cur_ide
+
+#ifdef applec
+#define cur_ide gbk_ide_mpw
+#else
+#define cur_ide gbk_ide_bgc
+#endif
+
+#endif /* cur_ide */
+
+
+#ifndef ide_vers
+
+#if gbk_ide_xcd == cur_ide
+#define ide_vers 9410
+#elif gbk_ide_msv == cur_ide
+#define ide_vers 15000
+#else
+#define ide_vers 1
+#endif
+
+#endif /* ide_vers */
+
+
+#ifndef UseCmndLine
+#define UseCmndLine 0
+#endif
+
+
+#ifndef NeedSegmenting
+
+#if gbk_ide_mpw == cur_ide
+#define NeedSegmenting 1
+#else
+#define NeedSegmenting 0
+#endif
+
+#endif /* NeedSegmenting */
+
+
+#ifndef gbo_script
+
+#ifdef __plan9__
+#define gbo_script gbk_script_rc
+#else
+#if gbk_ide_mpw == cur_ide
+#define gbo_script gbk_script_mpw
+#else
+#define gbo_script gbk_script_bash
+#endif
+#endif
+
+#endif /* gbo_script */
+
+
+#ifndef WantWriteVarName
+#define WantWriteVarName 0
+#endif
+
+
+#ifndef WantWriteBldOpts
+#define WantWriteBldOpts 0
+#endif
--- /dev/null
+++ b/setup/CNFGOPTS.i
@@ -1,0 +1,50 @@
+/*
+	CNFGOPTS.i
+	Copyright (C) 2018 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	CoNFiGuration OPTionS
+
+	choices that can be used in CONFIGUR.i
+*/
+
+
+/* choices for cur_ide */
+
+#define gbk_ide_mpw 1 /* Macintosh Programmers Workshop */
+#define gbk_ide_mw8 2 /* Metrowerks CodeWarrior */
+#define gbk_ide_bgc 3 /* Gnu tools */
+#define gbk_ide_snc 4 /* Sun tools */
+#define gbk_ide_msv 5 /* Microsoft Visual C++ */
+#define gbk_ide_lcc 6 /* lcc-win32 - Jacob Navia */
+#define gbk_ide_dvc 7 /* Bloodshed Dev-C++ */
+#define gbk_ide_xcd 8 /* Apple XCode */
+	/* previously Apple Project Builder */
+#define gbk_ide_dmc 9 /* Digital Mars Compiler */
+#define gbk_ide_plc 10 /* Pelles C Compiler */
+#define gbk_ide_mgw 11 /* MinGW */
+#define gbk_ide_cyg 12 /* Cygwin */
+#define gbk_ide_dkp 13 /* devkitpro */
+#define gbk_ide_ccc 14 /* Generic command line c compiler */
+#define gbk_ide_mvc 15 /* Mini vMac C (a specific version of gcc) */
+#define gbk_ide_9pc 16 /* Plan 9 */
+
+/* choices for gbo_script */
+
+#define gbk_script_mpw 1
+#define gbk_script_applescript 2
+#define gbk_script_bash 3
+#define gbk_script_xp 4
+#define gbk_script_vbscript 5
+#define gbk_script_rc 6
--- /dev/null
+++ b/setup/CONFIGUR.i
@@ -1,0 +1,10 @@
+/*
+	CONFIGUR.i
+*/
+
+/*
+	CONFIGURation file
+
+	see CNFGDLFT.i and CNFGOPTS.i for things
+		that can go here.
+*/
--- /dev/null
+++ b/setup/COREDEFS.i
@@ -1,0 +1,90 @@
+/*
+	COREDEFS.i
+	Copyright (C) 2018 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	CORE DEFinitionS
+*/
+
+
+typedef unsigned long ui5b;
+typedef unsigned short ui4b;
+typedef unsigned char ui3b;
+
+typedef signed long si5b;
+typedef signed short si4b;
+typedef signed char si3b;
+
+typedef ui5b ui5r;
+typedef ui4b ui4r;
+typedef ui3b ui3r;
+
+typedef si5b si5r;
+typedef si4b si4r;
+typedef si3b si3r;
+
+typedef si3b *si3p;
+typedef ui3b *ui3p;
+typedef si4b *si4p;
+typedef ui4b *ui4p;
+typedef si5b *si5p;
+typedef ui5b *ui5p;
+
+typedef ui5p *ui5h;
+typedef ui4p *ui4h;
+typedef ui3p *ui3h;
+
+/*
+	define the largest supported
+	representation types.
+*/
+#define uimbl2sz 5
+typedef si5r simr;
+typedef ui5r uimr;
+
+typedef ui3b blnb;
+typedef ui3r blnr;
+#define trueblnr 1
+#define falseblnr 0
+
+typedef si4r tMyErr;
+
+typedef unsigned char MyPStr[256];
+typedef unsigned char *ps3p;
+typedef unsigned char MyCharR;
+typedef MyCharR *MyCharPtr;
+
+typedef unsigned char MyByte;
+typedef MyByte *MyPtr;
+
+#define nullpr ((void *) 0)
+
+#define DISCARDVAL (void)
+
+
+#define LOCALFUNC static
+#define GLOBALFUNC static
+#define EXPORTFUNC static
+#define TYPEDEFFUNC typedef
+
+#define LOCALPROC LOCALFUNC void
+#define GLOBALPROC GLOBALFUNC void
+#define EXPORTPROC EXPORTFUNC void
+#define TYPEDEFPROC TYPEDEFFUNC void
+
+#define LOCALVAR static
+#define GLOBALVAR static
+#define EXPORTVAR static
+
+GLOBALVAR MyPtr pDt;
--- /dev/null
+++ b/setup/DFFILDEF.i
@@ -1,0 +1,64 @@
+/*
+	DFFILDEF.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	DEFinitions for program SPecific FILe DEFinitions
+*/
+
+#define kDepDirCSrc 0
+#define kDepDirCnfg 1
+
+typedef void (*tDoOneDepends)(int DepDir, char *s);
+
+typedef void (*tDoDependsForC)(tDoOneDepends p);
+
+typedef void (*tDoOneCFile)(char *s, int DepDir, long Flgm,
+	tDoDependsForC depends);
+
+typedef void (*tWriteOneExtension)(char *s);
+
+typedef void (*tWriteExtensionList)(tWriteOneExtension p);
+
+typedef void (*tWriteOneDocType)(
+	char *ShortName,
+	char *MacType,
+	char *LongName,
+	tWriteExtensionList WriteExtensionList);
+
+#if 0
+#define kCSrcFlagAsmAvail 0
+#define kCSrcFlagAltSrc 1
+#endif
+#define kCSrcFlagSkip 1
+#define kCSrcFlagUseAPI 2
+#define kCSrcFlagSortFirst 3
+#define kCSrcFlagNoSource 4
+#define kCSrcFlagNoHeader 5
+#define kCSrcFlagOjbc 6
+
+#define kCSrcFlgmNone 0
+#if 0
+#define kCSrcFlgmAltSrc (1 << kCSrcFlagAltSrc)
+#endif
+#define kCSrcFlgmSkip (1 << kCSrcFlagSkip)
+#define kCSrcFlgmUseAPI (1 << kCSrcFlagUseAPI)
+#define kCSrcFlgmSortFirst (1 << kCSrcFlagSortFirst)
+#define kCSrcFlgmNoSource (1 << kCSrcFlagNoSource)
+#define kCSrcFlgmNoHeader (1 << kCSrcFlagNoHeader)
+#define kCSrcFlgmOjbc (1 << kCSrcFlagOjbc)
+
+#define CSrcFlagsUseIf(b) ((b) ? kCSrcFlgmNone : kCSrcFlgmSkip)
+#define CSrcFlagsUseHdrIf(b) (CSrcFlagsUseIf(b) | kCSrcFlgmNoSource)
+#define CSrcFlagsUseSrcIf(b) (CSrcFlagsUseIf(b) | kCSrcFlgmNoHeader)
--- /dev/null
+++ b/setup/GNBLDOPT.i
@@ -1,0 +1,1610 @@
+/*
+	GNBLDOPT.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	GeNeric BuiLD OPTions
+*/
+
+/* --- default definitions for SPBASDEF --- */
+
+#ifndef MayUseSound
+#define MayUseSound 1
+#endif
+
+#ifndef UseOpenGLinOSX
+#define UseOpenGLinOSX 0
+#endif
+
+#ifndef UseMachinOSX
+#define UseMachinOSX 0
+#endif
+
+#ifndef NeedIntFormatInfo
+#define NeedIntFormatInfo 0
+#endif
+
+#ifndef ModPPCi3rTypes
+#define ModPPCi3rTypes 0
+#endif
+
+/* --- end of default definitions for SPBASDEF --- */
+
+LOCALVAR blnr OnlyUserOptions = falseblnr;
+LOCALVAR blnr DoingDevOpts = falseblnr;
+
+LOCALVAR ui3r olv_cur;
+
+LOCALFUNC tMyErr CurArgIsOption(char *s, ui3r *olv)
+{
+	tMyErr err;
+	MyPStr t;
+
+	if (! CurArgIsCStr_v2(s)) {
+		err = kMyErrNoMatch;
+	} else
+	if (DoingDevOpts && OnlyUserOptions) {
+		PStrFromCStr(t, s);
+		PStrApndCStr(t, " is a developer only option");
+		err = ReportParseFailPStr(t);
+	} else
+	if (*olv == olv_cur) {
+		PStrFromCStr(t, s);
+		PStrApndCStr(t, " has appeared more than once");
+		err = ReportParseFailPStr(t);
+	} else
+	if (kMyErr_noErr != (err = AdvanceTheArg())) {
+		/* fail */
+	} else
+	{
+		*olv = olv_cur;
+		err = kMyErr_noErr;
+	}
+
+	return err;
+}
+
+typedef char * (* tGetName)(int i);
+
+LOCALFUNC blnr GetCurArgNameIndex(int n, tGetName p,
+	int *r)
+{
+	blnr v;
+	int i;
+
+	for (i = 0; i < n; ++i) {
+		if (CurArgIsCStr_v2(p(i))) {
+			*r = i;
+			v = trueblnr;
+			goto label_1;
+		}
+	}
+	v = falseblnr;
+
+label_1:
+	return v;
+}
+
+#define nanblnr 2
+
+#define kListOptionAuto (-1)
+
+LOCALFUNC tMyErr FindNamedOption(char *s, int n, tGetName p,
+	int *r, ui3r *olv)
+{
+	tMyErr err;
+	MyPStr t;
+
+	if (kMyErr_noErr != (err = CurArgIsOption(s, olv))) {
+		/* no */
+	} else
+	if (The_arg_end) {
+		PStrFromCStr(t, "Expecting an argument for ");
+		PStrApndCStr(t, s);
+		PStrApndCStr(t, " when reached end");
+		err = ReportParseFailPStr(t);
+	} else
+	if (GetCurArgNameIndex(n, p, r)) {
+		err = AdvanceTheArg();
+	} else
+	if (CurArgIsCStr_v2("*")) {
+		*r = kListOptionAuto;
+		err = AdvanceTheArg();
+	} else
+	{
+		PStrFromCStr(t, "Unknown value for ");
+		PStrApndCStr(t, s);
+		err = ReportParseFailPStr(t);
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr BooleanTryAsOptionNot(char *s, blnr *r, ui3r *olv)
+{
+	tMyErr err;
+	MyPStr t;
+
+	if (kMyErr_noErr != (err = CurArgIsOption(s, olv))) {
+		/* no */
+	} else
+	if (The_arg_end) {
+		PStrFromCStr(t, "Expecting a boolean argument for ");
+		PStrApndCStr(t, s);
+		PStrApndCStr(t, " when reached end");
+		err = ReportParseFailPStr(t);
+	} else
+	if (CurArgIsCStr_v2("1")) {
+		*r = trueblnr;
+		err = AdvanceTheArg();
+	} else
+	if (CurArgIsCStr_v2("0")) {
+		*r = falseblnr;
+		err = AdvanceTheArg();
+	} else
+	if (CurArgIsCStr_v2("*")) {
+		*r = nanblnr;
+		err = AdvanceTheArg();
+	} else
+	{
+		PStrFromCStr(t, "Expecting a boolean argument for ");
+		PStrApndCStr(t, s);
+		err = ReportParseFailPStr(t);
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr FlagTryAsOptionNot(char *s, blnr *r, ui3r *olv)
+{
+	tMyErr err;
+
+	if (kMyErr_noErr != (err = CurArgIsOption(s, olv))) {
+		/* no */
+	} else
+	{
+		err = kMyErr_noErr;
+		*r = trueblnr;
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr GetCurArgOptionAsNumber(char *s, long *r)
+{
+	tMyErr err;
+	MyPStr t0;
+	MyPStr t;
+
+	if (The_arg_end) {
+		PStrFromCStr(t, "Expecting a number argument for ");
+		PStrApndCStr(t, s);
+		PStrApndCStr(t, " when reached end");
+		err = ReportParseFailPStr(t);
+	} else {
+		GetCurArgAsPStr(t0);
+		*r = PStrToSimr(t0);
+		/* StringToNum(t0, r); */
+		PStrFromSimr(*r, t);
+		/* NumToString(*r, t); */
+		if (! PStrEq(t0, t)) {
+			PStrFromCStr(t, "Expecting a number argument for ");
+			PStrApndCStr(t, s);
+			PStrApndCStr(t, " but got ");
+			PStrAppend(t, t0);
+			err = ReportParseFailPStr(t);
+		} else
+		{
+			err = AdvanceTheArg();
+		}
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr NumberTryAsOptionNot(char *s, long *r, ui3r *olv)
+{
+	tMyErr err;
+
+	if (kMyErr_noErr != (err = CurArgIsOption(s, olv))) {
+		/* no */
+	} else
+	if (kMyErr_noErr != (err = GetCurArgOptionAsNumber(s, r))) {
+		/* fail */
+	} else
+	{
+		err = kMyErr_noErr;
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptNamedOption(char *s, tGetName p, int i, int i0)
+{
+	if (i != i0) {
+		WriteCStrToDestFile(" ");
+		WriteCStrToDestFile(s);
+		WriteCStrToDestFile(" ");
+		WriteCStrToDestFile(p(i));
+	}
+}
+
+LOCALPROC WrtOptNumberOption(char *s, int i, int i0)
+{
+	if (i != i0) {
+		WriteCStrToDestFile(" ");
+		WriteCStrToDestFile(s);
+		WriteCStrToDestFile(" ");
+		WriteUnsignedToOutput(i);
+	}
+}
+
+LOCALPROC WrtOptSimrOption(char *s, simr i, simr i0)
+{
+	if (i != i0) {
+		WriteCStrToDestFile(" ");
+		WriteCStrToDestFile(s);
+		WriteCStrToDestFile(" ");
+		WriteSignedLongToOutput(i);
+	}
+}
+
+LOCALPROC WrtOptBooleanOption(char *s, blnr i, blnr i0)
+{
+	if (i != i0) {
+		WriteCStrToDestFile(" ");
+		WriteCStrToDestFile(s);
+		WriteCStrToDestFile(" ");
+		WriteCStrToDestFile(i ? "1" : "0");
+	}
+}
+
+LOCALPROC WrtOptFlagOption(char *s, blnr v)
+{
+	if (v) {
+		WriteCStrToDestFile(" ");
+		WriteCStrToDestFile(s);
+	}
+}
+
+
+/* option: Branch */
+
+LOCALVAR uimr Branch;
+LOCALVAR ui3r olv_Branch;
+
+LOCALPROC ResetBranchOption(void)
+{
+	olv_Branch = 0;
+}
+
+LOCALFUNC tMyErr TryAsBranchOptionNot(void)
+{
+	return NumberTryAsOptionNot("-br",
+		(long *)&Branch, &olv_Branch);
+}
+
+LOCALFUNC tMyErr ChooseBranch(void)
+{
+	if (0 == olv_Branch) {
+		Branch = MajorVersion;
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptBranchOption(void)
+{
+	WriteCStrToDestFile("-br");
+	WriteCStrToDestFile(" ");
+	WriteUnsignedToOutput(MajorVersion);
+}
+
+
+/* option: target */
+
+enum {
+	gbk_targ_m68k, /* MacOS 68K */
+	gbk_targ_mfpu, /* MacOS 68K with FPU */
+	gbk_targ_mppc, /* MacOS OS 9 for PowerPC */
+	gbk_targ_mach, /* MacOS X Macho */
+	gbk_targ_imch, /* MacOS X Intel */
+	gbk_targ_mc64, /* MacOS X for x64 */
+	gbk_targ_wx86, /* Windows */
+	gbk_targ_wx64, /* Windows on x64 */
+	gbk_targ_lx86, /* X11 for linux on x86 */
+	gbk_targ_lppc, /* X11 for linux on PowerPC */
+	gbk_targ_lx64, /* X11 for linux on x64 */
+	gbk_targ_larm, /* X11 for linux on arm (debian armel) */
+	gbk_targ_lspr, /* X11 for linux on SPARC */
+	gbk_targ_fbsd, /* FreeBSD for x86 */
+	gbk_targ_fb64, /* FreeBSD for x64 */
+	gbk_targ_fbpc, /* FreeBSD for PowerPC */
+	gbk_targ_obsd, /* OpenBSD for x86 */
+	gbk_targ_ob64, /* OpenBSD for x64 */
+	gbk_targ_nbsd, /* NetBSD for x86 */
+	gbk_targ_nb64, /* NetBSD for x64 */
+	gbk_targ_dbsd, /* Dragonfly BSD for x86 */
+	gbk_targ_db64, /* Dragonfly BSD for x64 */
+	gbk_targ_slrs, /* Solaris SPARC */
+	gbk_targ_sl86, /* Solaris Intel */
+	gbk_targ_oind, /* OpenIndiana for x86 */
+	gbk_targ_oi64, /* OpenIndiana for x64 */
+	gbk_targ_minx, /* Minix on x86 */
+	gbk_targ_wcar, /* Windows CE on ARM */
+	gbk_targ_wc86, /* Windows CE (emulator) on x86 */
+	gbk_targ_carb, /* MacOS Carbon lib for OS 9 and OS X */
+	gbk_targ_mx11, /* X11 for MacOS X PowerPC */
+	gbk_targ_mi11, /* X11 for MacOS X Intel */
+	gbk_targ_mx64, /* X11 for MacOS X x64 */
+	gbk_targ_cygw, /* Cygwin/X */
+	gbk_targ_xgen, /* Generic X11 */
+	gbk_targ_ndsa, /* Nintendo DS on ARM  */
+	gbk_targ_irix, /* Silicon Graphics's IRIX on MIPS */
+	gbk_targ_9x86, /* Plan 9 on x86 */
+	gbk_targ_9x64, /* Plan 9 on x64 */
+	gbk_targ_9arm, /* Plan 9 on arm */
+	gbk_targ_9a64, /* Plan 9 on aarch64 */
+	kNumTargets
+};
+
+LOCALVAR int cur_targ;
+LOCALVAR ui3r olv_targ;
+
+LOCALPROC ResetTargetOption(void)
+{
+	cur_targ = kListOptionAuto;
+	olv_targ = 0;
+}
+
+LOCALFUNC char * GetTargetName(int i)
+{
+	char *s;
+
+	switch (i) {
+		case gbk_targ_m68k:
+			s = "m68k";
+			break;
+		case gbk_targ_mfpu:
+			s = "mfpu";
+			break;
+		case gbk_targ_mppc:
+			s = "mppc";
+			break;
+		case gbk_targ_carb:
+			s = "carb";
+			break;
+		case gbk_targ_mach:
+			s = "mach";
+			break;
+		case gbk_targ_imch:
+			s = "imch";
+			break;
+		case gbk_targ_mc64:
+			s = "mc64";
+			break;
+		case gbk_targ_wx86:
+			s = "wx86";
+			break;
+		case gbk_targ_mx11:
+			s = "mx11";
+			break;
+		case gbk_targ_mi11:
+			s = "mi11";
+			break;
+		case gbk_targ_mx64:
+			s = "mx64";
+			break;
+		case gbk_targ_lx86:
+			s = "lx86";
+			break;
+		case gbk_targ_slrs:
+			s = "slrs";
+			break;
+		case gbk_targ_sl86:
+			s = "sl86";
+			break;
+		case gbk_targ_fbsd:
+			s = "fbsd";
+			break;
+		case gbk_targ_fb64:
+			s = "fb64";
+			break;
+		case gbk_targ_fbpc:
+			s = "fbpc";
+			break;
+		case gbk_targ_obsd:
+			s = "obsd";
+			break;
+		case gbk_targ_ob64:
+			s = "ob64";
+			break;
+		case gbk_targ_nbsd:
+			s = "nbsd";
+			break;
+		case gbk_targ_nb64:
+			s = "nb64";
+			break;
+		case gbk_targ_dbsd:
+			s = "dbsd";
+			break;
+		case gbk_targ_db64:
+			s = "db64";
+			break;
+		case gbk_targ_oind:
+			s = "oind";
+			break;
+		case gbk_targ_oi64:
+			s = "oi64";
+			break;
+		case gbk_targ_minx:
+			s = "minx";
+			break;
+		case gbk_targ_wcar:
+			s = "wcar";
+			break;
+		case gbk_targ_wc86:
+			s = "wc86";
+			break;
+		case gbk_targ_lppc:
+			s = "lppc";
+			break;
+		case gbk_targ_lx64:
+			s = "lx64";
+			break;
+		case gbk_targ_wx64:
+			s = "wx64";
+			break;
+		case gbk_targ_larm:
+			s = "larm";
+			break;
+		case gbk_targ_lspr:
+			s = "lspr";
+			break;
+		case gbk_targ_cygw:
+			s = "cygw";
+			break;
+		case gbk_targ_xgen:
+			s = "xgen";
+			break;
+		case gbk_targ_ndsa:
+			s = "ndsa";
+			break;
+		case gbk_targ_irix:
+			s = "irix";
+			break;
+		case gbk_targ_9x86:
+			s = "9x86";
+			break;
+		case gbk_targ_9x64:
+			s = "9x64";
+			break;
+		case gbk_targ_9arm:
+			s = "9arm";
+			break;
+		case gbk_targ_9a64:
+			s = "9a64";
+			break;
+		default:
+			s = "(unknown Target)";
+			break;
+	}
+	return s;
+}
+
+LOCALFUNC tMyErr TryAsTargetOptionNot(void)
+{
+	return FindNamedOption("-t", kNumTargets, GetTargetName,
+		&cur_targ, &olv_targ);
+}
+
+LOCALFUNC tMyErr ChooseTarg(void)
+{
+	tMyErr err;
+
+	if (kListOptionAuto == cur_targ) {
+		err = ReportParseFailure("target not specified ('-t' switch)");
+	} else {
+		err = kMyErr_noErr;
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptTarg(void)
+{
+	WriteCStrToDestFile(" ");
+	WriteCStrToDestFile("-t");
+	WriteCStrToDestFile(" ");
+	WriteCStrToDestFile(GetTargetName(cur_targ));
+}
+
+
+/* option: debug level */
+
+enum {
+	gbk_dbg_off,
+	gbk_dbg_test,
+	gbk_dbg_on,
+	kNumDebugLevels
+};
+
+LOCALVAR int gbo_dbg;
+LOCALVAR ui3r olv_dbg;
+
+LOCALPROC ResetDbgOption(void)
+{
+	gbo_dbg = kListOptionAuto;
+	olv_dbg = 0;
+}
+
+LOCALFUNC char * GetDbgLvlName(int i)
+{
+	char *s;
+
+	switch (i) {
+		case gbk_dbg_on:
+			s = "d";
+			break;
+		case gbk_dbg_test:
+			s = "t";
+			break;
+		case gbk_dbg_off:
+			s = "s";
+			break;
+		default:
+			s = "(unknown Debug Level)";
+			break;
+	}
+	return s;
+}
+
+LOCALFUNC tMyErr TryAsDbgOptionNot(void)
+{
+	return FindNamedOption("-d",
+		kNumDebugLevels, GetDbgLvlName, &gbo_dbg, &olv_dbg);
+}
+
+#define dfo_dbg() gbk_dbg_off
+
+LOCALFUNC tMyErr ChooseDbgOption(void)
+{
+	if (kListOptionAuto == gbo_dbg) {
+		gbo_dbg = dfo_dbg();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptDbgOption(void)
+{
+	WrtOptNamedOption("-d", GetDbgLvlName, gbo_dbg, dfo_dbg());
+}
+
+
+/* option: language */
+
+enum {
+	gbk_lang_eng,
+	gbk_lang_fre,
+	gbk_lang_ita,
+	gbk_lang_ger,
+	gbk_lang_dut,
+	gbk_lang_spa,
+	gbk_lang_pol,
+	gbk_lang_ptb,
+	gbk_lang_cat,
+	gbk_lang_cze,
+	gbk_lang_srl,
+	kNumLangLevels
+};
+
+LOCALVAR int gbo_lang;
+LOCALVAR ui3r olv_lang;
+
+LOCALPROC ResetLangOption(void)
+{
+	gbo_lang = kListOptionAuto;
+	olv_lang = 0;
+}
+
+LOCALFUNC char * GetLangName(int i)
+{
+	/* ISO 639-2/B */
+	char *s;
+
+	switch (i) {
+		case gbk_lang_eng:
+			s = "eng";
+			break;
+		case gbk_lang_fre:
+			s = "fre";
+			break;
+		case gbk_lang_ita:
+			s = "ita";
+			break;
+		case gbk_lang_ger:
+			s = "ger";
+			break;
+		case gbk_lang_dut:
+			s = "dut";
+			break;
+		case gbk_lang_spa:
+			s = "spa";
+			break;
+		case gbk_lang_pol:
+			s = "pol";
+			break;
+		case gbk_lang_ptb:
+			s = "ptb";
+			break;
+		case gbk_lang_cat:
+			s = "cat";
+			break;
+		case gbk_lang_cze:
+			s = "cze";
+			break;
+		case gbk_lang_srl:
+			s = "srl";
+			break;
+		default:
+			s = "(unknown Language Level)";
+			break;
+	}
+	return s;
+}
+
+LOCALFUNC tMyErr TryAsLangOptionNot(void)
+{
+	return FindNamedOption("-lang",
+		kNumLangLevels, GetLangName, &gbo_lang, &olv_lang);
+}
+
+LOCALFUNC char * GetLProjName(int i)
+{
+	/*
+		As used in OS X, IETF language tags, except when not
+	*/
+	char *s;
+
+	switch (i) {
+		case gbk_lang_eng:
+			s = "English";
+			break;
+		case gbk_lang_fre:
+			s = "French";
+			break;
+		case gbk_lang_ita:
+			s = "Italian";
+			break;
+		case gbk_lang_ger:
+			s = "German";
+			break;
+		case gbk_lang_dut:
+			s = "Dutch";
+			break;
+		case gbk_lang_spa:
+			s = "Spanish";
+			break;
+		case gbk_lang_pol:
+			s = "pl";
+			break;
+		case gbk_lang_ptb:
+			s = "pt_BR";
+			break;
+		case gbk_lang_cat:
+			s = "ca";
+			break;
+		case gbk_lang_cze:
+			s = "cs";
+			break;
+		case gbk_lang_srl:
+			s = "sr";
+			break;
+		default:
+			s = "(unknown Language Level)";
+			break;
+	}
+	return s;
+}
+
+#define dfo_lang() gbk_lang_eng
+
+LOCALFUNC tMyErr ChooseLangOption(void)
+{
+	if (kListOptionAuto == gbo_lang) {
+		gbo_lang = dfo_lang();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptLangOption(void)
+{
+	WrtOptNamedOption("-lang", GetLangName, gbo_lang, dfo_lang());
+}
+
+
+/* option: IconMaster */
+
+#ifndef WantIconMasterDflt
+#define WantIconMasterDflt falseblnr
+#endif
+
+LOCALVAR blnr WantIconMaster;
+LOCALVAR ui3r olv_IconMaster;
+
+LOCALPROC ResetIconMaster(void)
+{
+	WantIconMaster = nanblnr;
+	olv_IconMaster = 0;
+}
+
+LOCALFUNC tMyErr TryAsIconMasterNot(void)
+{
+	return BooleanTryAsOptionNot("-im",
+		&WantIconMaster, &olv_IconMaster);
+}
+
+LOCALFUNC tMyErr ChooseIconMaster(void)
+{
+	if (nanblnr == WantIconMaster) {
+		WantIconMaster = WantIconMasterDflt;
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptIconMaster(void)
+{
+	WrtOptBooleanOption("-im", WantIconMaster, WantIconMasterDflt);
+}
+
+
+/* option: Test Compile Time Error */
+
+LOCALVAR blnr gbo_TstCompErr;
+LOCALVAR ui3r olv_TstCompErr;
+
+LOCALPROC ResetTstCompErr(void)
+{
+	gbo_TstCompErr = nanblnr;
+	olv_TstCompErr = 0;
+}
+
+LOCALFUNC tMyErr TryAsTstCompErrNot(void)
+{
+	return BooleanTryAsOptionNot("-cte",
+		&gbo_TstCompErr, &olv_TstCompErr);
+}
+
+#define dfo_TstCompErr() falseblnr
+
+LOCALFUNC tMyErr ChooseTstCompErr(void)
+{
+	if (nanblnr == gbo_TstCompErr) {
+		gbo_TstCompErr = dfo_TstCompErr();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptTstCompErr(void)
+{
+	WrtOptBooleanOption("-cte", gbo_TstCompErr, dfo_TstCompErr());
+}
+
+
+/* option: Test Build System Error */
+
+LOCALFUNC tMyErr TryAsTstBldSysErr(void)
+{
+	tMyErr err;
+
+	if (! CurArgIsCStr_v2("-bte")) {
+		err = kMyErrNoMatch;
+	} else {
+		err = ReportParseFailure("Testing Build System Error");
+	}
+
+	return err;
+}
+
+
+/* option: target cpu family */
+
+enum {
+	gbk_cpufam_68k, /* Motorola 680x0 */
+	gbk_cpufam_ppc, /* PowerPC */
+	gbk_cpufam_x86, /* Intel 80x86 */
+	gbk_cpufam_spr, /* SPARC */
+	gbk_cpufam_arm, /* ARM */
+	gbk_cpufam_x64, /* x86-64 (aka AMD64, Intel 64) */
+	gbk_cpufam_mip, /* MIPS */
+	gbk_cpufam_gen, /* Generic (don't know) */
+	gbk_cpufam_a64, /* AARCH64 */
+	kNumCPUFamilies
+};
+
+LOCALVAR int gbo_cpufam;
+LOCALVAR ui3r olv_cpufam;
+
+LOCALPROC ResetCPUFamOption(void)
+{
+	gbo_cpufam = kListOptionAuto;
+	olv_cpufam = 0;
+}
+
+LOCALFUNC char * GetCPUFamName(int i)
+{
+	char *s;
+
+	switch (i) {
+		case gbk_cpufam_68k:
+			s = "68k";
+			break;
+		case gbk_cpufam_ppc:
+			s = "ppc";
+			break;
+		case gbk_cpufam_x86:
+			s = "x86";
+			break;
+		case gbk_cpufam_spr:
+			s = "spr";
+			break;
+		case gbk_cpufam_arm:
+			s = "arm";
+			break;
+		case gbk_cpufam_x64:
+			s = "x64";
+			break;
+		case gbk_cpufam_mip:
+			s = "mip";
+			break;
+		case gbk_cpufam_gen:
+			s = "gen";
+			break;
+		default:
+			s = "(unknown CPU)";
+			break;
+	}
+	return s;
+}
+
+LOCALFUNC tMyErr TryAsCPUFamOptionNot(void)
+{
+	return FindNamedOption("-cpu",
+		kNumCPUFamilies, GetCPUFamName, &gbo_cpufam, &olv_cpufam);
+}
+
+LOCALFUNC int dfo_cpufam(void)
+{
+	int v;
+
+	switch (cur_targ) {
+		case gbk_targ_m68k:
+		case gbk_targ_mfpu:
+			v = gbk_cpufam_68k;
+			break;
+		case gbk_targ_mppc:
+		case gbk_targ_carb:
+		case gbk_targ_mach:
+		case gbk_targ_mx11:
+		case gbk_targ_lppc:
+		case gbk_targ_fbpc:
+			v = gbk_cpufam_ppc;
+			break;
+		case gbk_targ_wx86:
+		case gbk_targ_wc86:
+		case gbk_targ_lx86:
+		case gbk_targ_sl86:
+		case gbk_targ_fbsd:
+		case gbk_targ_obsd:
+		case gbk_targ_nbsd:
+		case gbk_targ_dbsd:
+		case gbk_targ_oind:
+		case gbk_targ_minx:
+		case gbk_targ_imch:
+		case gbk_targ_mi11:
+		case gbk_targ_cygw:
+		case gbk_targ_9x86:
+			v = gbk_cpufam_x86;
+			break;
+		case gbk_targ_lspr:
+		case gbk_targ_slrs:
+			v = gbk_cpufam_spr;
+			break;
+		case gbk_targ_wcar:
+		case gbk_targ_ndsa:
+		case gbk_targ_larm:
+		case gbk_targ_9arm:
+			v = gbk_cpufam_arm;
+			break;
+		case gbk_targ_mc64:
+		case gbk_targ_lx64:
+		case gbk_targ_wx64:
+		case gbk_targ_fb64:
+		case gbk_targ_ob64:
+		case gbk_targ_nb64:
+		case gbk_targ_db64:
+		case gbk_targ_oi64:
+		case gbk_targ_mx64:
+		case gbk_targ_9x64:
+			v = gbk_cpufam_x64;
+			break;
+		case gbk_targ_irix:
+			v = gbk_cpufam_mip;
+			break;
+		case gbk_targ_xgen:
+			v = gbk_cpufam_gen;
+			break;
+		case gbk_targ_9a64:
+			v = gbk_cpufam_a64;
+			break;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseCPUFam(void)
+{
+	if (kListOptionAuto == gbo_cpufam) {
+		gbo_cpufam = dfo_cpufam();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptCPUFam(void)
+{
+	WrtOptNamedOption("-cpu", GetCPUFamName, gbo_cpufam, dfo_cpufam());
+}
+
+/* derived option: target family */
+
+enum {
+	gbk_targfam_cmac, /* Classic Mac */
+	gbk_targfam_mach, /* OS X Macho */
+	gbk_targfam_mswn, /* Microsoft Windows */
+	gbk_targfam_linx, /* Linux */
+	gbk_targfam_fbsd, /* FreeBSD */
+	gbk_targfam_obsd, /* OpenBSD */
+	gbk_targfam_nbsd, /* NetBSD */
+	gbk_targfam_dbsd, /* Dragonfly BSD */
+	gbk_targfam_slrs, /* Solaris */
+	gbk_targfam_oind, /* OpenIndiana */
+	gbk_targfam_irix, /* Silicon Graphics's IRIX */
+	gbk_targfam_minx, /* Minix */
+	gbk_targfam_wnce, /* Windows CE */
+	gbk_targfam_carb, /* MacOS Carbon lib for OS 9 and OS X */
+	gbk_targfam_mx11, /* X11 for MacOS X */
+	gbk_targfam_cygw, /* Cygwin/X */
+	gbk_targfam_xgen, /* Generic X11 */
+	gbk_targfam_lnds, /* libnds for Nintendo DS */
+	gbk_targfam_nein, /* Plan 9 */
+	kNumTargFamilies
+};
+
+LOCALVAR int gbo_targfam;
+
+LOCALFUNC tMyErr ChooseTargFam(void)
+{
+	switch (cur_targ) {
+		case gbk_targ_m68k:
+		case gbk_targ_mfpu:
+		case gbk_targ_mppc:
+			gbo_targfam = gbk_targfam_cmac;
+			break;
+		case gbk_targ_mach:
+		case gbk_targ_imch:
+		case gbk_targ_mc64:
+			gbo_targfam = gbk_targfam_mach;
+			break;
+		case gbk_targ_wx86:
+		case gbk_targ_wx64:
+			gbo_targfam = gbk_targfam_mswn;
+			break;
+		case gbk_targ_lx86:
+		case gbk_targ_lppc:
+		case gbk_targ_lx64:
+		case gbk_targ_larm:
+		case gbk_targ_lspr:
+			gbo_targfam = gbk_targfam_linx;
+			break;
+		case gbk_targ_slrs:
+		case gbk_targ_sl86:
+			gbo_targfam = gbk_targfam_slrs;
+			break;
+		case gbk_targ_fbsd:
+		case gbk_targ_fb64:
+		case gbk_targ_fbpc:
+			gbo_targfam = gbk_targfam_fbsd;
+			break;
+		case gbk_targ_obsd:
+		case gbk_targ_ob64:
+			gbo_targfam = gbk_targfam_obsd;
+			break;
+		case gbk_targ_nbsd:
+		case gbk_targ_nb64:
+			gbo_targfam = gbk_targfam_nbsd;
+			break;
+		case gbk_targ_dbsd:
+		case gbk_targ_db64:
+			gbo_targfam = gbk_targfam_dbsd;
+			break;
+		case gbk_targ_oind:
+		case gbk_targ_oi64:
+			gbo_targfam = gbk_targfam_oind;
+			break;
+		case gbk_targ_minx:
+			gbo_targfam = gbk_targfam_minx;
+			break;
+		case gbk_targ_irix:
+			gbo_targfam = gbk_targfam_irix;
+			break;
+		case gbk_targ_wcar:
+		case gbk_targ_wc86:
+			gbo_targfam = gbk_targfam_wnce;
+			break;
+		case gbk_targ_carb:
+			gbo_targfam = gbk_targfam_carb;
+			break;
+		case gbk_targ_mx11:
+		case gbk_targ_mi11:
+		case gbk_targ_mx64:
+			gbo_targfam = gbk_targfam_mx11;
+			break;
+		case gbk_targ_cygw:
+			gbo_targfam = gbk_targfam_cygw;
+			break;
+		case gbk_targ_ndsa:
+			gbo_targfam = gbk_targfam_lnds;
+			break;
+		case gbk_targ_9x86:
+		case gbk_targ_9x64:
+		case gbk_targ_9arm:
+		case gbk_targ_9a64:
+			gbo_targfam = gbk_targfam_nein;
+			break;
+		case gbk_targ_xgen:
+		default:
+			gbo_targfam = gbk_targfam_xgen;
+			break;
+	}
+
+	return kMyErr_noErr;
+}
+
+
+/* option: api family */
+
+enum {
+	gbk_apifam_mac,
+	gbk_apifam_osx,
+	gbk_apifam_win,
+	gbk_apifam_xwn,
+	gbk_apifam_nds,
+	gbk_apifam_gtk,
+	gbk_apifam_sdl,
+	gbk_apifam_sd2,
+	gbk_apifam_cco,
+	gbk_apifam_9dr,
+	kNumAPIFamilies
+};
+
+LOCALVAR int gbo_apifam;
+LOCALVAR ui3r olv_apifam;
+
+LOCALPROC ResetAPIFamOption(void)
+{
+	gbo_apifam = kListOptionAuto;
+	olv_apifam = 0;
+}
+
+LOCALFUNC char * GetAPIFamName(int i)
+{
+	char *s;
+
+	switch (i) {
+		case gbk_apifam_mac:
+			s = "mac";
+			break;
+		case gbk_apifam_osx:
+			s = "osx";
+			break;
+		case gbk_apifam_win:
+			s = "win";
+			break;
+		case gbk_apifam_xwn:
+			s = "xwn";
+			break;
+		case gbk_apifam_nds:
+			s = "nds";
+			break;
+		case gbk_apifam_gtk:
+			s = "gtk";
+			break;
+		case gbk_apifam_sdl:
+			s = "sdl";
+			break;
+		case gbk_apifam_sd2:
+			s = "sd2";
+			break;
+		case gbk_apifam_cco:
+			s = "cco";
+			break;
+		case gbk_apifam_9dr:
+			s = "9dr";
+			break;
+		default:
+			s = "(unknown API)";
+			break;
+	}
+	return s;
+}
+
+LOCALFUNC tMyErr TryAsAPIFamOptionNot(void)
+{
+	return FindNamedOption("-api",
+		kNumAPIFamilies, GetAPIFamName, &gbo_apifam, &olv_apifam);
+}
+
+LOCALFUNC int dfo_apifam(void)
+{
+	int v;
+
+	switch (gbo_targfam) {
+		case gbk_targfam_cmac:
+			v = gbk_apifam_mac;
+			break;
+		case gbk_targfam_mach:
+		case gbk_targfam_carb:
+			if (gbk_cpufam_x64 == gbo_cpufam) {
+				v = gbk_apifam_cco;
+			} else {
+				v = gbk_apifam_osx;
+			}
+			break;
+		case gbk_targfam_mswn:
+		case gbk_targfam_wnce:
+			v = gbk_apifam_win;
+			break;
+		case gbk_targfam_linx:
+		case gbk_targfam_slrs:
+		case gbk_targfam_fbsd:
+		case gbk_targfam_obsd:
+		case gbk_targfam_nbsd:
+		case gbk_targfam_dbsd:
+		case gbk_targfam_oind:
+		case gbk_targfam_minx:
+		case gbk_targfam_irix:
+		case gbk_targfam_mx11:
+		case gbk_targfam_cygw:
+		case gbk_targfam_xgen:
+			v = gbk_apifam_xwn;
+			break;
+		case gbk_targfam_lnds:
+			v = gbk_apifam_nds;
+			break;
+		case gbk_targfam_nein:
+			v = gbk_apifam_9dr;
+			break;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseAPIFam(void)
+{
+	if (kListOptionAuto == gbo_apifam) {
+		gbo_apifam = dfo_apifam();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptAPIFam(void)
+{
+	WrtOptNamedOption("-api", GetAPIFamName, gbo_apifam, dfo_apifam());
+}
+
+
+/* option: print file list */
+
+LOCALVAR blnr CurPrintCFiles;
+LOCALVAR ui3r olv_PrintCFiles;
+
+LOCALPROC ResetListOption(void)
+{
+	CurPrintCFiles = falseblnr;
+	olv_PrintCFiles = 0;
+}
+
+LOCALFUNC tMyErr TryAsListOptionNot(void)
+{
+	return FlagTryAsOptionNot("-l", &CurPrintCFiles, &olv_PrintCFiles);
+}
+
+LOCALFUNC tMyErr ChooseListOption(void)
+{
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptListOption(void)
+{
+	WrtOptFlagOption("-l", CurPrintCFiles);
+}
+
+/* derived option: application is os x bundle (folder) */
+
+LOCALVAR blnr HaveMacBundleApp;
+LOCALVAR blnr WantUnTranslocate;
+
+LOCALFUNC tMyErr ChooseHaveMacBundleApp(void)
+{
+	HaveMacBundleApp = (gbk_targfam_mach == gbo_targfam)
+		|| ((gbk_targfam_carb == gbo_targfam)
+			&& (gbk_ide_mpw == cur_ide));
+#if 0
+	WantUnTranslocate = (gbk_apifam_cco == gbo_apifam)
+		&& ((gbk_cpufam_x64 == gbo_cpufam)
+			|| (gbk_cpufam_x86 == gbo_cpufam));
+#else
+	WantUnTranslocate = falseblnr;
+		/*
+			on second thought, probably not a good
+			idea to use undocumented calls.
+		*/
+#endif
+
+	return kMyErr_noErr;
+}
+
+/* derived option: have macintosh resources */
+
+LOCALVAR blnr HaveMacRrscs;
+
+LOCALFUNC tMyErr ChooseHaveMacRrscs(void)
+{
+	HaveMacRrscs = (gbk_apifam_mac == gbo_apifam)
+		|| ((gbk_targfam_carb == gbo_targfam)
+			&& ! (gbk_ide_mpw == cur_ide));
+
+	return kMyErr_noErr;
+}
+
+
+/* option: Abbrev Name */
+
+LOCALVAR char vStrAppAbbrev[8 + 1];
+LOCALVAR ui3r olv_AbbrevName;
+
+LOCALPROC ResetAbbrevName(void)
+{
+	vStrAppAbbrev[0] = 0;
+	olv_AbbrevName = 0;
+}
+
+LOCALFUNC tMyErr TryAsAbbrevNameOptionNot(void)
+{
+	tMyErr err;
+	MyPStr t;
+
+	if (kMyErr_noErr != (err =
+		CurArgIsOption("-an", &olv_AbbrevName)))
+	{
+		/* no */
+	} else
+	if (The_arg_end) {
+		PStrFromCStr(t, "Expecting an argument for ");
+		PStrApndCStr(t, "-an");
+		PStrApndCStr(t, " when reached end");
+		err = ReportParseFailPStr(t);
+	} else
+	{
+		GetCurArgAsCStr(vStrAppAbbrev, 8);
+		err = AdvanceTheArg();
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr ChooseAbbrevName(void)
+{
+	if (0 == vStrAppAbbrev[0]) {
+		CStrCopy(vStrAppAbbrev, kStrAppAbbrev);
+	}
+
+	return kMyErr_noErr;
+}
+
+
+/* option: Variation Name */
+
+LOCALVAR char vVariationName[64 + 1];
+LOCALVAR ui3r olv_VariationName;
+
+LOCALPROC ResetVariationName(void)
+{
+	vVariationName[0] = 0;
+	olv_VariationName = 0;
+}
+
+LOCALFUNC tMyErr TryAsVariationNameOptionNot(void)
+{
+	tMyErr err;
+	MyPStr t;
+
+	if (kMyErr_noErr != (err =
+		CurArgIsOption("-n", &olv_VariationName)))
+	{
+		/* no */
+	} else
+	if (The_arg_end) {
+		PStrFromCStr(t, "Expecting an argument for ");
+		PStrApndCStr(t, "-n");
+		PStrApndCStr(t, " when reached end");
+		err = ReportParseFailPStr(t);
+	} else
+	{
+		GetCurArgAsCStr(vVariationName, 64);
+		err = AdvanceTheArg();
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr ChooseVariationName(void)
+{
+	if (0 == vVariationName[0]) {
+		MyPStr s;
+
+		PStrFromCStr(s, vStrAppAbbrev);
+		PStrApndCStr(s, "-");
+		PStrApndNUimr(s, MajorVersion, 2);
+		PStrApndCStr(s, ".");
+		PStrApndNUimr(s, MinorVersion, 2);
+		PStrApndCStr(s, "-");
+		/* PStrApndCStr(s, GetIdeName(cur_ide)); */
+		PStrApndCStr(s, GetTargetName(cur_targ));
+		/* PStrApndCStr(s, GetDbgLvlName(gbo_dbg)); */
+		CStrFromPStr(s, vVariationName);
+	}
+
+	return kMyErr_noErr;
+}
+
+
+/* option: Need International Characters */
+
+LOCALVAR blnr NeedIntl;
+LOCALVAR ui3r olv_NeedIntl;
+
+LOCALPROC ResetNeedIntl(void)
+{
+	NeedIntl = falseblnr;
+	olv_NeedIntl = 0;
+}
+
+LOCALFUNC tMyErr TryAsNeedIntlNot(void)
+{
+	return FlagTryAsOptionNot("-intl", &NeedIntl, &olv_NeedIntl);
+}
+
+LOCALFUNC tMyErr ChooseNeedIntl(void)
+{
+	return kMyErr_noErr;
+}
+
+
+/* option: Demo Message */
+
+LOCALVAR blnr WantDemoMsg;
+LOCALVAR ui3r olv_DemoMsg;
+
+LOCALPROC ResetDemoMsg(void)
+{
+	WantDemoMsg = nanblnr;
+	olv_DemoMsg = 0;
+}
+
+LOCALFUNC tMyErr TryAsDemoMsgNot(void)
+{
+	return BooleanTryAsOptionNot("-dmo", &WantDemoMsg, &olv_DemoMsg);
+}
+
+#define dfo_DemoMsg() falseblnr
+
+LOCALFUNC tMyErr ChooseDemoMsg(void)
+{
+	if (nanblnr == WantDemoMsg) {
+		WantDemoMsg = dfo_DemoMsg();
+	}
+
+	return kMyErr_noErr;
+}
+
+
+/* option: Activation Code */
+
+LOCALVAR blnr WantActvCode;
+#define NumKeyCon 7
+LOCALVAR long KeyCon[NumKeyCon];
+LOCALVAR ui3r olv_ActvCode;
+
+LOCALPROC ResetActvCode(void)
+{
+	WantActvCode = falseblnr;
+	olv_ActvCode = 0;
+}
+
+LOCALFUNC tMyErr TryAsActvCodeNot(void)
+{
+	tMyErr err;
+	int i;
+
+	if (kMyErr_noErr != (err = CurArgIsOption("-act", &olv_ActvCode))) {
+		/* no */
+	} else
+	{
+		WantActvCode = trueblnr;
+		for (i = 0; i < NumKeyCon; ++i) {
+			err = GetCurArgOptionAsNumber("-act", &KeyCon[i]);
+			if (kMyErr_noErr != err) {
+				goto Label_1;
+			}
+		}
+		err = kMyErr_noErr;
+Label_1:
+		;
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr ChooseActvCode(void)
+{
+	return kMyErr_noErr;
+}
+
+
+/* --- end of default definition of options --- */
+
+LOCALPROC GNResetCommandLineParameters(void)
+{
+	ResetBranchOption();
+	ResetTargetOption();
+	ResetDbgOption();
+	ResetLangOption();
+	ResetIconMaster();
+	ResetTstCompErr();
+}
+
+LOCALFUNC tMyErr TryAsGNOptionNot(void)
+{
+	tMyErr err;
+
+	if (kMyErrNoMatch == (err = TryAsBranchOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsTargetOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsDbgOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsLangOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsIconMasterNot()))
+	if (kMyErrNoMatch == (err = TryAsTstCompErrNot()))
+	if (kMyErrNoMatch == (err = TryAsTstBldSysErr()))
+	{
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr AutoChooseGNSettings(void)
+{
+	tMyErr err;
+
+	if (kMyErr_noErr == (err = ChooseBranch()))
+	if (kMyErr_noErr == (err = ChooseTarg()))
+	if (kMyErr_noErr == (err = ChooseDbgOption()))
+	if (kMyErr_noErr == (err = ChooseLangOption()))
+	if (kMyErr_noErr == (err = ChooseIconMaster()))
+	if (kMyErr_noErr == (err = ChooseTstCompErr()))
+	{
+		err = kMyErr_noErr;
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptGNSettings(void)
+{
+	WrtOptBranchOption();
+	WrtOptTarg();
+	WrtOptDbgOption();
+	WrtOptLangOption();
+	WrtOptIconMaster();
+	WrtOptTstCompErr();
+}
+
+LOCALPROC GNDevResetCommandLineParameters(void)
+{
+	ResetCPUFamOption();
+	ResetAPIFamOption();
+	ResetListOption();
+	ResetAbbrevName();
+	ResetVariationName();
+	ResetNeedIntl();
+	ResetDemoMsg();
+	ResetActvCode();
+}
+
+LOCALFUNC tMyErr TryAsGNDevOptionNot(void)
+{
+	tMyErr err;
+
+	DoingDevOpts = trueblnr;
+
+	if (kMyErrNoMatch == (err = TryAsCPUFamOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsAPIFamOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsListOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsAbbrevNameOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsVariationNameOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsNeedIntlNot()))
+	if (kMyErrNoMatch == (err = TryAsDemoMsgNot()))
+	if (kMyErrNoMatch == (err = TryAsActvCodeNot()))
+	{
+	}
+
+	DoingDevOpts = falseblnr;
+
+	return err;
+}
+
+LOCALFUNC tMyErr AutoChooseGNDevSettings(void)
+{
+	tMyErr err;
+
+	if (kMyErr_noErr == (err = ChooseCPUFam()))
+	if (kMyErr_noErr == (err = ChooseTargFam())) /* derived */
+	if (kMyErr_noErr == (err = ChooseAPIFam()))
+	if (kMyErr_noErr == (err = ChooseListOption()))
+	if (kMyErr_noErr == (err = ChooseHaveMacBundleApp())) /* derived */
+	if (kMyErr_noErr == (err = ChooseHaveMacRrscs())) /* derived */
+	if (kMyErr_noErr == (err = ChooseAbbrevName()))
+	if (kMyErr_noErr == (err = ChooseVariationName()))
+	if (kMyErr_noErr == (err = ChooseNeedIntl()))
+	if (kMyErr_noErr == (err = ChooseDemoMsg()))
+	if (kMyErr_noErr == (err = ChooseActvCode()))
+	{
+		err = kMyErr_noErr;
+	}
+
+	return err;
+}
+
+#if 0
+LOCALPROC WrtOptGNDevSettings(void)
+{
+	WrtOptCPUFam();
+	WrtOptAPIFam();
+	WrtOptListOption();
+	/* Maintainer */
+	/* HomePage */
+	/* Sponsor */
+	/* VariationName */
+	/* AbbrevName */
+	/* ConfigDir */
+	/* Err2File */
+	/* WantDemoMsg */
+	/* WantActvCode */
+}
+#endif
--- /dev/null
+++ b/setup/SPBASDEF.i
@@ -1,0 +1,34 @@
+/*
+	SPBASDEF.i
+	Copyright (C) 2009 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	program SPecific BASic DEFinitions
+*/
+
+
+#define kStrAppName "Mini vMac"
+#define kStrAppAbbrev "minivmac" /* [a-z0-9_]{1,8} */
+#define MajorVersion 36
+#define MinorVersion 04
+#define kStrCopyrightYear "2018"
+#define kMacCreatorSig "MnvM"
+#define kBundleIdentifier "com.gryphel.minivmac"
+#define kShortDescription "miniature Macintosh emulator"
+
+#define Have_SPBLDOPT 1
+#define Have_SPCNFGGL 1
+#define Have_SPCNFGAP 1
+
+#define UseOpenGLinOSX 1
--- /dev/null
+++ b/setup/SPBLDOPT.i
@@ -1,0 +1,3945 @@
+/*
+	SPBLDOPT.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	program SPecific BuiLD OPTions
+*/
+
+/* option: model */
+
+enum {
+	gbk_mdl_Twig43,
+	gbk_mdl_Twiggy,
+	gbk_mdl_128K,
+	gbk_mdl_512Ke,
+	gbk_mdl_Plus,
+	gbk_mdl_SE,
+	gbk_mdl_SEFDHD,
+	gbk_mdl_Classic,
+	gbk_mdl_PB100,
+	gbk_mdl_II,
+	gbk_mdl_IIx,
+	kNumModels
+};
+
+LOCALVAR int cur_mdl;
+LOCALVAR ui3r olv_mdl;
+
+LOCALPROC ResetModelOption(void)
+{
+	cur_mdl = kListOptionAuto;
+	olv_mdl = 0;
+}
+
+LOCALFUNC char * GetModelName(int i)
+{
+	char *s;
+
+	switch (i) {
+		case gbk_mdl_Twig43:
+			s = "Twig43";
+			break;
+		case gbk_mdl_Twiggy:
+			s = "Twiggy";
+			break;
+		case gbk_mdl_128K:
+			s = "128K";
+			break;
+		case gbk_mdl_512Ke:
+			s = "512Ke";
+			break;
+		case gbk_mdl_Plus:
+			s = "Plus";
+			break;
+		case gbk_mdl_SE:
+			s = "SE";
+			break;
+		case gbk_mdl_SEFDHD:
+			s = "SEFDHD";
+			break;
+		case gbk_mdl_Classic:
+			s = "Classic";
+			break;
+		case gbk_mdl_PB100:
+			s = "PB100";
+			break;
+		case gbk_mdl_II:
+			s = "II";
+			break;
+		case gbk_mdl_IIx:
+			s = "IIx";
+			break;
+		default:
+			s = "(unknown Model)";
+			break;
+	}
+	return s;
+}
+
+LOCALFUNC tMyErr TryAsModelOptionNot(void)
+{
+	return FindNamedOption("-m", kNumModels, GetModelName,
+		&cur_mdl, &olv_mdl);
+}
+
+#define dfo_mdl() gbk_mdl_Plus
+
+LOCALVAR blnr cur_mIIorIIX;
+
+LOCALFUNC tMyErr ChooseModel(void)
+{
+	if (kListOptionAuto == cur_mdl) {
+		cur_mdl = dfo_mdl();
+	}
+
+	cur_mIIorIIX = (gbk_mdl_II == cur_mdl) || (gbk_mdl_IIx == cur_mdl);
+
+#if 0
+	if (cur_mIIorIIX) {
+		if (gbk_cpufam_68k == gbo_cpufam) {
+			err = ReportParseFailure(
+				"Mac II emulation is not supported on Macintosh 680x0");
+		}
+	}
+#endif
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptModelOption(void)
+{
+	WrtOptNamedOption("-m", GetModelName, cur_mdl, dfo_mdl());
+}
+
+
+/* option: horizontal resolution */
+
+LOCALVAR uimr cur_hres;
+LOCALVAR ui3r olv_hres;
+
+LOCALPROC ResetHResOption(void)
+{
+	olv_hres = 0;
+}
+
+LOCALFUNC tMyErr TryAsHResOptionNot(void)
+{
+	return NumberTryAsOptionNot("-hres",
+		(long *)&cur_hres, &olv_hres);
+}
+
+LOCALFUNC uimr dfo_hres(void)
+{
+	uimr v;
+
+	if (cur_mIIorIIX) {
+		v = 640;
+	} else if (gbk_mdl_PB100 == cur_mdl) {
+		v = 640;
+	} else {
+		v = 512;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseHRes(void)
+{
+	tMyErr err;
+	MyPStr t;
+	MyPStr s;
+
+	if (0 == olv_hres) {
+		cur_hres = dfo_hres();
+		err = kMyErr_noErr;
+	} else {
+		if ((cur_hres & 0x1F) != 0) {
+			PStrFromCStr(t, "-hres must be a multiple of 32."
+				" The next lowest multiple is ");
+			PStrFromUimr(cur_hres & ~ 0x1F, s);
+			PStrAppend(t, s);
+			err = ReportParseFailPStr(t);
+		} else if (cur_hres < 128) {
+			err = ReportParseFailure("-hres must be >= 128");
+		} else if (cur_hres >= (uimr)32 * 1024) {
+			err = ReportParseFailure("-hres must be < 32k");
+		} else {
+			err = kMyErr_noErr;
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptHResOption(void)
+{
+	WrtOptNumberOption("-hres", cur_hres, dfo_hres());
+}
+
+
+/* option: vertical resolution */
+
+LOCALVAR uimr cur_vres;
+LOCALVAR ui3r olv_vres;
+
+LOCALPROC ResetVResOption(void)
+{
+	olv_vres = 0;
+}
+
+LOCALFUNC tMyErr TryAsVResOptionNot(void)
+{
+	return NumberTryAsOptionNot("-vres", (long *)&cur_vres, &olv_vres);
+}
+
+LOCALFUNC uimr dfo_vres(void)
+{
+	uimr v;
+
+	if (cur_mIIorIIX) {
+		v = 480;
+	} else if (gbk_mdl_PB100 == cur_mdl) {
+		v = 400;
+	} else {
+		v = 342;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseVRes(void)
+{
+	tMyErr err;
+
+	if (0 == olv_vres) {
+		cur_vres = dfo_vres();
+		err = kMyErr_noErr;
+	} else {
+		if (cur_vres < 128) {
+			err = ReportParseFailure("-vres must be >= 128");
+		} else if (cur_vres >= (uimr)32 * 1024) {
+			err = ReportParseFailure("-vres must be < 32k");
+		} else {
+			err = kMyErr_noErr;
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptVResOption(void)
+{
+	WrtOptNumberOption("-vres", cur_vres, dfo_vres());
+}
+
+
+/* option: screen depth */
+
+LOCALVAR uimr cur_ScrnDpth;
+LOCALVAR ui3r olv_ScrnDpth;
+
+LOCALPROC ResetScrnDpthOption(void)
+{
+	olv_ScrnDpth = 0;
+}
+
+LOCALFUNC tMyErr TryAsScrnDpthOptionNot(void)
+{
+	return NumberTryAsOptionNot("-depth",
+		(long *)&cur_ScrnDpth, &olv_ScrnDpth);
+}
+
+LOCALFUNC uimr dfo_ScrnDpth(void)
+{
+	uimr v;
+
+	if (cur_mIIorIIX) {
+		v = 3;
+	} else {
+		v = 0;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseScrnDpth(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+
+	if (0 == olv_ScrnDpth) {
+		cur_ScrnDpth = dfo_ScrnDpth();
+	} else {
+		if (cur_mIIorIIX) {
+			if (cur_ScrnDpth > 5) {
+				err = ReportParseFailure("-depth must be <= 5");
+			}
+		} else {
+			if (cur_ScrnDpth != 0) {
+				err = ReportParseFailure(
+					"-depth must be 0 for this model");
+			}
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptScrnDpth(void)
+{
+	WrtOptNumberOption("-depth", cur_ScrnDpth, dfo_ScrnDpth());
+}
+
+
+/* option: Initial FullScreen */
+
+LOCALVAR blnr WantInitFullScreen;
+LOCALVAR ui3r olv_InitFullScreen;
+
+LOCALPROC ResetInitFullScreen(void)
+{
+	WantInitFullScreen = nanblnr;
+	olv_InitFullScreen = 0;
+}
+
+LOCALFUNC tMyErr TryAsInitFullScreenNot(void)
+{
+	return BooleanTryAsOptionNot("-fullscreen",
+		&WantInitFullScreen, &olv_InitFullScreen);
+}
+
+LOCALFUNC blnr dfo_InitFullScreen(void)
+{
+	blnr v;
+
+	v = gbk_targfam_wnce == gbo_targfam;
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseInitFullScreen(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+
+	if (nanblnr == WantInitFullScreen) {
+		WantInitFullScreen = dfo_InitFullScreen();
+	} else {
+		if (! WantInitFullScreen) {
+			if (gbk_targ_wcar == cur_targ) {
+				err = ReportParseFailure(
+					"-fullscreen 0 is not supported for -t wcar");
+			}
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptInitFullScreen(void)
+{
+	WrtOptBooleanOption("-fullscreen",
+		WantInitFullScreen, dfo_InitFullScreen());
+}
+
+
+/* option: Variable FullScreen */
+
+LOCALVAR blnr WantVarFullScreen;
+LOCALVAR ui3r olv_VarFullScreen;
+
+LOCALPROC ResetVarFullScreen(void)
+{
+	WantVarFullScreen = nanblnr;
+	olv_VarFullScreen = 0;
+}
+
+LOCALFUNC tMyErr TryAsVarFullScreenNot(void)
+{
+	return BooleanTryAsOptionNot("-var-fullscreen",
+		&WantVarFullScreen, &olv_VarFullScreen);
+}
+
+LOCALFUNC blnr dfo_VarFullScreen(void)
+{
+	blnr v;
+
+	if ((gbk_apifam_gtk == gbo_apifam)
+		|| (gbk_targfam_wnce == gbo_targfam))
+	{
+		v = falseblnr;
+	} else {
+		v = trueblnr;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseVarFullScreen(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+
+	if (nanblnr == WantVarFullScreen) {
+		WantVarFullScreen = dfo_VarFullScreen();
+	} else {
+		if (WantVarFullScreen) {
+			if (gbk_targ_wcar == cur_targ) {
+				err = ReportParseFailure(
+					"-var-fullscreen is not supported for -t wcar");
+			}
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptVarFullScreen(void)
+{
+	WrtOptBooleanOption("-var-fullscreen",
+		WantVarFullScreen, dfo_VarFullScreen());
+}
+
+
+/* option: magnification factor */
+
+LOCALVAR uimr cur_MagFctr;
+LOCALVAR ui3r olv_MagFctr;
+
+LOCALPROC ResetMagFctrOption(void)
+{
+	olv_MagFctr = 0;
+}
+
+LOCALFUNC tMyErr TryAsMagFctrOptionNot(void)
+{
+	return NumberTryAsOptionNot("-mf",
+		(long *)&cur_MagFctr, &olv_MagFctr);
+}
+
+LOCALFUNC uimr dfo_MagFctr(void)
+{
+	uimr v;
+
+	if (gbk_apifam_gtk == gbo_apifam) {
+		/* temporary, until implemented */
+		v = 1;
+	} else {
+		v = 2;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseMagFctr(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+
+	if (0 == olv_MagFctr) {
+		cur_MagFctr = dfo_MagFctr();
+	} else {
+		if (cur_MagFctr < 1) {
+			err = ReportParseFailure("-mf must be >= 1");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptMagFctrOption(void)
+{
+	WrtOptNumberOption("-mf", cur_MagFctr, dfo_MagFctr());
+}
+
+
+/* option: Initial Magnify */
+
+LOCALVAR blnr WantInitMagnify;
+LOCALVAR ui3r olv_InitMagnify;
+
+LOCALPROC ResetInitMagnify(void)
+{
+	WantInitMagnify = nanblnr;
+	olv_InitMagnify = 0;
+}
+
+LOCALFUNC tMyErr TryAsInitMagnifyNot(void)
+{
+	return BooleanTryAsOptionNot("-magnify",
+		&WantInitMagnify, &olv_InitMagnify);
+}
+
+#define dfo_InitMagnify() falseblnr
+
+LOCALFUNC tMyErr ChooseInitMagnify(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+	if (nanblnr == WantInitMagnify) {
+		WantInitMagnify = dfo_InitMagnify();
+	} else {
+		if (WantInitMagnify && (cur_MagFctr == 1)) {
+			err = ReportParseFailure(
+				"-magnify 1 does not make sense with -mf 1");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptInitMagnify(void)
+{
+	WrtOptBooleanOption("-magnify",
+		WantInitMagnify, dfo_InitMagnify());
+}
+
+
+/* option: sound */
+
+LOCALVAR blnr MySoundEnabled;
+LOCALVAR ui3r olv_SoundEnabled;
+
+LOCALPROC ResetSoundOption(void)
+{
+	MySoundEnabled = nanblnr;
+	olv_SoundEnabled = 0;
+}
+
+LOCALFUNC tMyErr TryAsSoundOptionNot(void)
+{
+	return BooleanTryAsOptionNot("-sound",
+		&MySoundEnabled, &olv_SoundEnabled);
+}
+
+LOCALFUNC blnr dfo_SoundEnabled(void)
+{
+	blnr v;
+
+	v = (gbk_apifam_mac == gbo_apifam)
+		|| (gbk_apifam_osx == gbo_apifam)
+		|| (gbk_apifam_win == gbo_apifam)
+		|| (gbk_apifam_sdl == gbo_apifam)
+		|| (gbk_apifam_sd2 == gbo_apifam)
+		|| (gbk_apifam_9dr == gbo_apifam)
+		|| (gbk_apifam_cco == gbo_apifam)
+		|| ((gbk_apifam_xwn == gbo_apifam)
+			&& ((gbo_targfam == gbk_targfam_linx)
+				|| (gbo_targfam == gbk_targfam_fbsd)
+				|| (gbo_targfam == gbk_targfam_nbsd)));
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseSoundEnabled(void)
+{
+	if (nanblnr == MySoundEnabled) {
+		MySoundEnabled = dfo_SoundEnabled();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptSoundOption(void)
+{
+	WrtOptBooleanOption("-sound", MySoundEnabled, dfo_SoundEnabled());
+}
+
+
+/* option: sound api */
+
+enum {
+	gbk_sndapi_none,
+	gbk_sndapi_alsa,
+	gbk_sndapi_ddsp,
+	kNumSndApiLevels
+};
+
+LOCALVAR int gbo_sndapi;
+LOCALVAR ui3r olv_sndapi;
+
+LOCALPROC ResetSndApiOption(void)
+{
+	gbo_sndapi = kListOptionAuto;
+	olv_sndapi = 0;
+}
+
+LOCALFUNC char * GetSndApiName(int i)
+{
+	char *s;
+
+	switch (i) {
+		case gbk_sndapi_none:
+			s = "none";
+			break;
+		case gbk_sndapi_alsa:
+			s = "alsa";
+			break;
+		case gbk_sndapi_ddsp:
+			s = "ddsp";
+			break;
+		default:
+			s = "(unknown sound api)";
+			break;
+	}
+	return s;
+}
+
+LOCALFUNC tMyErr TryAsSndApiOptionNot(void)
+{
+	return FindNamedOption("-snd-api",
+		kNumSndApiLevels, GetSndApiName, &gbo_sndapi, &olv_sndapi);
+}
+
+LOCALFUNC int dfo_sndapi(void)
+{
+	int v;
+
+	if (! MySoundEnabled) {
+		v = gbk_sndapi_none;
+	} else if (gbk_apifam_xwn != gbo_apifam) {
+		v = gbk_sndapi_none;
+	} else if (gbo_targfam == gbk_targfam_linx) {
+		v = gbk_sndapi_alsa;
+	} else {
+		v = gbk_sndapi_ddsp;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseSndApiOption(void)
+{
+	if (kListOptionAuto == gbo_sndapi) {
+		gbo_sndapi = dfo_sndapi();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptSndApiOption(void)
+{
+	WrtOptNamedOption("-snd-api", GetSndApiName,
+		gbo_sndapi, dfo_sndapi());
+}
+
+
+/* option: sound sample size */
+
+LOCALVAR uimr cur_SoundSampSz;
+LOCALVAR ui3r olv_SoundSampSz;
+
+LOCALPROC ResetSoundSampSzOption(void)
+{
+	olv_SoundSampSz = 0;
+}
+
+LOCALFUNC tMyErr TryAsSoundSampSzOptionNot(void)
+{
+	return NumberTryAsOptionNot("-sss",
+		(long *)&cur_SoundSampSz, &olv_SoundSampSz);
+}
+
+LOCALFUNC uimr dfo_SoundSampSz(void)
+{
+	uimr v;
+
+	if (gbk_sndapi_ddsp == gbo_sndapi) {
+		v = 4;
+	} else {
+		v = 3;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseSoundSampSz(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+
+
+	if (0 == olv_SoundSampSz) {
+		cur_SoundSampSz = dfo_SoundSampSz();
+	} else {
+		if ((cur_SoundSampSz < 3) || (cur_SoundSampSz > 4)) {
+			err = ReportParseFailure(
+				"-sss must be 3 or 4");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptSoundSampSzOption(void)
+{
+	WrtOptNumberOption("-sss", cur_SoundSampSz, dfo_SoundSampSz());
+}
+
+
+/* option: number of drives */
+
+LOCALVAR uimr cur_numdrives;
+LOCALVAR ui3r olv_numdrives;
+
+LOCALPROC ResetNumDrivesOption(void)
+{
+	olv_numdrives = 0;
+}
+
+LOCALFUNC tMyErr TryAsNumDrivesOptionNot(void)
+{
+	return NumberTryAsOptionNot("-drives",
+		(long *)&cur_numdrives, &olv_numdrives);
+}
+
+LOCALFUNC uimr dfo_numdrives(void)
+{
+	uimr v;
+
+	if (cur_mdl < gbk_mdl_512Ke) {
+		v = 2;
+	} else {
+		v = 6;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseNumDrives(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+
+
+	if (0 == olv_numdrives) {
+		cur_numdrives = dfo_numdrives();
+	} else {
+		if ((cur_numdrives <= 0) || (cur_numdrives > 32)) {
+			err = ReportParseFailure(
+				"-drives must be a number between 1 and 32");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptNumDrivesOption(void)
+{
+	WrtOptNumberOption("-drives", cur_numdrives, dfo_numdrives());
+}
+
+
+/* option: disk driver - support tags */
+
+LOCALVAR blnr SonySupportTags;
+LOCALVAR ui3r olv_SonySupportTags;
+
+LOCALPROC ResetSonySupportTags(void)
+{
+	SonySupportTags = nanblnr;
+	olv_SonySupportTags = 0;
+}
+
+LOCALFUNC tMyErr TryAsSonySupportTagsNot(void)
+{
+	return BooleanTryAsOptionNot("-sony-tag",
+		&SonySupportTags, &olv_SonySupportTags);
+}
+
+#define dfo_SonySupportTags() falseblnr
+
+LOCALFUNC tMyErr ChooseSonySupportTags(void)
+{
+	if (nanblnr == SonySupportTags) {
+		SonySupportTags = dfo_SonySupportTags();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptSonySupportTags(void)
+{
+	WrtOptBooleanOption("-sony-tag",
+		SonySupportTags, dfo_SonySupportTags());
+}
+
+
+/* option: disk driver - calculate checksums */
+
+LOCALVAR blnr SonyWantChecksumsUpdated;
+LOCALVAR ui3r olv_SonyWantChecksumsUpdated;
+
+LOCALPROC ResetSonyWantChecksumsUpdated(void)
+{
+	SonyWantChecksumsUpdated = nanblnr;
+	olv_SonyWantChecksumsUpdated = 0;
+}
+
+LOCALFUNC tMyErr TryAsSonyWantChecksumsUpdatedNot(void)
+{
+	return BooleanTryAsOptionNot("-sony-sum",
+		&SonyWantChecksumsUpdated, &olv_SonyWantChecksumsUpdated);
+}
+
+#define dfo_SonyWantChecksumsUpdated() falseblnr
+
+LOCALFUNC tMyErr ChooseSonyWantChecksumsUpdated(void)
+{
+	if (nanblnr == SonyWantChecksumsUpdated) {
+		SonyWantChecksumsUpdated = dfo_SonyWantChecksumsUpdated();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptSonyWantChecksumsUpdated(void)
+{
+	WrtOptBooleanOption("-sony-sum",
+		SonyWantChecksumsUpdated, dfo_SonyWantChecksumsUpdated());
+}
+
+
+/* option: disk driver - support disk copy 4.2 format */
+
+LOCALVAR blnr SonySupportDC42;
+LOCALVAR ui3r olv_SonySupportDC42;
+
+LOCALPROC ResetSonySupportDC42(void)
+{
+	SonySupportDC42 = nanblnr;
+	olv_SonySupportDC42 = 0;
+}
+
+LOCALFUNC tMyErr TryAsSonySupportDC42Not(void)
+{
+	return BooleanTryAsOptionNot("-sony-dc42",
+		&SonySupportDC42, &olv_SonySupportDC42);
+}
+
+#define dfo_SonySupportDC42() trueblnr
+
+LOCALFUNC tMyErr ChooseSonySupportDC42(void)
+{
+	if (nanblnr == SonySupportDC42) {
+		SonySupportDC42 = dfo_SonySupportDC42();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptSonySupportDC42(void)
+{
+	WrtOptBooleanOption("-sony-dc42",
+		SonySupportDC42, dfo_SonySupportDC42());
+}
+
+
+/* option: Save Dialog Enable */
+
+LOCALVAR blnr gbo_SaveDialogEnable;
+LOCALVAR ui3r olv_SaveDialogEnable;
+
+LOCALPROC ResetSaveDialogEnable(void)
+{
+	gbo_SaveDialogEnable = nanblnr;
+	olv_SaveDialogEnable = 0;
+}
+
+LOCALFUNC tMyErr TryAsSaveDialogEnable(void)
+{
+	return BooleanTryAsOptionNot("-svd",
+		&gbo_SaveDialogEnable, &olv_SaveDialogEnable);
+}
+
+#define dfo_SaveDialogEnable() trueblnr
+
+LOCALFUNC tMyErr ChooseSaveDialogEnable(void)
+{
+	if (nanblnr == gbo_SaveDialogEnable) {
+		gbo_SaveDialogEnable = dfo_SaveDialogEnable();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptSaveDialogEnable(void)
+{
+	WrtOptBooleanOption("-svd",
+		gbo_SaveDialogEnable, dfo_SaveDialogEnable());
+}
+
+
+/* option: Insert Ith Disk Image */
+
+LOCALVAR blnr WantInsertIthDisk;
+LOCALVAR ui3r olv_InsertIthDisk;
+
+LOCALPROC ResetInsertIthDisk(void)
+{
+	WantInsertIthDisk = nanblnr;
+	olv_InsertIthDisk = 0;
+}
+
+LOCALFUNC tMyErr TryAsInsertIthDisk(void)
+{
+	return BooleanTryAsOptionNot("-iid",
+		&WantInsertIthDisk, &olv_InsertIthDisk);
+}
+
+#define dfo_InsertIthDisk() falseblnr
+
+LOCALFUNC tMyErr ChooseInsertIthDisk(void)
+{
+	if (nanblnr == WantInsertIthDisk) {
+		WantInsertIthDisk = dfo_InsertIthDisk();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptInsertIthDisk(void)
+{
+	WrtOptBooleanOption("-iid",
+		WantInsertIthDisk, dfo_InsertIthDisk());
+}
+
+
+/* option: Command Option Swap */
+
+LOCALVAR blnr WantCmndOptSwap;
+LOCALVAR ui3r olv_CmndOptSwap;
+
+LOCALPROC ResetCmndOptSwap(void)
+{
+	WantCmndOptSwap = falseblnr;
+	olv_CmndOptSwap = 0;
+}
+
+LOCALFUNC tMyErr TryAsCmndOptSwapNot(void)
+{
+	return FlagTryAsOptionNot("-ccs",
+		&WantCmndOptSwap, &olv_CmndOptSwap);
+}
+
+LOCALFUNC tMyErr ChooseCmndOptSwap(void)
+{
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptCmndOptSwap(void)
+{
+	WrtOptFlagOption("-ccs", WantCmndOptSwap);
+}
+
+
+/* option: key mapping */
+
+enum {
+	gbk_keynam_Control,
+	gbk_keynam_Command,
+	gbk_keynam_Option,
+	gbk_keynam_Shift,
+	gbk_keynam_CapsLock,
+	gbk_keynam_Escape,
+	gbk_keynam_BackSlash,
+	gbk_keynam_Slash,
+	gbk_keynam_Grave,
+	gbk_keynam_Enter,
+	gbk_keynam_PageUp,
+	gbk_keynam_PageDown,
+	gbk_keynam_Home,
+	gbk_keynam_End,
+	gbk_keynam_Help,
+	gbk_keynam_ForwardDel,
+	gbk_keynam_F1,
+	gbk_keynam_F2,
+	gbk_keynam_F3,
+	gbk_keynam_F4,
+	gbk_keynam_F5,
+	kNumKeyNames
+};
+
+enum {
+	gbk_keynam_RControl = kNumKeyNames,
+	gbk_keynam_RCommand,
+	gbk_keynam_ROption,
+	gbk_keynam_RShift,
+	kNumSrcKeyNames
+};
+
+enum {
+	gbk_keynam_CM = kNumKeyNames,
+	kNumDstKeyNames
+};
+
+LOCALVAR ui3b gbo_keymap[kNumSrcKeyNames];
+LOCALVAR ui3r olv_keymap[kNumSrcKeyNames];
+
+LOCALPROC ResetKeyMapOption(void)
+{
+	uimr i;
+
+	for (i = 0; i < kNumSrcKeyNames; ++i) {
+		gbo_keymap[i] = 0xFF;
+		olv_keymap[i] = 0;
+	}
+}
+
+LOCALFUNC char * GetKeyMapName(int i)
+{
+	char *s;
+
+	switch (i) {
+		case gbk_keynam_Control:
+			s = "Control";
+			break;
+		case gbk_keynam_Command:
+			s = "Command";
+			break;
+		case gbk_keynam_Option:
+			s = "Option";
+			break;
+		case gbk_keynam_Shift:
+			s = "Shift";
+			break;
+		case gbk_keynam_CapsLock:
+			s = "CapsLock";
+			break;
+		case gbk_keynam_Escape:
+			s = "Escape";
+			break;
+		case gbk_keynam_BackSlash:
+			s = "BackSlash";
+			break;
+		case gbk_keynam_Slash:
+			s = "Slash";
+			break;
+		case gbk_keynam_Grave:
+			s = "Grave";
+			break;
+		case gbk_keynam_Enter:
+			s = "Enter";
+			break;
+		case gbk_keynam_PageUp:
+			s = "PageUp";
+			break;
+		case gbk_keynam_PageDown:
+			s = "PageDown";
+			break;
+		case gbk_keynam_Home:
+			s = "Home";
+			break;
+		case gbk_keynam_End:
+			s = "End";
+			break;
+		case gbk_keynam_Help:
+			s = "Help";
+			break;
+		case gbk_keynam_ForwardDel:
+			s = "ForwardDel";
+			break;
+		case gbk_keynam_F1:
+			s = "F1";
+			break;
+		case gbk_keynam_F2:
+			s = "F2";
+			break;
+		case gbk_keynam_F3:
+			s = "F3";
+			break;
+		case gbk_keynam_F4:
+			s = "F4";
+			break;
+		case gbk_keynam_F5:
+			s = "F5";
+			break;
+		default:
+			s = "(unknown key)";
+			break;
+	}
+
+	return s;
+}
+
+LOCALFUNC char * GetSrcKeyMapName(int i)
+{
+	char *s;
+
+	switch (i) {
+		case gbk_keynam_RControl:
+			s = "RControl";
+			break;
+		case gbk_keynam_RCommand:
+			s = "RCommand";
+			break;
+		case gbk_keynam_ROption:
+			s = "ROption";
+			break;
+		case gbk_keynam_RShift:
+			s = "RShift";
+			break;
+		default:
+			s = GetKeyMapName(i);
+			break;
+	}
+
+	return s;
+}
+
+LOCALFUNC char * GetDstKeyMapName(int i)
+{
+	char *s;
+
+	switch (i) {
+		case gbk_keynam_CM:
+			s = "CM";
+			break;
+		default:
+			s = GetKeyMapName(i);
+			break;
+	}
+
+	return s;
+}
+
+LOCALFUNC tMyErr TryAsKeyMapOptionNot(void)
+{
+	tMyErr err;
+	MyPStr t;
+	int k;
+	int j;
+
+	if (! CurArgIsCStr_v2("-km")) {
+		err = kMyErrNoMatch;
+	} else
+	if (kMyErr_noErr != (err = AdvanceTheArg())) {
+		/* fail */
+	} else
+	if (The_arg_end) {
+		PStrFromCStr(t,
+			"Expecting a src argument for -km when reached end");
+		err = ReportParseFailPStr(t);
+	} else
+	if (! GetCurArgNameIndex(kNumSrcKeyNames, GetSrcKeyMapName, &k)) {
+		PStrFromCStr(t, "Unknown source value for -km");
+		err = ReportParseFailPStr(t);
+	} else
+	if (olv_keymap[k] == olv_cur) {
+		PStrFromCStr(t,
+			"same -km src value has appeared more than once");
+		err = ReportParseFailPStr(t);
+	} else
+	if (kMyErr_noErr != (err = AdvanceTheArg())) {
+		/* fail */
+	} else
+	if (The_arg_end) {
+		PStrFromCStr(t,
+			"Expecting a dst argument for -km when reached end");
+		err = ReportParseFailPStr(t);
+	} else
+	if (! GetCurArgNameIndex(kNumDstKeyNames, GetDstKeyMapName, &j)) {
+		if (CurArgIsCStr_v2("*")) {
+			olv_keymap[k] = olv_cur;
+			gbo_keymap[k] = 0xFF;
+			err = AdvanceTheArg();
+		} else
+		{
+			PStrFromCStr(t, "Unknown dst value for -km");
+			err = ReportParseFailPStr(t);
+		}
+	} else
+
+	{
+		olv_keymap[k] = olv_cur;
+		gbo_keymap[k] = j;
+		err = AdvanceTheArg();
+	}
+
+	return err;
+}
+
+LOCALPROC dfo_keyset(ui3b *a, uimr i, ui3r v)
+{
+	a[i] = v;
+
+	if (0xFF == gbo_keymap[i]) {
+		gbo_keymap[i] = v;
+	}
+}
+
+LOCALPROC dfo_keymap(ui3b *a)
+{
+	uimr i;
+
+	dfo_keyset(a, gbk_keynam_Control,
+		WantCmndOptSwap ? gbk_keynam_Command : gbk_keynam_CM);
+	dfo_keyset(a, gbk_keynam_Command,
+		WantCmndOptSwap ? gbk_keynam_CM : gbk_keynam_Command);
+
+	for (i = gbk_keynam_Option; i <= gbk_keynam_ForwardDel; ++i) {
+		dfo_keyset(a, i, i);
+	}
+
+	dfo_keyset(a, gbk_keynam_F1, gbk_keynam_Option);
+	dfo_keyset(a, gbk_keynam_F2, gbk_keynam_Command);
+
+	for (i = gbk_keynam_F3; i <= gbk_keynam_F5; ++i) {
+		dfo_keyset(a, i, i);
+	}
+
+	dfo_keyset(a, gbk_keynam_RControl, gbo_keymap[gbk_keynam_Control]);
+	dfo_keyset(a, gbk_keynam_RCommand, gbo_keymap[gbk_keynam_Command]);
+	dfo_keyset(a, gbk_keynam_ROption, gbo_keymap[gbk_keynam_Option]);
+	dfo_keyset(a, gbk_keynam_RShift, gbo_keymap[gbk_keynam_Shift]);
+}
+
+LOCALFUNC ui3r KeyMapInverse(uimr v)
+{
+	uimr i;
+
+	for (i = 0; i < kNumSrcKeyNames; ++i) {
+		if (v == gbo_keymap[i]) {
+			return i;
+		}
+	}
+
+	return 0xFF;
+}
+
+LOCALVAR ui3r ControlModeKey;
+
+LOCALFUNC tMyErr ChooseKeyMap(void)
+{
+	tMyErr err;
+	ui3b a[kNumSrcKeyNames];
+
+	dfo_keymap(a);
+
+	ControlModeKey = KeyMapInverse(gbk_keynam_CM);
+
+	if (0xFF == ControlModeKey) {
+		err = ReportParseFailure(
+			"-km : no key maps to CM");
+	} else {
+		err = kMyErr_noErr;
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptKeyMap(void)
+{
+	ui3b a[kNumSrcKeyNames];
+	uimr i;
+
+	dfo_keymap(a);
+
+	for (i = 0; i < kNumSrcKeyNames; ++i) {
+		if (gbo_keymap[i] != a[i]) {
+			WriteCStrToDestFile(" -km ");
+			WriteCStrToDestFile(GetSrcKeyMapName(i));
+			WriteCStrToDestFile(" ");
+			WriteCStrToDestFile(GetDstKeyMapName(gbo_keymap[i]));
+		}
+	}
+}
+
+
+/* option: emulated key toggle mapping */
+
+LOCALVAR int gbo_EKTMap;
+LOCALVAR ui3r olv_EKTMap;
+
+LOCALPROC ResetEKTMapOption(void)
+{
+	gbo_EKTMap = kListOptionAuto;
+	olv_EKTMap = 0;
+}
+
+LOCALFUNC tMyErr TryAsEKTMapOptionNot(void)
+{
+	return FindNamedOption("-ekt",
+		kNumKeyNames, GetKeyMapName, &gbo_EKTMap, &olv_EKTMap);
+}
+
+LOCALFUNC int dfo_EKTMap(void)
+{
+	blnr a[kNumKeyNames];
+	uimr i;
+	uimr j;
+
+	for (i = 0; i < kNumKeyNames; ++i) {
+		a[i] = falseblnr;
+	}
+
+	for (i = 0; i < kNumSrcKeyNames; ++i) {
+		j = gbo_keymap[i];
+		if (j < kNumKeyNames) {
+			a[j] = trueblnr;
+		}
+	}
+
+	for (i = 0; i < kNumKeyNames; ++i) {
+		if (! a[i]) {
+			return i;
+		}
+	}
+
+	return gbk_keynam_Control;
+}
+
+LOCALFUNC tMyErr ChooseEKTMap(void)
+{
+	if (kListOptionAuto == gbo_EKTMap) {
+		gbo_EKTMap = dfo_EKTMap();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptEKTMap(void)
+{
+	WrtOptNamedOption("-ekt", GetKeyMapName, gbo_EKTMap, dfo_EKTMap());
+}
+
+
+/* option: Alternate Keyboard Mode */
+
+LOCALVAR blnr WantAltKeysMode;
+LOCALVAR ui3r olv_WantAltKeysMode;
+
+LOCALPROC ResetAltKeysMode(void)
+{
+	WantAltKeysMode = falseblnr;
+	olv_WantAltKeysMode = 0;
+}
+
+LOCALFUNC tMyErr TryAsAltKeysModeNot(void)
+{
+	return FlagTryAsOptionNot("-akm",
+		&WantAltKeysMode, &olv_WantAltKeysMode);
+}
+
+LOCALFUNC tMyErr ChooseAltKeysMode(void)
+{
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptAltKeysMode(void)
+{
+	WrtOptFlagOption("-akm", WantAltKeysMode);
+}
+
+
+/* option: ItnlKyBdFix */
+
+LOCALVAR blnr ItnlKyBdFix;
+LOCALVAR ui3r olv_ItnlKyBdFix;
+
+LOCALPROC ResetItnlKyBdFixOption(void)
+{
+	ItnlKyBdFix = nanblnr;
+}
+
+LOCALFUNC tMyErr TryAsItnlKyBdFixNot(void)
+{
+	return BooleanTryAsOptionNot("-ikb",
+		&ItnlKyBdFix, &olv_ItnlKyBdFix);
+}
+
+LOCALFUNC blnr dfo_ItnlKyBdFix(void)
+{
+	blnr v;
+
+	v = (gbk_apifam_win == gbo_apifam);
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseItnlKyBdFix(void)
+{
+	tMyErr err = kMyErr_noErr;
+
+	if (nanblnr == ItnlKyBdFix) {
+		ItnlKyBdFix = dfo_ItnlKyBdFix();
+	} else {
+		if (ItnlKyBdFix) {
+			if (gbk_apifam_win != gbo_apifam) {
+				err = ReportParseFailure("-ikb is only for Windows");
+			}
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptItnlKyBdFix(void)
+{
+	WrtOptBooleanOption("-ikb", ItnlKyBdFix, dfo_ItnlKyBdFix());
+}
+
+
+/* option: LocalTalk emulation */
+
+LOCALVAR blnr WantLocalTalk;
+LOCALVAR ui3r olv_LocalTalk;
+
+LOCALPROC ResetLocalTalk(void)
+{
+	WantLocalTalk = falseblnr;
+	olv_LocalTalk = 0;
+}
+
+LOCALFUNC tMyErr TryAsLocalTalkNot(void)
+{
+	return FlagTryAsOptionNot("-lt", &WantLocalTalk, &olv_LocalTalk);
+}
+
+LOCALFUNC tMyErr ChooseLocalTalk(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+
+	if (WantLocalTalk) {
+		if ((gbk_apifam_osx != gbo_apifam)
+			&& (gbk_apifam_cco != gbo_apifam))
+		{
+			err = ReportParseFailure(
+				"-lt is so far only implemented for OS X");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptLocalTalk(void)
+{
+	WrtOptFlagOption("-lt", WantLocalTalk);
+}
+
+
+/* option: initial speed */
+
+enum {
+	gbk_speed_AllOut,
+	gbk_speed_1X,
+	gbk_speed_2X,
+	gbk_speed_4X,
+	gbk_speed_8X,
+	gbk_speed_16X,
+	gbk_speed_32X,
+	kNumSpeeds
+};
+
+LOCALVAR int CurInitSpeed;
+LOCALVAR ui3r olv_InitSpeed;
+
+LOCALPROC ResetInitSpeedOption(void)
+{
+	CurInitSpeed = kListOptionAuto;
+	olv_InitSpeed = 0;
+}
+
+LOCALFUNC char * GetInitSpeedName(int i)
+{
+	char *s;
+
+	switch (i) {
+		case gbk_speed_AllOut:
+			s = "a";
+			break;
+		case gbk_speed_1X:
+			s = "z";
+			break;
+		case gbk_speed_2X:
+			s = "1";
+			break;
+		case gbk_speed_4X:
+			s = "2";
+			break;
+		case gbk_speed_8X:
+			s = "3";
+			break;
+		case gbk_speed_16X:
+			s = "4";
+			break;
+		case gbk_speed_32X:
+			s = "5";
+			break;
+		default:
+			s = "(unknown Speed)";
+			break;
+	}
+	return s;
+}
+
+LOCALFUNC tMyErr TryAsInitSpeedOptionNot(void)
+{
+	return FindNamedOption("-speed",
+		kNumSpeeds, GetInitSpeedName, &CurInitSpeed, &olv_InitSpeed);
+}
+
+LOCALFUNC int dfo_InitSpeed(void)
+{
+	int v;
+
+	if (cur_mIIorIIX) {
+		v = gbk_speed_4X;
+	} else {
+		v = gbk_speed_8X;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseInitSpeed(void)
+{
+	if (kListOptionAuto == CurInitSpeed) {
+		CurInitSpeed = dfo_InitSpeed();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptInitSpeedOption(void)
+{
+	WrtOptNamedOption("-speed", GetInitSpeedName,
+		CurInitSpeed, dfo_InitSpeed());
+}
+
+
+/* option: Initial Run In Background */
+
+LOCALVAR blnr WantInitBackground;
+LOCALVAR ui3r olv_InitBackground;
+
+LOCALPROC ResetInitBackground(void)
+{
+	WantInitBackground = nanblnr;
+	olv_InitBackground = 0;
+}
+
+LOCALFUNC tMyErr TryAsInitBackgroundNot(void)
+{
+	return BooleanTryAsOptionNot("-bg",
+		&WantInitBackground, &olv_InitBackground);
+}
+
+LOCALFUNC blnr dfo_InitBackground(void)
+{
+	blnr v;
+
+	if (WantLocalTalk) {
+		v = trueblnr;
+	} else {
+		v = falseblnr;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseInitBackground(void)
+{
+	if (nanblnr == WantInitBackground) {
+		WantInitBackground = dfo_InitBackground();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptInitBackground(void)
+{
+	WrtOptBooleanOption("-bg", WantInitBackground,
+		dfo_InitBackground());
+}
+
+
+/* option: Initial AutoSlow */
+
+LOCALVAR blnr WantInitAutoSlow;
+LOCALVAR ui3r olv_InitAutoSlow;
+
+LOCALPROC ResetInitAutoSlow(void)
+{
+	WantInitAutoSlow = nanblnr;
+	olv_InitAutoSlow = 0;
+}
+
+LOCALFUNC tMyErr TryAsInitAutoSlowNot(void)
+{
+	return BooleanTryAsOptionNot("-as",
+		&WantInitAutoSlow, &olv_InitAutoSlow);
+}
+
+LOCALFUNC blnr dfo_InitAutoSlow(void)
+{
+	blnr v;
+
+	v = ! cur_mIIorIIX;
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseInitAutoSlow(void)
+{
+	if (nanblnr == WantInitAutoSlow) {
+		WantInitAutoSlow = dfo_InitAutoSlow();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptInitAutoSlow(void)
+{
+	WrtOptBooleanOption("-as", WantInitAutoSlow, dfo_InitAutoSlow());
+}
+
+
+/* option: Timing Accuracy */
+
+LOCALVAR uimr timingacc;
+LOCALVAR ui3r olv_timingacc;
+
+LOCALPROC ResetTimingAccuracyOption(void)
+{
+	olv_timingacc = 0;
+}
+
+LOCALFUNC tMyErr TryAsTimingAccuracyOptionNot(void)
+{
+	return NumberTryAsOptionNot("-ta",
+		(long *)&timingacc, &olv_timingacc);
+}
+
+#define dfo_timingacc() 1
+
+LOCALFUNC tMyErr ChooseTimingAccuracy(void)
+{
+	if (0 == olv_timingacc) {
+		timingacc = dfo_timingacc();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptTimingAccuracy(void)
+{
+	WrtOptNumberOption("-ta", timingacc, dfo_timingacc());
+}
+
+
+/* option: Emulated CPU version */
+
+LOCALVAR uimr em_cpu_vers;
+LOCALVAR ui3r olv_em_cpu_vers;
+
+LOCALPROC ResetEmCpuVersOption(void)
+{
+	olv_em_cpu_vers = 0;
+}
+
+LOCALFUNC tMyErr TryAsEmCpuVersOptionNot(void)
+{
+	return NumberTryAsOptionNot("-em-cpu",
+		(long *)&em_cpu_vers, &olv_em_cpu_vers);
+}
+
+LOCALFUNC uimr dfo_em_cpu_vers(void)
+{
+	uimr v;
+
+	if (cur_mIIorIIX) {
+		v = 2;
+	} else {
+		v = 0;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseEmCpuVers(void)
+{
+	if (0 == olv_em_cpu_vers) {
+		em_cpu_vers = dfo_em_cpu_vers();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptEmCpuVers(void)
+{
+	WrtOptNumberOption("-em-cpu", em_cpu_vers, dfo_em_cpu_vers());
+}
+
+
+/* option: memory size */
+
+enum {
+	gbk_msz_128K,
+	gbk_msz_512K,
+	gbk_msz_1M,
+	gbk_msz_2M,
+	gbk_msz_2_5M,
+	gbk_msz_4M,
+	gbk_msz_5M,
+	gbk_msz_8M,
+	kNumMemSizs
+};
+
+LOCALVAR int cur_msz;
+LOCALVAR ui3r olv_msz;
+
+LOCALPROC ResetMemSizOption(void)
+{
+	cur_msz = kListOptionAuto;
+	olv_msz = 0;
+}
+
+LOCALFUNC char * GetMemSizName(int i)
+{
+	char *s;
+
+	switch (i) {
+		case gbk_msz_128K:
+			s = "128K";
+			break;
+		case gbk_msz_512K:
+			s = "512K";
+			break;
+		case gbk_msz_1M:
+			s = "1M";
+			break;
+		case gbk_msz_2M:
+			s = "2M";
+			break;
+		case gbk_msz_2_5M:
+			s = "2.5M";
+			break;
+		case gbk_msz_4M:
+			s = "4M";
+			break;
+		case gbk_msz_5M:
+			s = "5M";
+			break;
+		case gbk_msz_8M:
+			s = "8M";
+			break;
+		default:
+			s = "(unknown Memory Size)";
+			break;
+	}
+	return s;
+}
+
+LOCALFUNC tMyErr TryAsMemSizOptionNot(void)
+{
+	return FindNamedOption("-mem",
+		kNumMemSizs, GetMemSizName, &cur_msz, &olv_msz);
+}
+
+LOCALFUNC int dfo_msz(void)
+{
+	int v;
+
+	switch (cur_mdl) {
+		case gbk_mdl_Twig43:
+		case gbk_mdl_Twiggy:
+		case gbk_mdl_128K:
+			v = gbk_msz_128K;
+			break;
+		case gbk_mdl_512Ke:
+			v = gbk_msz_512K;
+			break;
+		case gbk_mdl_II:
+		case gbk_mdl_IIx:
+			v = gbk_msz_8M;
+			break;
+		case gbk_mdl_Plus:
+		case gbk_mdl_SE:
+		case gbk_mdl_SEFDHD:
+		case gbk_mdl_Classic:
+		case gbk_mdl_PB100:
+		default:
+			v = gbk_msz_4M;
+			break;
+	}
+	if (gbk_targfam_lnds == gbo_targfam) {
+		if (v > gbk_msz_2M) {
+			v = gbk_msz_2M;
+		}
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseMemSiz(void)
+{
+	if (kListOptionAuto == cur_msz) {
+		cur_msz = dfo_msz();
+	} else {
+		/* should error check here */
+		/* no, checked in ChooseMemBankSizes */
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptMemSizOption(void)
+{
+	WrtOptNamedOption("-mem", GetMemSizName, cur_msz, dfo_msz());
+}
+
+/* memory bank sizes */
+
+LOCALVAR uimr RAMa_Size;
+LOCALVAR uimr RAMb_Size;
+
+#define ln2_msz_64K 16
+#define ln2_msz_128K 17
+#define ln2_msz_256K 18
+#define ln2_msz_512K 19
+#define ln2_msz_1M 20
+#define ln2_msz_2M 21
+#define ln2_msz_4M 22
+#define ln2_msz_8M 23
+
+LOCALFUNC tMyErr ChooseMemBankSizes(void)
+{
+	tMyErr err;
+	RAMa_Size = 0;
+	RAMb_Size = 0;
+
+	switch (cur_mdl) {
+		case gbk_mdl_Twig43:
+		case gbk_mdl_Twiggy:
+		case gbk_mdl_128K:
+		case gbk_mdl_512Ke:
+			if (cur_msz == gbk_msz_128K) {
+				RAMa_Size = ln2_msz_128K;
+			} else
+			if (cur_msz == gbk_msz_512K) {
+				RAMa_Size = ln2_msz_512K;
+			} else
+			{
+				/* unsupported */
+			}
+			break;
+		case gbk_mdl_Plus:
+		case gbk_mdl_SE:
+		case gbk_mdl_SEFDHD:
+		case gbk_mdl_Classic:
+			if (cur_msz == gbk_msz_128K) {
+				if (gbk_mdl_Plus == cur_mdl) {
+					RAMa_Size = ln2_msz_128K;
+				}
+			} else
+			if (cur_msz == gbk_msz_512K) {
+				RAMa_Size = ln2_msz_512K;
+			} else
+			if (cur_msz == gbk_msz_1M) {
+				RAMa_Size = ln2_msz_512K;
+				RAMb_Size = ln2_msz_512K;
+			} else
+			if (cur_msz == gbk_msz_2M) {
+				RAMa_Size = ln2_msz_2M;
+			} else
+			if (cur_msz == gbk_msz_2_5M) {
+				RAMa_Size = ln2_msz_2M;
+				RAMb_Size = ln2_msz_512K;
+			} else
+			if (cur_msz == gbk_msz_4M) {
+				RAMa_Size = ln2_msz_2M;
+				RAMb_Size = ln2_msz_2M;
+			} else
+			{
+				/* unsupported */
+			}
+			break;
+		case gbk_mdl_II:
+		case gbk_mdl_IIx:
+			if (cur_msz == gbk_msz_1M) {
+				RAMa_Size = ln2_msz_1M;
+			} else
+			if (cur_msz == gbk_msz_2M) {
+				RAMa_Size = ln2_msz_1M;
+				RAMb_Size = ln2_msz_1M;
+			} else
+			if (cur_msz == gbk_msz_4M) {
+				RAMa_Size = ln2_msz_4M;
+			} else
+			if (cur_msz == gbk_msz_5M) {
+				RAMa_Size = ln2_msz_4M;
+				RAMb_Size = ln2_msz_1M;
+			} else
+			if (cur_msz == gbk_msz_8M) {
+				RAMa_Size = ln2_msz_4M;
+				RAMb_Size = ln2_msz_4M;
+			} else
+			{
+				/* unsupported */
+			}
+			break;
+		case gbk_mdl_PB100:
+			if (cur_msz == gbk_msz_4M) {
+				RAMa_Size = ln2_msz_4M;
+			} else
+			{
+				/* unsupported */
+			}
+		default:
+			/* unsupported */
+			break;
+	}
+
+	if (0 == RAMa_Size) {
+		err = ReportParseFailure(
+			"memory size (-mem) unsupported for this model (-m)");
+	} else {
+		err = kMyErr_noErr;
+	}
+
+	return err;
+}
+
+
+/* option: Parameter RAM CaretBlinkTime */
+	/* usually in 3 (Fast), 8 (Medium), 15 (Slow) */
+
+LOCALVAR uimr cur_CaretBlinkTime;
+LOCALVAR ui3r olv_CaretBlinkTime;
+
+LOCALPROC ResetCaretBlinkTimeOption(void)
+{
+	olv_CaretBlinkTime = 0;
+}
+
+LOCALFUNC tMyErr TryAsCaretBlinkTimeOptionNot(void)
+{
+	return NumberTryAsOptionNot("-cbt",
+		(long *)&cur_CaretBlinkTime, &olv_CaretBlinkTime);
+}
+
+LOCALFUNC uimr dfo_CaretBlinkTime(void)
+{
+	uimr v;
+
+	if (cur_mIIorIIX) {
+		v = 8;
+	} else {
+		v = 3;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseCaretBlinkTime(void)
+{
+	tMyErr err;
+
+
+	err = kMyErr_noErr;
+	if (0 == olv_CaretBlinkTime) {
+		cur_CaretBlinkTime = dfo_CaretBlinkTime();
+	} else {
+		if ((cur_CaretBlinkTime <= 0) || (cur_CaretBlinkTime > 15)) {
+			err = ReportParseFailure(
+				"-cbt must be a number between 1 and 15");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptCaretBlinkTime(void)
+{
+	WrtOptNumberOption("-cbt",
+		cur_CaretBlinkTime, dfo_CaretBlinkTime());
+}
+
+
+/* option: Parameter RAM DoubleClickTime */
+	/* usually in 5 (Fast), 8 (Medium), 12 (Slow) */
+
+LOCALVAR uimr cur_DoubleClickTime;
+LOCALVAR ui3r olv_DoubleClickTime;
+
+LOCALPROC ResetDoubleClickTimeOption(void)
+{
+	olv_DoubleClickTime = 0;
+}
+
+LOCALFUNC tMyErr TryAsDoubleClickTimeOptionNot(void)
+{
+	return NumberTryAsOptionNot("-dct",
+		(long *)&cur_DoubleClickTime, &olv_DoubleClickTime);
+}
+
+LOCALFUNC uimr dfo_DoubleClickTime(void)
+{
+	uimr v;
+
+	if (cur_mIIorIIX) {
+		v = 8;
+	} else {
+		v = 5;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseDoubleClickTime(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+
+
+	if (0 == olv_DoubleClickTime) {
+		cur_DoubleClickTime = dfo_DoubleClickTime();
+	} else {
+		if ((cur_DoubleClickTime <= 0) || (cur_DoubleClickTime > 15)) {
+			err = ReportParseFailure(
+				"-dct must be a number between 1 and 15");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptDoubleClickTime(void)
+{
+	WrtOptNumberOption("-dct",
+		cur_DoubleClickTime, dfo_DoubleClickTime());
+}
+
+
+/* option: Parameter RAM MenuBlink */
+	/* in 0..3 */
+
+LOCALVAR uimr cur_MenuBlink;
+LOCALVAR ui3r olv_MenuBlink;
+
+LOCALPROC ResetMenuBlinkOption(void)
+{
+	olv_MenuBlink = 0;
+}
+
+LOCALFUNC tMyErr TryAsMenuBlinkOptionNot(void)
+{
+	return NumberTryAsOptionNot("-mnb",
+		(long *)&cur_MenuBlink, &olv_MenuBlink);
+}
+
+#define dfo_MenuBlink() 3
+
+LOCALFUNC tMyErr ChooseMenuBlink(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+	if (0 == olv_MenuBlink) {
+		cur_MenuBlink = dfo_MenuBlink();
+	} else {
+		if (cur_MenuBlink > 3) {
+			err = ReportParseFailure(
+				"-mnb must be a number between 0 and 3");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptMenuBlink(void)
+{
+	WrtOptNumberOption("-mnb", cur_MenuBlink, dfo_MenuBlink());
+}
+
+
+/* option: Parameter RAM AutoKeyThresh */
+	/* usually in 0 (Off), A (Long), 6, 4, 3 (Short) */
+
+LOCALVAR uimr cur_AutoKeyThresh;
+LOCALVAR ui3r olv_AutoKeyThresh;
+
+LOCALPROC ResetAutoKeyThreshOption(void)
+{
+	olv_AutoKeyThresh = 0;
+}
+
+LOCALFUNC tMyErr TryAsAutoKeyThreshOptionNot(void)
+{
+	return NumberTryAsOptionNot("-kyt",
+		(long *)&cur_AutoKeyThresh, &olv_AutoKeyThresh);
+}
+
+#define dfo_AutoKeyThresh() 6
+
+LOCALFUNC tMyErr ChooseAutoKeyThresh(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+	if (0 == olv_AutoKeyThresh) {
+		cur_AutoKeyThresh = dfo_AutoKeyThresh();
+	} else {
+		if (cur_AutoKeyThresh > 15) {
+			err = ReportParseFailure(
+				"-kyt must be a number between 0 and 15");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptAutoKeyThresh(void)
+{
+	WrtOptNumberOption("-kyt", cur_AutoKeyThresh, dfo_AutoKeyThresh());
+}
+
+
+/* option: Parameter RAM AutoKeyRate */
+	/* usually in 0 (Slow), 6, 4, 3, 1 (Fast) */
+
+LOCALVAR uimr cur_AutoKeyRate;
+LOCALVAR ui3r olv_AutoKeyRate;
+
+LOCALPROC ResetAutoKeyRateOption(void)
+{
+	olv_AutoKeyRate = 0;
+}
+
+LOCALFUNC tMyErr TryAsAutoKeyRateOptionNot(void)
+{
+	return NumberTryAsOptionNot("-kyr",
+		(long *)&cur_AutoKeyRate, &olv_AutoKeyRate);
+}
+
+#define dfo_AutoKeyRate() 3
+
+LOCALFUNC tMyErr ChooseAutoKeyRate(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+	if (0 == olv_AutoKeyRate) {
+		cur_AutoKeyRate = dfo_AutoKeyRate();
+	} else {
+		if (cur_AutoKeyRate > 15) {
+			err = ReportParseFailure(
+				"-kyr must be a number between 0 and 15");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptAutoKeyRate(void)
+{
+	WrtOptNumberOption("-kyr", cur_AutoKeyRate, dfo_AutoKeyRate());
+}
+
+
+LOCALFUNC tMyErr ChooseHilColPart(char *s, uimr *cur_HilColV,
+	ui3r olv_HilColV, uimr dfo_HilColV)
+{
+	tMyErr err;
+	MyPStr t;
+
+	err = kMyErr_noErr;
+	if (0 == olv_HilColV) {
+		*cur_HilColV = dfo_HilColV;
+	} else {
+		if (! cur_mIIorIIX) {
+			if (0 != *cur_HilColV) {
+				PStrFromCStr(t, s);
+				PStrApndCStr(t,
+					" not allowed for this emulated computer");
+				err = ReportParseFailPStr(t);
+			}
+		} else
+		if (*cur_HilColV > 65535) {
+			PStrFromCStr(t, s);
+			PStrApndCStr(t, " must be a number between 0 and 65535");
+			err = ReportParseFailPStr(t);
+		}
+	}
+
+	return err;
+}
+
+/* option: Parameter RAM HilColRed */
+
+LOCALVAR uimr cur_HilColRed;
+LOCALVAR ui3r olv_HilColRed;
+
+LOCALPROC ResetHilColRedOption(void)
+{
+	olv_HilColRed = 0;
+}
+
+LOCALFUNC tMyErr TryAsHilColRedOptionNot(void)
+{
+	return NumberTryAsOptionNot("-hcr",
+		(long *)&cur_HilColRed, &olv_HilColRed);
+}
+
+#define dfo_HilColRed() 0
+
+LOCALFUNC tMyErr ChooseHilColRed(void)
+{
+	return ChooseHilColPart("-hcr", &cur_HilColRed, olv_HilColRed,
+		dfo_HilColRed());
+}
+
+LOCALPROC WrtOptHilColRed(void)
+{
+	WrtOptNumberOption("-hcr", cur_HilColRed, dfo_HilColRed());
+}
+
+
+/* option: Parameter RAM HilColGreen */
+
+LOCALVAR uimr cur_HilColGreen;
+LOCALVAR ui3r olv_HilColGreen;
+
+LOCALPROC ResetHilColGreenOption(void)
+{
+	olv_HilColGreen = 0;
+}
+
+LOCALFUNC tMyErr TryAsHilColGreenOptionNot(void)
+{
+	return NumberTryAsOptionNot("-hcg",
+		(long *)&cur_HilColGreen, &olv_HilColGreen);
+}
+
+#define dfo_HilColGreen() 0
+
+LOCALFUNC tMyErr ChooseHilColGreen(void)
+{
+	return ChooseHilColPart("-hcg", &cur_HilColGreen, olv_HilColGreen,
+		dfo_HilColGreen());
+}
+
+LOCALPROC WrtOptHilColGreen(void)
+{
+	WrtOptNumberOption("-hcg", cur_HilColGreen, dfo_HilColGreen());
+}
+
+
+/* option: Parameter RAM HilColBlue */
+
+LOCALVAR uimr cur_HilColBlue;
+LOCALVAR ui3r olv_HilColBlue;
+
+LOCALPROC ResetHilColBlueOption(void)
+{
+	olv_HilColBlue = 0;
+}
+
+LOCALFUNC tMyErr TryAsHilColBlueOptionNot(void)
+{
+	return NumberTryAsOptionNot("-hcb",
+		(long *)&cur_HilColBlue, &olv_HilColBlue);
+}
+
+#define dfo_HilColBlue() 0
+
+LOCALFUNC tMyErr ChooseHilColBlue(void)
+{
+	return ChooseHilColPart("-hcb", &cur_HilColBlue, olv_HilColBlue,
+		dfo_HilColBlue());
+}
+
+LOCALPROC WrtOptHilColBlue(void)
+{
+	WrtOptNumberOption("-hcb", cur_HilColBlue, dfo_HilColBlue());
+}
+
+
+/* option: Automatic Location */
+
+LOCALVAR blnr WantAutoLocation;
+LOCALVAR ui3r olv_AutoLocation;
+
+LOCALPROC ResetAutoLocation(void)
+{
+	WantAutoLocation = nanblnr;
+	olv_AutoLocation = 0;
+}
+
+LOCALFUNC tMyErr TryAsAutoLocationNot(void)
+{
+	return BooleanTryAsOptionNot("-alc",
+		&WantAutoLocation, &olv_AutoLocation);
+}
+
+#define dfo_AutoLocation() trueblnr
+
+LOCALFUNC tMyErr ChooseAutoLocation(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+	if (nanblnr == WantAutoLocation) {
+		WantAutoLocation = dfo_AutoLocation();
+	} else {
+		if (cur_mdl < gbk_mdl_Plus) {
+			err = ReportParseFailure(
+				"-alc not supported for this model (-m)");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptAutoLocation(void)
+{
+	WrtOptBooleanOption("-alc", WantAutoLocation, dfo_AutoLocation());
+}
+
+
+/* option: Location Latitude */
+
+LOCALVAR uimr cur_InitLatitude;
+LOCALVAR ui3r olv_InitLatitude;
+
+LOCALPROC ResetInitLatitudeOption(void)
+{
+	olv_InitLatitude = 0;
+}
+
+LOCALFUNC tMyErr TryAsInitLatitudeOptionNot(void)
+{
+	return NumberTryAsOptionNot("-lcy",
+		(long *)&cur_InitLatitude, &olv_InitLatitude);
+}
+
+#define dfo_InitLatitude() 0
+
+LOCALFUNC tMyErr ChooseInitLatitude(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+	if (0 == olv_InitLatitude) {
+		cur_InitLatitude = dfo_InitLatitude();
+	} else {
+		if (cur_mdl < gbk_mdl_Plus) {
+			err = ReportParseFailure(
+				"-lcy not supported for this model (-m)");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptInitLatitude(void)
+{
+	if (! WantAutoLocation) {
+		WrtOptSimrOption("-lcy", cur_InitLatitude, dfo_InitLatitude());
+	}
+}
+
+
+/* option: Location Longitude */
+
+LOCALVAR simr cur_InitLongitude;
+LOCALVAR ui3r olv_InitLongitude;
+
+LOCALPROC ResetInitLongitudeOption(void)
+{
+	olv_InitLongitude = 0;
+}
+
+LOCALFUNC tMyErr TryAsInitLongitudeOptionNot(void)
+{
+	return NumberTryAsOptionNot("-lcx",
+		&cur_InitLongitude, &olv_InitLongitude);
+}
+
+#define dfo_InitLongitude() 0
+
+LOCALFUNC tMyErr ChooseInitLongitude(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+	if (0 == olv_InitLongitude) {
+		cur_InitLongitude = dfo_InitLongitude();
+	} else {
+		if (cur_mdl < gbk_mdl_Plus) {
+			err = ReportParseFailure(
+				"-lcx not supported for this model (-m)");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptInitLongitude(void)
+{
+	if (! WantAutoLocation) {
+		WrtOptSimrOption("-lcx", cur_InitLongitude,
+			dfo_InitLongitude());
+	}
+}
+
+
+/* option: Automatic Time Zone */
+
+LOCALVAR blnr WantAutoTimeZone;
+LOCALVAR ui3r olv_AutoTimeZone;
+
+LOCALPROC ResetAutoTimeZone(void)
+{
+	WantAutoTimeZone = nanblnr;
+	olv_AutoTimeZone = 0;
+}
+
+LOCALFUNC tMyErr TryAsAutoTimeZoneNot(void)
+{
+	return BooleanTryAsOptionNot("-atz",
+		&WantAutoTimeZone, &olv_AutoTimeZone);
+}
+
+#define dfo_AutoTimeZone() trueblnr
+
+LOCALFUNC tMyErr ChooseAutoTimeZone(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+	if (nanblnr == WantAutoTimeZone) {
+		WantAutoTimeZone = dfo_AutoTimeZone();
+	} else {
+		if (cur_mdl < gbk_mdl_Plus) {
+			err = ReportParseFailure(
+				"-atz not supported for this model (-m)");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptAutoTimeZone(void)
+{
+	WrtOptBooleanOption("-atz", WantAutoTimeZone, dfo_AutoTimeZone());
+}
+
+
+/* option: Daylight Savings Time */
+
+LOCALVAR blnr WantTzDST;
+LOCALVAR ui3r olv_TzDST;
+
+LOCALPROC ResetTzDST(void)
+{
+	WantTzDST = nanblnr;
+	olv_TzDST = 0;
+}
+
+LOCALFUNC tMyErr TryAsTzDSTNot(void)
+{
+	return BooleanTryAsOptionNot("-lcd",
+		&WantTzDST, &olv_TzDST);
+}
+
+#define dfo_TzDST() falseblnr
+
+LOCALFUNC tMyErr ChooseTzDST(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+	if (nanblnr == WantTzDST) {
+		WantTzDST = dfo_TzDST();
+	} else {
+		if (cur_mdl < gbk_mdl_Plus) {
+			err = ReportParseFailure(
+				"-lcd not supported for this model (-m)");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptTzDST(void)
+{
+	if (! WantAutoTimeZone) {
+		WrtOptBooleanOption("-lcd", WantTzDST, dfo_TzDST());
+	}
+}
+
+
+/* option: Time Zone Delta Hours */
+
+LOCALVAR simr cur_TzDeltH;
+LOCALVAR ui3r olv_TzDeltH;
+
+LOCALPROC ResetTzDeltHOption(void)
+{
+	olv_TzDeltH = 0;
+}
+
+LOCALFUNC tMyErr TryAsTzDeltHOptionNot(void)
+{
+	return NumberTryAsOptionNot("-lcz",
+		&cur_TzDeltH, &olv_TzDeltH);
+}
+
+
+/* option: Time Zone Delta Seconds */
+
+LOCALVAR simr cur_TzDeltS;
+LOCALVAR ui3r olv_TzDeltS;
+
+LOCALPROC ResetTzDeltSOption(void)
+{
+	olv_TzDeltS = 0;
+}
+
+LOCALFUNC tMyErr TryAsTzDeltSOptionNot(void)
+{
+	return NumberTryAsOptionNot("-lczs",
+		&cur_TzDeltS, &olv_TzDeltS);
+}
+
+#define dfo_TzDeltS() 0
+
+LOCALFUNC tMyErr ChooseTzDeltS(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+	if (cur_mdl < gbk_mdl_Plus) {
+		if ((0 != olv_TzDeltS) || (0 != olv_TzDeltH)) {
+			err = ReportParseFailure(
+				"-lczs and -lcz are not supported for this model (-m)");
+		}
+	} else if (0 == olv_TzDeltS) {
+		if (0 == olv_TzDeltH) {
+			cur_TzDeltS = dfo_TzDeltS();
+		} else {
+			cur_TzDeltS = cur_TzDeltH * 3600;
+		}
+	} else {
+		if (0 != olv_TzDeltH) {
+			err = ReportParseFailure(
+				"-lczs and -lcz can not both be used");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptTzDeltS(void)
+{
+	if (! WantAutoTimeZone) {
+		simr t = cur_TzDeltS / 3600;
+
+		if (t * 3600 ==  cur_TzDeltS) {
+			WrtOptSimrOption("-lcz", t, 0);
+		} else {
+			WrtOptSimrOption("-lczs", cur_TzDeltS, dfo_TzDeltS());
+		}
+	}
+}
+
+
+/* option: Speaker Volume */
+	/* usually in 3 (Fast), 8 (Medium), 15 (Slow) */
+
+LOCALVAR uimr cur_SpeakerVol;
+LOCALVAR ui3r olv_SpeakerVol;
+
+LOCALPROC ResetSpeakerVolOption(void)
+{
+	olv_SpeakerVol = 0;
+}
+
+LOCALFUNC tMyErr TryAsSpeakerVolOptionNot(void)
+{
+	return NumberTryAsOptionNot("-svl",
+		(long *)&cur_SpeakerVol, &olv_SpeakerVol);
+}
+
+LOCALFUNC uimr dfo_SpeakerVol(void)
+{
+	uimr v;
+
+	if (MySoundEnabled) {
+		v = 7;
+	} else {
+		v = 0;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseSpeakerVol(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+
+
+	if (0 == olv_SpeakerVol) {
+		cur_SpeakerVol = dfo_SpeakerVol();
+	} else {
+		if (cur_SpeakerVol >= 8) {
+			err = ReportParseFailure(
+				"-svl must be a number between 0 and 7");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptSpeakerVol(void)
+{
+	WrtOptNumberOption("-svl", cur_SpeakerVol, dfo_SpeakerVol());
+}
+
+
+/* option: Minimum Extension */
+
+LOCALVAR blnr WantMinExtn;
+LOCALVAR ui3r olv_WantMinExtn;
+
+LOCALPROC ResetWantMinExtn(void)
+{
+	WantMinExtn = falseblnr;
+	olv_WantMinExtn = 0;
+}
+
+LOCALFUNC tMyErr TryAsWantMinExtnNot(void)
+{
+	return FlagTryAsOptionNot("-min-extn",
+		&WantMinExtn, &olv_WantMinExtn);
+}
+
+LOCALFUNC tMyErr ChooseWantMinExtn(void)
+{
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptMinExtn(void)
+{
+	WrtOptFlagOption("-min-extn", WantMinExtn);
+}
+
+
+/* option: MouseMotion */
+
+LOCALVAR blnr MyMouseMotion;
+LOCALVAR ui3r olv_MouseMotion;
+
+LOCALPROC ResetMouseMotionOption(void)
+{
+	MyMouseMotion = nanblnr;
+	olv_MouseMotion = 0;
+}
+
+LOCALFUNC tMyErr TryAsMouseMotionOptionNot(void)
+{
+	return BooleanTryAsOptionNot("-emm",
+		&MyMouseMotion, &olv_MouseMotion);
+}
+
+LOCALFUNC blnr dfo_MouseMotion(void)
+{
+	blnr v;
+
+	v = (gbk_apifam_gtk != gbo_apifam);
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseMouseMotion(void)
+{
+
+	if (nanblnr == MyMouseMotion) {
+		MyMouseMotion = dfo_MouseMotion();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptMouseMotion(void)
+{
+	WrtOptBooleanOption("-emm", MyMouseMotion, dfo_MouseMotion());
+}
+
+
+/* option: GrabKeysFullScreen */
+
+LOCALVAR blnr WantGrabKeysFS;
+LOCALVAR ui3r olv_GrabKeysFS;
+
+LOCALPROC ResetGrabKeysFS(void)
+{
+	WantGrabKeysFS = nanblnr;
+	olv_GrabKeysFS = 0;
+}
+
+LOCALFUNC tMyErr TryAsGrabKeysFSNot(void)
+{
+	return BooleanTryAsOptionNot("-gkf",
+		&WantGrabKeysFS, &olv_GrabKeysFS);
+}
+
+#define dfo_GrabKeysFS() trueblnr
+
+LOCALFUNC tMyErr ChooseGrabKeysFS(void)
+{
+	if (nanblnr == WantGrabKeysFS) {
+		WantGrabKeysFS = dfo_GrabKeysFS();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptGrabKeysFS(void)
+{
+	WrtOptBooleanOption("-gkf", WantGrabKeysFS, dfo_GrabKeysFS());
+}
+
+
+/* option: Enable Control Interrupt */
+
+LOCALVAR blnr WantEnblCtrlInt;
+LOCALVAR ui3r olv_EnblCtrlInt;
+
+LOCALPROC ResetEnblCtrlInt(void)
+{
+	WantEnblCtrlInt = nanblnr;
+	olv_EnblCtrlInt = 0;
+}
+
+LOCALFUNC tMyErr TryAsEnblCtrlIntNot(void)
+{
+	return BooleanTryAsOptionNot("-eci",
+		&WantEnblCtrlInt, &olv_EnblCtrlInt);
+}
+
+#define dfo_EnblCtrlInt() trueblnr
+
+LOCALFUNC tMyErr ChooseEnblCtrlInt(void)
+{
+	if (nanblnr == WantEnblCtrlInt) {
+		WantEnblCtrlInt = dfo_EnblCtrlInt();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptEnblCtrlInt(void)
+{
+	WrtOptBooleanOption("-eci", WantEnblCtrlInt, dfo_EnblCtrlInt());
+}
+
+
+/* option: Enable Control Reset */
+
+LOCALVAR blnr WantEnblCtrlRst;
+LOCALVAR ui3r olv_EnblCtrlRst;
+
+LOCALPROC ResetEnblCtrlRst(void)
+{
+	WantEnblCtrlRst = nanblnr;
+	olv_EnblCtrlRst = 0;
+}
+
+LOCALFUNC tMyErr TryAsEnblCtrlRstNot(void)
+{
+	return BooleanTryAsOptionNot("-ecr",
+		&WantEnblCtrlRst, &olv_EnblCtrlRst);
+}
+
+#define dfo_EnblCtrlRst() trueblnr
+
+LOCALFUNC tMyErr ChooseEnblCtrlRst(void)
+{
+	if (nanblnr == WantEnblCtrlRst) {
+		WantEnblCtrlRst = dfo_EnblCtrlRst();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptEnblCtrlRst(void)
+{
+	WrtOptBooleanOption("-ecr", WantEnblCtrlRst, dfo_EnblCtrlRst());
+}
+
+
+/* option: Enable Control K (emulated control toggle) */
+
+LOCALVAR blnr WantEnblCtrlKtg;
+LOCALVAR ui3r olv_EnblCtrlKtg;
+
+LOCALPROC ResetEnblCtrlKtg(void)
+{
+	WantEnblCtrlKtg = nanblnr;
+	olv_EnblCtrlKtg = 0;
+}
+
+LOCALFUNC tMyErr TryAsEnblCtrlKtgNot(void)
+{
+	return BooleanTryAsOptionNot("-eck",
+		&WantEnblCtrlKtg, &olv_EnblCtrlKtg);
+}
+
+#define dfo_EnblCtrlKtg() trueblnr
+
+LOCALFUNC tMyErr ChooseEnblCtrlKtg(void)
+{
+	if (nanblnr == WantEnblCtrlKtg) {
+		WantEnblCtrlKtg = dfo_EnblCtrlKtg();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptEnblCtrlKtg(void)
+{
+	WrtOptBooleanOption("-eck", WantEnblCtrlKtg, dfo_EnblCtrlKtg());
+}
+
+
+/* option: Want Color Image */
+
+LOCALVAR blnr WantColorImage;
+LOCALVAR ui3r olv_ColorImage;
+
+LOCALPROC ResetWantColorImage(void)
+{
+	WantColorImage = nanblnr;
+	olv_ColorImage = 0;
+}
+
+LOCALFUNC tMyErr TryAsWantColorImageNot(void)
+{
+	return BooleanTryAsOptionNot("-ci",
+		&WantColorImage, &olv_ColorImage);
+}
+
+LOCALFUNC blnr dfo_ColorImage(void)
+{
+	blnr v;
+
+	if (gbk_apifam_xwn == gbo_apifam) {
+		v = trueblnr;
+	} else {
+		/* leave as default */
+		v = nanblnr;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseWantColorImage(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+
+	if (nanblnr == WantColorImage) {
+		WantColorImage = dfo_ColorImage();
+	} else {
+		if (gbk_apifam_xwn != gbo_apifam) {
+			err = ReportParseFailure(
+				"-ci is only for -api xwn");
+		} else
+		if ((! WantColorImage) && (cur_ScrnDpth != 0)) {
+			err = ReportParseFailure(
+				"-ci 0 requires -depth 0");
+		} else
+		{
+			/* ok */
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptColorImage(void)
+{
+	WrtOptBooleanOption("-ci", WantColorImage, dfo_ColorImage());
+}
+
+
+/* option: Alternate Happy Mac Icons */
+
+enum {
+	gbk_AHM_none,
+	gbk_AHM_aside,
+	gbk_AHM_cheese,
+	gbk_AHM_evil,
+	gbk_AHM_horror,
+	gbk_AHM_lady_mac,
+	gbk_AHM_moustache,
+	gbk_AHM_nerdy,
+	gbk_AHM_pirate,
+	gbk_AHM_sleepy,
+	gbk_AHM_sly,
+	gbk_AHM_sunglasses,
+	gbk_AHM_surprise,
+	gbk_AHM_tongue,
+	gbk_AHM_yuck,
+	gbk_AHM_zombie,
+
+	kNumAHMs
+};
+
+LOCALVAR int cur_AltHappyMac;
+LOCALVAR ui3r olv_AltHappyMac;
+
+LOCALPROC ResetAltHappyMacOption(void)
+{
+	cur_AltHappyMac = kListOptionAuto;
+	olv_AltHappyMac = 0;
+}
+
+LOCALFUNC char * GetAltHappyMacName(int i)
+{
+	char *s;
+
+	switch (i) {
+		case gbk_AHM_none:
+			s = "none";
+			break;
+		case gbk_AHM_aside:
+			s = "aside";
+			break;
+		case gbk_AHM_cheese:
+			s = "cheese";
+			break;
+		case gbk_AHM_evil:
+			s = "evil";
+			break;
+		case gbk_AHM_horror:
+			s = "horror";
+			break;
+		case gbk_AHM_lady_mac:
+			s = "lady_mac";
+			break;
+		case gbk_AHM_moustache:
+			s = "moustache";
+			break;
+		case gbk_AHM_nerdy:
+			s = "nerdy";
+			break;
+		case gbk_AHM_pirate:
+			s = "pirate";
+			break;
+		case gbk_AHM_sleepy:
+			s = "sleepy";
+			break;
+		case gbk_AHM_sly:
+			s = "sly";
+			break;
+		case gbk_AHM_sunglasses:
+			s = "sunglasses";
+			break;
+		case gbk_AHM_surprise:
+			s = "surprise";
+			break;
+		case gbk_AHM_tongue:
+			s = "tongue";
+			break;
+		case gbk_AHM_yuck:
+			s = "yuck";
+			break;
+		case gbk_AHM_zombie:
+			s = "zombie";
+			break;
+
+		default:
+			s = "(unknown Alt Happy Mac Icon)";
+			break;
+	}
+	return s;
+}
+
+LOCALFUNC tMyErr TryAsAltHappyMacOptionNot(void)
+{
+	return FindNamedOption("-ahm", kNumAHMs, GetAltHappyMacName,
+		&cur_AltHappyMac, &olv_AltHappyMac);
+}
+
+#define dfo_AltHappyMac() gbk_AHM_none
+
+LOCALFUNC tMyErr ChooseAltHappyMac(void)
+{
+	if (kListOptionAuto == cur_AltHappyMac) {
+		cur_AltHappyMac = dfo_AltHappyMac();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptAltHappyMac(void)
+{
+	WrtOptNamedOption("-ahm", GetAltHappyMacName,
+		cur_AltHappyMac, dfo_AltHappyMac());
+}
+
+
+/* option: ROM size */
+
+LOCALVAR uimr cur_RomSize;
+LOCALVAR ui3r olv_RomSize;
+
+LOCALPROC ResetRomSizeOption(void)
+{
+	olv_RomSize = 0;
+}
+
+LOCALFUNC tMyErr TryAsRomSizeOptionNot(void)
+{
+	return NumberTryAsOptionNot("-rsz",
+		(long *)&cur_RomSize, &olv_RomSize);
+}
+
+LOCALFUNC uimr dfo_RomSize(void)
+{
+	uimr v;
+
+	switch (cur_mdl) {
+		case gbk_mdl_Twig43:
+		case gbk_mdl_Twiggy:
+		case gbk_mdl_128K:
+			v = ln2_msz_64K; /* 64 KB */
+			break;
+		case gbk_mdl_512Ke:
+		case gbk_mdl_Plus:
+			v = ln2_msz_128K; /* 128 KB */
+			break;
+		case gbk_mdl_SE:
+		case gbk_mdl_SEFDHD:
+		case gbk_mdl_PB100:
+		case gbk_mdl_II:
+		case gbk_mdl_IIx:
+			v = ln2_msz_256K; /* 256 KB */
+			break;
+		case gbk_mdl_Classic:
+		default:
+			v = ln2_msz_512K; /* 512 KB */
+			break;
+	}
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseRomSize(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+
+
+	if (0 == olv_RomSize) {
+		cur_RomSize = dfo_RomSize();
+	} else {
+		if ((cur_RomSize < 16) || (cur_RomSize > 31)) {
+			err = ReportParseFailure(
+				"-rsz must be a number between 16 and 31");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptRomSize(void)
+{
+	WrtOptNumberOption("-rsz", cur_RomSize, dfo_RomSize());
+}
+
+
+/* option: Want Check RomCheck Sum */
+
+LOCALVAR blnr WantCheckRomCheckSum;
+LOCALVAR ui3r olv_CheckRomCheckSum;
+
+LOCALPROC ResetCheckRomCheckSum(void)
+{
+	WantCheckRomCheckSum = nanblnr;
+	olv_CheckRomCheckSum = 0;
+}
+
+LOCALFUNC tMyErr TryAsCheckRomCheckSumNot(void)
+{
+	return BooleanTryAsOptionNot("-chr",
+		&WantCheckRomCheckSum, &olv_CheckRomCheckSum);
+}
+
+#define dfo_CheckRomCheckSum() trueblnr
+
+LOCALFUNC tMyErr ChooseCheckRomCheckSum(void)
+{
+	if (nanblnr == WantCheckRomCheckSum) {
+		WantCheckRomCheckSum = dfo_CheckRomCheckSum();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptCheckRomCheckSum(void)
+{
+	WrtOptBooleanOption("-chr",
+		WantCheckRomCheckSum, dfo_CheckRomCheckSum());
+}
+
+
+/* option: Want Disable Rom Check */
+
+LOCALVAR blnr WantDisableRomCheck;
+LOCALVAR ui3r olv_DisableRomCheck;
+
+LOCALPROC ResetDisableRomCheck(void)
+{
+	WantDisableRomCheck = nanblnr;
+	olv_DisableRomCheck = 0;
+}
+
+LOCALFUNC tMyErr TryAsDisableRomCheckNot(void)
+{
+	return BooleanTryAsOptionNot("-drc",
+		&WantDisableRomCheck, &olv_DisableRomCheck);
+}
+
+#define dfo_DisableRomCheck() trueblnr
+
+LOCALFUNC tMyErr ChooseDisableRomCheck(void)
+{
+	if (nanblnr == WantDisableRomCheck) {
+		WantDisableRomCheck = dfo_DisableRomCheck();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptDisableRomCheck(void)
+{
+	WrtOptBooleanOption("-drc",
+		WantDisableRomCheck, dfo_DisableRomCheck());
+}
+
+
+/* option: Want Disable Ram Test */
+
+LOCALVAR blnr WantDisableRamTest;
+LOCALVAR ui3r olv_DisableRamTest;
+
+LOCALPROC ResetDisableRamTest(void)
+{
+	WantDisableRamTest = nanblnr;
+	olv_DisableRamTest = 0;
+}
+
+LOCALFUNC tMyErr TryAsDisableRamTestNot(void)
+{
+	return BooleanTryAsOptionNot("-drt",
+		&WantDisableRamTest, &olv_DisableRamTest);
+}
+
+#define dfo_DisableRamTest() trueblnr
+
+LOCALFUNC tMyErr ChooseDisableRamTest(void)
+{
+	if (nanblnr == WantDisableRamTest) {
+		WantDisableRamTest = dfo_DisableRamTest();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptDisableRamTest(void)
+{
+	WrtOptBooleanOption("-drt",
+		WantDisableRamTest, dfo_DisableRamTest());
+}
+
+
+/* option: Want Disassembly */
+
+LOCALVAR blnr WantDisasm;
+LOCALVAR ui3r olv_WantDisasm;
+
+LOCALPROC ResetWantDisasm(void)
+{
+	WantDisasm = nanblnr;
+	olv_WantDisasm = 0;
+}
+
+LOCALFUNC tMyErr TryAsWantDisasmNot(void)
+{
+	return BooleanTryAsOptionNot("-dis",
+		&WantDisasm, &olv_WantDisasm);
+}
+
+#define dfo_WantDisasm() falseblnr
+
+LOCALFUNC tMyErr ChooseWantDisasm(void)
+{
+	if (nanblnr == WantDisasm) {
+		WantDisasm = dfo_WantDisasm();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptWantDisasmNot(void)
+{
+	WrtOptBooleanOption("-dis", WantDisasm, dfo_WantDisasm());
+}
+
+
+/* option: dbglog_HAVE */
+
+LOCALVAR blnr DbgLogHAVE;
+LOCALVAR ui3r olv_DbgLogHAVE;
+
+LOCALPROC ResetDbgLogHAVE(void)
+{
+	DbgLogHAVE = nanblnr;
+	olv_DbgLogHAVE = 0;
+}
+
+LOCALFUNC tMyErr TryAsDbgLogHAVENot(void)
+{
+	return BooleanTryAsOptionNot("-log", &DbgLogHAVE, &olv_DbgLogHAVE);
+}
+
+#define dfo_DbgLogHAVE() WantDisasm
+
+LOCALFUNC tMyErr ChooseDbgLogHAVE(void)
+{
+	if (nanblnr == DbgLogHAVE) {
+		DbgLogHAVE = dfo_DbgLogHAVE();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptDbgLogHAVE(void)
+{
+	WrtOptBooleanOption("-log", DbgLogHAVE, dfo_DbgLogHAVE());
+}
+
+
+/* option: Abnormal Reports */
+
+LOCALVAR blnr gbo_AbnormalReports;
+LOCALVAR ui3r olv_AbnormalReports;
+
+LOCALPROC ResetAbnormalReports(void)
+{
+	gbo_AbnormalReports = nanblnr;
+	olv_AbnormalReports = 0;
+}
+
+LOCALFUNC tMyErr TryAsAbnormalReportsNot(void)
+{
+	return BooleanTryAsOptionNot("-abr", &gbo_AbnormalReports,
+		&olv_AbnormalReports);
+}
+
+#define dfo_AbnormalReports() DbgLogHAVE
+
+LOCALFUNC tMyErr ChooseAbnormalReports(void)
+{
+	if (nanblnr == gbo_AbnormalReports) {
+		gbo_AbnormalReports = dfo_AbnormalReports();
+	}
+
+	return kMyErr_noErr;
+}
+
+LOCALPROC WrtOptAbnormalReports(void)
+{
+	WrtOptBooleanOption("-abr", gbo_AbnormalReports,
+		dfo_AbnormalReports());
+}
+
+
+/* option: Screen VSync */
+
+LOCALVAR blnr WantScreenVSync;
+LOCALVAR ui3r olv_ScreenVSync;
+
+LOCALPROC ResetScreenVSync(void)
+{
+	WantScreenVSync = nanblnr;
+	olv_ScreenVSync = 0;
+}
+
+LOCALFUNC tMyErr TryAsScreenVSyncNot(void)
+{
+	return BooleanTryAsOptionNot("-vsync",
+		&WantScreenVSync, &olv_ScreenVSync);
+}
+
+#define dfo_ScreenVSync() falseblnr
+
+LOCALFUNC tMyErr ChooseScreenVSync(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+	if (nanblnr == WantScreenVSync) {
+		WantScreenVSync = dfo_ScreenVSync();
+	} else {
+		if (WantScreenVSync && (gbk_apifam_osx != gbo_apifam)) {
+			err = ReportParseFailure(
+				"-vsync is so far only implemented for OS X");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptScreenVSync(void)
+{
+	WrtOptBooleanOption("-vsync", WantScreenVSync, dfo_ScreenVSync());
+}
+
+
+/* option: Graphics Switching */
+
+LOCALVAR blnr WantGraphicsSwitching;
+LOCALVAR ui3r olv_GraphicsSwitching;
+
+LOCALPROC ResetGraphicsSwitching(void)
+{
+	WantGraphicsSwitching = nanblnr;
+	olv_GraphicsSwitching = 0;
+}
+
+LOCALFUNC tMyErr TryAsGraphicsSwitchingNot(void)
+{
+	return BooleanTryAsOptionNot("-gse",
+		&WantGraphicsSwitching, &olv_GraphicsSwitching);
+}
+
+#define dfo_GraphicsSwitching() falseblnr
+
+LOCALFUNC tMyErr ChooseGraphicsSwitching(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+	if (nanblnr == WantGraphicsSwitching) {
+		WantGraphicsSwitching = dfo_GraphicsSwitching();
+	} else {
+		if (WantGraphicsSwitching && (gbk_apifam_cco != gbo_apifam)) {
+			err = ReportParseFailure(
+				"-gse is so far only implemented for cocoa on OS X");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptGraphicsSwitching(void)
+{
+	WrtOptBooleanOption("-gse", WantGraphicsSwitching,
+		dfo_GraphicsSwitching());
+}
+
+
+/* option: Signing */
+
+LOCALVAR blnr WantSigning;
+LOCALVAR ui3r olv_Signing;
+
+LOCALPROC ResetSigning(void)
+{
+	WantSigning = nanblnr;
+	olv_Signing = 0;
+}
+
+LOCALFUNC tMyErr TryAsSigningNot(void)
+{
+	return BooleanTryAsOptionNot("-sgn",
+		&WantSigning, &olv_Signing);
+}
+
+LOCALFUNC blnr dfo_Signing(void)
+{
+	blnr v;
+
+	v = (gbk_apifam_cco == gbo_apifam);
+
+	return v;
+}
+
+LOCALFUNC tMyErr ChooseSigning(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+	if (nanblnr == WantSigning) {
+		WantSigning = dfo_Signing();
+	} else {
+		if (WantSigning && (gbk_apifam_cco != gbo_apifam)) {
+			err = ReportParseFailure(
+				"-sgn is so far only implemented for cocoa on OS X");
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptSigning(void)
+{
+	WrtOptBooleanOption("-sgn", WantSigning,
+		dfo_Signing());
+}
+
+
+/* option: Sandbox */
+
+LOCALVAR blnr WantSandbox;
+LOCALVAR ui3r olv_Sandbox;
+
+LOCALPROC ResetSandbox(void)
+{
+	WantSandbox = nanblnr;
+	olv_Sandbox = 0;
+}
+
+LOCALFUNC tMyErr TryAsSandboxNot(void)
+{
+	return BooleanTryAsOptionNot("-sbx",
+		&WantSandbox, &olv_Sandbox);
+}
+
+#define dfo_Sandbox() falseblnr
+
+LOCALFUNC tMyErr ChooseSandbox(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+	if (nanblnr == WantSandbox) {
+		WantSandbox = dfo_Sandbox();
+	} else {
+		if (WantSandbox) {
+			if (gbk_apifam_cco != gbo_apifam) {
+				err = ReportParseFailure("-sbx"
+					" is so far only implemented for cocoa on OS X");
+			} else
+			if (! WantSigning) {
+				err = ReportParseFailure("-sbx"
+					" requires -sgn 1");
+			} else
+			{
+				/* ok */
+			}
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptSandbox(void)
+{
+	WrtOptBooleanOption("-sbx", WantSandbox,
+		dfo_Sandbox());
+}
+
+/* ------ */
+
+LOCALVAR blnr NeedScrnHack;
+LOCALVAR blnr NeedVidMem;
+
+LOCALFUNC tMyErr ChooseScreenOpts(void)
+{
+	tMyErr err;
+
+	err = kMyErr_noErr;
+	if (! cur_mIIorIIX) {
+		if (cur_hres * cur_vres > (uimr)2 * 1024 * 1024) {
+			err = ReportParseFailure(
+				"-hres and -vres multiplied must be < 2M");
+		}
+	}
+
+	if ((gbk_mdl_PB100 == cur_mdl)
+		|| cur_mIIorIIX)
+	{
+		NeedScrnHack = falseblnr;
+		NeedVidMem = trueblnr;
+	} else {
+		NeedScrnHack = (cur_hres != dfo_hres())
+			|| (cur_vres != dfo_vres());
+		NeedVidMem = NeedScrnHack;
+	}
+
+	return err;
+}
+
+LOCALVAR blnr EmVidCard;
+
+/* video memory size */
+
+LOCALVAR uimr VidMemSize;
+
+LOCALFUNC tMyErr ChooseVidMemSize(void)
+{
+	tMyErr err;
+
+	EmVidCard = cur_mIIorIIX;
+
+	VidMemSize = (((cur_hres * cur_vres) << cur_ScrnDpth) + 7) >> 3;
+
+	--VidMemSize;
+	VidMemSize |= (VidMemSize >> 1);
+	VidMemSize |= (VidMemSize >> 2);
+	VidMemSize |= (VidMemSize >> 4);
+	VidMemSize |= (VidMemSize >> 8);
+	VidMemSize |= (VidMemSize >> 16);
+	++VidMemSize;
+
+	err = kMyErr_noErr;
+	if (! NeedVidMem) {
+		VidMemSize = 0;
+	} else if (EmVidCard) {
+		if (VidMemSize > 4 * 1024 * 1024) {
+			err = ReportParseFailure(
+				"video memory must be <= 4M");
+		} else if (VidMemSize <= 0x00008000) {
+			VidMemSize = 0x00008000;
+		}
+	} else if (gbk_mdl_PB100 == cur_mdl) {
+		VidMemSize = 0x00008000;
+	} else {
+		/* VidMemSize = 0x00020000; */
+
+		if (VidMemSize > 256 * 1024) {
+			err = ReportParseFailure(
+				"video memory must be <= 256K");
+		} else if (VidMemSize <= 0x00004000) {
+			VidMemSize = 0x00004000;
+		}
+	}
+
+	return err;
+}
+
+/* figure out what hardware to emulate */
+
+LOCALVAR blnr EmClassicKbrd;
+LOCALVAR blnr EmADB;
+LOCALVAR blnr EmRTC;
+LOCALVAR blnr EmPMU;
+LOCALVAR blnr EmVIA2;
+LOCALVAR blnr EmASC;
+
+LOCALFUNC tMyErr ChooseMiscEmHardware(void)
+{
+	EmClassicKbrd = cur_mdl <= gbk_mdl_Plus;
+
+	if (EmClassicKbrd) {
+		EmADB = falseblnr;
+		EmRTC = trueblnr;
+		EmPMU = falseblnr;
+	} else
+	if ((cur_mdl <= gbk_mdl_Classic)
+		|| cur_mIIorIIX)
+	{
+		EmADB = trueblnr;
+		EmRTC = trueblnr;
+		EmPMU = falseblnr;
+	} else
+	{
+		EmADB = falseblnr;
+		EmRTC = falseblnr;
+		EmPMU = trueblnr;
+	}
+
+	EmVIA2 = cur_mIIorIIX;
+	EmASC = (gbk_mdl_PB100 == cur_mdl) || cur_mIIorIIX;
+
+	return kMyErr_noErr;
+}
+
+/* total memory size */
+
+#define dbglog_buflnsz 18
+
+#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */
+#define kLnOneBuffLen 9
+
+#define dbhBufferSize (((1UL << kLn2SoundBuffers) + 1UL) \
+	<< (kLnOneBuffLen + cur_SoundSampSz - 3))
+
+#define vMacScreenNumBytes ((((cur_hres * cur_vres) \
+	<< cur_ScrnDpth) + 7) >> 3)
+
+LOCALVAR uimr TotMemSize;
+
+LOCALFUNC tMyErr ChooseTotMemSize(void)
+{
+	TotMemSize = 0;
+
+	if (DbgLogHAVE) {
+		TotMemSize += (1 << dbglog_buflnsz);
+	}
+
+
+	/* CntrlDisplayBuff */
+	TotMemSize += vMacScreenNumBytes;
+
+	/* screencomparebuff */
+	TotMemSize += vMacScreenNumBytes;
+
+	if (1 != cur_MagFctr) {
+		/* ScalingBuff */
+		TotMemSize += vMacScreenNumBytes * cur_MagFctr * cur_MagFctr;
+
+		/* ScalingTabl */
+		TotMemSize += 256 * cur_MagFctr;
+	}
+
+	if (MySoundEnabled) {
+		/* TheSoundBuffer */
+		TotMemSize += dbhBufferSize;
+	}
+
+	TotMemSize += (1 << RAMa_Size);
+	if (0 != RAMb_Size) {
+		TotMemSize += (1 << RAMb_Size);
+	}
+
+	if (EmVidCard) {
+		TotMemSize += 0x000800; /* kVidROM_Size */
+	}
+
+	if (NeedVidMem) {
+		TotMemSize += VidMemSize;
+	}
+
+	TotMemSize += 512 * 1024UL;
+		/* for M68KITAB */
+
+	return kMyErr_noErr;
+}
+
+/* ------ */
+
+LOCALPROC SPResetCommandLineParameters(void)
+{
+	ResetModelOption();
+	ResetHResOption();
+	ResetVResOption();
+	ResetScrnDpthOption();
+	ResetInitFullScreen();
+	ResetVarFullScreen();
+	ResetMagFctrOption();
+	ResetInitMagnify();
+	ResetSoundOption();
+	ResetSndApiOption();
+	ResetSoundSampSzOption();
+	ResetNumDrivesOption();
+	ResetSonySupportTags();
+	ResetSonyWantChecksumsUpdated();
+	ResetSonySupportDC42();
+	ResetSaveDialogEnable();
+	ResetInsertIthDisk();
+	ResetCmndOptSwap();
+	ResetKeyMapOption();
+	ResetEKTMapOption();
+	ResetAltKeysMode();
+	ResetItnlKyBdFixOption();
+	ResetLocalTalk();
+	ResetInitSpeedOption();
+	ResetInitBackground();
+	ResetInitAutoSlow();
+	ResetTimingAccuracyOption();
+	ResetEmCpuVersOption();
+	ResetMemSizOption();
+	ResetCaretBlinkTimeOption();
+	ResetDoubleClickTimeOption();
+	ResetMenuBlinkOption();
+	ResetAutoKeyThreshOption();
+	ResetAutoKeyRateOption();
+	ResetHilColRedOption();
+	ResetHilColGreenOption();
+	ResetHilColBlueOption();
+	ResetAutoLocation();
+	ResetInitLatitudeOption();
+	ResetInitLongitudeOption();
+	ResetAutoTimeZone();
+	ResetTzDST();
+	ResetTzDeltHOption();
+	ResetTzDeltSOption();
+	ResetSpeakerVolOption();
+	ResetWantMinExtn();
+	ResetMouseMotionOption();
+	ResetGrabKeysFS();
+	ResetEnblCtrlInt();
+	ResetEnblCtrlRst();
+	ResetEnblCtrlKtg();
+	ResetWantColorImage();
+	ResetAltHappyMacOption();
+	ResetRomSizeOption();
+	ResetCheckRomCheckSum();
+	ResetDisableRomCheck();
+	ResetDisableRamTest();
+	ResetWantDisasm();
+	ResetDbgLogHAVE();
+	ResetAbnormalReports();
+	ResetScreenVSync();
+	ResetGraphicsSwitching();
+	ResetSigning();
+	ResetSandbox();
+}
+
+LOCALFUNC tMyErr TryAsSPOptionNot(void)
+{
+	tMyErr err;
+
+	if (kMyErrNoMatch == (err = TryAsModelOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsHResOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsVResOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsScrnDpthOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsInitFullScreenNot()))
+	if (kMyErrNoMatch == (err = TryAsVarFullScreenNot()))
+	if (kMyErrNoMatch == (err = TryAsMagFctrOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsInitMagnifyNot()))
+	if (kMyErrNoMatch == (err = TryAsSoundOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsSndApiOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsSoundSampSzOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsNumDrivesOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsSonySupportTagsNot()))
+	if (kMyErrNoMatch == (err = TryAsSonyWantChecksumsUpdatedNot()))
+	if (kMyErrNoMatch == (err = TryAsSonySupportDC42Not()))
+	if (kMyErrNoMatch == (err = TryAsSaveDialogEnable()))
+	if (kMyErrNoMatch == (err = TryAsInsertIthDisk()))
+	if (kMyErrNoMatch == (err = TryAsCmndOptSwapNot()))
+	if (kMyErrNoMatch == (err = TryAsKeyMapOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsEKTMapOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsAltKeysModeNot()))
+	if (kMyErrNoMatch == (err = TryAsItnlKyBdFixNot()))
+	if (kMyErrNoMatch == (err = TryAsLocalTalkNot()))
+	if (kMyErrNoMatch == (err = TryAsInitSpeedOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsInitBackgroundNot()))
+	if (kMyErrNoMatch == (err = TryAsInitAutoSlowNot()))
+	if (kMyErrNoMatch == (err = TryAsTimingAccuracyOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsEmCpuVersOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsMemSizOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsCaretBlinkTimeOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsDoubleClickTimeOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsMenuBlinkOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsAutoKeyThreshOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsAutoKeyRateOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsHilColRedOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsHilColGreenOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsHilColBlueOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsAutoLocationNot()))
+	if (kMyErrNoMatch == (err = TryAsInitLatitudeOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsInitLongitudeOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsAutoTimeZoneNot()))
+	if (kMyErrNoMatch == (err = TryAsTzDSTNot()))
+	if (kMyErrNoMatch == (err = TryAsTzDeltHOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsTzDeltSOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsSpeakerVolOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsWantMinExtnNot()))
+	if (kMyErrNoMatch == (err = TryAsMouseMotionOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsGrabKeysFSNot()))
+	if (kMyErrNoMatch == (err = TryAsEnblCtrlIntNot()))
+	if (kMyErrNoMatch == (err = TryAsEnblCtrlRstNot()))
+	if (kMyErrNoMatch == (err = TryAsEnblCtrlKtgNot()))
+	if (kMyErrNoMatch == (err = TryAsWantColorImageNot()))
+	if (kMyErrNoMatch == (err = TryAsAltHappyMacOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsRomSizeOptionNot()))
+	if (kMyErrNoMatch == (err = TryAsCheckRomCheckSumNot()))
+	if (kMyErrNoMatch == (err = TryAsDisableRomCheckNot()))
+	if (kMyErrNoMatch == (err = TryAsDisableRamTestNot()))
+	if (kMyErrNoMatch == (err = TryAsWantDisasmNot()))
+	if (kMyErrNoMatch == (err = TryAsDbgLogHAVENot()))
+	if (kMyErrNoMatch == (err = TryAsAbnormalReportsNot()))
+	if (kMyErrNoMatch == (err = TryAsScreenVSyncNot()))
+	if (kMyErrNoMatch == (err = TryAsGraphicsSwitchingNot()))
+	if (kMyErrNoMatch == (err = TryAsSigningNot()))
+	if (kMyErrNoMatch == (err = TryAsSandboxNot()))
+	{
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr AutoChooseSPSettings(void)
+{
+	tMyErr err;
+
+	if (kMyErr_noErr == (err = ChooseModel()))
+	if (kMyErr_noErr == (err = ChooseHRes()))
+	if (kMyErr_noErr == (err = ChooseVRes()))
+	if (kMyErr_noErr == (err = ChooseScrnDpth()))
+	if (kMyErr_noErr == (err = ChooseInitFullScreen()))
+	if (kMyErr_noErr == (err = ChooseVarFullScreen()))
+	if (kMyErr_noErr == (err = ChooseMagFctr()))
+	if (kMyErr_noErr == (err = ChooseInitMagnify()))
+	if (kMyErr_noErr == (err = ChooseSoundEnabled()))
+	if (kMyErr_noErr == (err = ChooseSndApiOption()))
+	if (kMyErr_noErr == (err = ChooseSoundSampSz()))
+	if (kMyErr_noErr == (err = ChooseNumDrives()))
+	if (kMyErr_noErr == (err = ChooseSonySupportTags()))
+	if (kMyErr_noErr == (err = ChooseSonyWantChecksumsUpdated()))
+	if (kMyErr_noErr == (err = ChooseSonySupportDC42()))
+	if (kMyErr_noErr == (err = ChooseSaveDialogEnable()))
+	if (kMyErr_noErr == (err = ChooseInsertIthDisk()))
+	if (kMyErr_noErr == (err = ChooseCmndOptSwap()))
+	if (kMyErr_noErr == (err = ChooseKeyMap()))
+	if (kMyErr_noErr == (err = ChooseEKTMap()))
+	if (kMyErr_noErr == (err = ChooseAltKeysMode()))
+	if (kMyErr_noErr == (err = ChooseItnlKyBdFix()))
+	if (kMyErr_noErr == (err = ChooseLocalTalk()))
+	if (kMyErr_noErr == (err = ChooseInitSpeed()))
+	if (kMyErr_noErr == (err = ChooseInitBackground()))
+	if (kMyErr_noErr == (err = ChooseInitAutoSlow()))
+	if (kMyErr_noErr == (err = ChooseTimingAccuracy()))
+	if (kMyErr_noErr == (err = ChooseEmCpuVers()))
+	if (kMyErr_noErr == (err = ChooseMemSiz()))
+	if (kMyErr_noErr == (err = ChooseMemBankSizes())) /* derived */
+	if (kMyErr_noErr == (err = ChooseCaretBlinkTime()))
+	if (kMyErr_noErr == (err = ChooseDoubleClickTime()))
+	if (kMyErr_noErr == (err = ChooseMenuBlink()))
+	if (kMyErr_noErr == (err = ChooseAutoKeyThresh()))
+	if (kMyErr_noErr == (err = ChooseAutoKeyRate()))
+	if (kMyErr_noErr == (err = ChooseHilColRed()))
+	if (kMyErr_noErr == (err = ChooseHilColGreen()))
+	if (kMyErr_noErr == (err = ChooseHilColBlue()))
+	if (kMyErr_noErr == (err = ChooseAutoLocation()))
+	if (kMyErr_noErr == (err = ChooseInitLatitude()))
+	if (kMyErr_noErr == (err = ChooseInitLongitude()))
+	if (kMyErr_noErr == (err = ChooseAutoTimeZone()))
+	if (kMyErr_noErr == (err = ChooseTzDST()))
+	/* if (kMyErr_noErr == (err = ChooseTzDeltH())) */
+	if (kMyErr_noErr == (err = ChooseTzDeltS()))
+	if (kMyErr_noErr == (err = ChooseSpeakerVol()))
+	if (kMyErr_noErr == (err = ChooseWantMinExtn()))
+	if (kMyErr_noErr == (err = ChooseMouseMotion()))
+	if (kMyErr_noErr == (err = ChooseGrabKeysFS()))
+	if (kMyErr_noErr == (err = ChooseEnblCtrlInt()))
+	if (kMyErr_noErr == (err = ChooseEnblCtrlRst()))
+	if (kMyErr_noErr == (err = ChooseEnblCtrlKtg()))
+	if (kMyErr_noErr == (err = ChooseWantColorImage()))
+	if (kMyErr_noErr == (err = ChooseAltHappyMac()))
+	if (kMyErr_noErr == (err = ChooseRomSize()))
+	if (kMyErr_noErr == (err = ChooseCheckRomCheckSum()))
+	if (kMyErr_noErr == (err = ChooseDisableRomCheck()))
+	if (kMyErr_noErr == (err = ChooseDisableRamTest()))
+
+	if (kMyErr_noErr == (err = ChooseWantDisasm()))
+	if (kMyErr_noErr == (err = ChooseDbgLogHAVE()))
+	if (kMyErr_noErr == (err = ChooseAbnormalReports()))
+	if (kMyErr_noErr == (err = ChooseScreenVSync()))
+	if (kMyErr_noErr == (err = ChooseGraphicsSwitching()))
+	if (kMyErr_noErr == (err = ChooseSigning()))
+	if (kMyErr_noErr == (err = ChooseSandbox()))
+
+	if (kMyErr_noErr == (err = ChooseScreenOpts())) /* derived */
+	if (kMyErr_noErr == (err = ChooseVidMemSize())) /* derived */
+	if (kMyErr_noErr == (err = ChooseMiscEmHardware())) /* derived */
+	if (kMyErr_noErr == (err = ChooseTotMemSize())) /* derived */
+	{
+		err = kMyErr_noErr;
+	}
+
+	return err;
+}
+
+LOCALPROC WrtOptSPSettings(void)
+{
+	WrtOptModelOption();
+	WrtOptHResOption();
+	WrtOptVResOption();
+	WrtOptScrnDpth();
+	WrtOptInitFullScreen();
+	WrtOptVarFullScreen();
+	WrtOptMagFctrOption();
+	WrtOptInitMagnify();
+	WrtOptSoundOption();
+	WrtOptSndApiOption();
+	WrtOptSoundSampSzOption();
+	WrtOptNumDrivesOption();
+	WrtOptSonySupportTags();
+	WrtOptSonyWantChecksumsUpdated();
+	WrtOptSonySupportDC42();
+	WrtOptSaveDialogEnable();
+	WrtOptInsertIthDisk();
+	WrtOptCmndOptSwap();
+	WrtOptKeyMap();
+	WrtOptEKTMap();
+	WrtOptAltKeysMode();
+	WrtOptItnlKyBdFix();
+	WrtOptLocalTalk();
+	WrtOptInitSpeedOption();
+	WrtOptInitBackground();
+	WrtOptInitAutoSlow();
+	WrtOptTimingAccuracy();
+	WrtOptEmCpuVers();
+	WrtOptMemSizOption();
+	WrtOptCaretBlinkTime();
+	WrtOptDoubleClickTime();
+	WrtOptMenuBlink();
+	WrtOptAutoKeyThresh();
+	WrtOptAutoKeyRate();
+	WrtOptHilColRed();
+	WrtOptHilColGreen();
+	WrtOptHilColBlue();
+	WrtOptAutoLocation();
+	WrtOptInitLatitude();
+	WrtOptInitLongitude();
+	WrtOptAutoTimeZone();
+	WrtOptTzDST();
+	/* WrtOptTzDeltH(); */
+	WrtOptTzDeltS();
+	WrtOptSpeakerVol();
+	WrtOptMinExtn();
+	WrtOptMouseMotion();
+	WrtOptGrabKeysFS();
+	WrtOptEnblCtrlInt();
+	WrtOptEnblCtrlRst();
+	WrtOptEnblCtrlKtg();
+	WrtOptColorImage();
+	WrtOptAltHappyMac();
+	WrtOptRomSize();
+	WrtOptCheckRomCheckSum();
+	WrtOptDisableRomCheck();
+	WrtOptDisableRamTest();
+	WrtOptWantDisasmNot();
+	WrtOptDbgLogHAVE();
+	WrtOptAbnormalReports();
+	WrtOptScreenVSync();
+	WrtOptGraphicsSwitching();
+	WrtOptSigning();
+	WrtOptSandbox();
+}
--- /dev/null
+++ b/setup/SPCNFGAP.i
@@ -1,0 +1,286 @@
+/*
+	SPCNFGAP.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	program SPecific CoNFiGuration of API users
+
+	(that is, configuration settings that are used
+	only by platform specific code)
+*/
+
+
+LOCALPROC WriteAppSpecificCNFGRAPIoptions(void)
+{
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define RomFileName \"");
+	switch (cur_mdl) {
+		case gbk_mdl_Twig43:
+			WriteCStrToDestFile("Twig43.ROM");
+			break;
+		case gbk_mdl_Twiggy:
+			WriteCStrToDestFile("Twiggy.ROM");
+			break;
+		case gbk_mdl_128K:
+			WriteCStrToDestFile("Mac128K.ROM");
+			break;
+		case gbk_mdl_SE:
+			WriteCStrToDestFile("MacSE.ROM");
+			break;
+		case gbk_mdl_SEFDHD:
+			WriteCStrToDestFile("SEFDHD.ROM");
+			break;
+		case gbk_mdl_Classic:
+			WriteCStrToDestFile("Classic.ROM");
+			break;
+		case gbk_mdl_PB100:
+			WriteCStrToDestFile("PB100.ROM");
+			break;
+		case gbk_mdl_II:
+			WriteCStrToDestFile("MacII.ROM");
+			break;
+		case gbk_mdl_IIx:
+			WriteCStrToDestFile("MacIIx.ROM");
+			break;
+		case gbk_mdl_512Ke:
+		case gbk_mdl_Plus:
+		default:
+			WriteCStrToDestFile("vMac.ROM");
+			break;
+	}
+	WriteCStrToDestFile("\"");
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define kCheckSumRom_Size ");
+	if (gbk_mdl_Classic == cur_mdl) {
+		WriteCStrToDestFile("0x040000"); /* 256 KB */
+	} else {
+		WriteCStrToDestFile("0x");
+		WriteHexLongToOutput(1UL << cur_RomSize);
+	}
+	WriteEndDestFileLn();
+
+	switch (cur_mdl) {
+		case gbk_mdl_Twig43:
+			WriteDestFileLn("#define kRomCheckSum1 0x27F4E04B");
+			break;
+		case gbk_mdl_Twiggy:
+			WriteDestFileLn("#define kRomCheckSum1 0x2884371D");
+			break;
+		case gbk_mdl_128K:
+			WriteDestFileLn("#define kRomCheckSum1 0x28BA61CE");
+			WriteDestFileLn("#define kRomCheckSum2 0x28BA4E50");
+			break;
+		case gbk_mdl_SE:
+			WriteDestFileLn("#define kRomCheckSum1 0xB2E362A8");
+			break;
+		case gbk_mdl_SEFDHD:
+			WriteDestFileLn("#define kRomCheckSum1 0xB306E171");
+			break;
+		case gbk_mdl_Classic:
+			WriteDestFileLn("#define kRomCheckSum1 0xA49F9914");
+			break;
+		case gbk_mdl_PB100:
+			WriteDestFileLn("#define kRomCheckSum1 0x96645F9C");
+			break;
+		case gbk_mdl_II:
+			WriteDestFileLn("#define kRomCheckSum1 0x9779D2C4");
+			WriteDestFileLn("#define kRomCheckSum2 0x97221136");
+			break;
+		case gbk_mdl_IIx:
+			WriteDestFileLn("#define kRomCheckSum1 0x97221136");
+			break;
+		case gbk_mdl_512Ke:
+		case gbk_mdl_Plus:
+		default:
+			WriteDestFileLn("#define kRomCheckSum1 0x4D1EEEE1");
+				/* Mac Plus ROM v 1, 'Lonely Hearts' */
+			WriteDestFileLn("#define kRomCheckSum2 0x4D1EEAE1");
+				/* Mac Plus ROM v 2, 'Lonely Heifers' */
+			WriteDestFileLn("#define kRomCheckSum3 0x4D1F8172");
+				/* Mac Plus ROM v 3, 'Loud Harmonicas' */
+			break;
+	}
+
+	if (! WantCheckRomCheckSum) {
+		WriteCompCondBool("CheckRomCheckSum", WantCheckRomCheckSum);
+	}
+
+	WriteCompCondBool("RomStartCheckSum", (cur_mdl >= gbk_mdl_Twiggy));
+
+	if (DbgLogHAVE) {
+		WriteDefineUimr("dbglog_buflnsz", dbglog_buflnsz);
+	}
+
+	if (gbk_targfam_wnce == gbo_targfam) {
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("#define EnableShellLinks 0");
+		WriteDestFileLn("#define EnableDragDrop 0");
+		WriteDestFileLn("#define UseTimerThread 0");
+	} else if (gbk_targfam_lnds == gbo_targfam) {
+		WriteDestFileLn("#define EnableDragDrop 0");
+	} else {
+		WriteDestFileLn("#define EnableDragDrop 1");
+	}
+	WriteCompCondBool("SaveDialogEnable", gbo_SaveDialogEnable);
+	WriteCompCondBool("EnableAltKeysMode", WantAltKeysMode);
+	{
+		uimr i;
+
+		for (i = 0; i < kNumSrcKeyNames; ++i) {
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("#define MKC_formac_");
+			WriteCStrToDestFile(GetSrcKeyMapName(i));
+			WriteCStrToDestFile(" MKC_");
+			WriteCStrToDestFile(GetDstKeyMapName(gbo_keymap[i]));
+			WriteEndDestFileLn();
+		}
+	}
+
+	if (gbk_keynam_Control == ControlModeKey) {
+		/* kStrCntrlKyName */
+	} else {
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("#define kControlModeKey \"");
+		WriteCStrToDestFile(GetSrcKeyMapName(ControlModeKey));
+		WriteCStrToDestFile("\"");
+		WriteEndDestFileLn();
+	}
+
+	if (gbk_keynam_Control == gbo_EKTMap) {
+		/* kStrCntrlKyName */
+	} else {
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("#define kUnMappedKey \"");
+		WriteCStrToDestFile(GetDstKeyMapName(gbo_EKTMap));
+		WriteCStrToDestFile("\"");
+		WriteEndDestFileLn();
+	}
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define MKC_UnMappedKey ");
+	WriteCStrToDestFile(" MKC_");
+	WriteCStrToDestFile(GetDstKeyMapName(gbo_EKTMap));
+	WriteEndDestFileLn();
+
+	WriteCompCondBool("VarFullScreen", WantVarFullScreen);
+	if (WantVarFullScreen) {
+		WriteCompCondBool("WantInitFullScreen", WantInitFullScreen);
+	}
+	WriteCompCondBool("MayFullScreen",
+		WantVarFullScreen || WantInitFullScreen);
+	WriteCompCondBool("MayNotFullScreen",
+		WantVarFullScreen || ! WantInitFullScreen);
+
+	WriteCompCondBool("WantInitMagnify", WantInitMagnify);
+
+	WriteCompCondBool("EnableMagnify", 1 != cur_MagFctr);
+	if (1 != cur_MagFctr) {
+		WriteDefineUimr("MyWindowScale", cur_MagFctr);
+	}
+
+	if (nanblnr != WantColorImage) {
+		WriteCompCondBool("UseColorImage", WantColorImage);
+	}
+
+	WriteCompCondBool("WantInitRunInBackground", WantInitBackground);
+	WriteCompCondBool("WantInitNotAutoSlow", ! WantInitAutoSlow);
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define WantInitSpeedValue ");
+	if (gbk_speed_AllOut == CurInitSpeed) {
+		WriteCStrToDestFile("-1");
+	} else {
+		WriteUnsignedToOutput(CurInitSpeed - 1);
+	}
+	WriteEndDestFileLn();
+
+	if (WantScreenVSync) {
+		WriteDestFileLn("#define UseAGLdoublebuff 1");
+	}
+
+	if (WantGraphicsSwitching) {
+		WriteDestFileLn("#define WantGraphicsSwitching 1");
+	}
+
+	if (! WantGrabKeysFS) {
+		WriteDestFileLn("#define GrabKeysFullScreen 0");
+	}
+
+	WriteCompCondBool("WantEnblCtrlInt", WantEnblCtrlInt);
+	WriteCompCondBool("WantEnblCtrlRst", WantEnblCtrlRst);
+	WriteCompCondBool("WantEnblCtrlKtg", WantEnblCtrlKtg);
+
+	WriteCompCondBool("NeedRequestInsertDisk",
+		(gbk_apifam_gtk == gbo_apifam)
+		|| (gbk_apifam_mac == gbo_apifam)
+		|| (gbk_apifam_win == gbo_apifam)
+		|| (gbk_apifam_osx == gbo_apifam)
+		|| (gbk_apifam_cco == gbo_apifam)
+		);
+
+	if (WantInsertIthDisk) {
+		WriteDestFileLn("#define NeedRequestIthDisk 1");
+	}
+
+	WriteCompCondBool("NeedDoMoreCommandsMsg",
+		(gbk_apifam_gtk == gbo_apifam)
+		|| (gbk_apifam_mac == gbo_apifam)
+		|| (gbk_apifam_win == gbo_apifam)
+		|| (gbk_apifam_osx == gbo_apifam)
+		|| (gbk_apifam_cco == gbo_apifam)
+		);
+	WriteCompCondBool("NeedDoAboutMsg",
+		(gbk_apifam_gtk == gbo_apifam)
+		|| (gbk_apifam_mac == gbo_apifam)
+		|| (gbk_apifam_win == gbo_apifam)
+		|| (gbk_apifam_osx == gbo_apifam)
+		|| (gbk_apifam_cco == gbo_apifam)
+		);
+	WriteCompCondBool("UseControlKeys", trueblnr);
+	WriteCompCondBool("UseActvCode", WantActvCode);
+	WriteCompCondBool("EnableDemoMsg", WantDemoMsg);
+
+	if (WantActvCode) {
+		int i;
+
+		WriteBlankLineToDestFile();
+		for (i = 0; i < NumKeyCon; ++i) {
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("#define KeyCon");
+			WriteUnsignedToOutput(i);
+			WriteSpaceToDestFile();
+			WriteUnsignedToOutput(KeyCon[i]);
+			WriteEndDestFileLn();
+		}
+	}
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("/* version and other info to display to user */");
+
+	WriteBlankLineToDestFile();
+
+	WriteCompCondBool("NeedIntlChars",
+		(gbk_lang_eng != gbo_lang) || NeedIntl);
+	if (gbk_apifam_win == gbo_apifam) {
+		WriteCompCondBool("ItnlKyBdFix", ItnlKyBdFix);
+	}
+	WriteCDefQuote("kStrAppName", WriteStrAppUnabrevName);
+	WriteCDefQuote("kAppVariationStr", WriteAppVariationStr);
+	WriteCDefQuote("kStrCopyrightYear", WriteAppCopyrightYearStr);
+	WriteCDefQuote("kMaintainerName", WriteMaintainerName);
+	WriteCDefQuote("kStrHomePage", WriteHomePage);
+}
--- /dev/null
+++ b/setup/SPCNFGGL.i
@@ -1,0 +1,103 @@
+/*
+	SPCNFGGL.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	program SPecific CoNFiGuration GLobals
+*/
+
+LOCALPROC WriteAppSpecificCNFGGLOBoptions(void)
+{
+	WriteBlankLineToDestFile();
+
+	WriteCompCondBool("MySoundRecenterSilence", falseblnr);
+
+	WriteDefineUimr("kLn2SoundSampSz", cur_SoundSampSz);
+
+	WriteBlankLineToDestFile();
+
+#if 0 /* not used currently */
+	WriteCompCondBool("Debug", gbk_dbg_off != gbo_dbg);
+#endif
+
+	WriteCompCondBool("dbglog_HAVE", DbgLogHAVE);
+
+	WriteCompCondBool("WantAbnormalReports", gbo_AbnormalReports);
+
+	WriteBlankLineToDestFile();
+
+	WriteDefineUimr("NumDrives", cur_numdrives);
+
+	WriteCompCondBool("IncludeSonyRawMode", (! WantMinExtn)
+		&& (gbk_apifam_nds != gbo_apifam));
+	WriteCompCondBool("IncludeSonyGetName",
+		(! WantMinExtn) && (gbk_apifam_gtk != gbo_apifam)
+		&& (gbk_apifam_nds != gbo_apifam)
+		&& (gbk_apifam_sdl != gbo_apifam)
+		&& (gbk_apifam_sd2 != gbo_apifam));
+	WriteCompCondBool("IncludeSonyNew",
+		(! WantMinExtn) && (gbk_apifam_gtk != gbo_apifam)
+		&& (gbk_apifam_sdl != gbo_apifam)
+		&& (gbk_apifam_sd2 != gbo_apifam)
+		&& (gbk_apifam_nds != gbo_apifam));
+	WriteCompCondBool("IncludeSonyNameNew",
+		(! WantMinExtn) && (gbk_apifam_gtk != gbo_apifam)
+		&& (gbk_apifam_sdl != gbo_apifam)
+		&& (gbk_apifam_sd2 != gbo_apifam)
+		&& (gbk_apifam_nds != gbo_apifam));
+
+	WriteBlankLineToDestFile();
+
+	WriteDefineUimr("vMacScreenHeight", cur_vres);
+	WriteDefineUimr("vMacScreenWidth", cur_hres);
+	WriteDefineUimr("vMacScreenDepth", cur_ScrnDpth);
+
+
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define kROM_Size ");
+	WriteCStrToDestFile("0x");
+	WriteHexLongToOutput(1UL << cur_RomSize);
+	WriteEndDestFileLn();
+
+
+	WriteBlankLineToDestFile();
+
+	WriteCompCondBool("IncludePbufs",
+		1 /* ((! WantMinExtn) || WantActvCode || WantDemoMsg) */
+			&& (gbk_apifam_gtk != gbo_apifam)
+			&& (gbk_apifam_nds != gbo_apifam));
+
+	WriteDefineUimr("NumPbufs", 4);
+
+
+	WriteBlankLineToDestFile();
+
+	WriteCompCondBool("EnableMouseMotion", MyMouseMotion);
+
+	WriteBlankLineToDestFile();
+
+	WriteCompCondBool("IncludeHostTextClipExchange",
+		1 /* ((! WantMinExtn) || WantActvCode || WantDemoMsg) */
+			&& (gbk_apifam_gtk != gbo_apifam)
+			&& (gbk_apifam_sdl != gbo_apifam)
+			&& (gbk_apifam_nds != gbo_apifam));
+
+	WriteDestFileLn("#define EnableAutoSlow 1");
+	WriteCompCondBool("EmLocalTalk", WantLocalTalk);
+
+	WriteCompCondBool("AutoLocation", WantAutoLocation);
+	WriteCompCondBool("AutoTimeZone", WantAutoTimeZone);
+}
--- /dev/null
+++ b/setup/SPFILDEF.i
@@ -1,0 +1,296 @@
+/*
+	SPFILDEF.i
+	Copyright (C) 2012 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	program SPecific FILe DEFinitions
+*/
+
+
+
+/* --- list of source files --- */
+
+static void DoMYOSGLUEdepends(tDoOneDepends p)
+{
+	{
+		char *s = nullpr;
+
+		switch (gbo_lang) {
+			case gbk_lang_eng:
+				s = "STRCNENG.h";
+				break;
+			case gbk_lang_fre:
+				s = "STRCNFRE.h";
+				break;
+			case gbk_lang_ita:
+				s = "STRCNITA.h";
+				break;
+			case gbk_lang_ger:
+				s = "STRCNGER.h";
+				break;
+			case gbk_lang_dut:
+				s = "STRCNDUT.h";
+				break;
+			case gbk_lang_spa:
+				s = "STRCNSPA.h";
+				break;
+			case gbk_lang_pol:
+				s = "STRCNPOL.h";
+				break;
+			case gbk_lang_ptb:
+				s = "STRCNPTB.h";
+				break;
+			case gbk_lang_cat:
+				s = "STRCNCAT.h";
+				break;
+			case gbk_lang_cze:
+				s = "STRCNCZE.h";
+				break;
+			case gbk_lang_srl:
+				s = "STRCNSRL.h";
+				break;
+		}
+
+		if (nullpr != s) {
+			p(kDepDirCSrc, s);
+		}
+	}
+
+	p(kDepDirCnfg, "STRCONST.h");
+	p(kDepDirCSrc, "INTLCHAR.h");
+	p(kDepDirCSrc, "COMOSGLU.h");
+	if (WantLocalTalk) {
+		p(kDepDirCSrc, "BPFILTER.h");
+	}
+	if (WantAltKeysMode) {
+		p(kDepDirCSrc, "ALTKEYSM.h");
+	}
+	p(kDepDirCSrc, "CONTROLM.h");
+	if (gbk_sndapi_none != gbo_sndapi) {
+		{
+			char *s = nullpr;
+
+			switch (gbo_sndapi) {
+				case gbk_sndapi_alsa:
+					s = "SGLUALSA.h";
+					break;
+				case gbk_sndapi_ddsp:
+					s = "SGLUDDSP.h";
+					break;
+			}
+
+			if (nullpr != s) {
+				p(kDepDirCSrc, s);
+			}
+		}
+		p(kDepDirCnfg, "SOUNDGLU.h");
+	}
+}
+
+static void DoMINEM68Kdepends(tDoOneDepends p)
+{
+	if (cur_mIIorIIX) {
+		p(kDepDirCSrc, "FPMATHEM.h");
+		p(kDepDirCSrc, "FPCPEMDV.h");
+	}
+}
+
+static void DoROMEMDEVdepends(tDoOneDepends p)
+{
+	if (NeedScrnHack) {
+		p(kDepDirCSrc, "SCRNHACK.h");
+	}
+	if (gbk_AHM_none != cur_AltHappyMac) {
+		p(kDepDirCSrc, "HPMCHACK.h");
+	}
+}
+
+static void DoAllSrcFiles(tDoOneCFile p)
+{
+	blnr WantSCRNMAPR = (gbk_apifam_osx == gbo_apifam)
+		|| (gbk_apifam_mac == gbo_apifam)
+		|| (gbk_apifam_cco == gbo_apifam)
+		|| (gbk_apifam_xwn == gbo_apifam)
+		|| (gbk_apifam_9dr == gbo_apifam)
+		|| (gbk_apifam_sdl == gbo_apifam)
+		|| (gbk_apifam_sd2 == gbo_apifam);
+	blnr WantSCRNTRNS = WantSCRNMAPR && (cur_ScrnDpth != 0);
+
+	p("CNFGRAPI", kDepDirCnfg, kCSrcFlgmNoSource, nullpr);
+	p("CNFGGLOB", kDepDirCnfg, kCSrcFlgmNoSource, nullpr);
+	p("SYSDEPNS", kDepDirCSrc, kCSrcFlgmNoSource, nullpr);
+	p("ENDIANAC", kDepDirCSrc, kCSrcFlgmNoSource, nullpr);
+	p("MYOSGLUE", kDepDirCSrc, kCSrcFlgmNoSource, nullpr);
+
+	p("STRCNENG", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(gbk_lang_eng == gbo_lang), nullpr);
+	p("STRCNFRE", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(gbk_lang_fre == gbo_lang), nullpr);
+	p("STRCNITA", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(gbk_lang_ita == gbo_lang), nullpr);
+	p("STRCNGER", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(gbk_lang_ger == gbo_lang), nullpr);
+	p("STRCNDUT", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(gbk_lang_dut == gbo_lang), nullpr);
+	p("STRCNSPA", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(gbk_lang_spa == gbo_lang), nullpr);
+	p("STRCNPOL", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(gbk_lang_pol == gbo_lang), nullpr);
+	p("STRCNPTB", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(gbk_lang_ptb == gbo_lang), nullpr);
+	p("STRCNCAT", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(gbk_lang_cat == gbo_lang), nullpr);
+	p("STRCNCZE", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(gbk_lang_cze == gbo_lang), nullpr);
+	p("STRCNSRL", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(gbk_lang_srl == gbo_lang), nullpr);
+
+	p("STRCONST", kDepDirCnfg, kCSrcFlgmNoSource, nullpr);
+	p("INTLCHAR", kDepDirCSrc, kCSrcFlgmNoSource, nullpr);
+	p("COMOSGLU", kDepDirCSrc, kCSrcFlgmNoSource, nullpr);
+	p("BPFILTER", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(WantLocalTalk), nullpr);
+	p("ALTKEYSM", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(WantAltKeysMode), nullpr);
+	p("ACTVCODE", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(WantActvCode), nullpr);
+	p("CONTROLM", kDepDirCSrc, kCSrcFlgmNoSource, nullpr);
+	p("PBUFSTDC", kDepDirCSrc,
+		CSrcFlagsUseHdrIf((gbk_apifam_xwn == gbo_apifam)
+			|| (gbk_apifam_sd2 == gbo_apifam)
+			|| (gbk_apifam_9dr == gbo_apifam)
+			|| (gbk_apifam_sdl == gbo_apifam)
+			),
+		nullpr);
+	p("SCRNMAPR", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(WantSCRNMAPR), nullpr);
+	p("SCRNTRNS", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(WantSCRNTRNS), nullpr);
+	p("DATE2SEC", kDepDirCSrc, kCSrcFlgmNoSource, nullpr);
+
+	p("SGLUALSA", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(gbk_sndapi_alsa == gbo_sndapi), nullpr);
+	p("SGLUDDSP", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(gbk_sndapi_ddsp == gbo_sndapi), nullpr);
+
+	p("SOUNDGLU", kDepDirCnfg,
+		CSrcFlagsUseHdrIf(gbk_sndapi_none != gbo_sndapi), nullpr);
+
+	p("OSGLUMAC", kDepDirCSrc,
+		kCSrcFlgmUseAPI
+			| CSrcFlagsUseSrcIf(gbk_apifam_mac == gbo_apifam),
+		DoMYOSGLUEdepends);
+	p("OSGLUOSX", kDepDirCSrc,
+		kCSrcFlgmUseAPI
+			| CSrcFlagsUseSrcIf(gbk_apifam_osx == gbo_apifam),
+		DoMYOSGLUEdepends);
+	p("OSGLUWIN", kDepDirCSrc,
+		kCSrcFlgmUseAPI
+			| CSrcFlagsUseSrcIf(gbk_apifam_win == gbo_apifam),
+		DoMYOSGLUEdepends);
+	p("OSGLUXWN", kDepDirCSrc,
+		kCSrcFlgmUseAPI
+			| CSrcFlagsUseSrcIf(gbk_apifam_xwn == gbo_apifam),
+		DoMYOSGLUEdepends);
+	p("OSGLUNDS", kDepDirCSrc,
+		kCSrcFlgmUseAPI
+			| CSrcFlagsUseSrcIf(gbk_apifam_nds == gbo_apifam),
+		DoMYOSGLUEdepends);
+	p("OSGLUGTK", kDepDirCSrc,
+		kCSrcFlgmUseAPI
+			| CSrcFlagsUseSrcIf(gbk_apifam_gtk == gbo_apifam),
+		DoMYOSGLUEdepends);
+	p("OSPLAN9", kDepDirCSrc,
+		kCSrcFlgmUseAPI
+			| CSrcFlagsUseSrcIf(gbk_apifam_9dr == gbo_apifam),
+		DoMYOSGLUEdepends);
+	p("OSGLUSDL", kDepDirCSrc,
+		kCSrcFlgmUseAPI
+			| CSrcFlagsUseSrcIf(gbk_apifam_sdl == gbo_apifam),
+		DoMYOSGLUEdepends);
+	p("OSGLUSD2", kDepDirCSrc,
+		kCSrcFlgmUseAPI
+			| CSrcFlagsUseSrcIf(gbk_apifam_sd2 == gbo_apifam),
+		DoMYOSGLUEdepends);
+	p("OSGLUCCO", kDepDirCSrc,
+		kCSrcFlgmUseAPI | kCSrcFlgmOjbc
+			| CSrcFlagsUseSrcIf(gbk_apifam_cco == gbo_apifam),
+		DoMYOSGLUEdepends);
+
+	p("EMCONFIG", kDepDirCnfg, kCSrcFlgmNoSource, nullpr);
+	p("GLOBGLUE", kDepDirCSrc, kCSrcFlgmNone, nullpr);
+	p("M68KITAB", kDepDirCSrc, kCSrcFlgmNone, nullpr);
+	p("DISAM68K", kDepDirCSrc, CSrcFlagsUseIf(WantDisasm), nullpr);
+	p("FPMATHEM", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(cur_mIIorIIX),
+		nullpr);
+	p("FPCPEMDV", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(cur_mIIorIIX),
+		nullpr);
+
+	p("MINEM68K", kDepDirCSrc, kCSrcFlgmSortFirst, DoMINEM68Kdepends);
+		/*
+			Put the most speed critical part of the
+			program first, to help ensure consistent
+			alignment for it, regardless of changes
+			to rest of program.
+			Speed can depend subtly, basically
+			randomly, on how code is aligned.
+		*/
+
+	p("VIAEMDEV", kDepDirCSrc, kCSrcFlgmNone, nullpr);
+	p("VIA2EMDV", kDepDirCSrc, CSrcFlagsUseIf(EmVIA2), nullpr);
+	p("IWMEMDEV", kDepDirCSrc, kCSrcFlgmNone, nullpr);
+	p("SCCEMDEV", kDepDirCSrc, kCSrcFlgmNone, nullpr);
+	p("RTCEMDEV", kDepDirCSrc, CSrcFlagsUseIf(EmRTC), nullpr);
+	p("SCRNHACK", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(NeedScrnHack), nullpr);
+	p("HPMCHACK", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(gbk_AHM_none != cur_AltHappyMac), nullpr);
+	p("ROMEMDEV", kDepDirCSrc, kCSrcFlgmNone, DoROMEMDEVdepends);
+	p("SCSIEMDV", kDepDirCSrc, kCSrcFlgmNone, nullpr);
+	p("SONYEMDV", kDepDirCSrc, kCSrcFlgmNone, nullpr);
+	p("SCRNEMDV", kDepDirCSrc, kCSrcFlgmNone, nullpr);
+	p("VIDEMDEV", kDepDirCSrc, CSrcFlagsUseIf(EmVidCard), nullpr);
+	p("MOUSEMDV", kDepDirCSrc, kCSrcFlgmNone, nullpr);
+	p("KBRDEMDV", kDepDirCSrc, CSrcFlagsUseIf(EmClassicKbrd), nullpr);
+	p("ADBSHARE", kDepDirCSrc,
+		CSrcFlagsUseHdrIf(cur_mdl >= gbk_mdl_SE), nullpr);
+	p("ADBEMDEV", kDepDirCSrc, CSrcFlagsUseIf(EmADB), nullpr);
+	p("PMUEMDEV", kDepDirCSrc, CSrcFlagsUseIf(EmPMU), nullpr);
+	p("ASCEMDEV", kDepDirCSrc, CSrcFlagsUseIf(EmASC), nullpr);
+	p("SNDEMDEV", kDepDirCSrc,
+		CSrcFlagsUseIf((! EmASC) && (gbk_mdl_PB100 != cur_mdl)
+			&& MySoundEnabled),
+		nullpr);
+	p("PROGMAIN", kDepDirCSrc, kCSrcFlgmNone, nullpr);
+}
+
+/* --- list of document types --- */
+
+static void WriteRomExtensions(tWriteOneExtension p)
+{
+	p("rom");
+}
+
+static void WriteDskExtensions(tWriteOneExtension p)
+{
+	p("dsk");
+}
+
+static void DoAllDocTypes(tWriteOneDocType p)
+{
+	p("ROM", "ROM!", "Rom image", WriteRomExtensions);
+	p("DSK", "MvIm", "Disk image", WriteDskExtensions);
+}
--- /dev/null
+++ b/setup/SPOTHRCF.i
@@ -1,0 +1,903 @@
+/*
+	SPOTHRCF.i
+	Copyright (C) 2008 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	program SPecific write OTHer ConFiguration files
+*/
+
+LOCALPROC WriteAppCNFGGLOBContents(void)
+{
+	WriteCommonCNFGGLOBContents();
+
+	if (cur_mIIorIIX) {
+		Write64bitConfig();
+	}
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn(
+		"/* capabilities provided by platform specific code */");
+
+	WriteBlankLineToDestFile();
+
+	WriteCompCondBool("MySoundEnabled", MySoundEnabled);
+
+	WriteAppSpecificCNFGGLOBoptions();
+}
+
+LOCALPROC WriteBldOpts(void)
+{
+	Branch = MajorVersion;
+
+	WrtOptGNSettings();
+	WrtOptSPSettings();
+}
+
+LOCALPROC WriteAppCNFGRAPIContents(void)
+{
+	WriteCommonCNFGRAPIContents();
+
+	WriteAppSpecificCNFGRAPIoptions();
+
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define kBldOpts \"");
+	WriteBldOpts();
+	WriteCStrToDestFile("\"");
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteOneWire(char *a, char *b)
+{
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("\tWire_");
+	WriteCStrToDestFile(a);
+	WriteCStrToDestFile("_");
+	WriteCStrToDestFile(b);
+	WriteCStrToDestFile(",");
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define ");
+	WriteCStrToDestFile(b);
+	WriteCStrToDestFile(" (Wires[Wire_");
+	WriteCStrToDestFile(a);
+	WriteCStrToDestFile("_");
+	WriteCStrToDestFile(b);
+	WriteCStrToDestFile("])");
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define ");
+	WriteCStrToDestFile(a);
+	WriteCStrToDestFile(" (Wires[Wire_");
+	WriteCStrToDestFile(a);
+	WriteCStrToDestFile("_");
+	WriteCStrToDestFile(b);
+	WriteCStrToDestFile("])");
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteConfigureWires(void)
+{
+	WriteDestFileLn(
+		"/* the Wire variables are 1/0, not true/false */");
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("enum {");
+	if (cur_mIIorIIX) {
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_unknown_SoundDisable,");
+		WriteDestFileLn(
+			"#define SoundDisable (Wires[Wire_unknown_SoundDisable])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_unknown_SoundVolb0,");
+		WriteDestFileLn(
+			"#define SoundVolb0 (Wires[Wire_unknown_SoundVolb0])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_unknown_SoundVolb1,");
+		WriteDestFileLn(
+			"#define SoundVolb1 (Wires[Wire_unknown_SoundVolb1])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_unknown_SoundVolb2,");
+		WriteDestFileLn(
+			"#define SoundVolb2 (Wires[Wire_unknown_SoundVolb2])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA1_iA0_unknown,");
+		WriteDestFileLn(
+			"#define VIA1_iA0 (Wires[Wire_VIA1_iA0_unknown])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA1_iA1_unknown,");
+		WriteDestFileLn(
+			"#define VIA1_iA1 (Wires[Wire_VIA1_iA1_unknown])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA1_iA2_unknown,");
+		WriteDestFileLn(
+			"#define VIA1_iA2 (Wires[Wire_VIA1_iA2_unknown])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn(
+			"\tWire_VIA1_iB7_unknown,"
+			" /* for compatibility with SoundDisable */");
+		WriteDestFileLn(
+			"#define VIA1_iB7 (Wires[Wire_VIA1_iB7_unknown])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA2_InterruptRequest,");
+		WriteDestFileLn(
+			"#define VIA2_InterruptRequest"
+			" (Wires[Wire_VIA2_InterruptRequest])");
+		WriteDestFileLn(
+			"#define VIA2_interruptChngNtfy VIAorSCCinterruptChngNtfy");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA2_iA7_unknown,");
+		WriteDestFileLn(
+			"#define VIA2_iA7 (Wires[Wire_VIA2_iA7_unknown])");
+		WriteDestFileLn(
+			"#define VIA2_iA7_ChangeNtfy Addr32_ChangeNtfy");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA2_iA6_unknown,");
+		WriteDestFileLn(
+			"#define VIA2_iA6 (Wires[Wire_VIA2_iA6_unknown])");
+		WriteDestFileLn(
+			"#define VIA2_iA6_ChangeNtfy Addr32_ChangeNtfy");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA2_iB7_unknown,");
+		WriteDestFileLn(
+			"#define VIA2_iB7 (Wires[Wire_VIA2_iB7_unknown])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA2_iCB2_unknown,");
+		WriteDestFileLn(
+			"#define VIA2_iCB2 (Wires[Wire_VIA2_iCB2_unknown])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA2_iB2_PowerOff,");
+		WriteDestFileLn(
+			"#define VIA2_iB2 (Wires[Wire_VIA2_iB2_PowerOff])");
+		WriteDestFileLn(
+			"#define VIA2_iB2_ChangeNtfy PowerOff_ChangeNtfy");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA2_iB3_Addr32,");
+		WriteDestFileLn(
+			"#define VIA2_iB3 (Wires[Wire_VIA2_iB3_Addr32])");
+		WriteDestFileLn(
+			"#define Addr32 (Wires[Wire_VIA2_iB3_Addr32])");
+		WriteDestFileLn(
+			"#define VIA2_iB3_ChangeNtfy Addr32_ChangeNtfy");
+	}
+
+	if (cur_mdl <= gbk_mdl_Classic) {
+		WriteOneWire("VIA1_iA0", "SoundVolb0");
+		WriteOneWire("VIA1_iA1", "SoundVolb1");
+		WriteOneWire("VIA1_iA2", "SoundVolb2");
+	}
+
+	if ((cur_mdl <= gbk_mdl_Plus) || cur_mIIorIIX)
+	{
+		WriteOneWire("VIA1_iA4", "MemOverlay");
+		WriteDestFileLn(
+			"#define VIA1_iA4_ChangeNtfy MemOverlay_ChangeNtfy");
+	} else {
+		if (cur_mdl <= gbk_mdl_Classic) {
+			WriteBlankLineToDestFile();
+			WriteDestFileLn("\tWire_VIA1_iA4_DriveSel,");
+			WriteDestFileLn(
+				"#define VIA1_iA4 (Wires[Wire_VIA1_iA4_DriveSel])");
+		}
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_MemOverlay,");
+		WriteDestFileLn("#define MemOverlay (Wires[Wire_MemOverlay])");
+	}
+
+	if (cur_mdl <= gbk_mdl_Classic) {
+		WriteOneWire("VIA1_iA6", "SCRNvPage2");
+	}
+
+	if (gbk_mdl_PB100 == cur_mdl) {
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_SCCwaitrq,");
+		WriteDestFileLn("#define SCCwaitrq (Wires[Wire_SCCwaitrq])");
+
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA1_iA0_PmuBus0,");
+		WriteDestFileLn("\tWire_VIA1_iA1_PmuBus1,");
+		WriteDestFileLn("\tWire_VIA1_iA2_PmuBus2,");
+		WriteDestFileLn("\tWire_VIA1_iA3_PmuBus3,");
+		WriteDestFileLn("\tWire_VIA1_iA4_PmuBus4,");
+		WriteDestFileLn("\tWire_VIA1_iA5_PmuBus5,");
+		WriteDestFileLn("\tWire_VIA1_iA6_PmuBus6,");
+		WriteDestFileLn("\tWire_VIA1_iA7_PmuBus7,");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn(
+			"#define VIA1_iA0 (Wires[Wire_VIA1_iA0_PmuBus0])");
+		WriteDestFileLn(
+			"#define VIA1_iA1 (Wires[Wire_VIA1_iA1_PmuBus1])");
+		WriteDestFileLn(
+			"#define VIA1_iA2 (Wires[Wire_VIA1_iA2_PmuBus2])");
+		WriteDestFileLn(
+			"#define VIA1_iA3 (Wires[Wire_VIA1_iA3_PmuBus3])");
+		WriteDestFileLn(
+			"#define VIA1_iA4 (Wires[Wire_VIA1_iA4_PmuBus4])");
+		WriteDestFileLn(
+			"#define VIA1_iA5 (Wires[Wire_VIA1_iA5_PmuBus5])");
+		WriteDestFileLn(
+			"#define VIA1_iA6 (Wires[Wire_VIA1_iA6_PmuBus6])");
+		WriteDestFileLn(
+			"#define VIA1_iA7 (Wires[Wire_VIA1_iA7_PmuBus7])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA1_iB0_PmuToReady,");
+		WriteDestFileLn(
+			"#define VIA1_iB0 (Wires[Wire_VIA1_iB0_PmuToReady])");
+		WriteDestFileLn(
+			"#define PmuToReady (Wires[Wire_VIA1_iB0_PmuToReady])");
+		WriteDestFileLn(
+			"#define VIA1_iB0_ChangeNtfy PmuToReady_ChangeNtfy");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA1_iB1_PmuFromReady,");
+		WriteDestFileLn(
+			"#define VIA1_iB1 (Wires[Wire_VIA1_iB1_PmuFromReady])");
+		WriteDestFileLn(
+			"#define PmuFromReady (Wires[Wire_VIA1_iB1_PmuFromReady])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA1_iB2_Unknown,");
+		WriteDestFileLn(
+			"#define VIA1_iB2 (Wires[Wire_VIA1_iB2_Unknown])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA1_iB3_Unknown,");
+		WriteDestFileLn(
+			"#define VIA1_iB3 (Wires[Wire_VIA1_iB3_Unknown])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA1_iB4_Unknown,");
+		WriteDestFileLn(
+			"#define VIA1_iB4 (Wires[Wire_VIA1_iB4_Unknown])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA1_iB5_Unknown,");
+		WriteDestFileLn(
+			"#define VIA1_iB5 (Wires[Wire_VIA1_iB5_Unknown])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA1_iB6_Unknown,");
+		WriteDestFileLn(
+			"#define VIA1_iB6 (Wires[Wire_VIA1_iB6_Unknown])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA1_iB7_Unknown,");
+		WriteDestFileLn(
+			"#define VIA1_iB7 (Wires[Wire_VIA1_iB7_Unknown])");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA1_iCB2_Unknown,");
+		WriteDestFileLn(
+			"#define VIA1_iCB2 (Wires[Wire_VIA1_iCB2_Unknown])");
+	} else {
+		WriteOneWire("VIA1_iA5", "IWMvSel");
+
+		WriteOneWire("VIA1_iA7", "SCCwaitrq");
+
+		WriteOneWire("VIA1_iB0", "RTCdataLine");
+		WriteDestFileLn(
+			"#define VIA1_iB0_ChangeNtfy RTCdataLine_ChangeNtfy");
+
+		WriteOneWire("VIA1_iB1", "RTCclock");
+		WriteDestFileLn(
+			"#define VIA1_iB1_ChangeNtfy RTCclock_ChangeNtfy");
+
+		WriteOneWire("VIA1_iB2", "RTCunEnabled");
+		WriteDestFileLn(
+			"#define VIA1_iB2_ChangeNtfy RTCunEnabled_ChangeNtfy");
+
+		if (cur_mdl <= gbk_mdl_Plus) {
+			WriteOneWire("VIA1_iA3", "SoundBuffer");
+			WriteOneWire("VIA1_iB3", "MouseBtnUp");
+			WriteOneWire("VIA1_iB4", "MouseX2");
+			WriteOneWire("VIA1_iB5", "MouseY2");
+
+			WriteBlankLineToDestFile();
+			WriteDestFileLn("\tWire_VIA1_iCB2_KybdDat,");
+			WriteDestFileLn(
+				"#define VIA1_iCB2 (Wires[Wire_VIA1_iCB2_KybdDat])");
+			WriteDestFileLn(
+				"#define VIA1_iCB2_ChangeNtfy Kybd_DataLineChngNtfy");
+		} else {
+			WriteBlankLineToDestFile();
+			WriteDestFileLn("\tWire_VIA1_iA3_SCCvSync,");
+			WriteDestFileLn(
+				"#define VIA1_iA3 (Wires[Wire_VIA1_iA3_SCCvSync])");
+
+			WriteOneWire("VIA1_iB3", "ADB_Int");
+
+			WriteOneWire("VIA1_iB4", "ADB_st0");
+			WriteDestFileLn(
+				"#define VIA1_iB4_ChangeNtfy ADBstate_ChangeNtfy");
+
+			WriteOneWire("VIA1_iB5", "ADB_st1");
+			WriteDestFileLn(
+				"#define VIA1_iB5_ChangeNtfy ADBstate_ChangeNtfy");
+
+			WriteOneWire("VIA1_iCB2", "ADB_Data");
+			WriteDestFileLn(
+				"#define VIA1_iCB2_ChangeNtfy ADB_DataLineChngNtfy");
+		}
+	}
+
+	if (cur_mdl <= gbk_mdl_Plus) {
+		WriteOneWire("VIA1_iB6", "SCRNbeamInVid");
+	} else if (cur_mdl <= gbk_mdl_Classic) {
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VIA1_iB6_SCSIintenable,");
+		WriteDestFileLn(
+			"#define VIA1_iB6 (Wires[Wire_VIA1_iB6_SCSIintenable])");
+	}
+
+	if (cur_mdl <= gbk_mdl_Classic) {
+		WriteOneWire("VIA1_iB7", "SoundDisable");
+	}
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("\tWire_VIA1_InterruptRequest,");
+	WriteDestFileLn(
+		"#define VIA1_InterruptRequest"
+		" (Wires[Wire_VIA1_InterruptRequest])");
+	WriteDestFileLn(
+		"#define VIA1_interruptChngNtfy VIAorSCCinterruptChngNtfy");
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("\tWire_SCCInterruptRequest,");
+	WriteDestFileLn(
+		"#define SCCInterruptRequest"
+		" (Wires[Wire_SCCInterruptRequest])");
+	WriteDestFileLn(
+		"#define SCCinterruptChngNtfy VIAorSCCinterruptChngNtfy");
+
+	if (cur_mdl <= gbk_mdl_Plus) {
+	} else {
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_ADBMouseDisabled,");
+		WriteDestFileLn(
+			"#define ADBMouseDisabled (Wires[Wire_ADBMouseDisabled])");
+	}
+
+	if (cur_mIIorIIX) {
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VBLinterrupt,");
+		WriteDestFileLn(
+			"#define Vid_VBLinterrupt (Wires[Wire_VBLinterrupt])");
+		WriteDestFileLn("#define VIA2_iA0 (Wires[Wire_VBLinterrupt])");
+
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("\tWire_VBLintunenbl,");
+		WriteDestFileLn(
+			"#define Vid_VBLintunenbl (Wires[Wire_VBLintunenbl])");
+	}
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("\tkNumWires");
+	WriteDestFileLn("};");
+}
+
+LOCALPROC WriteConfigureVIA1(void)
+{
+	WriteDestFileLn("/* VIA configuration */");
+
+	if (gbk_mdl_Classic == cur_mdl) {
+		WriteDestFileLn("#define VIA1_ORA_FloatVal 0xF7");
+	} else if (cur_mIIorIIX) {
+		WriteDestFileLn("#define VIA1_ORA_FloatVal 0xBF");
+		WriteDestFileLn(
+			"\t/* bit 6 used to check version of hardware */");
+	} else {
+		WriteDestFileLn("#define VIA1_ORA_FloatVal 0xFF");
+	}
+
+	WriteDestFileLn("#define VIA1_ORB_FloatVal 0xFF");
+
+	if (cur_mdl <= gbk_mdl_Classic) {
+		WriteDestFileLn("#define VIA1_ORA_CanIn 0x80");
+		WriteDestFileLn("#define VIA1_ORA_CanOut 0x7F");
+	} else if (gbk_mdl_PB100 == cur_mdl) {
+		WriteDestFileLn("#define VIA1_ORA_CanIn 0xFF");
+		WriteDestFileLn("#define VIA1_ORA_CanOut 0xFF");
+	} else if (cur_mIIorIIX) {
+		WriteDestFileLn("#define VIA1_ORA_CanIn 0x80");
+		WriteDestFileLn("#define VIA1_ORA_CanOut 0x3F");
+	} else {
+		WriteDestFileLn("#define VIA1_ORA_CanIn 0x00");
+		WriteDestFileLn("#define VIA1_ORA_CanOut 0x00");
+	}
+
+	if (cur_mdl <= gbk_mdl_Plus) {
+		WriteDestFileLn("#define VIA1_ORB_CanIn 0x79");
+		WriteDestFileLn("#define VIA1_ORB_CanOut 0x87");
+	} else if (cur_mdl <= gbk_mdl_Classic) {
+		WriteDestFileLn("#define VIA1_ORB_CanIn 0x09");
+		WriteDestFileLn("#define VIA1_ORB_CanOut 0xF7");
+	} else if (gbk_mdl_PB100 == cur_mdl) {
+		WriteDestFileLn("#define VIA1_ORB_CanIn 0x02");
+		WriteDestFileLn("#define VIA1_ORB_CanOut 0xFD");
+	} else if (cur_mIIorIIX) {
+		WriteDestFileLn("#define VIA1_ORB_CanIn 0x09");
+		WriteDestFileLn("#define VIA1_ORB_CanOut 0xB7");
+	} else {
+		WriteDestFileLn("#define VIA1_ORB_CanIn 0x00");
+		WriteDestFileLn("#define VIA1_ORB_CanOut 0x00");
+	}
+
+	if (cur_mdl <= gbk_mdl_Plus) {
+		WriteDestFileLn("#define VIA1_IER_Never0 (1 << 1)");
+		WriteDestFileLn(
+			"#define VIA1_IER_Never1 ((1 << 3) | (1 << 4))");
+	} else if (cur_mdl <= gbk_mdl_Classic) {
+		WriteDestFileLn("#define VIA1_IER_Never0 0x00");
+		WriteDestFileLn(
+			"#define VIA1_IER_Never1 ((1 << 3) | (1 << 4))");
+	} else if (gbk_mdl_PB100 == cur_mdl) {
+		WriteDestFileLn("#define VIA1_IER_Never0 0x00");
+		WriteDestFileLn("#define VIA1_IER_Never1 0x0C");
+	} else if (cur_mIIorIIX) {
+		WriteDestFileLn("#define VIA1_IER_Never0 0x00");
+		WriteDestFileLn("#define VIA1_IER_Never1 0x58");
+	} else {
+		WriteDestFileLn("#define VIA1_IER_Never0 0xFF");
+		WriteDestFileLn("#define VIA1_IER_Never1 0xFF");
+	}
+
+	if (gbk_mdl_PB100 == cur_mdl) {
+		WriteDestFileLn("#define VIA1_CB2modesAllowed 0x03");
+		WriteDestFileLn("#define VIA1_CA2modesAllowed 0x03");
+	} else {
+		WriteDestFileLn("#define VIA1_CB2modesAllowed 0x01");
+		WriteDestFileLn("#define VIA1_CA2modesAllowed 0x01");
+	}
+}
+
+LOCALPROC WriteConfigureVIA2(void)
+{
+	WriteDestFileLn("/* VIA 2 configuration */");
+
+	WriteDestFileLn("#define VIA2_ORA_FloatVal 0xFF");
+	WriteDestFileLn("#define VIA2_ORB_FloatVal 0xFF");
+
+	if (cur_mIIorIIX) {
+		WriteDestFileLn("#define VIA2_ORA_CanIn 0x01");
+		WriteDestFileLn("#define VIA2_ORA_CanOut 0xC0");
+	} else {
+		WriteDestFileLn("#define VIA2_ORA_CanIn 0x00");
+		WriteDestFileLn("#define VIA2_ORA_CanOut 0x00");
+	}
+
+	if (cur_mIIorIIX) {
+		WriteDestFileLn("#define VIA2_ORB_CanIn 0x00");
+		WriteDestFileLn("#define VIA2_ORB_CanOut 0x8C");
+	} else {
+		WriteDestFileLn("#define VIA2_ORB_CanIn 0x00");
+		WriteDestFileLn("#define VIA2_ORB_CanOut 0x00");
+	}
+
+	if (cur_mIIorIIX) {
+		WriteDestFileLn("#define VIA2_IER_Never0 0x00");
+		WriteDestFileLn("#define VIA2_IER_Never1 0xED");
+	} else {
+		WriteDestFileLn("#define VIA2_IER_Never0 0xFF");
+		WriteDestFileLn("#define VIA2_IER_Never1 0xFF");
+	}
+
+	WriteDestFileLn("#define VIA2_CB2modesAllowed 0x01");
+	WriteDestFileLn("#define VIA2_CA2modesAllowed 0x01");
+}
+
+LOCALPROC WriteAppSTRCONSTcontents(void)
+{
+	char *s;
+
+	switch (gbo_lang) {
+		case gbk_lang_eng:
+			s = "ENG";
+			break;
+		case gbk_lang_fre:
+			s = "FRE";
+			break;
+		case gbk_lang_ita:
+			s = "ITA";
+			break;
+		case gbk_lang_ger:
+			s = "GER";
+			break;
+		case gbk_lang_dut:
+			s = "DUT";
+			break;
+		case gbk_lang_spa:
+			s = "SPA";
+			break;
+		case gbk_lang_pol:
+			s = "POL";
+			break;
+		case gbk_lang_ptb:
+			s = "PTB";
+			break;
+		case gbk_lang_cat:
+			s = "CAT";
+			break;
+		case gbk_lang_cze:
+			s = "CZE";
+			break;
+		case gbk_lang_srl:
+			s = "SRL";
+			break;
+		default:
+			s = "???";
+			break;
+	}
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#include ");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile("STRCN");
+	WriteCStrToDestFile(s);
+	WriteCStrToDestFile(".h");
+	WriteQuoteToDestFile();
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteAppSOUNDGLUcontents(void)
+{
+	char *s;
+
+	switch (gbo_sndapi) {
+		case gbk_sndapi_alsa:
+			s = "ALSA";
+			break;
+		case gbk_sndapi_ddsp:
+			s = "DDSP";
+			break;
+		default:
+			s = "???";
+			break;
+	}
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#include ");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile("SGLU");
+	WriteCStrToDestFile(s);
+	WriteCStrToDestFile(".h");
+	WriteQuoteToDestFile();
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteAppEMCONFIGcontents(void)
+{
+	WriteDestFileLn("/*");
+	++DestFileIndent;
+		WriteDestFileLn(
+			"Configuration options used by platform independent code.");
+		WriteConfigurationWarning();
+	--DestFileIndent;
+	WriteDestFileLn("*/");
+
+	WriteBlankLineToDestFile();
+
+	WriteCompCondBool("EmClassicKbrd", EmClassicKbrd);
+	WriteCompCondBool("EmADB", EmADB);
+	WriteCompCondBool("EmRTC", EmRTC);
+	WriteCompCondBool("EmPMU", EmPMU);
+	WriteCompCondBool("EmVIA2", EmVIA2);
+	WriteCompCondBool("Use68020", em_cpu_vers >= 2);
+	WriteCompCondBool("EmFPU",
+		cur_mIIorIIX);
+	WriteCompCondBool("EmMMU", falseblnr);
+	WriteCompCondBool("EmASC", EmASC);
+
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define CurEmMd kEmMd_");
+	WriteCStrToDestFile(GetModelName(cur_mdl));
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define kMyClockMult ");
+	if (cur_mIIorIIX) {
+		WriteCStrToDestFile("2");
+	} else {
+		WriteCStrToDestFile("1");
+	}
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+	WriteCompCondBool("WantCycByPriOp", timingacc != 0);
+	WriteCompCondBool("WantCloserCyc", timingacc >= 2);
+
+	if (gbk_ide_mvc == cur_ide) {
+		if (gbk_cpufam_x64 == gbo_cpufam) {
+			WriteBlankLineToDestFile();
+			WriteDestFileLn("#define r_pc_p \"r15\"");
+			WriteDestFileLn("#define r_MaxCyclesToGo \"r14\"");
+			WriteDestFileLn("#define r_pc_pHi \"r13\"");
+		}
+
+		if (gbk_cpufam_ppc == gbo_cpufam) {
+			WriteBlankLineToDestFile();
+			WriteDestFileLn("#define r_regs \"r14\"");
+			WriteDestFileLn("#define r_pc_p \"r15\"");
+			WriteDestFileLn("#define r_MaxCyclesToGo \"r16\"");
+			WriteDestFileLn("#define r_pc_pHi \"r17\"");
+		}
+
+		if (gbk_cpufam_arm == gbo_cpufam) {
+			WriteBlankLineToDestFile();
+			WriteDestFileLn("#define r_regs \"r4\"");
+			WriteDestFileLn("#define r_pc_p \"r5\"");
+			if (gbk_targ_wcar != cur_targ) {
+				WriteDestFileLn("#define r_MaxCyclesToGo \"r6\"");
+				WriteDestFileLn("#define r_pc_pHi \"r7\"");
+			}
+		}
+	}
+
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define kRAMa_Size ");
+	WriteCStrToDestFile("0x");
+	WriteHexLongToOutput(1 << RAMa_Size);
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define kRAMb_Size ");
+	if (0 == RAMb_Size) {
+		WriteCStrToDestFile("0");
+	} else {
+		WriteCStrToDestFile("0x");
+		WriteHexLongToOutput(1 << RAMb_Size);
+	}
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+
+	if (NeedScrnHack) {
+		WriteCompCondBool("UseLargeScreenHack", NeedScrnHack);
+	}
+	WriteCompCondBool("IncludeVidMem", NeedVidMem);
+	if (NeedVidMem) {
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("#define kVidMemRAM_Size ");
+		WriteCStrToDestFile("0x");
+		WriteHexLongToOutput(VidMemSize);
+		WriteEndDestFileLn();
+	}
+
+	WriteBlankLineToDestFile();
+
+	WriteCompCondBool("EmVidCard", EmVidCard);
+	if (EmVidCard) {
+		WriteDestFileLn("#define kVidROM_Size 0x000800");
+	}
+
+	WriteBlankLineToDestFile();
+
+	if (cur_mIIorIIX) {
+		WriteDestFileLn("#define MaxATTListN 20");
+	} else {
+		WriteDestFileLn("#define MaxATTListN 16");
+	}
+
+	WriteCompCondBool("IncludeExtnPbufs",
+		(! WantMinExtn) && (gbk_apifam_gtk != gbo_apifam)
+		&& (gbk_apifam_nds != gbo_apifam));
+	WriteCompCondBool("IncludeExtnHostTextClipExchange",
+		(! WantMinExtn) && (gbk_apifam_gtk != gbo_apifam)
+		&& (gbk_apifam_sdl != gbo_apifam)
+		&& (gbk_apifam_nds != gbo_apifam));
+
+	WriteBlankLineToDestFile();
+
+	WriteCompCondBool("Sony_SupportDC42", SonySupportDC42);
+	WriteCompCondBool("Sony_SupportTags", SonySupportTags);
+	WriteCompCondBool("Sony_WantChecksumsUpdated",
+		SonyWantChecksumsUpdated);
+	WriteDestFileLn("#define Sony_VerifyChecksums 0");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define CaretBlinkTime 0x");
+	WriteHexByteToOutput(cur_CaretBlinkTime);
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define SpeakerVol 0x");
+	WriteHexByteToOutput(cur_SpeakerVol);
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define DoubleClickTime 0x");
+	WriteHexByteToOutput(cur_DoubleClickTime);
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define MenuBlink 0x");
+	WriteHexByteToOutput(cur_MenuBlink);
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define AutoKeyThresh 0x");
+	WriteHexByteToOutput(cur_AutoKeyThresh);
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define AutoKeyRate 0x");
+	WriteHexByteToOutput(cur_AutoKeyRate);
+	WriteEndDestFileLn();
+
+	if (cur_mIIorIIX) {
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("#define pr_HilColRed 0x");
+		WriteHexWordToOutput(cur_HilColRed);
+		WriteEndDestFileLn();
+
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("#define pr_HilColGreen 0x");
+		WriteHexWordToOutput(cur_HilColGreen);
+		WriteEndDestFileLn();
+
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("#define pr_HilColBlue 0x");
+		WriteHexWordToOutput(cur_HilColBlue);
+		WriteEndDestFileLn();
+	}
+
+	if (! WantAutoLocation) {
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("#define CurMacLatitude 0x");
+		WriteHexLongToOutput(cur_InitLatitude);
+		WriteEndDestFileLn();
+
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("#define CurMacLongitude 0x");
+		WriteHexLongToOutput(cur_InitLongitude);
+		WriteEndDestFileLn();
+	}
+	if (! WantAutoTimeZone) {
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("#define CurMacDelta 0x");
+		WriteHexLongToOutput(((WantTzDST ? 1UL : 0) << 31)
+			| (((ui5r)cur_TzDeltS) & 0x00FFFFFF));
+		WriteEndDestFileLn();
+	}
+
+	WriteBlankLineToDestFile();
+	WriteBlankLineToDestFile();
+
+	WriteConfigureWires();
+
+	WriteBlankLineToDestFile();
+
+
+
+	WriteBlankLineToDestFile();
+
+	WriteConfigureVIA1();
+
+
+	if (EmVIA2) {
+		WriteBlankLineToDestFile();
+		WriteConfigureVIA2();
+	}
+
+	WriteBlankLineToDestFile();
+	if (cur_mdl <= gbk_mdl_Plus) {
+		WriteDestFileLn("#define Mouse_Enabled SCC_InterruptsEnabled");
+	} else {
+		WriteDestFileLn("#define Mouse_Enabled() (! ADBMouseDisabled)");
+	}
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn(
+		"#define VIA1_iCA1_PulseNtfy VIA1_iCA1_Sixtieth_PulseNtfy");
+	WriteDestFileLn(
+		"#define Sixtieth_PulseNtfy VIA1_iCA1_Sixtieth_PulseNtfy");
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn(
+		"#define VIA1_iCA2_PulseNtfy"
+		" VIA1_iCA2_RTC_OneSecond_PulseNtfy");
+	WriteDestFileLn(
+		"#define RTC_OneSecond_PulseNtfy"
+		" VIA1_iCA2_RTC_OneSecond_PulseNtfy");
+
+	if (cur_mIIorIIX) {
+		WriteBlankLineToDestFile();
+		WriteDestFileLn(
+			"#define VIA2_iCA1_PulseNtfy"
+			" VIA2_iCA1_Vid_VBLinterrupt_PulseNtfy");
+		WriteDestFileLn(
+			"#define Vid_VBLinterrupt_PulseNotify"
+			" VIA2_iCA1_Vid_VBLinterrupt_PulseNtfy");
+
+		WriteBlankLineToDestFile();
+		WriteDestFileLn(
+			"#define VIA2_iCB1_PulseNtfy"
+			" VIA2_iCB1_ASC_interrupt_PulseNtfy");
+		WriteDestFileLn(
+			"#define ASC_interrupt_PulseNtfy"
+			" VIA2_iCB1_ASC_interrupt_PulseNtfy");
+	}
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("#define GetSoundInvertTime VIA1_GetT1InvertTime");
+
+	if (EmClassicKbrd) {
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("#define KYBD_ShiftInData VIA1_ShiftOutData");
+		WriteDestFileLn("#define KYBD_ShiftOutData VIA1_ShiftInData");
+	}
+	if (EmADB) {
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("#define ADB_ShiftInData VIA1_ShiftOutData");
+		WriteDestFileLn("#define ADB_ShiftOutData VIA1_ShiftInData");
+	}
+
+	if (! WantDisableRomCheck) {
+		WriteCompCondBool("DisableRomCheck", WantDisableRomCheck);
+	}
+	if (! WantDisableRamTest) {
+		WriteCompCondBool("DisableRamTest", WantDisableRamTest);
+	}
+
+	if (gbk_AHM_none != cur_AltHappyMac) {
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("#define CurAltHappyMac kAHM_");
+		WriteCStrToDestFile(GetAltHappyMacName(cur_AltHappyMac));
+		WriteEndDestFileLn();
+	}
+
+	WriteBlankLineToDestFile();
+	if (cur_mIIorIIX) {
+		WriteDestFileLn("#define kExtn_Block_Base 0x50F0C000");
+	} else {
+		WriteDestFileLn("#define kExtn_Block_Base 0x00F40000");
+	}
+	WriteDestFileLn("#define kExtn_ln2Spc 5");
+
+	WriteBlankLineToDestFile();
+	if (gbk_mdl_PB100 == cur_mdl) {
+		WriteDestFileLn("#define kROM_Base 0x00900000");
+	} else if (cur_mIIorIIX) {
+		WriteDestFileLn("#define kROM_Base 0x00800000");
+	} else {
+		WriteDestFileLn("#define kROM_Base 0x00400000");
+	}
+	WriteDestFileLn("#define kROM_ln2Spc 20");
+
+	WriteBlankLineToDestFile();
+	WriteCompCondBool("WantDisasm", WantDisasm);
+	WriteCompCondBool("ExtraAbnormalReports", falseblnr);
+}
+
+LOCALPROC WriteAppSpecificConfigFiles(void)
+{
+	WriteADstFile1("my_config_d",
+		"CNFGGLOB", ".h", "C Configuration file",
+		WriteAppCNFGGLOBContents);
+	WriteADstFile1("my_config_d",
+		"CNFGRAPI", ".h", "C API Configuration file",
+		WriteAppCNFGRAPIContents);
+	WriteADstFile1("my_config_d",
+		"EMCONFIG", ".h", "C Platform Independent Configuration file",
+		WriteAppEMCONFIGcontents);
+	WriteADstFile1("my_config_d",
+		"STRCONST", ".h", "Language Configuration file",
+		WriteAppSTRCONSTcontents);
+
+	if (gbk_sndapi_none != gbo_sndapi) {
+		WriteADstFile1("my_config_d",
+			"SOUNDGLU", ".h", "Sound Configuration file",
+			WriteAppSOUNDGLUcontents);
+	}
+}
--- /dev/null
+++ b/setup/STRUTILS.i
@@ -1,0 +1,277 @@
+/*
+	STRUTILS.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	STRing UTILitieS
+
+	Some very basic string macros and routines.
+*/
+
+
+#define PStrLength(s) (*(s))
+#define PStrToMyCharPtr(s) ((s) + 1)
+
+#define PStrMaxLength 255
+
+#define SizeOfListMyChar(n) (n)
+#define PStrToPtr(s) ((MyPtr)PStrToMyCharPtr(s))
+#define PStrToSize(s) (SizeOfListMyChar(PStrLength(s)))
+#define PStrToTotSize(s) (SizeOfListMyChar(PStrLength(s) + 1))
+	/* + 1 for length byte */
+
+#define PStrClear(s) PStrLength(s) = 0
+
+GLOBALPROC PStrCopy(ps3p r, ps3p s)
+{
+	MyMoveBytes((MyPtr)s, (MyPtr)r, PStrToTotSize(s));
+}
+
+GLOBALPROC PStrApndChar(ps3p s, MyCharR x)
+{
+	si4r n = s[0] + 1;
+
+	if (n <= PStrMaxLength) {
+		s[0] = (MyCharR)n;
+		s[n] = x;
+	}
+}
+
+GLOBALPROC PStrPrependChar(ps3p s, MyCharR x)
+{
+	ps3p p = s;
+	si4r n0 = *p++;
+	si4r n = n0 + 1;
+
+	if (n <= PStrMaxLength) {
+		MyMoveBytes((MyPtr)p, (MyPtr)(p + 1), SizeOfListMyChar(n0));
+		s[1] = x;
+		s[0] = (MyCharR)n;
+	}
+}
+
+GLOBALPROC PStrAppend(ps3p r, ps3p s)
+{
+	ps3p p = s;
+	ps3p q = r;
+	si4r m = *p++;
+	si4r n = *q++;
+
+	if (n + m > PStrMaxLength) {
+		m = PStrMaxLength - n;
+	}
+
+	*r = (MyCharR)(n + m);
+	MyMoveBytes((MyPtr)p, (MyPtr)(q + n), m);
+}
+
+GLOBALFUNC uimr CStrLength(char *s)
+{
+	char *p = s;
+
+	while (0 != *p++) {
+	}
+	return p - s - 1;
+}
+
+GLOBALPROC PStrFromCStr(ps3p r, /* CONST */ char *s)
+{
+	uimr L;
+
+	L = CStrLength(s);
+	if (L > PStrMaxLength) {
+		L = PStrMaxLength;
+	}
+	*r++ = (MyCharR)L;
+	MyMoveBytes((MyPtr)s, (MyPtr)r, L);
+}
+
+GLOBALPROC PStrFromChar(ps3p r, char x)
+{
+	r[0] = 1;
+	r[1] = x;
+}
+
+GLOBALPROC PStrFromPtr(MyPtr p, uimr L, ps3p s)
+{
+	uimr tL;
+
+	if (L <= PStrMaxLength) {
+		tL = L;
+	} else {
+		tL = PStrMaxLength;
+	}
+	s[0] = (MyCharR)tL;
+	MyMoveBytes(p, PStrToPtr(s), SizeOfListMyChar(tL));
+}
+
+GLOBALPROC PStrApndCStr(ps3p r, /* CONST */ char *s)
+{
+	MyPStr t;
+
+	PStrFromCStr(t, s);
+	PStrAppend(r, t);
+}
+
+GLOBALFUNC blnr PStrEq(ps3p s1, ps3p s2)
+{
+	register si4r i;
+	MyCharPtr p1 = s1;
+	MyCharPtr p2 = s2;
+	MyCharR n = *p1++;
+	MyCharR m = *p2++;
+
+	if (n != m) {
+		return falseblnr;
+	} else {
+		for (i = n; --i >= 0; ) {
+			if (*p1++ != *p2++) {
+				return falseblnr;
+			}
+		}
+		return trueblnr;
+	}
+}
+
+GLOBALFUNC blnr CStrEq(char *s1, char *s2)
+{
+	MyCharR c1;
+
+	while ((c1 = *s1++) == *s2++) {
+		if (0 == c1) {
+			return trueblnr;
+		}
+	}
+	return falseblnr;
+}
+
+GLOBALPROC CStrFromPtr(MyPtr p, uimr L, char *s)
+{
+	MyMoveBytes(p, (MyPtr)s, SizeOfListMyChar(L));
+	s[L] = (MyCharR)0;
+}
+
+GLOBALPROC CStrFromPStr(ps3p x, char *s)
+{
+	CStrFromPtr(PStrToMyCharPtr(x), PStrLength(x), s);
+}
+
+GLOBALPROC CStrCopy(char *r, char *s)
+{
+	while (0 != (*r++ = *s++)) {
+	}
+}
+
+LOCALPROC ReversePStr(ps3p s)
+{
+	MyCharR c;
+	MyCharR *p1 = PStrToMyCharPtr(s);
+	MyCharR *p2 = p1 + PStrLength(s) - 1;
+
+	while (p1 < p2) {
+		c = *p1;
+		*p1 = *p2;
+		*p2 = c;
+		++p1;
+		--p2;
+	}
+}
+
+LOCALPROC PStrFromUimr(uimr v, ps3p s)
+{
+	MyCharR *p = PStrToMyCharPtr(s);
+	uimr newv;
+
+	do {
+		newv = v / (uimr)10;
+		*p++ = '0' + (v - newv * 10);
+		v = newv;
+	} while (v != 0);
+	s[0] = p - PStrToMyCharPtr(s);
+
+	ReversePStr(s);
+}
+
+LOCALFUNC uimr MyCharPtrToUimr(MyCharPtr p, MyCharR n)
+{
+	register si4r i;
+	uimr v = 0;
+
+	for (i = n; --i >= 0; ) {
+		v = (v * 10) + (*p++ - '0');
+	}
+
+	return v;
+}
+
+LOCALFUNC uimr PStrToUimr(ps3p s)
+{
+	MyCharPtr p = s;
+	MyCharR n = *p++;
+
+	return MyCharPtrToUimr(p, n);
+}
+
+LOCALFUNC simr PStrToSimr(ps3p s)
+{
+	simr v;
+	MyCharPtr p = s;
+	MyCharR n = *p++;
+
+	if (0 == n) {
+		v = 0;
+	} else if ('-' == p[0]) {
+		v = - MyCharPtrToUimr(++p, --n);
+	} else {
+		v = MyCharPtrToUimr(p, n);
+	}
+
+	return v;
+}
+
+LOCALPROC PStrFromSimr(simr v, ps3p s)
+{
+	if (v < 0) {
+		PStrFromUimr(- v, s);
+		PStrPrependChar(s, '-');
+	} else {
+		PStrFromUimr(v, s);
+	}
+}
+
+LOCALPROC PStrFromNUimr(uimr v, ui3r n, ps3p s)
+{
+	uimr i;
+	uimr newv;
+	MyCharR *p = PStrToMyCharPtr(s);
+
+	s[0] = n;
+	for (i = n + 1; 0 != --i; ) {
+		newv = v / (uimr)10;
+		*p++ = '0' + (v - newv * 10);
+		v = newv;
+	}
+
+	ReversePStr(s);
+}
+
+GLOBALPROC PStrApndNUimr(ps3p r, uimr v, ui3r n)
+{
+	MyPStr t;
+
+	PStrFromNUimr(v, n, t);
+	PStrAppend(r, t);
+}
+
+#define Have_STRUTILS 1
--- /dev/null
+++ b/setup/USFILDEF.i
@@ -1,0 +1,499 @@
+/*
+	USFILDEF.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	USe program SPecific FILe DEFinitions
+*/
+
+LOCALPROC NullProc(void)
+{
+}
+
+LOCALVAR unsigned int FileCounter;
+
+struct DoSrcFile_r
+{
+	MyPtr SavepDt;
+	char *s;
+	long Flgm;
+	int DepDir;
+	tDoDependsForC depends;
+	MyProc p;
+};
+
+typedef struct DoSrcFile_r DoSrcFile_r;
+
+#define DoSrcFile_gd() ((DoSrcFile_r *)(pDt))
+
+LOCALPROC DoASrcFileWithSetupProc0(
+	char *s, int DepDir, long Flgm, tDoDependsForC depends)
+{
+	DoSrcFile_gd()->s = s;
+	DoSrcFile_gd()->Flgm = Flgm;
+	DoSrcFile_gd()->DepDir = DepDir;
+	DoSrcFile_gd()->depends = depends;
+
+	DoSrcFile_gd()->p();
+
+	++FileCounter;
+}
+
+LOCALPROC DoASrcFileWithSetupProc(
+	char *s, int DepDir, long Flgm, tDoDependsForC depends)
+{
+	if (0 == (Flgm & kCSrcFlgmNoSource))
+	if (0 == (Flgm & kCSrcFlgmSkip))
+	{
+		DoASrcFileWithSetupProc0(s, DepDir, Flgm, depends);
+	}
+}
+
+LOCALPROC DoAllSrcFilesWithSetup(MyProc p)
+{
+	DoSrcFile_r r;
+
+	r.SavepDt = pDt;
+	r.p = p;
+	pDt = (MyPtr)&r;
+
+	FileCounter = 0;
+	DoAllSrcFiles(DoASrcFileWithSetupProc);
+
+	pDt = r.SavepDt;
+}
+
+LOCALPROC DoAllSrcFilesSortWithSetup1(
+	char *s, int DepDir, long Flgm, tDoDependsForC depends)
+{
+	if (0 == (Flgm & kCSrcFlgmNoSource))
+	if (0 == (Flgm & kCSrcFlgmSkip))
+	{
+		if (0 != (Flgm & kCSrcFlgmSortFirst)) {
+			DoASrcFileWithSetupProc0(s, DepDir, Flgm, depends);
+		} else {
+			++FileCounter;
+		}
+	}
+}
+
+LOCALPROC DoAllSrcFilesSortWithSetup2(
+	char *s, int DepDir, long Flgm, tDoDependsForC depends)
+{
+	if (0 == (Flgm & kCSrcFlgmNoSource))
+	if (0 == (Flgm & kCSrcFlgmSkip))
+	{
+		if (0 == (Flgm & kCSrcFlgmSortFirst)) {
+			DoASrcFileWithSetupProc0(s, DepDir, Flgm, depends);
+		} else {
+			++FileCounter;
+		}
+	}
+}
+
+LOCALPROC DoAllSrcFilesSortWithSetup(MyProc p)
+{
+	DoSrcFile_r r;
+
+	r.SavepDt = pDt;
+	r.p = p;
+	pDt = (MyPtr)&r;
+
+	FileCounter = 0;
+	DoAllSrcFiles(DoAllSrcFilesSortWithSetup1);
+	FileCounter = 0;
+	DoAllSrcFiles(DoAllSrcFilesSortWithSetup2);
+
+	pDt = r.SavepDt;
+}
+
+LOCALFUNC char * GetSrcFileFileXtns(void)
+{
+	char *s;
+	blnr UseObjc = ((DoSrcFile_gd()->Flgm & kCSrcFlgmOjbc) != 0);
+
+	if (UseObjc) {
+		s = ".m";
+	} else {
+		s = ".c";
+	}
+
+	return s;
+}
+
+LOCALPROC WriteSrcFileFileName(void)
+{
+	WriteCStrToDestFile(DoSrcFile_gd()->s);
+	WriteCStrToDestFile(GetSrcFileFileXtns());
+}
+
+LOCALPROC WriteSrcFileFilePath(void)
+{
+	WriteFileInDirToDestFile0(Write_src_d_ToDestFile,
+		WriteSrcFileFileName);
+}
+
+LOCALPROC WriteSrcFileHeaderName(void)
+{
+	WriteCStrToDestFile(DoSrcFile_gd()->s);
+	WriteCStrToDestFile(".h");
+}
+
+LOCALPROC WriteSrcFileHeaderPath(void)
+{
+	WriteFileInDirToDestFile0(Write_src_d_ToDestFile,
+		WriteSrcFileHeaderName);
+}
+
+LOCALPROC WriteSrcFileObjName(void)
+{
+	WriteCStrToDestFile(DoSrcFile_gd()->s);
+	switch (cur_ide) {
+		case gbk_ide_msv:
+		case gbk_ide_dmc:
+		case gbk_ide_plc:
+			WriteCStrToDestFile(".obj");
+			break;
+		case gbk_ide_9pc:
+			WriteCStrToDestFile(".$O");
+			break;
+		default:
+			WriteCStrToDestFile(".o");
+			break;
+	}
+}
+
+LOCALPROC WriteSrcFileObjPath(void)
+{
+	WriteFileInDirToDestFile0(Write_obj_d_ToDestFile,
+		WriteSrcFileObjName);
+}
+
+LOCALPROC DoAllExtraHeaders2WithSetupProc(
+	char *s, int DepDir, long Flgm, tDoDependsForC depends)
+{
+	if (0 == (Flgm & kCSrcFlgmNoHeader))
+	if (0 != (Flgm & kCSrcFlgmNoSource))
+	if (0 == (Flgm & kCSrcFlgmSkip))
+	{
+		DoASrcFileWithSetupProc0(s, DepDir, Flgm, depends);
+	}
+}
+
+LOCALPROC DoAllExtraHeaders2WithSetup(MyProc p)
+{
+	DoSrcFile_r r;
+
+	r.SavepDt = pDt;
+	r.p = p;
+	pDt = (MyPtr)&r;
+
+	FileCounter = 0;
+	DoAllSrcFiles(DoAllExtraHeaders2WithSetupProc);
+
+	pDt = r.SavepDt;
+}
+
+LOCALPROC WriteExtraHeaderFileName(void)
+{
+	WriteCStrToDestFile(DoSrcFile_gd()->s);
+	WriteCStrToDestFile(".h");
+}
+
+LOCALPROC WriteExtraHeaderFilePath(void)
+{
+	WriteFileInDirToDestFile0(
+		((kDepDirCnfg == DoSrcFile_gd()->DepDir)
+			? Write_cfg_d_ToDestFile
+			: Write_src_d_ToDestFile),
+		WriteExtraHeaderFileName);
+}
+
+LOCALVAR unsigned int DocTypeCounter;
+
+struct DoDocType_r
+{
+	MyPtr SavepDt;
+	char *ShortName;
+	char *MacType;
+	char *LongName;
+	tWriteExtensionList WriteExtensionList;
+	MyProc p;
+};
+
+typedef struct DoDocType_r DoDocType_r;
+
+#define DoDocType_gd() ((DoDocType_r *)(pDt))
+
+LOCALPROC DoAllDocTypesWithSetupProc(char *ShortName,
+	char *MacType,
+	char *LongName,
+	tWriteExtensionList WriteExtensionList)
+{
+	DoDocType_gd()->ShortName = ShortName;
+	DoDocType_gd()->MacType = MacType;
+	DoDocType_gd()->LongName = LongName;
+	DoDocType_gd()->WriteExtensionList = WriteExtensionList;
+
+	DoDocType_gd()->p();
+
+	++DocTypeCounter;
+}
+
+LOCALPROC DoAppAndAllDocTypes0(tWriteOneDocType p)
+{
+	p("APP", "APPL", "Application", NULL);
+	DoAllDocTypes(p);
+}
+
+LOCALPROC DoAppAndAllDocTypes(tWriteOneDocType p)
+{
+	p("APP", "APPL", "Application", NULL);
+	if (WantIconMaster) {
+		DoAllDocTypes(p);
+	}
+}
+
+LOCALPROC DoAllDocTypesWithSetup(MyProc p)
+{
+	DoDocType_r r;
+
+	r.SavepDt = pDt;
+	r.p = p;
+	pDt = (MyPtr)&r;
+
+	DocTypeCounter = 0;
+	DoAppAndAllDocTypes(DoAllDocTypesWithSetupProc);
+
+	pDt = r.SavepDt;
+}
+
+LOCALPROC WriteDocTypeIconShortName(void)
+{
+	WriteCStrToDestFile(DoDocType_gd()->ShortName);
+}
+
+LOCALPROC WriteDocTypeIconFileName(void)
+{
+	WriteCStrToDestFile("ICON");
+	WriteDocTypeIconShortName();
+	switch (gbo_targfam) {
+		case gbk_targfam_cmac:
+			WriteCStrToDestFile("M.r");
+			break;
+		case gbk_targfam_mach:
+		case gbk_targfam_carb:
+			WriteCStrToDestFile("O.icns");
+			break;
+		case gbk_targfam_mswn:
+		case gbk_targfam_wnce:
+			WriteCStrToDestFile("W.ico");
+			break;
+	}
+}
+
+LOCALPROC WriteDocTypeIconFilePath(void)
+{
+	WriteFileInDirToDestFile0(Write_src_d_ToDestFile,
+		WriteDocTypeIconFileName);
+}
+
+LOCALPROC WriteDocTypeIconMacType(void)
+{
+	WriteCStrToDestFile(DoDocType_gd()->MacType);
+}
+
+LOCALPROC WriteDocTypeCopyMachoFile(void)
+{
+	WriteCopyFile(WriteDocTypeIconFilePath,
+		Write_tmachores_d_ToDestFile);
+}
+
+typedef void (*tWriteOneFrameWorkType)(char *s);
+
+static void DoAllFrameWorks(tWriteOneFrameWorkType p)
+{
+	if (gbk_apifam_cco == gbo_apifam) {
+		p("AppKit");
+		p("AudioUnit");
+#if UseOpenGLinOSX
+		p("OpenGL");
+#endif
+	} else {
+		p("Carbon");
+#if UseOpenGLinOSX
+		p("OpenGL");
+		p("AGL");
+#endif
+	}
+}
+
+struct DoFrameWork_r
+{
+	MyPtr SavepDt;
+	char *s;
+	MyProc p;
+};
+
+typedef struct DoFrameWork_r DoFrameWork_r;
+
+#define DoFrameWork_gd() ((DoFrameWork_r *)(pDt))
+
+LOCALPROC DoAllFrameWorksWithSetupProc(char *s)
+{
+	DoFrameWork_gd()->s = s;
+
+	DoFrameWork_gd()->p();
+
+	++FileCounter;
+}
+
+LOCALPROC DoAllFrameWorksWithSetup(MyProc p)
+{
+	DoFrameWork_r r;
+
+	r.SavepDt = pDt;
+	r.p = p;
+	pDt = (MyPtr)&r;
+
+	FileCounter = 0;
+	DoAllFrameWorks(DoAllFrameWorksWithSetupProc);
+
+	pDt = r.SavepDt;
+}
+
+LOCALPROC WriteFileToCFilesList(MyProc p)
+{
+	WriteBgnDestFileLn();
+	p();
+	WriteEndDestFileLn();
+}
+
+LOCALPROC DoSrcExtraHeaderFile(void)
+{
+	WriteFileToCFilesList(WriteExtraHeaderFilePath);
+}
+
+LOCALPROC DoSrcFileAddToList(void)
+{
+	WriteFileToCFilesList(WriteSrcFileHeaderPath);
+	WriteFileToCFilesList(WriteSrcFileFilePath);
+}
+
+LOCALPROC WriteCFilesListContents(void)
+{
+	DoAllExtraHeaders2WithSetup(DoSrcExtraHeaderFile);
+	DoAllSrcFilesWithSetup(DoSrcFileAddToList);
+}
+
+LOCALPROC WriteCFilesList(void)
+{
+	/* list of c files */
+
+	WriteADstFile1("my_project_d",
+		"c_files", "", "list of c files",
+		WriteCFilesListContents);
+}
+
+LOCALPROC Write_tmachoShell(void)
+{
+	WriteRmDir(WriteAppNamePath);
+	WriteRmDir(Write_tmachobun_d_ToDestFile);
+	WriteMkDir(Write_tmachobun_d_ToDestFile);
+	WriteMkDir(Write_tmachocontents_d_ToDestFile);
+	WriteMkDir(Write_tmachomac_d_ToDestFile);
+	WriteMkDir(Write_tmachores_d_ToDestFile);
+	WriteMkDir(Write_tmacholang_d_ToDestFile);
+	DoAllDocTypesWithSetup(WriteDocTypeCopyMachoFile);
+	WriteCopyFile(WriteInfoPlistFilePath,
+		Write_tmachocontents_d_ToDestFile);
+	WriteEchoToNewFile(Write_tmachoLangDummyContents,
+		Write_tmachoLangDummyPath, trueblnr);
+	WriteEchoToNewFile(Write_tmachoPkgInfoContents,
+		Write_tmachoPkgInfoPath, falseblnr);
+	WriteMoveDir(Write_tmachobun_d_ToDestFile, WriteAppNamePath);
+}
+
+LOCALPROC Write_tmachoShellDeps(void)
+{
+	WriteMakeDependFile(Write_srcAppIconPath);
+}
+
+LOCALPROC WritepDtSrcPath(void)
+{
+	WriteFileInDirToDestFile0(Write_src_d_ToDestFile, WritepDtString);
+}
+
+LOCALPROC WritepDtCfgPath(void)
+{
+	WriteFileInDirToDestFile0(Write_cfg_d_ToDestFile, WritepDtString);
+}
+
+LOCALPROC DoSrcDependsMakeCompile(int DepDir, char *s)
+{
+	MyPtr SavepDt = pDt;
+	pDt = (MyPtr)s;
+	WriteMakeDependFile((kDepDirCnfg == DepDir)
+		? WritepDtCfgPath
+		: WritepDtSrcPath);
+	pDt = SavepDt;
+}
+
+LOCALPROC DoSrcFileMakeCompileDeps(void)
+{
+	WriteMakeDependFile(WriteSrcFileFilePath);
+	if (DoSrcFile_gd()->depends != nullpr) {
+		DoSrcFile_gd()->depends(DoSrcDependsMakeCompile);
+	}
+	WriteMakeDependFile(WriteCNFGGLOBPath);
+}
+
+LOCALPROC DoSrcFileMakeCompileBody(void)
+{
+	WriteCompileC(WriteSrcFileFilePath, WriteSrcFileObjPath,
+		(DoSrcFile_gd()->Flgm & kCSrcFlgmUseAPI) != 0);
+	WriteBlankLineToDestFile();
+}
+
+LOCALPROC DoSrcFileMakeCompile(void)
+{
+	WriteMakeRule(WriteSrcFileObjPath,
+		DoSrcFileMakeCompileDeps,
+		DoSrcFileMakeCompileBody);
+	
+}
+
+LOCALPROC DoSrcFileStandardMakeObjects(void)
+{
+	WriteBgnDestFileLn();
+	WriteSrcFileObjPath();
+	WriteSpaceToDestFile();
+	WriteBackSlashToDestFile();
+	WriteEndDestFileLn();
+}
+
+LOCALPROC DoAllSrcFilesStandardMakeObjects(void)
+{
+	DoAllSrcFilesSortWithSetup(DoSrcFileStandardMakeObjects);
+}
+
+LOCALPROC DoSrcFileStandardEraseFile(void)
+{
+	WriteRmFile(WriteSrcFileObjPath);
+}
+
+LOCALPROC DoAllSrcFilesStandardErase(void)
+{
+	DoAllSrcFilesWithSetup(DoSrcFileStandardEraseFile);
+}
--- /dev/null
+++ b/setup/WRBGCFLS.i
@@ -1,0 +1,492 @@
+/*
+	WRBGCFLS.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	WRite Bash Gnu C specific FiLeS
+*/
+
+
+#define WriteXCDcallgcc WriteCompileCExec
+#if 0
+LOCALPROC WriteXCDcallgcc(void)
+{
+#if 0
+	if ((gbk_ide_xcd == cur_ide) && (ide_vers >= 2100)
+		&& (ide_vers < 2200))
+	{
+		/*
+			This doesn't seem to make any difference in default
+			Xcode 2.1 install. Current guess is that default
+			headers don't support MACOSX_DEPLOYMENT_TARGET,
+			but the ide is supporting 10.4 sdk that is
+			included but not installed by default.
+		*/
+		WriteCStrToDestFile("export MACOSX_DEPLOYMENT_TARGET=10.");
+		if (gbk_cpufam_ppc == gbo_cpufam) {
+			WriteCStrToDestFile("1");
+		} else {
+			WriteCStrToDestFile("4");
+		}
+		WriteCStrToDestFile(" ; ");
+	}
+#endif
+	WriteCStrToDestFile("gcc");
+}
+#endif
+
+LOCALPROC WriteBgcCompileAsmLinkCommonOptions(void)
+{
+	if ((gbk_ide_xcd == cur_ide) && (ide_vers >= 2100)) {
+		switch (cur_targ) {
+			case gbk_targ_mach:
+			case gbk_targ_imch:
+			case gbk_targ_mc64:
+			case gbk_targ_mx11:
+			case gbk_targ_mi11:
+			case gbk_targ_mx64:
+				if (gbk_cpufam_x86 == gbo_cpufam) {
+					WriteCStrToDestFile(" -arch i386");
+				} else if (gbk_cpufam_x64 == gbo_cpufam) {
+					WriteCStrToDestFile(" -arch x86_64");
+				} else {
+					WriteCStrToDestFile(" -arch ppc");
+				}
+				break;
+			default:
+				break;
+		}
+	}
+	if (gbk_targfam_oind == gbo_targfam) {
+		if (gbk_cpufam_x64 == gbo_cpufam) {
+			WriteCStrToDestFile(" -m64");
+		}
+	} else if (gbk_targfam_lnds == gbo_targfam) {
+		WriteCStrToDestFile(" -marm -mthumb-interwork");
+	}
+}
+
+LOCALPROC WriteBgcLinkOSGlucompileCommonOptions(void)
+{
+	if ((gbk_ide_xcd == cur_ide) && (ide_vers >= 2200)) {
+		if ((gbk_apifam_osx == gbo_apifam)
+			|| (gbk_apifam_cco == gbo_apifam))
+		{
+			if (gbk_cpufam_ppc == gbo_cpufam) {
+				WriteCStrToDestFile(" -mmacosx-version-min=10.1");
+			} else
+			if (gbk_cpufam_x64 == gbo_cpufam) {
+				WriteCStrToDestFile(" -mmacosx-version-min=10.5");
+			} else
+			{
+				WriteCStrToDestFile(" -mmacosx-version-min=10.4");
+			}
+			WriteCStrToDestFile(" -isysroot");
+			if (ide_vers >= 3200) {
+				WriteCStrToDestFile(" /Developer/SDKs/MacOSX10.6.sdk");
+			} else if ((ide_vers >= 3100)
+				|| (gbk_cpufam_x64 == gbo_cpufam))
+			{
+				WriteCStrToDestFile(" /Developer/SDKs/MacOSX10.5.sdk");
+			} else {
+				WriteCStrToDestFile(" /Developer/SDKs/MacOSX10.4u.sdk");
+			}
+		}
+	}
+}
+
+LOCALPROC WriteBgcCompileLinkCommonOptions(void)
+{
+	if (gbk_dbg_on == gbo_dbg) {
+		WriteCStrToDestFile(" -g");
+	}
+}
+
+LOCALPROC WriteBgcCOptions(void)
+{
+	WriteCStrToDestFile(
+		" -Wall -Wmissing-prototypes -Wno-uninitialized");
+
+	if (gbk_apifam_nds != gbo_apifam) {
+		WriteCStrToDestFile(" -Wundef -Wstrict-prototypes");
+	}
+	if (gbk_ide_cyg == cur_ide) {
+		if (gbk_targfam_cygw != gbo_targfam) {
+			WriteCStrToDestFile(" -mno-cygwin");
+		}
+	}
+	if (gbk_ide_xcd == cur_ide) {
+		WriteCStrToDestFile(" -fpascal-strings");
+	}
+	if (gbk_ide_xcd == cur_ide) {
+		switch (cur_targ) {
+			case gbk_targ_mach:
+			case gbk_targ_imch:
+			case gbk_targ_mc64:
+			case gbk_targ_mx11:
+			case gbk_targ_mi11:
+			case gbk_targ_mx64:
+				WriteCStrToDestFile(" -mdynamic-no-pic");
+				break;
+		}
+	}
+	WriteBgcCompileAsmLinkCommonOptions();
+	WriteBgcCompileLinkCommonOptions();
+
+	if (gbk_apifam_nds == gbo_apifam) {
+		WriteCStrToDestFile(" -march=armv5te -mtune=arm946e-s");
+	}
+
+	if (1 /* WantConfigDir */) {
+		WriteCStrToDestFile(" -I");
+		Write_cfg_d_ToDestFile();
+		WriteCStrToDestFile(" -I");
+		Write_src_d_ToDestFile();
+	}
+}
+
+LOCALPROC WriteBgcCOptOptions(void)
+{
+	if (gbk_dbg_on != gbo_dbg) {
+		/* WriteCStrToDestFile(" -O3"); */
+		if (gbk_targfam_lnds == gbo_targfam) {
+			WriteCStrToDestFile(" -O2");
+		} else {
+			WriteCStrToDestFile(" -Os");
+		}
+	} else {
+		WriteCStrToDestFile(" -O0");
+	}
+}
+
+LOCALPROC DoFrameWorkBGCaddFile(void)
+{
+	WriteCStrToDestFile(" -framework ");
+	WriteCStrToDestFile(DoFrameWork_gd()->s);
+}
+
+LOCALPROC Write_machoRsrcBgcDeps(void)
+{
+	WriteMakeDependFile(WriteMainRsrcSrcPath);
+	WriteMakeDependFile(Write_machoAppIconPath);
+}
+
+LOCALPROC Write_machoRsrcBgcBuild(void)
+{
+	WriteDestFileLn("/Developer/Tools/Rez \\");
+	++DestFileIndent;
+		WriteDestFileLn("-i /Developer/Headers/FlatCarbon \\");
+		WriteBgnDestFileLn();
+			WriteCStrToDestFile("\"");
+			WriteMainRsrcSrcPath();
+			WriteCStrToDestFile("\" \\");
+		WriteEndDestFileLn();
+		WriteBgnDestFileLn();
+			WriteCStrToDestFile("-o \"");
+			Write_machoRsrcPath();
+			WriteCStrToDestFile("\" \\");
+		WriteEndDestFileLn();
+		WriteDestFileLn("-useDF");
+	--DestFileIndent;
+}
+
+LOCALPROC WriteBashGccMakeFile(void)
+{
+	WriteDestFileLn("# make file generated by gryphel build system");
+
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("mk_COptionsCommon = -c");
+	WriteBgcCOptions();
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("mk_COptionsOSGLU = $(mk_COptionsCommon)");
+	WriteBgcLinkOSGlucompileCommonOptions();
+	WriteBgcCOptOptions();
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("mk_COptions = $(mk_COptionsCommon)");
+	WriteBgcCOptOptions();
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn(".PHONY: TheDefaultOutput clean");
+
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("TheDefaultOutput :");
+	WriteMakeDependFile(Write_machobinpath_ToDestFile);
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+	DoAllSrcFilesWithSetup(DoSrcFileMakeCompile);
+
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("ObjFiles = ");
+	WriteBackSlashToDestFile();
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		DoAllSrcFilesStandardMakeObjects();
+		WriteBlankLineToDestFile();
+	--DestFileIndent;
+
+	if (HaveMacBundleApp) {
+		WriteBlankLineToDestFile();
+		WriteMakeRule(Write_machoAppIconPath,
+			Write_tmachoShellDeps,
+			Write_tmachoShell);
+	}
+	if (gbk_apifam_win == gbo_apifam) {
+		WriteBlankLineToDestFile();
+		WriteBgnDestFileLn();
+		WriteMainRsrcObjPath();
+		WriteCStrToDestFile(": ");
+		WriteMainRsrcSrcPath();
+		WriteEndDestFileLn();
+		++DestFileIndent;
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("windres.exe");
+			WriteCStrToDestFile(" -i");
+			WritePathArgInMakeCmnd(WriteMainRsrcSrcPath);
+			WriteCStrToDestFile(" --input-format=rc -o");
+			WritePathArgInMakeCmnd(WriteMainRsrcObjPath);
+			WriteCStrToDestFile(" -O coff  --include-dir SRC");
+			WriteEndDestFileLn();
+		--DestFileIndent;
+		WriteBlankLineToDestFile();
+	}
+
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	Write_machobinpath_ToDestFile();
+	WriteCStrToDestFile(" : $(ObjFiles)");
+	if (HaveMacBundleApp) {
+		WriteMakeDependFile(Write_machoAppIconPath);
+	}
+	if (HaveMacRrscs) {
+		WriteMakeDependFile(Write_machoRsrcPath);
+	}
+	if (gbk_apifam_win == gbo_apifam) {
+		WriteMakeDependFile(WriteMainRsrcObjPath);
+	}
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		WriteBgnDestFileLn();
+		WriteXCDcallgcc();
+		WriteCStrToDestFile(" \\");
+		WriteEndDestFileLn();
+		++DestFileIndent;
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("-o");
+			if (gbk_apifam_nds == gbo_apifam) {
+				WritePathArgInMakeCmnd(WriteBinElfObjObjPath);
+			} else {
+				WritePathArgInMakeCmnd(Write_machobinpath_ToDestFile);
+			}
+			WriteCStrToDestFile(" \\");
+			WriteEndDestFileLn();
+
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("$(ObjFiles)");
+			if ((gbk_apifam_osx == gbo_apifam)
+				|| (gbk_apifam_cco == gbo_apifam))
+			{
+				DoAllFrameWorksWithSetup(DoFrameWorkBGCaddFile);
+				if (ide_vers >= 4000) {
+					WriteCStrToDestFile(" -Wl,-no_pie");
+				}
+			} else if (gbk_apifam_win == gbo_apifam) {
+				WritePathArgInMakeCmnd(WriteMainRsrcObjPath);
+				if (gbk_targ_wcar == cur_targ) {
+					WriteCStrToDestFile(
+						" -lcommctrl -lcoredll -laygshell -lmmtimer");
+				} else {
+					WriteCStrToDestFile(
+						" -mwindows -lwinmm -lole32 -luuid");
+					if (gbk_ide_cyg == cur_ide) {
+						WriteCStrToDestFile(" -mno-cygwin");
+					}
+				}
+			} else if (gbk_apifam_gtk == gbo_apifam) {
+				WriteCStrToDestFile(" `pkg-config --libs gtk+-2.0`");
+			} else if (gbk_apifam_sdl == gbo_apifam) {
+				if (gbk_targfam_mach == gbo_targfam) {
+					WriteCStrToDestFile(" -L/usr/local/lib -lSDLmain"
+						" -lSDL -Wl,-framework,Cocoa");
+				} else {
+					WriteCStrToDestFile(" -lSDL");
+				}
+			} else if (gbk_apifam_sd2 == gbo_apifam) {
+				if (gbk_targfam_mach == gbo_targfam) {
+					WriteCStrToDestFile(
+						" -Wl,-framework,Cocoa,-framework,SDL2");
+				} else {
+					WriteCStrToDestFile(" -lSDL2");
+				}
+			} else if (gbk_apifam_nds == gbo_apifam) {
+				WriteCStrToDestFile(" -L$(DEVKITPRO)/libnds/lib");
+				WriteCStrToDestFile(" -lfilesystem -lfat -lnds9");
+			} else {
+				if (gbk_targfam_slrs == gbo_targfam) {
+					WriteCStrToDestFile(" -lposix4");
+				}
+#if MayUseSound
+				if (gbk_sndapi_alsa == gbo_sndapi) {
+					WriteCStrToDestFile(" -ldl");
+#if 0
+					WriteCStrToDestFile(" -lasound");
+#endif
+				} else if (gbk_sndapi_ddsp == gbo_sndapi) {
+					if ((gbk_targfam_nbsd == gbo_targfam)
+						|| (gbk_targfam_obsd == gbo_targfam))
+					{
+						WriteCStrToDestFile(" -lossaudio");
+					}
+				}
+#endif
+#if 0
+				WriteCStrToDestFile(" -lXext");
+#endif
+				if (gbk_targfam_nbsd == gbo_targfam) {
+					WriteCStrToDestFile(" -L/usr/X11R7/lib");
+					WriteCStrToDestFile(" -R/usr/X11R7/lib");
+				} else if (gbk_targfam_dbsd == gbo_targfam) {
+					WriteCStrToDestFile(" -L/usr/pkg/lib");
+				} else if (gbk_targfam_minx == gbo_targfam) {
+					WriteCStrToDestFile(" -L/usr/pkg/X11R6/lib");
+				} else if (gbk_targfam_irix == gbo_targfam) {
+					WriteCStrToDestFile(" -L/usr/lib/X11");
+				} else {
+					WriteCStrToDestFile(" -L/usr/X11R6/lib");
+				}
+				WriteCStrToDestFile(" -lX11");
+			}
+			if (gbk_apifam_nds == gbo_apifam) {
+				WriteCStrToDestFile(" -specs=ds_arm9.specs");
+			}
+			WriteBgcCompileAsmLinkCommonOptions();
+			WriteBgcLinkOSGlucompileCommonOptions();
+			WriteBgcCompileLinkCommonOptions();
+			WriteEndDestFileLn();
+		--DestFileIndent;
+		if (gbk_dbg_on != gbo_dbg) {
+			switch (cur_ide) {
+				case gbk_ide_bgc:
+					if ((gbk_targfam_minx == gbo_targfam)
+						|| (gbk_targfam_linx == gbo_targfam)
+						|| (gbk_targfam_oind == gbo_targfam)
+							/*
+								for oi64, strip makes it larger!
+								but still compresses smaller.
+							*/
+						|| (gbk_targfam_fbsd == gbo_targfam)
+						|| (gbk_targfam_obsd == gbo_targfam)
+						|| (gbk_targfam_nbsd == gbo_targfam)
+						|| (gbk_targfam_dbsd == gbo_targfam)
+						)
+					{
+						WriteBgnDestFileLn();
+						WriteCStrToDestFile("strip --strip-unneeded");
+						WritePathArgInMakeCmnd(
+							Write_machobinpath_ToDestFile);
+						WriteEndDestFileLn();
+					} else if (gbk_targfam_irix == gbo_targfam) {
+						WriteBgnDestFileLn();
+						WriteCStrToDestFile("strip -s");
+						WritePathArgInMakeCmnd(
+							Write_machobinpath_ToDestFile);
+						WriteEndDestFileLn();
+					}
+					break;
+				case gbk_ide_xcd:
+					WriteBgnDestFileLn();
+					WriteCStrToDestFile("strip -u -r");
+					WritePathArgInMakeCmnd(
+						Write_machobinpath_ToDestFile);
+					WriteEndDestFileLn();
+					break;
+				case gbk_ide_dvc:
+				case gbk_ide_mgw:
+				case gbk_ide_cyg:
+					WriteBgnDestFileLn();
+					WriteCStrToDestFile("strip.exe");
+					WritePathArgInMakeCmnd(WriteAppNamePath);
+					WriteEndDestFileLn();
+					break;
+				default:
+					break;
+			}
+		}
+		if (gbk_apifam_nds == gbo_apifam) {
+			WriteBgnDestFileLn();
+				WriteCStrToDestFile(
+					"$(DEVKITARM)/bin/arm-eabi-objcopy.exe -O binary");
+				WritePathArgInMakeCmnd(WriteBinElfObjObjPath);
+				WritePathArgInMakeCmnd(WriteBinArmObjObjPath);
+			WriteEndDestFileLn();
+			WriteBgnDestFileLn();
+				WriteCStrToDestFile("$(DEVKITARM)/bin/ndstool.exe -c");
+				WritePathArgInMakeCmnd(WriteAppNamePath);
+				WriteCStrToDestFile(" -9");
+				WritePathArgInMakeCmnd(WriteBinArmObjObjPath);
+				WriteCStrToDestFile(" -b $(DEVKITPRO)/libnds/icon.bmp");
+				WriteCStrToDestFile(
+					" \";www.devkitpro.org;www.drunkencoders.com\"");
+			WriteEndDestFileLn();
+		}
+	--DestFileIndent;
+
+	if (HaveMacRrscs) {
+		WriteBlankLineToDestFile();
+		WriteMakeRule(Write_machoRsrcPath,
+			Write_machoRsrcBgcDeps,
+			Write_machoRsrcBgcBuild);
+	}
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("clean :");
+	++DestFileIndent;
+		WriteDestFileLn("rm -f $(ObjFiles)");
+		if (HaveMacBundleApp) {
+			WriteRmDir(WriteAppNamePath);
+		} else {
+			if (gbk_apifam_win == gbo_apifam) {
+				WriteRmFile(WriteMainRsrcObjPath);
+			} else if (gbk_apifam_nds == gbo_apifam) {
+				WriteRmFile(WriteBinElfObjObjPath);
+				WriteRmFile(WriteBinArmObjObjPath);
+			}
+			WriteRmFile(WriteAppNamePath);
+		}
+	--DestFileIndent;
+}
+
+LOCALPROC WriteBashGccSpecificFiles(void)
+{
+	if (HaveMacBundleApp) {
+		WritePListData();
+	}
+
+	if (WantSandbox) {
+		WriteEntitlementsData();
+	}
+
+	WriteADstFile1("my_project_d",
+		"Makefile", "", "Make file",
+		WriteBashGccMakeFile);
+}
--- /dev/null
+++ b/setup/WRCCCFLS.i
@@ -1,0 +1,138 @@
+/*
+	WRCCCFLS.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	WRite generic Command line C Compiler specific FiLeS
+*/
+
+
+LOCALPROC WriteCccMakeFile(void)
+{
+	WriteDestFileLn("# make file generated by gryphel build system");
+
+	WriteBlankLineToDestFile();
+
+	WriteDestFileLn("mk_COptions = -c");
+	WriteCStrToDestFile(" -I");
+	Write_cfg_d_ToDestFile();
+	WriteCStrToDestFile(" -I");
+	Write_src_d_ToDestFile();
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("TheDefaultOutput : ");
+	Write_machobinpath_ToDestFile();
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+	DoAllSrcFilesWithSetup(DoSrcFileMakeCompile);
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("ObjFiles = ");
+	WriteBackSlashToDestFile();
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		DoAllSrcFilesStandardMakeObjects();
+		WriteBlankLineToDestFile();
+	--DestFileIndent;
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	Write_machobinpath_ToDestFile();
+	WriteCStrToDestFile(" : $(ObjFiles)");
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		WriteDestFileLn("cc \\");
+		++DestFileIndent;
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("-o ");
+			WriteQuoteToDestFile();
+			Write_machobinpath_ToDestFile();
+			WriteQuoteToDestFile();
+			WriteCStrToDestFile(" \\");
+			WriteEndDestFileLn();
+
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("$(ObjFiles)");
+#if 0
+			WriteCStrToDestFile(" -lXext");
+#endif
+			WriteCStrToDestFile(" -L/usr/X11R6/lib -lX11");
+			WriteEndDestFileLn();
+		--DestFileIndent;
+	--DestFileIndent;
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("clean :");
+	++DestFileIndent;
+		WriteDestFileLn("rm -f $(ObjFiles)");
+		WriteRmFile(WriteAppNamePath);
+	--DestFileIndent;
+}
+
+LOCALPROC WriteCccSpecificFiles(void)
+{
+	WriteADstFile1("my_project_d",
+		"Makefile", "", "Make file",
+		WriteCccMakeFile);
+}
+
+LOCALPROC Write9pcMkFile(void)
+{
+	WriteDestFileLn("# mkfile generated by gryphel build system");
+
+	WriteBlankLineToDestFile();
+
+	WriteDestFileLn("</$objtype/mkfile");
+	WriteBlankLineToDestFile();
+
+	WriteDestFileLn("BIN=/$objtype/bin/games");
+	WriteDestFileLn("CFLAGS=-p -D__plan9__ -Icfg -Isrc $CFLAGS");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("TARG=");
+	Write_machobinpath_ToDestFile();
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+	DoAllSrcFilesWithSetup(DoSrcFileMakeCompile);
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("OFILES=");
+	WriteBackSlashToDestFile();
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		DoAllSrcFilesStandardMakeObjects();
+		WriteBlankLineToDestFile();
+	--DestFileIndent;
+
+	WriteDestFileLn("$TARG: $OFILES");
+	++DestFileIndent;
+		WriteDestFileLn("$LD -o $target $OFILES");
+	--DestFileIndent;
+	WriteBlankLineToDestFile();
+
+	WriteDestFileLn("default:V: $TARG");
+	WriteBlankLineToDestFile();
+
+	WriteDestFileLn("</sys/src/cmd/mkone");
+}
+
+LOCALPROC Write9pcSpecificFiles(void)
+{
+	WriteADstFile1("my_project_d",
+		"mkfile", "", "mk file",
+		Write9pcMkFile);
+}
--- /dev/null
+++ b/setup/WRCNFGAP.i
@@ -1,0 +1,431 @@
+/*
+	WRCNFGAP.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	WRite "CNFGrAPi.h"
+*/
+
+LOCALPROC WriteOSXLocalTalkCNFGRAPI(void)
+{
+	WriteDestFileLn("#include <unistd.h>");
+	WriteDestFileLn("#include <netinet/in.h>");
+	WriteDestFileLn("#include <sys/socket.h>");
+	WriteDestFileLn("#include <net/if.h>");
+	WriteDestFileLn("#include <net/route.h>");
+	WriteDestFileLn("#include <net/if_dl.h>");
+	WriteDestFileLn("#include <arpa/inet.h>");
+	WriteDestFileLn("#include <sys/select.h>");
+	WriteDestFileLn("#include <sys/ioctl.h>");
+	WriteDestFileLn("#include <sys/sysctl.h>");
+	WriteDestFileLn("#include <net/bpf.h>");
+}
+
+LOCALPROC WriteCommonCNFGRAPIContents(void)
+{
+	WriteDestFileLn("/*");
+	++DestFileIndent;
+		WriteDestFileLn(
+			"Configuration options used by platform specific code.");
+		WriteConfigurationWarning();
+	--DestFileIndent;
+	WriteDestFileLn("*/");
+
+
+	if (gbo_TstCompErr) {
+		WriteDestFileLn("#error \"Testing Compile Time Error\"");
+	}
+
+	if (gbk_ide_msv == cur_ide) {
+		if (ide_vers >= 8000) {
+			WriteBlankLineToDestFile();
+			WriteDestFileLn("#define _CRT_SECURE_NO_DEPRECATE 1");
+		}
+		WriteBlankLineToDestFile();
+		WriteDestFileLn(
+			"/* ignore warning generated by system includes */");
+		if (ide_vers >= 6000) {
+			WriteDestFileLn("#pragma warning(push)");
+		}
+		WriteDestFileLn("#pragma warning(disable : 4201 4115 4214)");
+	}
+
+	WriteBlankLineToDestFile();
+
+	if (gbk_apifam_osx == gbo_apifam) {
+		if (gbk_targfam_carb == gbo_targfam) {
+			/* kIdeMW8 or kIdeMPW3_6_a1 */
+			if (gbk_ide_mw8 == cur_ide) {
+				WriteDestFileLn("#include <MacHeadersCarbon.h>");
+			} else
+			{
+				WriteDestFileLn("#include <Carbon.h>");
+				WriteDestFileLn("#include <stdlib.h>");
+				WriteDestFileLn("#include <string.h>");
+#if UseOpenGLinOSX
+				WriteDestFileLn("#include <agl.h>");
+#endif
+			}
+			WriteDestFileLn("#define UsingCarbonLib 1");
+		} else {
+			/* kIdeMW8 or kIdeBashGcc or kIdeAPB */
+			if (gbk_ide_mw8 == cur_ide) {
+				WriteDestFileLn("#include <MSL MacHeadersMach-O.h>");
+			}
+			WriteDestFileLn("#include <Carbon/Carbon.h>");
+#if UseOpenGLinOSX
+			WriteDestFileLn("#include <AGL/agl.h>");
+#endif
+#if UseMachinOSX
+			WriteDestFileLn("#include <mach/mach_interface.h>");
+			WriteDestFileLn("#include <mach/mach_port.h>");
+#endif
+			WriteDestFileLn("#include <unistd.h>");
+				/* for nanosleep */
+
+			if (WantLocalTalk) {
+				WriteOSXLocalTalkCNFGRAPI();
+			}
+		}
+	} else if (gbk_apifam_cco == gbo_apifam) {
+		WriteDestFileLn("#import <Cocoa/Cocoa.h>");
+#if MayUseSound
+		if (MySoundEnabled) {
+			WriteDestFileLn("#include <CoreAudio/CoreAudio.h>");
+			WriteDestFileLn("#include <AudioUnit/AudioUnit.h>");
+		}
+#endif
+#if UseOpenGLinOSX
+		WriteDestFileLn("#include <OpenGL/gl.h>");
+#endif
+		WriteDestFileLn("#include <stdio.h>");
+		WriteDestFileLn("#include <stdlib.h>");
+		WriteDestFileLn("#include <string.h>");
+		WriteDestFileLn("#include <sys/param.h>");
+		WriteDestFileLn("#include <sys/time.h>");
+		if (WantUnTranslocate) {
+			WriteDestFileLn("#include <dlfcn.h>");
+		}
+		if (WantLocalTalk) {
+			WriteOSXLocalTalkCNFGRAPI();
+		}
+	} else if (gbk_apifam_xwn == gbo_apifam) {
+		blnr HaveAppPathLink = falseblnr;
+		blnr HaveSysctlPath = (gbk_targfam_fbsd == gbo_targfam);
+
+		switch (gbo_targfam) {
+			case gbk_targfam_linx:
+			case gbk_targfam_nbsd:
+			case gbk_targfam_dbsd:
+			case gbk_targfam_oind:
+				HaveAppPathLink = trueblnr;
+				break;
+			default:
+				break;
+		}
+
+		if (gbk_targfam_minx == gbo_targfam) {
+			WriteDestFileLn(
+				"/* get nanosleep and gettimeofday. ugh */");
+			WriteDestFileLn("#define _POSIX_SOURCE 1");
+			WriteDestFileLn("#define _POSIX_C_SOURCE 200112L");
+		}
+		WriteDestFileLn("#include <stdio.h>");
+		WriteDestFileLn("#include <stdlib.h>");
+		WriteDestFileLn("#include <string.h>");
+		WriteDestFileLn("#include <time.h>");
+		WriteDestFileLn("#include <sys/time.h>");
+		WriteDestFileLn("#include <sys/times.h>");
+		WriteDestFileLn("#include <X11/Xlib.h>");
+		WriteDestFileLn("#include <X11/Xutil.h>");
+		WriteDestFileLn("#include <X11/keysym.h>");
+		WriteDestFileLn("#include <X11/keysymdef.h>");
+		WriteDestFileLn("#include <X11/Xatom.h>");
+#if 1
+		WriteDestFileLn("#include <fcntl.h>");
+#endif
+		/* if (WantActvCode) */ {
+			/* also now used for export file */
+			WriteDestFileLn("#include <sys/stat.h>");
+		}
+#if MayUseSound
+		if ((gbk_sndapi_alsa == gbo_sndapi)
+			|| (gbk_sndapi_ddsp == gbo_sndapi))
+		{
+			WriteDestFileLn("#include <errno.h>");
+		}
+#endif
+		if (HaveAppPathLink /* for readlink */
+#if MayUseSound
+			|| (gbk_sndapi_ddsp == gbo_sndapi)
+#endif
+			) /* for write */
+		{
+			WriteDestFileLn("#include <unistd.h>");
+		}
+		if (HaveSysctlPath) {
+			WriteDestFileLn("#include <sys/sysctl.h>");
+		}
+#if MayUseSound
+		if (MySoundEnabled) {
+			switch (gbo_sndapi) {
+				case gbk_sndapi_alsa:
+					WriteDestFileLn("#include <dlfcn.h>");
+#if 0
+					WriteDestFileLn("#include <alsa/asoundlib.h>");
+#endif
+					break;
+				case gbk_sndapi_ddsp:
+					WriteDestFileLn("#include <sys/ioctl.h>");
+					if (gbk_targfam_obsd == gbo_targfam) {
+						WriteDestFileLn("#include <soundcard.h>");
+					} else {
+						WriteDestFileLn("#include <sys/soundcard.h>");
+					}
+					break;
+				default:
+					break;
+			}
+		}
+#endif
+
+		WriteBlankLineToDestFile();
+		WriteCompCondBool("CanGetAppPath",
+			HaveAppPathLink || HaveSysctlPath);
+		WriteCompCondBool("HaveAppPathLink", HaveAppPathLink);
+		if (HaveAppPathLink) {
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("#define TheAppPathLink \"");
+			switch (gbo_targfam) {
+				case gbk_targfam_nbsd:
+					WriteCStrToDestFile("/proc/curproc/exe");
+					break;
+				case gbk_targfam_dbsd:
+					WriteCStrToDestFile("/proc/curproc/file");
+					break;
+				case gbk_targfam_oind:
+					WriteCStrToDestFile("/proc/self/path/a.out");
+					break;
+				case gbk_targfam_linx:
+				default:
+					WriteCStrToDestFile("/proc/self/exe");
+					break;
+			}
+			WriteCStrToDestFile("\"");
+			WriteEndDestFileLn();
+		}
+		WriteCompCondBool("HaveSysctlPath", HaveSysctlPath);
+
+#if MayUseSound
+		if (MySoundEnabled) {
+			if (gbk_sndapi_ddsp == gbo_sndapi) {
+				WriteBgnDestFileLn();
+				WriteCStrToDestFile("#define AudioDevPath \"");
+				switch (gbo_targfam) {
+					case gbk_targfam_nbsd:
+					case gbk_targfam_obsd:
+						WriteCStrToDestFile("/dev/audio");
+						break;
+					case gbk_targfam_fbsd:
+					case gbk_targfam_dbsd:
+					default:
+						WriteCStrToDestFile("/dev/dsp");
+						break;
+				}
+				WriteCStrToDestFile("\"");
+				WriteEndDestFileLn();
+			}
+		}
+#endif
+
+	} else if (gbk_apifam_nds == gbo_apifam) {
+		WriteDestFileLn("#define ARM9 1");
+
+		WriteDestFileLn("#include <nds.h>");
+		WriteDestFileLn("#include <filesystem.h>");
+		WriteDestFileLn("#include <fat.h>");
+
+		WriteDestFileLn("#include <stdio.h>");
+		WriteDestFileLn("#include <stdlib.h>");
+		WriteDestFileLn("#include <string.h>");
+		WriteDestFileLn("#include <time.h>");
+		WriteDestFileLn("#include <sys/time.h>");
+		WriteDestFileLn("#include <sys/times.h>");
+		WriteDestFileLn("#include <fcntl.h>");
+		WriteDestFileLn("#include <unistd.h>");
+	} else if (gbk_apifam_gtk == gbo_apifam) {
+		WriteDestFileLn("#include <gtk/gtk.h>");
+		WriteDestFileLn("#include <gdk/gdkkeysyms.h>");
+		WriteDestFileLn("#include <stdio.h>");
+		WriteDestFileLn("#include <stdlib.h>");
+		WriteDestFileLn("#include <string.h>");
+		WriteDestFileLn("#include <time.h>");
+		WriteDestFileLn("#include <sys/time.h>");
+		WriteDestFileLn("#include <sys/times.h>");
+	} else if (gbk_apifam_sdl == gbo_apifam) {
+		WriteDestFileLn("#include <SDL/SDL.h>");
+		WriteDestFileLn("#include <stdio.h>");
+		WriteDestFileLn("#include <stdlib.h>");
+		WriteDestFileLn("#include <string.h>");
+	} else if (gbk_apifam_sd2 == gbo_apifam) {
+		WriteDestFileLn("#include <SDL2/SDL.h>");
+		WriteDestFileLn("#include <stdio.h>");
+		WriteDestFileLn("#include <stdlib.h>");
+		WriteDestFileLn("#include <string.h>");
+	} else if (gbk_apifam_win == gbo_apifam) {
+		if ((gbk_ide_mvc == cur_ide)
+			&& (gbk_targfam_wnce == gbo_targfam))
+		{
+			WriteDestFileLn("#define WIN32 1");
+			WriteDestFileLn("#define _WIN32 1");
+			WriteDestFileLn("#define WINNT 1");
+			WriteDestFileLn("#define UNDER_CE 1");
+			WriteDestFileLn("#define __CEGCC__ 1");
+			WriteDestFileLn("#define __CEGCC32__ 1");
+			WriteDestFileLn("#define __MINGW32__ 1");
+			WriteDestFileLn("#define __MINGW32CE__ 1");
+			WriteDestFileLn("#define __COREDLL__ 1");
+			WriteDestFileLn("#define UNICODE 1");
+			WriteDestFileLn("#define _UNICODE 1");
+			WriteDestFileLn("#define _M_ARM 1");
+			WriteBlankLineToDestFile();
+		}
+		if (gbk_ide_mw8 == cur_ide) {
+			WriteDestFileLn("#include <Win32Headers.h>");
+		} else
+		{
+			WriteDestFileLn("#include <windows.h>");
+			WriteDestFileLn("#include <time.h>");
+			if (gbk_ide_lcc == cur_ide) {
+				WriteDestFileLn("#include <shellapi.h>");
+				WriteDestFileLn("#include <mmsystem.h>");
+			}
+		}
+		WriteDestFileLn("#include <shlobj.h>");
+		WriteDestFileLn("#include <tchar.h>");
+		if (gbk_targfam_wnce == gbo_targfam) {
+			WriteDestFileLn("#include <aygshell.h>");
+			WriteDestFileLn("#include <commdlg.h>");
+		}
+		if (gbk_ide_mvc == cur_ide) {
+			WriteBlankLineToDestFile();
+			WriteDestFileLn("#define _tWinMain WinMain");
+		}
+		if (gbk_ide_plc == cur_ide) {
+			WriteDestFileLn("#define _MAX_PATH MAX_PATH");
+		}
+	} else {
+		if (gbk_ide_mw8 == cur_ide) {
+			WriteDestFileLn("#include <MacHeaders.h>");
+			WriteDestFileLn("#include <CursorDevices.h>");
+			WriteDestFileLn("#define ShouldDefineQDGlobals 0");
+		} else
+		if (gbk_ide_mpw == cur_ide) {
+			WriteDestFileLn("#include <MacTypes.h>");
+			if (gbk_cpufam_68k != gbo_cpufam) {
+				WriteDestFileLn("#include <MixedMode.h>");
+			}
+			WriteDestFileLn("#include <Gestalt.h>");
+			WriteDestFileLn("#include <MacErrors.h>");
+			WriteDestFileLn("#include <MacMemory.h>");
+			WriteDestFileLn("#include <OSUtils.h>");
+			WriteDestFileLn("#include <QuickdrawText.h>");
+			WriteDestFileLn("#include <QuickDraw.h>");
+			if (gbk_cpufam_68k == gbo_cpufam) {
+				WriteDestFileLn("#include <SegLoad.h>");
+			}
+			WriteDestFileLn("#include <IntlResources.h>");
+			WriteDestFileLn("#include <Events.h>");
+			WriteDestFileLn("#include <Script.h>");
+			WriteDestFileLn("#include <Files.h>");
+			WriteDestFileLn("#include <Resources.h>");
+			WriteDestFileLn("#include <Fonts.h>");
+			WriteDestFileLn("#include <TextUtils.h>");
+			WriteDestFileLn("#include <FixMath.h>");
+			WriteDestFileLn("#include <ToolUtils.h>");
+			WriteDestFileLn("#include <Menus.h>");
+			WriteDestFileLn("#include <Scrap.h>");
+			WriteDestFileLn("#include <Controls.h>");
+			WriteDestFileLn("#include <ControlDefinitions.h>");
+			WriteDestFileLn("#include <AppleEvents.h>");
+			WriteDestFileLn("#include <Processes.h>");
+			WriteDestFileLn("#include <EPPC.h>");
+			WriteDestFileLn("#include <MacWindows.h>");
+			WriteDestFileLn("#include <TextEdit.h>");
+			WriteDestFileLn("#include <Dialogs.h>");
+			WriteDestFileLn("#include <Devices.h>");
+			WriteDestFileLn("#include <Palettes.h>");
+			WriteDestFileLn("#include <StandardFile.h>");
+			WriteDestFileLn("#include <Aliases.h>");
+			WriteDestFileLn("#include <Folders.h>");
+			WriteDestFileLn("#include <Balloons.h>");
+			WriteDestFileLn("#include <DiskInit.h>");
+			WriteDestFileLn("#include <LowMem.h>");
+			WriteDestFileLn("#include <Appearance.h>");
+			WriteDestFileLn("#include <Navigation.h>");
+			WriteDestFileLn("#include <Sound.h>");
+			WriteDestFileLn("#include <CursorDevices.h>");
+			WriteDestFileLn("#include <Traps.h>");
+		}
+	}
+
+	if ((gbk_ide_msv == cur_ide) && (ide_vers >= 6000)) {
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("/* restore warnings */");
+		WriteDestFileLn("#pragma warning(pop)");
+	}
+
+	WriteBlankLineToDestFile();
+
+	if (gbk_cpufam_68k == gbo_cpufam) {
+		if (gbk_ide_mpw == cur_ide) {
+			WriteDestFileLn("#define ShouldUnloadDataInit 1");
+			WriteDestFileLn("#define Windows85APIAvail 0");
+			WriteDestFileLn("#define NeedLongGlue 1");
+		}
+	}
+
+#if MayUseSound
+	if (MySoundEnabled) {
+		if (gbk_sndapi_alsa == gbo_sndapi)
+		if (gbk_cpufam_arm == gbo_cpufam)
+		{
+			WriteDestFileLn("#define RaspbianWorkAround 1");
+		}
+	}
+#endif
+
+	if (HaveMacBundleApp) {
+		WriteDestFileLn("#define MyAppIsBundle 1");
+	}
+	if (gbk_apifam_cco == gbo_apifam) {
+		WriteCompCondBool("WantUnTranslocate",
+			WantUnTranslocate);
+	}
+	if (gbk_apifam_win == gbo_apifam) {
+		if (WantIconMaster) {
+			WriteDestFileLn("#define InstallFileIcons 1");
+		}
+	}
+	if ((gbk_apifam_mac == gbo_apifam)
+		|| (gbk_apifam_osx == gbo_apifam))
+	{
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("#define kMacCreatorSig ");
+		WriteSingleQuoteToDestFile();
+		WriteCStrToDestFile(kMacCreatorSig);
+		WriteSingleQuoteToDestFile();
+		WriteEndDestFileLn();
+	}
+}
--- /dev/null
+++ b/setup/WRCNFGGL.i
@@ -1,0 +1,438 @@
+/*
+	WRCNFGGL.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	WRite "CNFGGLob.h"
+*/
+
+
+LOCALPROC WriteConfigurationWarning(void)
+{
+	WriteBlankLineToDestFile();
+	WriteDestFileLn(
+		"This file is automatically generated by the build system,");
+	WriteDestFileLn(
+		"which tries to know what options are valid in what");
+	WriteDestFileLn(
+		"combinations. Avoid changing this file manually unless");
+	WriteDestFileLn(
+		"you know what you're doing.");
+}
+
+LOCALPROC WriteCommonCNFGGLOBContents(void)
+{
+	WriteDestFileLn("/*");
+	++DestFileIndent;
+		WriteDestFileLn(
+			"Configuration options used by both platform specific");
+		WriteDestFileLn(
+			"and platform independent code.");
+		WriteConfigurationWarning();
+	--DestFileIndent;
+	WriteDestFileLn("*/");
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("/* adapt to current compiler/host processor */");
+
+	if (gbk_ide_mw8 == cur_ide) {
+		WriteDestFileLn("/* make sure this is correct CNFGGLOB */");
+
+		WriteCheckPreDef("__MWERKS__");
+		switch (gbo_cpufam) {
+			case gbk_cpufam_68k:
+				WriteCheckPreDef("__MC68K__");
+				if (gbk_targ_mfpu == cur_targ) {
+					WriteCheckPreDef("__MC68881__");
+				} else {
+					WriteCheckPreNDef("__MC68881__");
+				}
+				break;
+			case gbk_cpufam_ppc:
+				WriteCheckPreDef("__POWERPC__");
+				break;
+			case gbk_cpufam_x86:
+				WriteCheckPreDef("__INTEL__");
+				break;
+		}
+	} else if ((gbk_ide_bgc == cur_ide)
+		|| (gbk_ide_xcd == cur_ide)
+		|| (gbk_ide_mvc == cur_ide))
+	{
+		switch (gbo_cpufam) {
+			case gbk_cpufam_x86:
+				WriteDestFileLn("#ifdef __x86_64__");
+				WriteDestFileLn("#error \"source is configured for"
+					" 32 bit compiler\"");
+				WriteDestFileLn("#endif");
+				break;
+			case gbk_cpufam_x64:
+				WriteDestFileLn("#ifdef __i386__");
+				WriteDestFileLn("#error \"source is configured for"
+					" 64 bit compiler\"");
+				WriteDestFileLn("#endif");
+				break;
+		}
+	}
+
+	WriteBlankLineToDestFile();
+
+#if NeedIntFormatInfo
+	WriteCompCondBool("MostSigByteFirst",
+		(gbk_cpufam_68k == gbo_cpufam)
+		|| (gbk_cpufam_ppc == gbo_cpufam));
+	WriteCompCondBool("LeastSigByteFirst",
+		(gbk_cpufam_x86 == gbo_cpufam)
+		|| (gbk_cpufam_x64 == gbo_cpufam));
+	WriteCompCondBool("TwosCompSigned",
+		(gbk_cpufam_68k == gbo_cpufam)
+		|| (gbk_cpufam_ppc == gbo_cpufam)
+		|| (gbk_cpufam_x86 == gbo_cpufam)
+		|| (gbk_cpufam_x64 == gbo_cpufam));
+#endif
+
+	if (gbk_cpufam_68k == gbo_cpufam) {
+		WriteDestFileLn("#define HaveCPUfamM68K 1");
+	}
+
+	if ((gbk_ide_bgc == cur_ide)
+		|| (gbk_ide_xcd == cur_ide)
+		|| (gbk_ide_mvc == cur_ide)
+		|| (gbk_ide_cyg == cur_ide)
+		|| (gbk_ide_dkp == cur_ide))
+	{
+		WriteDestFileLn(
+			"#define MayInline inline __attribute__((always_inline))");
+	} else
+	if (gbk_ide_snc == cur_ide) {
+		WriteDestFileLn("#define MayInline inline");
+	} else
+	if (gbk_ide_mw8 == cur_ide) {
+		WriteDestFileLn("#define MayInline __inline__");
+	} else
+	if (gbk_ide_msv == cur_ide) {
+		if (ide_vers >= 6000) {
+			WriteDestFileLn("#define MayInline __forceinline");
+		} else {
+			WriteDestFileLn("#define MayInline __inline");
+		}
+	} else
+	{
+		/* WriteDestFileLn("#define MayInline"); */
+	}
+
+	if ((gbk_ide_bgc == cur_ide)
+		|| (gbk_ide_xcd == cur_ide)
+		|| (gbk_ide_mvc == cur_ide)
+		|| (gbk_ide_cyg == cur_ide)
+		|| (gbk_ide_dkp == cur_ide))
+	{
+		WriteDestFileLn(
+			"#define MayNotInline __attribute__((noinline))");
+	} else
+	if ((gbk_ide_msv == cur_ide) && (ide_vers >= 7000)) {
+		WriteDestFileLn("#define MayNotInline __declspec(noinline)");
+	} else
+	{
+		/* WriteDestFileLn("#define MayNotInline"); */
+	}
+
+	if (gbk_ide_mvc == cur_ide) {
+		if ((gbk_cpufam_68k == gbo_cpufam)
+			|| (gbk_cpufam_ppc == gbo_cpufam))
+		{
+			WriteDestFileLn("#define BigEndianUnaligned 1");
+			WriteDestFileLn("#define LittleEndianUnaligned 0");
+		} else if ((gbk_cpufam_x86 == gbo_cpufam)
+			|| (gbk_cpufam_x64 == gbo_cpufam))
+		{
+			WriteDestFileLn("#define BigEndianUnaligned 0");
+			WriteDestFileLn("#define LittleEndianUnaligned 1");
+		} else {
+			WriteDestFileLn("#define BigEndianUnaligned 0");
+			WriteDestFileLn("#define LittleEndianUnaligned 0");
+		}
+
+		if (gbk_cpufam_x86 == gbo_cpufam) {
+			WriteDestFileLn(
+				"#define my_reg_call __attribute__ ((regparm(3)))");
+		}
+
+		if (gbk_cpufam_x86 == gbo_cpufam) {
+			WriteDestFileLn(
+				"#define my_osglu_call __attribute__ "
+					"((force_align_arg_pointer))");
+		}
+
+		WriteDestFileLn("#define my_cond_rare(x) "
+			"(__builtin_expect(x, 0))");
+		WriteDestFileLn("#define Have_ASR 1");
+		if (gbk_cpufam_x64 == gbo_cpufam) {
+			WriteDestFileLn("#define HaveUi6Div 1");
+		}
+		if (gbk_targ_wcar == cur_targ) {
+			WriteDestFileLn("#define HaveUi5to6Mul 0");
+		}
+		if ((gbk_cpufam_x64 == gbo_cpufam)
+			|| (gbk_cpufam_ppc == gbo_cpufam)
+			|| (gbk_cpufam_arm == gbo_cpufam))
+		{
+			WriteDestFileLn("#define HaveGlbReg 1");
+		}
+		WriteDestFileLn(
+			"#define my_align_8 __attribute__ ((aligned (8)))");
+	}
+
+	WriteCompCondBool("SmallGlobals", gbk_cpufam_68k == gbo_cpufam);
+
+	if ((gbk_ide_bgc == cur_ide)
+		|| (gbk_ide_xcd == cur_ide)
+		|| (gbk_ide_mvc == cur_ide)
+		|| (gbk_ide_ccc == cur_ide)
+		|| (gbk_ide_dvc == cur_ide)
+		|| (gbk_ide_mgw == cur_ide)
+		|| (gbk_ide_dmc == cur_ide)
+		|| (gbk_ide_lcc == cur_ide)
+		|| (gbk_ide_cyg == cur_ide)
+		|| (gbk_ide_dkp == cur_ide)
+		)
+	{
+		WriteDestFileLn("#define cIncludeUnused 0");
+	} else {
+		WriteDestFileLn("#define cIncludeUnused 1");
+	}
+
+	if (gbk_ide_lcc == cur_ide) {
+		WriteDestFileLn("#define UnusedParam(x)");
+	} else {
+		WriteDestFileLn("#define UnusedParam(p) (void) p");
+	}
+
+	if (gbk_ide_msv == cur_ide) {
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("/* --- set up compiler options --- */");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("/* ignore integer conversion warnings */");
+		WriteDestFileLn(
+			"#pragma warning(disable : 4244 4761 4018 4245 4024 4305)");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("/* ignore unused inline warning */");
+		WriteDestFileLn("#pragma warning(disable : 4514 4714)");
+#if 0
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("/* ignore type redefinition warning */");
+		WriteDestFileLn("#pragma warning(disable : 4142)");
+#endif
+		WriteBlankLineToDestFile();
+		WriteDestFileLn(
+			"/* ignore unary minus operator"
+			" applied to unsigned type warning */");
+		WriteDestFileLn("#pragma warning(disable : 4146)");
+
+	if (cur_mIIorIIX
+		|| (em_cpu_vers >= 2))
+	{
+		/* C4127: conditional expression is constant */
+		/*
+			C4701: local variable may have been used without having
+			been initialized
+		*/
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("/* more warnings */");
+		WriteDestFileLn("#pragma warning(disable : 4127 4701)");
+	}
+
+	} else if (gbk_ide_plc == cur_ide) {
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("#pragma warn(disable: 2135 2137)");
+	}
+
+	if (gbk_ide_mw8 == cur_ide) {
+		if (gbk_dbg_on != gbo_dbg) {
+			WriteBlankLineToDestFile();
+			WriteDestFileLn("#ifdef OptForSpeed");
+			WriteDestFileLn("#pragma optimize_for_size off");
+			WriteDestFileLn("#endif");
+		}
+	}
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("/* --- integer types ---- */");
+
+	/*
+		define signed and unsigned integer types
+		for 8 bits, 16 bits, 32 bits, and so on.
+
+		the computer might not have integer types
+		of a given size. in this case should define
+		a type of correct size, such as a structure
+		type, even if the computer can't directly do
+		integer operations on it. then set
+		HaveReal?i?b to 0.
+	*/
+
+	/* 8 bits */
+
+	/* (ui3b)0 - (ui3b)1 == (ui3b)255 */
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("typedef unsigned char ui3b;");
+	WriteDestFileLn("#define HaveRealui3b 1");
+
+	/* sizeof(si3b) == sizeof(ui3b) */
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("typedef signed char si3b;");
+	WriteDestFileLn("#define HaveRealsi3b 1");
+
+	/* 16 bits */
+
+	/* (ui4b)0 - (ui4b)1 == (ui4b)65535 */
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("typedef unsigned short ui4b;");
+	WriteDestFileLn("#define HaveRealui4b 1");
+
+	/* sizeof(si4b) == sizeof(ui4b) */
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("typedef short si4b;");
+	WriteDestFileLn("#define HaveRealsi4b 1");
+
+	/* 32 bits */
+
+	/* (ui5b)0 - (ui5b)1 == (ui5b)4294967295 */
+	WriteBlankLineToDestFile();
+	if (gbk_cpufam_x64 == gbo_cpufam) {
+		WriteDestFileLn("typedef unsigned int ui5b;");
+	} else {
+		WriteDestFileLn("typedef unsigned long ui5b;");
+	}
+	WriteDestFileLn("#define HaveRealui5b 1");
+
+	/* sizeof(si5b) == sizeof(ui5b) */
+	WriteBlankLineToDestFile();
+	if (gbk_cpufam_x64 == gbo_cpufam) {
+		WriteDestFileLn("typedef int si5b;");
+	} else {
+		WriteDestFileLn("typedef long si5b;");
+	}
+	WriteDestFileLn("#define HaveRealsi5b 1");
+
+	/* 64 bits */ /* this is mostly for illustration, not used */
+#if 0
+	struct ui6b {
+		ui5b f0;
+		ui5b f1;
+	};
+	typedef struct ui6b ui6b;
+
+	struct si6b {
+		ui5b f0;
+		si5b f1;
+	};
+	typedef struct si6b si6b;
+#endif
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("#define HaveRealui6b 0");
+	WriteDestFileLn("#define HaveRealsi6b 0");
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("/* --- integer representation types ---- */");
+
+	/*
+		for each integer type, define
+		the most efficient representation
+		for parameter passing and temporary
+		variables on the current
+		computer.
+	*/
+
+	WriteBlankLineToDestFile();
+#if ModPPCi3rTypes
+	if (gbk_cpufam_ppc == gbo_cpufam) {
+		WriteDestFileLn("typedef ui5b ui3r;");
+		WriteDestFileLn("#define ui3beqr 0");
+	} else
+#endif
+	{
+		WriteDestFileLn("typedef ui3b ui3r;");
+		WriteDestFileLn("#define ui3beqr 1");
+	}
+
+	WriteBlankLineToDestFile();
+#if ModPPCi3rTypes
+	if (gbk_cpufam_ppc == gbo_cpufam) {
+		WriteDestFileLn("typedef si5b si3r;");
+		WriteDestFileLn("#define si3beqr 0");
+	} else
+#endif
+	{
+		WriteDestFileLn("typedef si3b si3r;");
+		WriteDestFileLn("#define si3beqr 1");
+	}
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("typedef ui4b ui4r;");
+	WriteDestFileLn("#define ui4beqr 1");
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("typedef si4b si4r;");
+	WriteDestFileLn("#define si4beqr 1");
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("typedef ui5b ui5r;");
+	WriteDestFileLn("#define ui5beqr 1");
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("typedef si5b si5r;");
+	WriteDestFileLn("#define si5beqr 1");
+
+	if (gbk_ide_mvc == cur_ide) {
+		if (gbk_cpufam_x86 == gbo_cpufam)
+		{
+			WriteBlankLineToDestFile();
+			WriteDestFileLn("/* for probable register parameters */");
+			WriteDestFileLn("#define ui4rr ui5r");
+			WriteDestFileLn("#define ui3rr ui5r");
+		} else if (gbk_cpufam_x64 == gbo_cpufam) {
+#if 0
+			WriteBlankLineToDestFile();
+			WriteDestFileLn("/* for probable register parameters */");
+			WriteDestFileLn("#define ui4rr unsigned long int");
+			WriteDestFileLn("#define ui3rr unsigned long int");
+#endif
+			WriteDestFileLn("#define si5rr signed long");
+		}
+
+		WriteBlankLineToDestFile();
+		WriteDestFileLn(
+			"#define MySwapUi5r(x) ((ui5r)__builtin_bswap32(x))");
+		WriteDestFileLn("#define HaveMySwapUi5r 1");
+	}
+}
+
+LOCALPROC Write64bitConfig(void)
+{
+	WriteBlankLineToDestFile();
+	if (gbk_ide_msv == cur_ide) {
+		WriteDestFileLn("typedef signed __int64 si6r;");
+		WriteDestFileLn("typedef signed __int64 si6b;");
+		WriteDestFileLn("typedef unsigned __int64 ui6r;");
+		WriteDestFileLn("typedef unsigned __int64 ui6b;");
+		WriteDestFileLn("#define LIT64(a) a##Ui64");
+	} else {
+		WriteDestFileLn("typedef signed long long si6r;");
+		WriteDestFileLn("typedef signed long long si6b;");
+		WriteDestFileLn("typedef unsigned long long ui6r;");
+		WriteDestFileLn("typedef unsigned long long ui6b;");
+		WriteDestFileLn("#define LIT64(a) a##ULL");
+	}
+}
--- /dev/null
+++ b/setup/WRDMCFLS.i
@@ -1,0 +1,100 @@
+/*
+	WRDMCFLS.i
+	Copyright (C) 2010 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	WRite Digital Mars Compiler specific FiLeS
+*/
+
+
+LOCALPROC WriteMainRsrcObjDMCbuild(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("rcc.exe -o");
+	WriteMainRsrcObjPath();
+	WriteSpaceToDestFile();
+	WriteMainRsrcSrcPath();
+	WriteCStrToDestFile(" -I");
+	Write_src_d_ToDestFile();
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteDMCclMakeFile(void)
+{
+	WriteDestFileLn("# make file generated by gryphel build system");
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("mk_COptions = -c -r -WA");
+	/* -o+space seems to generate bad code, compiler version 8.42n */
+	WriteCStrToDestFile(" -I");
+	Write_cfg_d_ToDestFile();
+	WriteCStrToDestFile(" -I");
+	Write_src_d_ToDestFile();
+	WriteEndDestFileLn();
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("TheDefaultOutput:");
+	WriteMakeDependFile(WriteAppNamePath);
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+	WriteBlankLineToDestFile();
+	DoAllSrcFilesWithSetup(DoSrcFileMakeCompile);
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("ObjFiles  = \\");
+	++DestFileIndent;
+		DoAllSrcFilesStandardMakeObjects();
+		WriteBlankLineToDestFile();
+	--DestFileIndent;
+
+	WriteBlankLineToDestFile();
+	WriteMakeRule(WriteMainRsrcObjPath,
+		WriteMainRsrcObjMSCdeps, WriteMainRsrcObjDMCbuild);
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteAppNamePath();
+	WriteCStrToDestFile(": $(ObjFiles) ");
+	WriteMainRsrcObjPath();
+	WriteEndDestFileLn();
+
+	++DestFileIndent;
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile(
+		"dmc.exe -L/exet:nt/su:windows:4.0 $(ObjFiles) ");
+	WriteMainRsrcObjPath();
+	WriteCStrToDestFile(" -o\"");
+	WriteAppNamePath();
+	WriteCStrToDestFile(
+		"\" winmm.lib ole32.lib uuid.lib comdlg32.lib shell32.lib"
+		" gdi32.lib");
+	WriteEndDestFileLn();
+	--DestFileIndent;
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("clean:");
+	++DestFileIndent;
+		DoAllSrcFilesStandardErase();
+		WriteRmFile(WriteMainRsrcObjPath);
+		WriteRmFile(WriteAppNamePath);
+	--DestFileIndent;
+}
+
+LOCALPROC WriteDMCSpecificFiles(void)
+{
+	WriteADstFile1("my_project_d",
+		"Makefile", "", "Make file",
+		WriteDMCclMakeFile);
+}
--- /dev/null
+++ b/setup/WRDVCFLS.i
@@ -1,0 +1,170 @@
+/*
+	WRDVCFLS.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	WRite bloodshed DeV-C++ specific FiLeS
+*/
+
+
+static void DoSrcFileDvcAddFile(void)
+{
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("[Unit");
+	WriteUnsignedToOutput(FileCounter + 1);
+	WriteCStrToDestFile("]");
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("FileName=");
+	WriteSrcFileFilePath();
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("CompileCpp=0");
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("Folder=");
+	WriteAppVariationStr();
+	WriteEndDestFileLn();
+	WriteDestFileLn("Compile=1");
+	WriteDestFileLn("Link=1");
+	WriteDestFileLn("Priority=1000");
+	WriteDestFileLn("OverrideBuildCmd=0");
+	WriteDestFileLn("BuildCmd=");
+}
+
+LOCALPROC WriteDevCProjectFile(void)
+{
+	WriteDestFileLn("[Project]");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("FileName=");
+	WriteStrAppAbbrev();
+	WriteCStrToDestFile(".dev");
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("Name=");
+	WriteAppVariationStr();
+	WriteEndDestFileLn();
+
+	DoAllSrcFilesWithSetup(NullProc);
+	++FileCounter; /* main.rc */
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("UnitCount=");
+	WriteUnsignedToOutput(FileCounter);
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("Type=0");
+	WriteDestFileLn("Ver=1");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("Includes=");
+	Write_cfg_d_ToDestFile();
+	WriteCStrToDestFile(" ");
+	Write_src_d_ToDestFile();
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("PrivateResource=");
+	WriteAppVariationStr();
+	WriteCStrToDestFile("_private.rc");
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("ResourceIncludes=");
+	Write_src_d_ToDestFile();
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("IsCpp=0");
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("ObjectOutput=");
+	Write_obj_d_ToDestFile();
+	WriteEndDestFileLn();
+	WriteDestFileLn("OverrideOutput=1");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("OverrideOutputName=");
+	WriteAppNamePath();
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("IncludeVersionInfo=0");
+	WriteDestFileLn("CompilerSet=0");
+	if (gbk_dbg_on == gbo_dbg) {
+		WriteDestFileLn("CompilerSettings=000000000000000100");
+		WriteDestFileLn(
+			"Compiler= -Wall -Wstrict-prototypes"
+			" -Wno-uninitialized -O0_@@_");
+	} else {
+		WriteDestFileLn("CompilerSettings=000000000000000000");
+		WriteDestFileLn(
+			"Compiler= -Wall -Wstrict-prototypes"
+			" -Wno-uninitialized -Os_@@_");
+	}
+	WriteDestFileLn("Linker=-lwinmm -lole32 -luuid_@@_");
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("[VersionInfo]");
+	WriteDestFileLn("Major=0");
+	WriteDestFileLn("Minor=1");
+	WriteDestFileLn("Release=1");
+	WriteDestFileLn("Build=1");
+	WriteDestFileLn("LanguageID=1033");
+	WriteDestFileLn("CharsetID=1252");
+	WriteDestFileLn("CompanyName=");
+	WriteDestFileLn("FileVersion=");
+	WriteDestFileLn("FileDescription=Developed using the Dev-C++ IDE");
+	WriteDestFileLn("InternalName=");
+	WriteDestFileLn("LegalCopyright=");
+	WriteDestFileLn("LegalTrademarks=");
+	WriteDestFileLn("OriginalFilename=");
+	WriteDestFileLn("ProductName=");
+	WriteDestFileLn("ProductVersion=");
+	WriteDestFileLn("AutoIncBuildNr=0");
+
+	DoAllSrcFilesWithSetup(DoSrcFileDvcAddFile);
+
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("[Unit");
+	WriteUnsignedToOutput(++FileCounter);
+	WriteCStrToDestFile("]");
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("FileName=");
+	WriteMainRsrcSrcPath();
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("CompileCpp=0");
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("Folder=");
+	WriteAppVariationStr();
+	WriteEndDestFileLn();
+	WriteDestFileLn("Compile=1");
+	WriteDestFileLn("Link=0");
+	WriteDestFileLn("Priority=1000");
+	WriteDestFileLn("OverrideBuildCmd=0");
+	WriteDestFileLn("BuildCmd=");
+
+	WriteBlankLineToDestFile();
+}
+
+LOCALPROC WriteDevCSpecificFiles(void)
+{
+	WriteADstFile1("my_project_d",
+		vStrAppAbbrev, ".dev", "Project file",
+		WriteDevCProjectFile);
+}
--- /dev/null
+++ b/setup/WRLCCFLS.i
@@ -1,0 +1,252 @@
+/*
+	WRLCCFLS.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	WRite LCC-win32 specific FiLeS
+*/
+
+
+LOCALPROC DoSrcFileLccAddFile(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("File");
+	WriteUnsignedToOutput(FileCounter + 1);
+	WriteCStrToDestFile("=");
+	WriteSrcFileFilePath();
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteLccErrFileName(void)
+{
+	WriteStrAppAbbrev();
+	WriteCStrToDestFile(".err");
+}
+
+LOCALPROC WriteLccErrFilePath(void)
+{
+	WriteFileInDirToDestFile0(Write_obj_d_ToDestFile,
+		WriteLccErrFileName);
+}
+
+LOCALPROC WriteLccW32WorkSpaceFile(void)
+{
+	WriteDestFileLn("; Wedit project file. Syntax: Name = value");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("[");
+	WriteAppVariationStr();
+	WriteCStrToDestFile("]");
+	WriteEndDestFileLn();
+
+	DoAllSrcFilesWithSetup(NullProc);
+	++FileCounter; /* main.rc */
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("PrjFiles=");
+	WriteUnsignedToOutput(FileCounter);
+	WriteEndDestFileLn();
+
+	DoAllSrcFilesWithSetup(DoSrcFileLccAddFile);
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("File");
+	WriteUnsignedToOutput(++FileCounter);
+	WriteCStrToDestFile("=");
+	WriteMainRsrcSrcPath();
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("ProjectFlags=0");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("Name=");
+	WriteAppVariationStr();
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("ProjectPath=");
+	WriteCStrToDestFile("c:\\output");
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("SourcesDir=");
+	/* setting it to my_c_src_d does not work */
+	WriteCStrToDestFile("c:\\output");
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("Includes=");
+	Write_cfg_d_ToDestFile();
+	WriteCStrToDestFile(" ");
+	Write_src_d_ToDestFile();
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("MakeDir=");
+	Write_obj_d_ToDestFile();
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("Exe=");
+	WriteAppNamePath();
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("DbgExeName=");
+	WriteAppNamePath();
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("DbgDir=");
+	Write_obj_d_ToDestFile();
+	WriteEndDestFileLn();
+
+	switch (gbo_dbg) {
+		case gbk_dbg_on:
+			WriteDestFileLn("CompilerFlags=6728");
+			break;
+		case gbk_dbg_test:
+			WriteDestFileLn("CompilerFlags=580");
+			break;
+		case gbk_dbg_off:
+			WriteDestFileLn("CompilerFlags=581");
+			break;
+	}
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("Libraries=");
+	WriteCStrToDestFile("shell32.lib ole32.lib uuid.lib winmm.lib");
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("ErrorFile=");
+	WriteLccErrFilePath();
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("CurrentFile=");
+	WriteCNFGGLOBPath();
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("OpenFiles=1");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("OpenFile1=");
+	WriteQuoteToDestFile();
+	WriteCNFGGLOBPath();
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(" 1 29 14 532 435");
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteLccW32SpecificFiles(void)
+{
+	WriteADstFile1("my_project_d",
+		vStrAppAbbrev, ".prj", "Project file",
+		WriteLccW32WorkSpaceFile);
+}
+
+
+LOCALPROC WriteMainRsrcObjLccbuild(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("lrc.exe -fo");
+	WriteMainRsrcObjPath();
+	WriteSpaceToDestFile();
+	WriteMainRsrcSrcPath();
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteLccW32clMakeFile(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile(
+		"# make file generated by gryphel build system");
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("mk_COptions= -c");
+	if (gbk_dbg_on != gbo_dbg) {
+		WriteCStrToDestFile(" -O");
+	} else {
+		WriteCStrToDestFile(" -g4");
+	}
+	WriteCStrToDestFile(" -A");
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("TheDefaultOutput:");
+	WriteMakeDependFile(WriteAppNamePath);
+	WriteEndDestFileLn();
+	WriteBlankLineToDestFile();
+	WriteBlankLineToDestFile();
+	DoAllSrcFilesWithSetup(DoSrcFileMakeCompile);
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("ObjFiles=\\");
+	++DestFileIndent;
+		DoAllSrcFilesStandardMakeObjects();
+		WriteBlankLineToDestFile();
+	--DestFileIndent;
+
+	WriteBlankLineToDestFile();
+	WriteBlankLineToDestFile();
+	WriteMakeRule(WriteMainRsrcObjPath,
+		WriteMainRsrcObjMSCdeps, WriteMainRsrcObjLccbuild);
+	WriteBlankLineToDestFile();
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteAppNamePath();
+	WriteCStrToDestFile(": $(ObjFiles) ");
+	WriteMainRsrcObjPath();
+	WriteEndDestFileLn();
+
+	++DestFileIndent;
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("lcclnk.exe");
+		if (gbk_dbg_on != gbo_dbg) {
+			WriteCStrToDestFile(" -s");
+		}
+		WriteCStrToDestFile(" -subsystem windows -o ");
+		WriteAppNamePath();
+		WriteCStrToDestFile(" $(ObjFiles) ");
+		WriteMainRsrcObjPath();
+		WriteCStrToDestFile(" \\");
+		WriteEndDestFileLn();
+		++DestFileIndent;
+			WriteDestFileLn(
+				"shell32.lib winmm.lib ole32.lib uuid.lib");
+		--DestFileIndent;
+	--DestFileIndent;
+	WriteBlankLineToDestFile();
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("clean:");
+	++DestFileIndent;
+		DoAllSrcFilesStandardErase();
+		WriteRmFile(WriteMainRsrcObjPath);
+		WriteRmFile(WriteAppNamePath);
+	--DestFileIndent;
+}
+
+LOCALPROC WriteLccW32clSpecificFiles(void)
+{
+	WriteADstFile1("my_project_d",
+		"Makefile", "", "Make file",
+		WriteLccW32clMakeFile);
+}
--- /dev/null
+++ b/setup/WRMACRES.i
@@ -1,0 +1,321 @@
+/*
+	WRMACRES.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	WRite MACintosh RESources configuration
+*/
+
+
+LOCALPROC WriteBeginResResource(char *types, int id)
+{
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("resource '");
+	WriteCStrToDestFile(types);
+	WriteSingleQuoteToDestFile();
+	WriteCStrToDestFile(" (");
+	WriteUnsignedToOutput(id);
+	WriteCStrToDestFile(") {");
+	WriteEndDestFileLn();
+	++DestFileIndent;
+}
+
+LOCALPROC WriteEndResResource(void)
+{
+	--DestFileIndent;
+	WriteDestFileLn("};");
+}
+
+LOCALPROC WriteQuotedInclude(char *name)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#include ");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(name);
+	WriteQuoteToDestFile();
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteResTypeComma(char *types)
+{
+	WriteBgnDestFileLn();
+	WriteSingleQuoteToDestFile();
+	WriteCStrToDestFile(types);
+	WriteSingleQuoteToDestFile();
+	WriteCStrToDestFile(",");
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteAFREFres(char *types, int i)
+{
+	WriteBeginResResource("FREF", 128 + i);
+		WriteResTypeComma(types);
+
+		WriteBgnDestFileLn();
+		WriteUnsignedToOutput(i);
+		WriteCStrToDestFile(",");
+		WriteEndDestFileLn();
+
+		WriteBgnDestFileLn();
+		WriteQuoteToDestFile();
+		WriteQuoteToDestFile();
+		WriteEndDestFileLn();
+	WriteEndResResource();
+}
+
+LOCALPROC WriteDocTypeDefIconId(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#define ");
+	WriteDocTypeIconShortName();
+	WriteCStrToDestFile("IconId ");
+	WriteUnsignedToOutput(128 + DocTypeCounter);
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteDocTypeFREFres(void)
+{
+	WriteAFREFres(DoDocType_gd()->MacType, DocTypeCounter);
+}
+
+LOCALPROC WriteDocTypeBNDLFREF(void)
+{
+	WriteBgnDestFileLn();
+	if (0 != DocTypeCounter) {
+		WriteCStrToDestFile(",");
+	}
+	WriteUnsignedToOutput(DocTypeCounter);
+	WriteCStrToDestFile(", ");
+	WriteUnsignedToOutput(128 + DocTypeCounter);
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteDocTypeBNDLICN(void)
+{
+	WriteBgnDestFileLn();
+	if (0 != DocTypeCounter) {
+		WriteCStrToDestFile(",");
+	}
+	WriteUnsignedToOutput(DocTypeCounter);
+	WriteCStrToDestFile(", ");
+	WriteDocTypeIconShortName();
+	WriteCStrToDestFile("IconId");
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteDocTypeIncludeIconFile(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("#include ");
+	WriteQuoteToDestFile();
+	WriteDocTypeIconFileName();
+	WriteQuoteToDestFile();
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteMacResConfigContents(void)
+{
+	WriteBlankLineToDestFile();
+	if (gbk_ide_mw8 == cur_ide) {
+		if (gbk_targfam_mach == gbo_targfam) {
+			WriteDestFileLn("#include <Carbon/Carbon.r>");
+		} else {
+			WriteQuotedInclude("Types.r");
+			WriteQuotedInclude("Icons.r");
+		}
+	} else
+	if ((gbk_ide_bgc == cur_ide)
+		|| (gbk_ide_xcd == cur_ide)
+		|| (gbk_ide_mvc == cur_ide))
+	{
+		WriteQuotedInclude("Carbon.r");
+	} else
+	if (gbk_ide_mpw == cur_ide) {
+		WriteQuotedInclude("Types.r");
+		WriteQuotedInclude("Icons.r");
+	}
+
+	WriteBlankLineToDestFile();
+
+	WriteCDefQuote("kStrAppName", WriteStrAppUnabrevName);
+	WriteCDefQuote("kAppVariationStr", WriteAppVariationStr);
+	WriteCDefQuote("kStrCopyrightYear", WriteAppCopyrightYearStr);
+	WriteCDefQuote("kStrHomePage", WriteHomePage);
+
+	if (gbk_targfam_mach != gbo_targfam) {
+		if (gbk_targfam_carb == gbo_targfam) {
+			WriteBlankLineToDestFile();
+			WriteDestFileLn("data 'plst' (0) {");
+			++DestFileIndent;
+				WriteDestFileLn("$\"00\"");
+			--DestFileIndent;
+			WriteDestFileLn("};");
+		}
+
+		WriteBlankLineToDestFile();
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("data '");
+		WriteCStrToDestFile(kMacCreatorSig);
+		WriteCStrToDestFile("' (0, \"Owner resource\") {");
+		WriteEndDestFileLn();
+		++DestFileIndent;
+			WriteDestFileLn("$\"00\"");
+		--DestFileIndent;
+		WriteDestFileLn("};");
+
+		WriteBeginResResource("vers", 1);
+			WriteBgnDestFileLn();
+			WriteDec2CharToOutput(MajorVersion);
+			WriteCStrToDestFile(",");
+			WriteEndDestFileLn();
+
+			WriteBgnDestFileLn();
+			WriteDec2CharToOutput(MinorVersion);
+#if 0
+			WriteCStrToDestFile(" * 16 + ");
+			WriteCStrToDestFile(kMinorSubVersion);
+#endif
+			WriteCStrToDestFile(",");
+			WriteEndDestFileLn();
+
+			WriteDestFileLn("release,");
+			WriteDestFileLn("0x0,");
+			WriteDestFileLn("0,");
+
+			WriteBgnDestFileLn();
+			WriteQuoteToDestFile();
+			WriteVersionStr();
+			WriteQuoteToDestFile();
+			WriteCStrToDestFile(",");
+			WriteEndDestFileLn();
+
+			WriteBgnDestFileLn();
+			WriteQuoteToDestFile();
+			WriteGetInfoString();
+			WriteQuoteToDestFile();
+			WriteEndDestFileLn();
+		WriteEndResResource();
+
+#if 0
+		WriteBeginResResource("vers", 2);
+			WriteDestFileLn("0x0,");
+			WriteDestFileLn("0x0,");
+			WriteDestFileLn("release,");
+			WriteDestFileLn("0x0,");
+			WriteDestFileLn("0,");
+			WriteBgnDestFileLn();
+			WriteQuoteToDestFile();
+			WriteQuoteToDestFile();
+			WriteCStrToDestFile(",");
+			WriteEndDestFileLn();
+			WriteBgnDestFileLn();
+			WriteQuoteToDestFile();
+			WriteCStrToDestFile(kShortDescription);
+			WriteQuoteToDestFile();
+			WriteEndDestFileLn();
+		WriteEndResResource();
+#endif
+
+		if (gbk_ide_mw8 != cur_ide) {
+			WriteBlankLineToDestFile();
+			WriteDestFileLn("resource 'SIZE' (-1) {");
+			++DestFileIndent;
+				WriteDestFileLn("reserved,");
+				WriteDestFileLn("acceptSuspendResumeEvents,");
+				WriteDestFileLn("reserved,");
+				WriteDestFileLn("canBackground,");
+				WriteDestFileLn("multiFinderAware,");
+				WriteDestFileLn("backgroundAndForeground,");
+				WriteDestFileLn("dontGetFrontClicks,");
+				WriteDestFileLn("ignoreChildDiedEvents,");
+				WriteDestFileLn("is32BitCompatible,");
+
+				/*
+					following 4 should be "reserved"
+					if api not available
+				*/
+				WriteDestFileLn("isHighLevelEventAware,");
+				WriteDestFileLn("localAndRemoteHLEvents,");
+				WriteDestFileLn("isStationeryAware,");
+				WriteDestFileLn("useTextEditServices,");
+
+				WriteDestFileLn("reserved,");
+				WriteDestFileLn("reserved,");
+				WriteDestFileLn("reserved,");
+
+				WriteBgnDestFileLn();
+				WriteUnsignedToOutput(TotMemSize + (2UL * 1024 * 1024));
+				WriteCStrToDestFile(",");
+				WriteEndDestFileLn();
+
+				WriteBgnDestFileLn();
+				WriteUnsignedToOutput(TotMemSize + (512UL * 1024));
+				WriteEndDestFileLn();
+			WriteEndResResource();
+		}
+
+		WriteBlankLineToDestFile();
+		DoAllDocTypesWithSetup(WriteDocTypeDefIconId);
+
+
+		DoAllDocTypesWithSetup(WriteDocTypeFREFres);
+		WriteAFREFres("****", DocTypeCounter);
+
+		WriteBeginResResource("BNDL", 128);
+			WriteResTypeComma(kMacCreatorSig);
+
+			WriteDestFileLn("0,");
+			WriteDestFileLn("{");
+			++DestFileIndent;
+				WriteResTypeComma("FREF");
+
+				WriteDestFileLn("{");
+				++DestFileIndent;
+					DoAllDocTypesWithSetup(WriteDocTypeBNDLFREF);
+					WriteDocTypeBNDLFREF();
+				--DestFileIndent;
+				WriteDestFileLn("},");
+
+				WriteResTypeComma("ICN#");
+
+				WriteDestFileLn("{");
+				++DestFileIndent;
+					DoAllDocTypesWithSetup(WriteDocTypeBNDLICN);
+					WriteBgnDestFileLn();
+					WriteCStrToDestFile(",");
+					WriteUnsignedToOutput(DocTypeCounter);
+					WriteCStrToDestFile(", 0");
+					WriteEndDestFileLn();
+				--DestFileIndent;
+				WriteDestFileLn("}");
+			--DestFileIndent;
+			WriteDestFileLn("}");
+		WriteEndResResource();
+
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("#define SmallIconAPIAvail 1");
+		WriteDestFileLn("#define ColorIconAPIAvail 1");
+
+		WriteBlankLineToDestFile();
+		DoAllDocTypesWithSetup(WriteDocTypeIncludeIconFile);
+	}
+}
+
+LOCALPROC WriteCommonCNFGRSRC(void)
+{
+	WriteADstFile1("my_config_d",
+		"CNFGRSRC", ".h", " Configuration file",
+		WriteMacResConfigContents);
+}
--- /dev/null
+++ b/setup/WRMPLIST.i
@@ -1,0 +1,314 @@
+/*
+	WRMPLIST.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	WRite Macintosh PLIST
+*/
+
+
+enum {
+	kPListRaw, /* native plist data */
+	kPListPLC, /* metrowerks property list compiler */
+	kNumPListFormats
+};
+
+LOCALVAR int CurPListFormat = kPListPLC;
+
+LOCALPROC WritePListProcString(MyProc p)
+{
+	if (CurPListFormat == kPListRaw) {
+		WriteXMLtagBeginProcValEndLine("string", p);
+	} else {
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("string ");
+		WriteQuoteToDestFile();
+		p();
+		WriteQuoteToDestFile();
+		WriteEndDestFileLn();
+	}
+}
+
+LOCALPROC WritePListString(char *s)
+{
+	MyPtr SavepDt = pDt;
+
+	pDt = (MyPtr)s;
+	WritePListProcString(WritepDtString);
+	pDt = SavepDt;
+}
+
+LOCALPROC WritePListKeyProcString(char *k, MyProc p)
+{
+	if (CurPListFormat == kPListRaw) {
+		WriteXMLtagBeginValEndLine("key", k);
+		WriteXMLtagBeginProcValEndLine("string", p);
+	} else {
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("key ");
+		WriteQuoteToDestFile();
+		WriteCStrToDestFile(k);
+		WriteQuoteToDestFile();
+		WriteCStrToDestFile(" value string ");
+		WriteQuoteToDestFile();
+		p();
+		WriteQuoteToDestFile();
+		WriteEndDestFileLn();
+	}
+}
+
+LOCALPROC WritePListKeyString(char *k, char *s)
+{
+	MyPtr SavepDt = pDt;
+
+	pDt = (MyPtr)s;
+	WritePListKeyProcString(k, WritepDtString);
+	pDt = SavepDt;
+}
+
+LOCALPROC WritePListBeginKeyArray(char *k)
+{
+	if (CurPListFormat == kPListRaw) {
+		WriteXMLtagBeginValEndLine("key", k);
+		WriteBeginXMLtagLine("array");
+	} else {
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("key ");
+		WriteQuoteToDestFile();
+		WriteCStrToDestFile(k);
+		WriteQuoteToDestFile();
+		WriteCStrToDestFile(" value array");
+		WriteEndDestFileLn();
+		WriteDestFileLn("[");
+		++DestFileIndent;
+	}
+}
+
+LOCALPROC WritePListEndKeyArray(void)
+{
+	if (CurPListFormat == kPListRaw) {
+		WriteEndXMLtagLine("array");
+	} else {
+		--DestFileIndent;
+		WriteDestFileLn("]");
+	}
+}
+
+LOCALPROC WritePListBeginDict(void)
+{
+	if (CurPListFormat == kPListRaw) {
+		WriteBeginXMLtagLine("dict");
+	} else {
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("dictionary");
+		WriteEndDestFileLn();
+		WriteDestFileLn("{");
+		++DestFileIndent;
+	}
+}
+
+LOCALPROC WritePListEndDict(void)
+{
+	if (CurPListFormat == kPListRaw) {
+		WriteEndXMLtagLine("dict");
+	} else {
+		--DestFileIndent;
+		WriteDestFileLn("}");
+	}
+}
+
+LOCALPROC WriteInfoPList(MyProc p)
+{
+	CurPListFormat = kPListRaw;
+
+	WriteDestFileLn("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+#if 0
+	WriteDestFileLn(
+		"<!DOCTYPE plist SYSTEM \"file://"
+		"localhost/System/Library/DTDs/PropertyList.dtd\">");
+	WriteDestFileLn("<plist version=\"0.9\">");
+#else
+	if ((gbk_ide_xcd == cur_ide) && (ide_vers >= 3100)) {
+		WriteDestFileLn(
+			"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\""
+			" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">");
+	} else {
+		WriteDestFileLn(
+			"<!DOCTYPE plist PUBLIC \"-//"
+			"Apple Computer//DTD PLIST 1.0//EN\""
+			" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">");
+	}
+	WriteDestFileLn("<plist version=\"1.0\">");
+#endif
+
+	p();
+
+	WriteDestFileLn("</plist>");
+}
+
+LOCALPROC WriteMainPLC(MyProc p)
+{
+	CurPListFormat = kPListPLC;
+
+	WriteDestFileLn("plist");
+	WriteDestFileLn("{");
+	++DestFileIndent;
+
+	p();
+
+	--DestFileIndent;
+	WriteDestFileLn("}");
+}
+
+LOCALPROC WritepDtIconTypeName(void)
+{
+	WriteStrAppUnabrevName();
+	WriteSpaceToDestFile();
+	WriteCStrToDestFile(DoDocType_gd()->LongName);
+}
+
+LOCALPROC WriteOneExtension2Array(char *s)
+{
+	WritePListString(s);
+}
+
+LOCALPROC WriteOneCFBundleDocumentType(void)
+{
+	if (0 != DocTypeCounter) {
+		WritePListBeginDict();
+			if (DoDocType_gd()->WriteExtensionList != nullpr) {
+				WritePListBeginKeyArray("CFBundleTypeExtensions");
+					DoDocType_gd()->WriteExtensionList(
+						WriteOneExtension2Array);
+				WritePListEndKeyArray();
+			}
+			WritePListKeyProcString("CFBundleTypeIconFile",
+				WriteDocTypeIconFileName);
+			WritePListKeyProcString("CFBundleTypeName",
+				WritepDtIconTypeName);
+			WritePListBeginKeyArray("CFBundleTypeOSTypes");
+				WritePListProcString(WriteDocTypeIconMacType);
+			WritePListEndKeyArray();
+			WritePListKeyString("CFBundleTypeRole", "Editor");
+		WritePListEndDict();
+	}
+}
+
+LOCALPROC WriteTheBundleIdentifier(void)
+{
+	WriteCStrToDestFile(kBundleIdentifier);
+	if (WantIconMaster) {
+		WriteCStrToDestFile(".im");
+	}
+}
+
+LOCALPROC WriteMyInfoPListContents(void)
+{
+	WritePListBeginDict();
+
+		/* in order preferred by latest xcode (alphabetical) */
+
+		WritePListKeyString("CFBundleDevelopmentRegion", "English");
+
+		WritePListBeginKeyArray("CFBundleDocumentTypes");
+			WritePListBeginDict();
+				WritePListBeginKeyArray("CFBundleTypeOSTypes");
+					WritePListString("****");
+				WritePListEndKeyArray();
+				WritePListKeyString("CFBundleTypeRole", "Editor");
+			WritePListEndDict();
+			DoAllDocTypesWithSetup(WriteOneCFBundleDocumentType);
+		WritePListEndKeyArray();
+
+		WritePListKeyString("CFBundleExecutable", vStrAppAbbrev);
+		WritePListKeyProcString("CFBundleGetInfoString",
+			WriteGetInfoString);
+		WritePListKeyString("CFBundleIconFile", "ICONAPPO.icns");
+		WritePListKeyProcString("CFBundleIdentifier",
+			WriteTheBundleIdentifier);
+		WritePListKeyString("CFBundleInfoDictionaryVersion", "6.0");
+		WritePListKeyProcString("CFBundleName", WriteStrAppUnabrevName);
+		WritePListKeyString("CFBundlePackageType", "APPL");
+		WritePListKeyProcString("CFBundleShortVersionString",
+			WriteVersionStr);
+		WritePListKeyProcString("CFBundleSignature",
+			Write_MacCreatorSigOrGeneric);
+		WritePListKeyProcString("CFBundleVersion", WriteVersionStr);
+		WritePListKeyString("LSRequiresCarbon", "1");
+		if (gbk_apifam_cco == gbo_apifam) {
+			WritePListKeyString("NSHighResolutionCapable", "1");
+		}
+		if (WantGraphicsSwitching) {
+			WritePListKeyString("NSSupportsAutomaticGraphicsSwitching",
+				"1");
+		}
+		if (gbk_apifam_sd2 == gbo_apifam) {
+			WritePListKeyString("SDL_FILESYSTEM_BASE_DIR_TYPE",
+				"parent");
+		}
+
+	WritePListEndDict();
+}
+
+LOCALPROC WriteMainPLCData(void)
+{
+	/* plist source */
+	WriteMainPLC(WriteMyInfoPListContents);
+}
+
+LOCALPROC WriteInfoPListData(void)
+{
+	/* Info.plist file */
+	WriteInfoPList(WriteMyInfoPListContents);
+}
+
+LOCALPROC WritePListData(void)
+{
+	if (gbk_ide_mw8 == cur_ide) {
+		WriteADstFile1("my_config_d",
+			"main", ".plc", "plist source",
+			WriteMainPLCData);
+	} else
+	{
+		WriteADstFile1("my_config_d",
+			"Info", ".plist", "plist source",
+			WriteInfoPListData);
+	}
+}
+
+LOCALPROC WriteEntitlementsData(void)
+{
+	WriteOpenDestFile("my_config_d",
+		vStrAppAbbrev, ".entitlements", "entitlements");
+
+	WriteDestFileLn("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+	WriteDestFileLn(
+		"<!DOCTYPE plist PUBLIC"
+		" \"-//Apple//DTD PLIST 1.0//EN\""
+		" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">");
+	WriteDestFileLn("<plist version=\"1.0\">");
+	WriteDestFileLn("<dict>");
+	++DestFileIndent;
+		WriteDestFileLn("<key>com.apple.security.app-sandbox</key>");
+		WriteDestFileLn("<true/>");
+		WriteDestFileLn("<key>"
+			"com.apple.security.files.user-selected.read-write"
+			"</key>");
+		WriteDestFileLn("<true/>");
+	--DestFileIndent;
+	WriteDestFileLn("</dict>");
+	WriteDestFileLn("</plist>");
+
+	WriteCloseDestFile();
+}
--- /dev/null
+++ b/setup/WRMPWFLS.i
@@ -1,0 +1,360 @@
+/*
+	WRMPWFLS.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	WRite Macintosh Programmer's Workshop specific FiLeS
+*/
+
+
+LOCALPROC WriteLONGGLUEContents(void)
+{
+	++DestFileIndent;
+		WriteDestFileLn("CASE ON");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("IMPORT long_main: CODE ");
+		WriteBlankLineToDestFile();
+	--DestFileIndent;
+	WriteDestFileLn("main PROC EXPORT");
+	++DestFileIndent;
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("JMP (long_main).L");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("ENDP");
+		WriteBlankLineToDestFile();
+		WriteDestFileLn("END");
+	--DestFileIndent;
+}
+
+LOCALPROC WriteLongGlueObjName(void)
+{
+	WriteCStrToDestFile("LONGGLUE.o");
+}
+
+LOCALPROC WriteLongGlueObjPath(void)
+{
+	WriteFileInDirToDestFile0(Write_obj_d_ToDestFile,
+		WriteLongGlueObjName);
+}
+
+LOCALPROC WriteLongGlueSourceName(void)
+{
+	WriteCStrToDestFile("LONGGLUE.S");
+}
+
+LOCALPROC WriteLongGlueSourcePath(void)
+{
+	WriteFileInDirToDestFile0(Write_cfg_d_ToDestFile,
+		WriteLongGlueSourceName);
+}
+
+LOCALPROC DoLongGlueMakeCompileDeps(void)
+{
+	WriteMakeDependFile(WriteLongGlueSourcePath);
+}
+
+LOCALPROC DoLongGlueMakeCompileBody(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("Asm");
+	WritePathArgInMakeCmnd(WriteLongGlueSourcePath);
+	WriteCStrToDestFile(" -o");
+	WritePathArgInMakeCmnd(WriteLongGlueObjPath);
+	WriteCStrToDestFile(" -model far");
+	WriteEndDestFileLn();
+}
+
+LOCALPROC DoSrcFileMPWMakeObjects(void)
+{
+	WriteBgnDestFileLn();
+	WriteQuoteToDestFile();
+	WriteSrcFileObjPath();
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(" \266");
+	WriteEndDestFileLn();
+}
+
+static void WriteMPWCOptions(blnr fast)
+{
+	if (gbk_cpufam_68k == gbo_cpufam) {
+		WriteCStrToDestFile(" -proto strict -w 17 -align mac68k -b");
+		if (gbk_targ_mfpu == cur_targ) {
+			WriteCStrToDestFile(" -mc68020 -mc68881 -elems881");
+		}
+		if (gbk_dbg_on != gbo_dbg) {
+			WriteCStrToDestFile(" -mbg off");
+		}
+		WriteCStrToDestFile(" -model farCode");
+	} else if (gbk_cpufam_ppc == gbo_cpufam) {
+		WriteCStrToDestFile(" -proto strict -w 17");
+		if (gbk_dbg_on == gbo_dbg) {
+			WriteCStrToDestFile(" -traceback");
+		}
+	}
+	if (gbk_dbg_on != gbo_dbg) {
+		if (fast) {
+			if (gbk_cpufam_68k == gbo_cpufam) {
+				WriteCStrToDestFile(" -opt speed");
+			} else if (gbk_cpufam_ppc == gbo_cpufam) {
+				WriteCStrToDestFile(" -opt speed");
+			}
+		} else {
+			if (gbk_cpufam_68k == gbo_cpufam) {
+				WriteCStrToDestFile(" -opt space");
+			} else if (gbk_cpufam_ppc == gbo_cpufam) {
+				WriteCStrToDestFile(" -opt size");
+				/* this may not be reliable? */
+			}
+		}
+	}
+
+	WriteCStrToDestFile(" -i ");
+	WriteQuoteToDestFile();
+	Write_cfg_d_ToDestFile();
+	WriteQuoteToDestFile();
+
+	WriteCStrToDestFile(" -i ");
+	WriteQuoteToDestFile();
+	Write_src_d_ToDestFile();
+	WriteQuoteToDestFile();
+}
+
+LOCALPROC WriteMainRsrcObjDeps(void)
+{
+	WriteMakeDependFile(WriteMainRsrcSrcPath);
+}
+
+LOCALPROC WriteMainRsrcObjMPWbody(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("Rez -t rsrc -c RSED -i \"{RIncludes}\"");
+
+	WriteCStrToDestFile(" -i ");
+	WriteQuoteToDestFile();
+	Write_cfg_d_ToDestFile();
+	WriteQuoteToDestFile();
+
+	WriteCStrToDestFile(" -i ");
+	WriteQuoteToDestFile();
+	Write_src_d_ToDestFile();
+	WriteQuoteToDestFile();
+
+	WriteCStrToDestFile(" ");
+	WriteQuoteToDestFile();
+	WriteMainRsrcSrcPath();
+	WriteQuoteToDestFile();
+
+	WriteCStrToDestFile(" -o ");
+	WriteQuoteToDestFile();
+	WriteMainRsrcObjPath();
+	WriteQuoteToDestFile();
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteMPWMakeFile(void)
+{
+	WriteDestFileLn("# make file generated by gryphel build system");
+
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("mk_COptions =");
+	WriteMPWCOptions(falseblnr);
+	WriteEndDestFileLn();
+	WriteBlankLineToDestFile();
+
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("TheDefaultOutput \304");
+	WriteMakeDependFile(Write_machobinpath_ToDestFile);
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+
+	if (gbk_cpufam_68k == gbo_cpufam) {
+		WriteMakeRule(WriteLongGlueObjPath,
+			DoLongGlueMakeCompileDeps,
+			DoLongGlueMakeCompileBody);
+	}
+
+	DoAllSrcFilesWithSetup(DoSrcFileMakeCompile);
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("ObjFiles = \266");
+	++DestFileIndent;
+		DoAllSrcFilesSortWithSetup(DoSrcFileMPWMakeObjects);
+		WriteBlankLineToDestFile();
+	--DestFileIndent;
+
+	if (HaveMacBundleApp) {
+		WriteBlankLineToDestFile();
+		WriteMakeRule(Write_machoAppIconPath,
+			Write_tmachoShellDeps,
+			Write_tmachoShell);
+	}
+
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("\"");
+	Write_machobinpath_ToDestFile();
+	WriteCStrToDestFile("\" \304");
+	WriteCStrToDestFile(" {ObjFiles}");
+	if (HaveMacBundleApp) {
+		WriteMakeDependFile(Write_machoAppIconPath);
+	} else {
+		WriteMakeDependFile(WriteMainRsrcObjPath);
+	}
+	if (gbk_cpufam_68k == gbo_cpufam) {
+		WritePathArgInMakeCmnd(WriteLongGlueObjPath);
+	}
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		if (HaveMacRrscs) {
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("Duplicate -y \"");
+			WriteMainRsrcObjPath();
+			WriteCStrToDestFile("\" \"");
+			Write_machobinpath_ToDestFile();
+			WriteCStrToDestFile("\"");
+			WriteEndDestFileLn();
+		}
+
+		WriteBgnDestFileLn();
+			if (gbk_cpufam_68k == gbo_cpufam) {
+				WriteCStrToDestFile("Link");
+				if (gbk_dbg_on != gbo_dbg) {
+					WriteCStrToDestFile(" -rn");
+				}
+				WriteCStrToDestFile(
+					" -model far -sg Main"
+					"=STDCLIB,SANELIB,CSANELib,SADEV,STDIO");
+			} else if (gbk_cpufam_ppc == gbo_cpufam) {
+				WriteCStrToDestFile("PPCLink");
+			}
+
+			if (gbk_targ_carb == cur_targ) {
+				WriteCStrToDestFile(" -m main");
+			}
+			WriteCStrToDestFile(" -t APPL -c ");
+			WriteCStrToDestFile(kMacCreatorSig);
+			WriteCStrToDestFile(" \266");
+		WriteEndDestFileLn();
+
+		++DestFileIndent;
+
+			WriteDestFileLn("{ObjFiles} \266");
+
+			if (gbk_targ_carb == cur_targ) {
+				WriteDestFileLn("\"{SharedLibraries}CarbonLib\" \266");
+#if UseOpenGLinOSX
+				WriteDestFileLn(
+					"\"{SharedLibraries}OpenGLLibraryStub\" \266");
+#endif
+				WriteDestFileLn("\"{PPCLibraries}PPCToolLibs.o\" \266");
+				WriteDestFileLn("\"{PPCLibraries}PPCCRuntime.o\" \266");
+				WriteDestFileLn("\"{SharedLibraries}StdCLib\" \266");
+			} else if (gbk_targ_mppc == cur_targ) {
+				WriteDestFileLn("\"{PPCLibraries}PPCToolLibs.o\" \266");
+				WriteDestFileLn("\"{PPCLibraries}PPCCRuntime.o\" \266");
+				WriteDestFileLn("\"{PPCLibraries}StdCRuntime.o\" \266");
+				WriteDestFileLn(
+					"\"{SharedLibraries}InterfaceLib\" \266");
+				WriteDestFileLn("\"{SharedLibraries}MathLib\" \266");
+				WriteDestFileLn("\"{SharedLibraries}StdCLib\" \266");
+				WriteDestFileLn("-weaklib AppearanceLib \266");
+				WriteDestFileLn(
+					"\"{SharedLibraries}AppearanceLib\" \266");
+				WriteDestFileLn("-weaklib MenusLib \266");
+				WriteDestFileLn("\"{SharedLibraries}MenusLib\" \266");
+				WriteDestFileLn("-weaklib NavigationLib \266");
+				WriteDestFileLn(
+					"\"{SharedLibraries}NavigationLib\" \266");
+				WriteDestFileLn("-weaklib DragLib \266");
+				WriteDestFileLn("\"{SharedLibraries}DragLib\" \266");
+				WriteDestFileLn("-weaklib WindowsLib \266");
+				WriteDestFileLn("\"{SharedLibraries}WindowsLib\" \266");
+			} else if (gbk_targ_m68k == cur_targ) {
+				WriteDestFileLn("\"{Libraries}Interface.o\" \266");
+				WriteDestFileLn("\"{Libraries}Navigation.o\" \266");
+				WriteDestFileLn("\"{Libraries}MacRuntime.o\" \266");
+				/* WriteDestFileLn("\"{Libraries}MathLib.o\" \266"); */
+			} else if (gbk_targ_mfpu == cur_targ) {
+				WriteDestFileLn("\"{Libraries}Interface.o\" \266");
+				WriteDestFileLn("\"{Libraries}Navigation.o\" \266");
+				WriteDestFileLn("\"{Libraries}MacRuntime.o\" \266");
+				/*
+					WriteDestFileLn("\"{Libraries}MathLib881.o\" \266");
+				*/
+			}
+			if (gbk_cpufam_68k == gbo_cpufam) {
+				WriteBgnDestFileLn();
+				WriteQuoteToDestFile();
+				WriteLongGlueObjPath();
+				WriteQuoteToDestFile();
+				WriteCStrToDestFile(" \266");
+				WriteEndDestFileLn();
+			}
+
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("-o");
+			WritePathArgInMakeCmnd(Write_machobinpath_ToDestFile);
+			WriteEndDestFileLn();
+		--DestFileIndent;
+
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("SetFile -d . -m .");
+		if (! HaveMacBundleApp) {
+			WriteCStrToDestFile(" -a B");
+		}
+		WriteCStrToDestFile(" \"");
+		Write_machobinpath_ToDestFile();
+		WriteCStrToDestFile("\"");
+		WriteEndDestFileLn();
+	--DestFileIndent;
+
+	if (HaveMacRrscs) {
+		WriteBlankLineToDestFile();
+		WriteMakeRule(WriteMainRsrcObjPath,
+			WriteMainRsrcObjDeps, WriteMainRsrcObjMPWbody);
+	}
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("clean \304");
+	++DestFileIndent;
+		WriteDestFileLn("Delete -i {ObjFiles}");
+		if (HaveMacBundleApp) {
+			WriteRmDir(WriteAppNamePath);
+		} else {
+			WriteRmFile(WriteAppNamePath);
+			WriteRmFile(WriteMainRsrcObjPath);
+		}
+	--DestFileIndent;
+	WriteBlankLineToDestFile();
+}
+
+LOCALPROC WriteMPWSpecificFiles(void)
+{
+	if (gbk_cpufam_68k == gbo_cpufam) {
+		WriteADstFile1("my_config_d",
+			"LONGGLUE", ".S", "entry point glue for large program",
+			WriteLONGGLUEContents);
+	}
+
+	if (HaveMacBundleApp) {
+		WritePListData();
+	}
+
+	WriteADstFile1("my_project_d",
+		"Makefile", "", "Make file",
+		WriteMPWMakeFile);
+}
--- /dev/null
+++ b/setup/WRMSCFLS.i
@@ -1,0 +1,2005 @@
+/*
+	WRMSCFLS.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	WRite Microsoft C specific FiLeS
+*/
+
+
+LOCALPROC WriteMSVCQuotedDefine(char *s)
+{
+	WriteCStrToDestFile(" /D ");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(s);
+	WriteQuoteToDestFile();
+}
+
+LOCALPROC WriteCLexeFlags(void)
+{
+	blnr WinCE = (gbk_targfam_wnce == gbo_targfam);
+	WriteCStrToDestFile("/nologo");
+
+#if 0
+	if (gbk_dbg_on != gbo_dbg) {
+		/* Optimizations : Minimize Size */
+		WriteCStrToDestFile(" /O1");
+	} else
+#endif
+	{
+		/* Maximize chance of correct compile */
+		/* Optimizations : Disabled */
+		WriteCStrToDestFile(" /Od");
+	}
+	if (WinCE) {
+		WriteCStrToDestFile(
+			" /D _WIN32_WCE=420 /D WIN32_PLATFORM_PSPC=400"
+			" /D UNDER_CE=420");
+		if (gbk_cpufam_arm == gbo_cpufam) {
+			WriteCStrToDestFile(
+				" /D \"ARM\" /D \"_ARM_\" /D \"ARMV4\"");
+		} else {
+			WriteCStrToDestFile(
+				" /D \"_i386_\" /D \"_X86_\" /D \"x86\" /D \"i_386_\"");
+		}
+	} else {
+		WriteMSVCQuotedDefine("WIN32");
+		WriteMSVCQuotedDefine("_WINDOWS");
+	}
+	if (gbk_dbg_on == gbo_dbg) {
+		WriteMSVCQuotedDefine("_DEBUG");
+	} else {
+		WriteMSVCQuotedDefine("NDEBUG");
+	}
+	if (WinCE) {
+		WriteMSVCQuotedDefine("UNICODE");
+		WriteMSVCQuotedDefine("_UNICODE");
+	} else {
+		if (ide_vers >= 6000) {
+			WriteMSVCQuotedDefine("_MBCS");
+		}
+	}
+
+	if ((gbk_dbg_on == gbo_dbg) && (gbk_targ_wx86 == cur_targ)) {
+		WriteCStrToDestFile(" /Gm"); /* minimal rebuild */
+	}
+
+	/* WriteCStrToDestFile(" /GX"); enable exception handling */
+
+	if (WinCE) {
+		if (gbk_cpufam_x86 == gbo_cpufam) {
+			WriteCStrToDestFile(" /Gs8192");
+				/* in the default template. why? */
+		}
+	}
+
+	if (gbk_dbg_on == gbo_dbg) {
+		if (ide_vers >= 7000) {
+			WriteCStrToDestFile(" /RTC1");
+		} else {
+			WriteCStrToDestFile(" /GZ");
+		}
+	} else {
+		WriteCStrToDestFile(" /GF"); /* string pooling */
+	}
+
+	if (WinCE) {
+		if (gbk_cpufam_arm == gbo_cpufam) {
+			if (gbk_dbg_on == gbo_dbg) {
+				WriteCStrToDestFile(" /M$(CECrtMTDebug)");
+			} else {
+				WriteCStrToDestFile(" /MC");
+			}
+		}
+		/*
+			default template doesn't do this for
+			x86. why not?
+		*/
+	} else {
+		if (gbk_dbg_on == gbo_dbg) {
+			if ((ide_vers >= 8000)
+				|| (gbk_cpufam_x64 == gbo_cpufam))
+			{
+				WriteCStrToDestFile(" /MTd");
+			} else {
+				WriteCStrToDestFile(" /MLd");
+			}
+		} else {
+			if ((ide_vers >= 8000)
+				|| (gbk_cpufam_x64 == gbo_cpufam))
+			{
+				WriteCStrToDestFile(" /MT");
+			} else {
+				WriteCStrToDestFile(" /ML");
+			}
+		}
+	}
+
+#if 0
+	if (ide_vers < 8000) {
+		WriteCStrToDestFile(" /GS");
+			/* became default later */
+		/*
+			perhaps instead use /GS- in later versions
+			maybe this should be an option set in SPBASDEF
+		*/
+	}
+#endif
+
+	WriteCStrToDestFile(" /W4");
+
+	WriteCStrToDestFile(" /c");
+
+	if ((ide_vers >= 7000) && (ide_vers < 9000)) {
+		/* Detect 64-bit Portability Issues */
+		WriteCStrToDestFile(" /Wp64");
+	}
+
+	if (ide_vers >= 7000) {
+		/* and probably earlier, at least back to 6.0 */
+		/* Enable Function-Level Linking */
+		WriteCStrToDestFile(" /Gy");
+	}
+
+	if (gbk_dbg_on == gbo_dbg) {
+		/* Debug Information Format */
+		if (WinCE || (gbk_targ_wx64 == cur_targ)) {
+			WriteCStrToDestFile(" /Zi");
+		} else {
+			WriteCStrToDestFile(" /ZI");
+		}
+	}
+}
+
+LOCALPROC WriteRCexeFlags(void)
+{
+	blnr WinCE = (gbk_targfam_wnce == gbo_targfam);
+
+	WriteCStrToDestFile("/l 0x409 /d ");
+	WriteQuoteToDestFile();
+	if (gbk_dbg_on == gbo_dbg) {
+		WriteCStrToDestFile("_DEBUG");
+	} else {
+		WriteCStrToDestFile("NDEBUG");
+	}
+	WriteQuoteToDestFile();
+	if (WinCE) {
+		WriteCStrToDestFile(
+			" /d UNDER_CE=420 /d _WIN32_WCE=420 /d \"UNICODE\""
+			" /d \"_UNICODE\" /d WIN32_PLATFORM_PSPC=400 /r");
+		if (gbk_cpufam_arm == gbo_cpufam) {
+			WriteCStrToDestFile(
+				" /d \"ARM\" /d \"_ARM_\" /d \"ARMV4\"");
+		} else {
+			WriteCStrToDestFile(
+				" /d \"_i386_\" /d \"_X86_\" /d \"x86\"");
+		}
+	}
+}
+
+LOCALPROC WriteFileToMSVCSource(MyProc p)
+{
+	WriteDestFileLn("# Begin Source File");
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("SOURCE=");
+	p();
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("# End Source File");
+}
+
+LOCALPROC WriteDocTypeMSVCresource(void)
+{
+	WriteFileToMSVCSource(WriteDocTypeIconFilePath);
+}
+
+LOCALPROC WriteMSVCBeginGroup(char *group, char *filter)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("# Begin Group ");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(group);
+	WriteQuoteToDestFile();
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("# PROP Default_Filter ");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(filter);
+	WriteQuoteToDestFile();
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteMSVCEndGroup(void)
+{
+	WriteDestFileLn("# End Group");
+}
+
+LOCALPROC WriteMSVCdbgLevelName(void)
+{
+	char *s;
+
+	switch (gbo_dbg) {
+		case gbk_dbg_on:
+			s = "Debug";
+			break;
+		case gbk_dbg_test:
+			s = "Test";
+			break;
+		case gbk_dbg_off:
+			s = "Release";
+			break;
+		default:
+			s = "(unknown Debug Level)";
+			break;
+	}
+
+	WriteCStrToDestFile(s);
+}
+
+LOCALPROC WriteMSVCTargetName00(void)
+{
+	blnr WinCE = (gbk_targfam_wnce == gbo_targfam);
+	WriteCStrToDestFile("Win32");
+	if (WinCE) {
+		if (gbk_cpufam_arm == gbo_cpufam) {
+			WriteCStrToDestFile(" (WCE ARMV4)");
+		} else {
+			WriteCStrToDestFile(" (WCE emulator)");
+		}
+	} else {
+		WriteCStrToDestFile(" (x86)");
+	}
+}
+
+LOCALPROC WriteMSVCTargetName0(void)
+{
+	WriteStrAppAbbrev();
+	WriteCStrToDestFile(" - ");
+	WriteMSVCTargetName00();
+	WriteSpaceToDestFile();
+	WriteMSVCdbgLevelName();
+}
+
+LOCALPROC WriteMSVCTargetName(void)
+{
+	WriteQuoteToDestFile();
+	WriteMSVCTargetName0();
+	WriteQuoteToDestFile();
+}
+
+LOCALPROC WriteMSVCMakefileName(void)
+{
+	WriteQuoteToDestFile();
+	WriteStrAppAbbrev();
+	if (gbk_targfam_wnce == gbo_targfam) {
+		WriteCStrToDestFile(".vcn");
+	} else {
+		WriteCStrToDestFile(".mak");
+	}
+	WriteQuoteToDestFile();
+}
+
+LOCALPROC WriteMSVCQuotedProp(char *p, char *s)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("# PROP ");
+	WriteCStrToDestFile(p);
+	WriteSpaceToDestFile();
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(s);
+	WriteQuoteToDestFile();
+	WriteEndDestFileLn();
+}
+
+LOCALPROC DoSrcFileMSVCAddFile(void)
+{
+	WriteDestFileLn("# Begin Source File");
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("SOURCE=");
+	WriteSrcFileFilePath();
+	WriteEndDestFileLn();
+#if 0
+	if (gbk_dbg_on != gbo_dbg) {
+		if (fast) {
+			WriteDestFileLn("# ADD CPP /O2 /Ob2");
+		}
+	}
+#endif
+	WriteDestFileLn("# End Source File");
+}
+
+LOCALPROC DoSrcFileMSVCAddHeader(void)
+{
+	if ((DoSrcFile_gd()->Flgm & kCSrcFlgmNoHeader) == 0) {
+		WriteDestFileLn("# Begin Source File");
+		WriteBlankLineToDestFile();
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("SOURCE=");
+		WriteSrcFileHeaderPath();
+		WriteEndDestFileLn();
+		WriteDestFileLn("# End Source File");
+	}
+}
+
+LOCALPROC DoExtraHeaderMSVCAdd(void)
+{
+	WriteDestFileLn("# Begin Source File");
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("SOURCE=");
+	WriteExtraHeaderFilePath();
+	WriteEndDestFileLn();
+	WriteDestFileLn("# End Source File");
+}
+
+LOCALFUNC char * MSVCWorkspaceExt(void)
+{
+	return (gbk_targfam_wnce == gbo_targfam)
+		? ".vcw" : ".dsw";
+}
+
+LOCALFUNC char * MSVCProjectExt(void)
+{
+	return (gbk_targfam_wnce == gbo_targfam)
+		? ".vcp" : ".dsp";
+}
+
+LOCALPROC WriteMSVCWorkSpaceFile(void)
+{
+	blnr WinCE = (gbk_targfam_wnce == gbo_targfam);
+	if (WinCE) {
+		WriteDestFileLn(
+			"Microsoft eMbedded Visual Tools Workspace File,"
+			" Format Version 4.00");
+	} else {
+		WriteDestFileLn(
+			"Microsoft Developer Studio Workspace File,"
+			" Format Version 6.00");
+	}
+	WriteDestFileLn(
+		"# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!");
+	WriteBlankLineToDestFile();
+	WriteDestFileLn(
+		"############################################################"
+		"###################");
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("Project: ");
+	WriteQuoteToDestFile();
+	WriteStrAppAbbrev();
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile("=.");
+	WriteBackSlashToDestFile();
+	WriteStrAppAbbrev();
+	WriteCStrToDestFile(MSVCProjectExt());
+	WriteCStrToDestFile(" - Package Owner=<4>");
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("Package=<5>");
+	WriteDestFileLn("{{{");
+	WriteDestFileLn("}}}");
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("Package=<4>");
+	WriteDestFileLn("{{{");
+	WriteDestFileLn("}}}");
+	WriteBlankLineToDestFile();
+	WriteDestFileLn(
+		"############################################################"
+		"###################");
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("Global:");
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("Package=<5>");
+	WriteDestFileLn("{{{");
+	WriteDestFileLn("}}}");
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("Package=<3>");
+	WriteDestFileLn("{{{");
+	WriteDestFileLn("}}}");
+	WriteBlankLineToDestFile();
+	WriteDestFileLn(
+		"############################################################"
+		"###################");
+	WriteBlankLineToDestFile();
+}
+
+LOCALPROC WriteMSVCProjectFile(void)
+{
+	blnr WinCE = (gbk_targfam_wnce == gbo_targfam);
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("# Microsoft ");
+	if (WinCE) {
+		WriteCStrToDestFile("eMbedded Visual Tools");
+	} else {
+		WriteCStrToDestFile("Developer Studio");
+	}
+	WriteCStrToDestFile(" Project File - Name=");
+	WriteQuoteToDestFile();
+	WriteStrAppAbbrev();
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(" - Package Owner=<4>");
+	WriteEndDestFileLn();
+
+	if (WinCE) {
+		WriteDestFileLn(
+			"# Microsoft eMbedded Visual Tools Generated Build File,"
+			" Format Version 6.02");
+	} else {
+		WriteDestFileLn(
+			"# Microsoft Developer Studio Generated Build File,"
+			" Format Version 6.00");
+	}
+	WriteDestFileLn("# ** DO NOT EDIT **");
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("# TARGTYPE ");
+	WriteQuoteToDestFile();
+	WriteMSVCTargetName00();
+	WriteCStrToDestFile(" Application");
+	WriteQuoteToDestFile();
+	if (WinCE) {
+		if (gbk_cpufam_arm == gbo_cpufam) {
+			WriteCStrToDestFile(" 0xa301");
+		} else {
+			WriteCStrToDestFile(" 0xa601");
+		}
+	} else {
+		WriteCStrToDestFile(" 0x0101");
+	}
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("CFG=");
+	/* WriteAppVariationStr(); */
+	WriteMSVCTargetName0();
+	WriteEndDestFileLn();
+
+	WriteDestFileLn(
+		"!MESSAGE This is not a valid makefile."
+		" To build this project using NMAKE,");
+	WriteDestFileLn("!MESSAGE use the Export Makefile command and run");
+	WriteDestFileLn("!MESSAGE ");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("!MESSAGE NMAKE /f ");
+	WriteMSVCMakefileName();
+	WriteCStrToDestFile(".");
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("!MESSAGE ");
+	WriteDestFileLn(
+		"!MESSAGE You can specify a configuration when running NMAKE");
+	WriteDestFileLn(
+		"!MESSAGE by defining the macro CFG on the command line."
+		" For example:");
+	WriteDestFileLn("!MESSAGE ");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("!MESSAGE NMAKE /f ");
+	WriteMSVCMakefileName();
+	WriteCStrToDestFile(" CFG=");
+	WriteMSVCTargetName();
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("!MESSAGE ");
+	WriteDestFileLn("!MESSAGE Possible choices for configuration are:");
+	WriteDestFileLn("!MESSAGE ");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("!MESSAGE ");
+	WriteMSVCTargetName();
+	WriteCStrToDestFile(" (based on ");
+	WriteQuoteToDestFile();
+	WriteMSVCTargetName00();
+	WriteCStrToDestFile(" Application");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(")");
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("!MESSAGE ");
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("# Begin Project");
+	WriteDestFileLn("# PROP AllowPerConfigDependencies 0");
+
+	WriteMSVCQuotedProp("Scc_ProjName", "");
+	WriteMSVCQuotedProp("Scc_LocalPath", "");
+
+	if (WinCE) {
+		WriteDestFileLn("# PROP ATL_Project 2"); /* not needed ? */
+	}
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("CPP=");
+	WriteCompileCExec();
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("MTL=midl.exe");
+	WriteDestFileLn("RSC=rc.exe");
+	WriteDestFileLn("# PROP BASE Use_MFC 0");
+	WriteDestFileLn("# PROP BASE Use_Debug_Libraries 1");
+
+	WriteMSVCQuotedProp("BASE Output_Dir", "Debug");
+	WriteMSVCQuotedProp("BASE Intermediate_Dir", "Debug");
+	WriteMSVCQuotedProp("BASE Target_Dir", "");
+
+	WriteDestFileLn("# PROP Use_MFC 0");
+	if (gbk_dbg_on == gbo_dbg) {
+		WriteDestFileLn("# PROP Use_Debug_Libraries 1");
+	} else {
+		WriteDestFileLn("# PROP Use_Debug_Libraries 0");
+	}
+
+	WriteMSVCQuotedProp("Output_Dir", obj_d_name);
+	WriteMSVCQuotedProp("Intermediate_Dir", obj_d_name);
+
+	WriteDestFileLn("# PROP Ignore_Export_Lib 0");
+
+	WriteMSVCQuotedProp("Target_Dir", "");
+
+	WriteDestFileLn("# ADD BASE CPP");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("# ADD CPP ");
+	WriteCLexeFlags();
+	if (! WinCE) {
+		WriteCStrToDestFile(" /FD");
+	}
+	WriteCStrToDestFile(" /I ");
+	WriteQuoteToDestFile();
+	Write_cfg_d_ToDestFile();
+	WriteQuoteToDestFile();
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("# ADD BASE MTL");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("# ADD MTL /nologo /D ");
+	WriteQuoteToDestFile();
+	if (gbk_dbg_on == gbo_dbg) {
+		WriteCStrToDestFile("_DEBUG");
+	} else {
+		WriteCStrToDestFile("NDEBUG");
+	}
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(" /mktyplib203 /win32");
+	if (WinCE) {
+		WriteCStrToDestFile(" /o \"NUL\"");
+	}
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("# ADD BASE RSC");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("# ADD RSC ");
+	WriteRCexeFlags();
+	WriteCStrToDestFile(" /I ");
+	WriteQuoteToDestFile();
+	Write_src_d_ToDestFile();
+	WriteQuoteToDestFile();
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("BSC32=bscmake.exe");
+	WriteDestFileLn("# ADD BASE BSC32");
+	WriteDestFileLn("# ADD BSC32 /nologo");
+	WriteDestFileLn("LINK32=link.exe");
+	WriteDestFileLn("# ADD BASE LINK32");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("# ADD LINK32");
+	if (WinCE) {
+		WriteCStrToDestFile(
+			" commctrl.lib coredll.lib aygshell.lib Mmtimer.lib");
+	} else {
+		WriteCStrToDestFile(
+			" kernel32.lib user32.lib gdi32.lib"
+			" winspool.lib comdlg32.lib advapi32.lib shell32.lib"
+			" ole32.lib oleaut32.lib uuid.lib winmm.lib");
+	}
+	WriteCStrToDestFile(" /nologo");
+	if (WinCE) {
+		WriteCStrToDestFile(
+			" /base:\"0x00010000\" /stack:0x10000,0x1000"
+			" /entry:\"WinMainCRTStartup\""
+			" /nodefaultlib:\"$(CENoDefaultLib)\"");
+	}
+
+	WriteCStrToDestFile(" /subsystem:");
+	if (WinCE) {
+		WriteCStrToDestFile("$(CESubsystem)");
+	} else {
+		WriteCStrToDestFile("windows");
+	}
+
+	if (gbk_dbg_on == gbo_dbg) {
+		WriteCStrToDestFile(" /debug");
+	} else {
+		WriteCStrToDestFile(" /incremental:no");
+	}
+	WriteCStrToDestFile(" /machine:");
+	if (gbk_cpufam_arm == gbo_cpufam) {
+		WriteCStrToDestFile("ARM");
+	} else {
+		if (WinCE) {
+			WriteCStrToDestFile("IX86");
+		} else {
+			WriteCStrToDestFile("I386"); /* maybe should be IX86 ? */
+		}
+	}
+
+	WriteCStrToDestFile(" /out:");
+	WriteQuoteToDestFile();
+	WriteAppNameStr();
+	WriteQuoteToDestFile();
+	if (WinCE) {
+		if (gbk_cpufam_arm == gbo_cpufam) {
+			WriteCStrToDestFile(" /align:\"4096\"");
+				/* is this really needed ? */
+		} else {
+			WriteCStrToDestFile(
+				" $(CEx86Corelibc) /nodefaultlib:\"OLDNAMES.lib\"");
+		}
+	}
+	if (gbk_dbg_on == gbo_dbg) {
+		WriteCStrToDestFile(" /pdbtype:sept");
+	}
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("# Begin Target");
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("# Name ");
+	WriteMSVCTargetName();
+	WriteEndDestFileLn();
+
+	WriteMSVCBeginGroup("Source Files",
+		"cpp;c;cxx;rc;def;r;odl;idl;hpj;bat");
+		DoAllSrcFilesWithSetup(
+			DoSrcFileMSVCAddFile);
+		WriteFileToMSVCSource(WriteMainRsrcSrcPath);
+	WriteMSVCEndGroup();
+
+	WriteMSVCBeginGroup("Header Files", "h;hpp;hxx;hm;inl");
+		DoAllSrcFilesWithSetup(
+			DoSrcFileMSVCAddHeader);
+	WriteMSVCEndGroup();
+
+	WriteMSVCBeginGroup("Resource Files",
+		"ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe");
+		DoAllDocTypesWithSetup(WriteDocTypeMSVCresource);
+	WriteMSVCEndGroup();
+
+	WriteMSVCBeginGroup("Include Files", "h;hpp;hxx;hm;inl");
+		DoAllExtraHeaders2WithSetup(DoExtraHeaderMSVCAdd);
+	WriteMSVCEndGroup();
+
+	WriteDestFileLn("# End Target");
+	WriteDestFileLn("# End Project");
+}
+
+LOCALPROC WriteMSVCSpecificFiles(void)
+{
+	WriteADstFile1("my_project_d",
+		vStrAppAbbrev, MSVCWorkspaceExt(), "Workspace file",
+		WriteMSVCWorkSpaceFile);
+	WriteADstFile1("my_project_d",
+		vStrAppAbbrev, MSVCProjectExt(), "Project file",
+		WriteMSVCProjectFile);
+}
+
+LOCALPROC WriteXMLQuotedProp(char *s, MyProc p)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile(s);
+	WriteCStrToDestFile("=");
+	WriteQuoteToDestFile();
+	p();
+	WriteQuoteToDestFile();
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteMSVCPlatformName(void)
+{
+	if (gbk_targ_wx64 == cur_targ) {
+		WriteCStrToDestFile("x64");
+	} else {
+		WriteCStrToDestFile("Win32");
+	}
+}
+
+LOCALPROC WriteMSVCXMLPlatformProps(void)
+{
+	WriteXMLQuotedProp("Name", WriteMSVCPlatformName);
+}
+
+LOCALPROC WriteMSVCXMLPlatforms(void)
+{
+	WriteXMLtaglinewithprops("Platform", WriteMSVCXMLPlatformProps);
+}
+
+LOCALPROC WriteMSVCXMLConfigurationName(void)
+{
+	WriteMSVCdbgLevelName();
+	WriteCStrToDestFile("|");
+	WriteMSVCPlatformName();
+}
+
+LOCALPROC WriteMSVCXMLConfigurationProps(void)
+{
+	WriteXMLQuotedProp("Name", WriteMSVCXMLConfigurationName);
+	WriteXMLQuotedProp("OutputDirectory", Write_obj_d_ToDestFile);
+	WriteXMLQuotedProp("IntermediateDirectory", Write_obj_d_ToDestFile);
+	WriteDestFileLn("ConfigurationType=\"1\"");
+	WriteDestFileLn("CharacterSet=\"2\"");
+	if (gbk_dbg_on != gbo_dbg) {
+		WriteDestFileLn("WholeProgramOptimization=\"0\"");
+	}
+}
+
+LOCALPROC WriteMSVCToolConfig(char *s, MyProc p)
+{
+	WriteDestFileLn("<Tool");
+	++DestFileIndent;
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("Name=");
+		WriteQuoteToDestFile();
+		WriteCStrToDestFile(s);
+		WriteQuoteToDestFile();
+		WriteEndDestFileLn();
+		if (NULL != p) {
+			p();
+		}
+	--DestFileIndent;
+	WriteDestFileLn("/>");
+}
+
+LOCALPROC WriteMSVCCompilerToolConfig(void)
+{
+#if 0
+	if (gbk_dbg_on != gbo_dbg) {
+		WriteDestFileLn("Optimization=\"1\"");
+		WriteDestFileLn("FavorSizeOrSpeed=\"0\"");
+		WriteDestFileLn("WholeProgramOptimization=\"false\"");
+		WriteDestFileLn("OmitFramePointers=\"true\"");
+	} else
+#endif
+	{
+		/* Maximize chance of correct compile */
+		WriteDestFileLn("Optimization=\"0\"");
+	}
+
+	if (gbk_dbg_on == gbo_dbg) {
+		WriteDestFileLn(
+			"PreprocessorDefinitions=\"WIN32;_DEBUG;_WINDOWS\"");
+		WriteDestFileLn("MinimalRebuild=\"true\"");
+	} else {
+		WriteDestFileLn(
+			"PreprocessorDefinitions=\"WIN32;NDEBUG;_WINDOWS\"");
+		WriteDestFileLn("StringPooling=\"true\"");
+	}
+
+	WriteXMLQuotedProp("AdditionalIncludeDirectories",
+		Write_cfg_d_ToDestFile);
+
+	WriteDestFileLn("ExceptionHandling=\"0\"");
+	if (gbk_dbg_on == gbo_dbg) {
+		WriteDestFileLn("BasicRuntimeChecks=\"3\"");
+		if (ide_vers >= 8000) {
+			WriteDestFileLn("RuntimeLibrary=\"1\"");
+		} else {
+			WriteDestFileLn("RuntimeLibrary=\"5\"");
+		}
+	} else {
+		if (ide_vers >= 8000) {
+			WriteDestFileLn("RuntimeLibrary=\"0\"");
+		} else {
+			WriteDestFileLn("RuntimeLibrary=\"4\"");
+		}
+	}
+	if (ide_vers < 8000) {
+		WriteDestFileLn("BufferSecurityCheck=\"false\"");
+			/* perhaps later versions also */
+			/* maybe this should be an option set in SPBASDEF */
+	}
+	WriteDestFileLn("EnableFunctionLevelLinking=\"true\"");
+	WriteDestFileLn("UsePrecompiledHeader=\"0\"");
+	WriteDestFileLn("WarningLevel=\"4\"");
+	if (ide_vers < 9000) {
+		WriteDestFileLn("Detect64BitPortabilityProblems=\"true\"");
+	}
+	if (gbk_dbg_on == gbo_dbg) {
+		WriteDestFileLn("DebugInformationFormat=\"4\"");
+	} else {
+		WriteDestFileLn("DebugInformationFormat=\"0\"");
+	}
+	WriteDestFileLn("CompileAs=\"0\"");
+}
+
+LOCALPROC WriteMSVCResourceCompilerToolConfig(void)
+{
+	WriteXMLQuotedProp("AdditionalIncludeDirectories",
+		Write_src_d_ToDestFile);
+}
+
+LOCALPROC WriteMSVCLinkerToolConfig(void)
+{
+	WriteDestFileLn("AdditionalDependencies=\"winmm.lib\"");
+	WriteXMLQuotedProp("OutputFile", WriteAppNamePath);
+	if (gbk_dbg_on == gbo_dbg) {
+		WriteDestFileLn("LinkIncremental=\"2\"");
+	} else {
+		WriteDestFileLn("LinkIncremental=\"1\"");
+	}
+	if (ide_vers >= 8000) {
+		WriteDestFileLn("GenerateManifest=\"false\"");
+	}
+	if (gbk_dbg_on == gbo_dbg) {
+		WriteDestFileLn("GenerateDebugInformation=\"true\"");
+	} else {
+		WriteDestFileLn("GenerateDebugInformation=\"false\"");
+	}
+	WriteDestFileLn("SubSystem=\"2\"");
+	if (gbk_dbg_on != gbo_dbg) {
+		WriteDestFileLn("OptimizeReferences=\"2\"");
+		WriteDestFileLn("EnableCOMDATFolding=\"2\"");
+	}
+	if (ide_vers >= 9000) {
+		WriteDestFileLn("RandomizedBaseAddress=\"1\"");
+		WriteDestFileLn("DataExecutionPrevention=\"0\"");
+	}
+	if (gbk_targ_wx64 == cur_targ) {
+		WriteDestFileLn("TargetMachine=\"17\"");
+	} else {
+		WriteDestFileLn("TargetMachine=\"1\"");
+	}
+}
+
+LOCALPROC WriteMSVCXMLConfigurationBody(void)
+{
+	WriteMSVCToolConfig("VCPreBuildEventTool", NULL);
+	WriteMSVCToolConfig("VCCustomBuildTool", NULL);
+	if (ide_vers >= 7100) {
+		WriteMSVCToolConfig("VCXMLDataGeneratorTool", NULL);
+	}
+	WriteMSVCToolConfig("VCWebServiceProxyGeneratorTool", NULL);
+	WriteMSVCToolConfig("VCMIDLTool", NULL);
+	WriteMSVCToolConfig("VCCLCompilerTool",
+		WriteMSVCCompilerToolConfig);
+	if (ide_vers >= 8000) {
+		WriteMSVCToolConfig("VCManagedResourceCompilerTool", NULL);
+	}
+	WriteMSVCToolConfig("VCResourceCompilerTool",
+		WriteMSVCResourceCompilerToolConfig);
+	WriteMSVCToolConfig("VCPreLinkEventTool", NULL);
+	WriteMSVCToolConfig("VCLinkerTool", WriteMSVCLinkerToolConfig);
+	if (ide_vers >= 8000) {
+		WriteMSVCToolConfig("VCALinkTool", NULL);
+		WriteMSVCToolConfig("VCManifestTool", NULL);
+		WriteMSVCToolConfig("VCXDCMakeTool", NULL);
+		WriteMSVCToolConfig("VCBscMakeTool", NULL);
+		WriteMSVCToolConfig("VCFxCopTool", NULL);
+		WriteMSVCToolConfig("VCAppVerifierTool", NULL);
+	} else if (ide_vers >= 7100) {
+		WriteMSVCToolConfig("VCManagedWrapperGeneratorTool", NULL);
+		WriteMSVCToolConfig("VCAuxiliaryManagedWrapperGeneratorTool",
+			NULL);
+	}
+	if (ide_vers < 9000) {
+		WriteMSVCToolConfig("VCWebDeploymentTool", NULL);
+	}
+	WriteMSVCToolConfig("VCPostBuildEventTool", NULL);
+}
+
+LOCALPROC WriteMSVCXMLConfigurations(void)
+{
+	WriteXMLtaggedLinesWithProps("Configuration",
+		WriteMSVCXMLConfigurationProps,
+		WriteMSVCXMLConfigurationBody);
+}
+
+LOCALPROC WriteMSVCXMLSourceFilesProps(void)
+{
+	WriteDestFileLn("Name=\"Source Files\"");
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("Filter=\"cpp;c");
+	if (ide_vers >= 8000) {
+		WriteCStrToDestFile(";cc");
+	}
+	WriteCStrToDestFile(";cxx;def;odl;idl;hpj;bat;asm");
+	if (ide_vers >= 7100) {
+		WriteCStrToDestFile(";asmx");
+	}
+	WriteCStrToDestFile("\"");
+	WriteEndDestFileLn();
+	if (ide_vers >= 7100) {
+		WriteDestFileLn(
+			"UniqueIdentifier=\"{"
+			"00020000-0000-0000-0000-000000000000}\"");
+	}
+}
+
+LOCALPROC DoMSVCXMLAddFile(MyProc p)
+{
+	WriteDestFileLn("<File");
+	++DestFileIndent;
+		WriteXMLQuotedProp("RelativePath", p);
+		WriteDestFileLn(">");
+	--DestFileIndent;
+	WriteDestFileLn("</File>");
+}
+
+LOCALPROC DoSrcFileMSVCXMLAddFile(void)
+{
+	DoMSVCXMLAddFile(WriteSrcFileFilePath);
+}
+
+LOCALPROC WriteMSVCXMLSourceFilesBody(void)
+{
+	DoAllSrcFilesWithSetup(DoSrcFileMSVCXMLAddFile);
+}
+
+LOCALPROC WriteMSVCXMLHeaderFilesProps(void)
+{
+	WriteDestFileLn("Name=\"Header Files\"");
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("Filter=\"h;hpp;hxx;hm;inl;inc");
+	if (ide_vers >= 7100) {
+		WriteCStrToDestFile(";xsd");
+	}
+	WriteCStrToDestFile("\"");
+	WriteEndDestFileLn();
+	if (ide_vers >= 7100) {
+		WriteDestFileLn(
+			"UniqueIdentifier=\"{"
+			"00030000-0000-0000-0000-000000000000}\"");
+	}
+}
+
+LOCALPROC DoSrcFileMSVCXMLAddHeader(void)
+{
+	if ((DoSrcFile_gd()->Flgm & kCSrcFlgmNoHeader) == 0) {
+		DoMSVCXMLAddFile(WriteSrcFileHeaderPath);
+	}
+}
+
+LOCALPROC WriteMSVCXMLHeaderFilesBody(void)
+{
+	DoAllSrcFilesWithSetup(DoSrcFileMSVCXMLAddHeader);
+}
+
+LOCALPROC WriteMSVCXMLResourceFilesProps(void)
+{
+	WriteDestFileLn("Name=\"Resource Files\"");
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile(
+		"Filter=\"rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;"
+		"jpeg;jpe");
+	if (ide_vers >= 7100) {
+		WriteCStrToDestFile(";resx");
+	}
+	if (ide_vers >= 8000) {
+		WriteCStrToDestFile(";tiff;tif;png;wav");
+	}
+	WriteCStrToDestFile("\"");
+	WriteEndDestFileLn();
+	if (ide_vers >= 7100) {
+		WriteDestFileLn(
+			"UniqueIdentifier=\"{"
+			"00040000-0000-0000-0000-000000000000}\"");
+	}
+}
+
+LOCALPROC WriteDocTypeMSVCXMLresource(void)
+{
+	DoMSVCXMLAddFile(WriteDocTypeIconFilePath);
+}
+
+LOCALPROC WriteMSVCXMLResourceFilesBody(void)
+{
+	DoMSVCXMLAddFile(WriteMainRsrcSrcPath);
+	DoAllDocTypesWithSetup(WriteDocTypeMSVCXMLresource);
+}
+
+LOCALPROC WriteMSVCXMLIncludeFilesProps(void)
+{
+	WriteDestFileLn("Name=\"Include Files\"");
+	WriteDestFileLn("Filter=\"h;hpp;hxx;hm;inl;inc;xsd\"");
+}
+
+LOCALPROC DoMSVCXMLAddAddExtraHeader(void)
+{
+	DoMSVCXMLAddFile(WriteExtraHeaderFilePath);
+}
+
+LOCALPROC WriteMSVCXMLIncludeFilesBody(void)
+{
+	DoAllExtraHeaders2WithSetup(DoMSVCXMLAddAddExtraHeader);
+}
+
+LOCALPROC WriteMSVCXMLFiles(void)
+{
+	WriteXMLtaggedLinesWithProps("Filter",
+		WriteMSVCXMLSourceFilesProps,
+		WriteMSVCXMLSourceFilesBody);
+	WriteXMLtaggedLinesWithProps("Filter",
+		WriteMSVCXMLHeaderFilesProps,
+		WriteMSVCXMLHeaderFilesBody);
+	WriteXMLtaggedLinesWithProps("Filter",
+		WriteMSVCXMLResourceFilesProps,
+		WriteMSVCXMLResourceFilesBody);
+	WriteXMLtaggedLinesWithProps("Filter",
+		WriteMSVCXMLIncludeFilesProps,
+		WriteMSVCXMLIncludeFilesBody);
+}
+
+LOCALPROC WriteMSVCXMLSolutionFile(void)
+{
+	if (ide_vers >= 8000) {
+		WriteDestFileLn("\357\273\277"); /* UTF-8 byte-order mark */
+	}
+
+	if (ide_vers >= 11000) {
+		WriteDestFileLn(
+			"Microsoft Visual Studio Solution File,"
+			" Format Version 12.00");
+		if (ide_vers >= 15000) {
+			WriteDestFileLn("# Visual Studio 15");
+		} else if (ide_vers >= 14000) {
+			WriteDestFileLn("# Visual Studio 14");
+		} else if (ide_vers >= 12000) {
+			WriteDestFileLn("# Visual Studio 2013");
+		} else {
+			WriteDestFileLn("# Visual Studio 2012");
+		}
+	} else if (ide_vers >= 10000) {
+		WriteDestFileLn(
+			"Microsoft Visual Studio Solution File,"
+			" Format Version 11.00");
+		WriteDestFileLn("# Visual Studio 2010");
+	} else if (ide_vers >= 9000) {
+		WriteDestFileLn(
+			"Microsoft Visual Studio Solution File,"
+			" Format Version 10.00");
+		/* WriteDestFileLn("# Visual C++ Express 2008"); */
+		WriteDestFileLn("# Visual Studio 2008");
+	} else if (ide_vers >= 8000) {
+		WriteDestFileLn(
+			"Microsoft Visual Studio Solution File,"
+			" Format Version 9.00");
+		/* WriteDestFileLn("# Visual C++ Express 2005"); */
+		WriteDestFileLn("# Visual Studio 2005");
+	} else if (ide_vers >= 7100) {
+		WriteDestFileLn(
+			"Microsoft Visual Studio Solution File,"
+			" Format Version 8.00");
+	} else {
+		WriteDestFileLn(
+			"Microsoft Visual Studio Solution File,"
+			" Format Version 7.00");
+	}
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile(
+		"Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"");
+	WriteStrAppAbbrev();
+	WriteCStrToDestFile("\", \"");
+	WriteStrAppAbbrev();
+	if (ide_vers >= 10000) {
+		WriteCStrToDestFile(".vcxproj");
+	} else {
+		WriteCStrToDestFile(".vcproj");
+	}
+	WriteCStrToDestFile(
+		"\", \"{00010000-0000-0000-0000-000000000000}\"");
+	WriteEndDestFileLn();
+	if ((ide_vers >= 7100) && (ide_vers < 8000)) {
+		++DestFileIndent;
+			WriteDestFileLn(
+				"ProjectSection(ProjectDependencies)"" = postProject");
+			WriteDestFileLn("EndProjectSection");
+		--DestFileIndent;
+	}
+	WriteDestFileLn("EndProject");
+	WriteDestFileLn("Global");
+	++DestFileIndent;
+		if (ide_vers >= 8000) {
+			WriteDestFileLn(
+				"GlobalSection(SolutionConfigurationPlatforms)"
+				" = preSolution");
+			++DestFileIndent;
+				WriteBgnDestFileLn();
+				WriteMSVCXMLConfigurationName();
+				WriteCStrToDestFile(" = ");
+				WriteMSVCXMLConfigurationName();
+				WriteEndDestFileLn();
+			--DestFileIndent;
+			WriteDestFileLn("EndGlobalSection");
+			WriteDestFileLn(
+				"GlobalSection(ProjectConfigurationPlatforms)"
+				" = postSolution");
+			++DestFileIndent;
+				WriteBgnDestFileLn();
+				WriteCStrToDestFile(
+					"{00010000-0000-0000-0000-000000000000}.");
+				WriteMSVCXMLConfigurationName();
+				WriteCStrToDestFile(".ActiveCfg = ");
+				WriteMSVCXMLConfigurationName();
+				WriteEndDestFileLn();
+				WriteBgnDestFileLn();
+				WriteCStrToDestFile(
+					"{00010000-0000-0000-0000-000000000000}.");
+				WriteMSVCXMLConfigurationName();
+				WriteCStrToDestFile(".Build.0 = ");
+				WriteMSVCXMLConfigurationName();
+				WriteEndDestFileLn();
+			--DestFileIndent;
+			WriteDestFileLn("EndGlobalSection");
+			WriteDestFileLn(
+				"GlobalSection(SolutionProperties) = preSolution");
+			++DestFileIndent;
+				WriteDestFileLn("HideSolutionNode = FALSE");
+			--DestFileIndent;
+			WriteDestFileLn("EndGlobalSection");
+		} else {
+			WriteDestFileLn(
+				"GlobalSection(SolutionConfiguration) = preSolution");
+			++DestFileIndent;
+				WriteBgnDestFileLn();
+				if (ide_vers >= 7100) {
+					WriteMSVCdbgLevelName();
+				} else {
+					WriteCStrToDestFile("ConfigName.0");
+				}
+				WriteCStrToDestFile(" = ");
+				WriteMSVCdbgLevelName();
+				WriteEndDestFileLn();
+			--DestFileIndent;
+			WriteDestFileLn("EndGlobalSection");
+			if (ide_vers < 7100) {
+				WriteCStrToDestFile(
+					"GlobalSection(ProjectDependencies)"
+					" = postSolution");
+				WriteCStrToDestFile("EndGlobalSection");
+			}
+			WriteDestFileLn(
+				"GlobalSection(ProjectConfiguration) = postSolution");
+			++DestFileIndent;
+				WriteBgnDestFileLn();
+				WriteCStrToDestFile(
+					"{00010000-0000-0000-0000-000000000000}.");
+				WriteMSVCdbgLevelName();
+				WriteCStrToDestFile(".ActiveCfg = ");
+				WriteMSVCXMLConfigurationName();
+				WriteEndDestFileLn();
+
+				WriteBgnDestFileLn();
+				WriteCStrToDestFile(
+					"{00010000-0000-0000-0000-000000000000}.");
+				WriteMSVCdbgLevelName();
+				WriteCStrToDestFile(".Build.0 = ");
+				WriteMSVCXMLConfigurationName();
+				WriteEndDestFileLn();
+			--DestFileIndent;
+			WriteDestFileLn("EndGlobalSection");
+			WriteDestFileLn(
+				"GlobalSection(ExtensibilityGlobals) = postSolution");
+			WriteDestFileLn("EndGlobalSection");
+			WriteDestFileLn(
+				"GlobalSection(ExtensibilityAddIns) = postSolution");
+			WriteDestFileLn("EndGlobalSection");
+		}
+	--DestFileIndent;
+	WriteDestFileLn("EndGlobal");
+}
+
+LOCALPROC WriteMSVCXMLProjectProps(void)
+{
+	WriteDestFileLn("ProjectType=\"Visual C++\"");
+	if (ide_vers >= 9000) {
+		WriteDestFileLn("Version=\"9.00\"");
+	} else if (ide_vers >= 8000) {
+		WriteDestFileLn("Version=\"8.00\"");
+	} else if (ide_vers >= 7100) {
+		WriteDestFileLn("Version=\"7.10\"");
+	} else {
+		WriteDestFileLn("Version=\"7.00\"");
+	}
+	WriteXMLQuotedProp("Name", WriteStrAppAbbrev);
+	WriteDestFileLn(
+		"ProjectGUID=\"{00010000-0000-0000-0000-000000000000}\"");
+	if (ide_vers >= 8000) {
+		WriteXMLQuotedProp("RootNamespace", WriteStrAppAbbrev);
+	}
+	WriteDestFileLn("Keyword=\"Win32Proj\"");
+	if (ide_vers >= 9000) {
+		WriteDestFileLn("TargetFrameworkVersion=\"131072\"");
+	}
+}
+
+LOCALPROC WriteMSVCXMLProjectBody(void)
+{
+	WriteXMLtaggedLines("Platforms", WriteMSVCXMLPlatforms);
+	if (ide_vers >= 8000) {
+		WriteXMLtaggedLines("ToolFiles", NULL);
+	}
+	WriteXMLtaggedLines("Configurations", WriteMSVCXMLConfigurations);
+	if (ide_vers >= 7100) {
+		WriteXMLtaggedLines("References", NULL);
+	}
+	WriteXMLtaggedLines("Files", WriteMSVCXMLFiles);
+	WriteXMLtaggedLines("Globals", NULL);
+}
+
+LOCALPROC WriteMSVCXMLProjectFile(void)
+{
+	WriteDestFileLn(
+		"<?xml version=\"1.0\" encoding=\"Windows-1252\"?>");
+	WriteXMLtaggedLinesWithProps("VisualStudioProject",
+		WriteMSVCXMLProjectProps,
+		WriteMSVCXMLProjectBody);
+}
+
+LOCALPROC WriteMSVCXMLSpecificFiles(void)
+{
+	WriteADstFile1("my_project_d",
+		vStrAppAbbrev, ".sln", "Solutions file",
+		WriteMSVCXMLSolutionFile);
+	WriteADstFile1("my_project_d",
+		vStrAppAbbrev, ".vcproj", "Project file",
+		WriteMSVCXMLProjectFile);
+}
+
+LOCALPROC DoSrcFileNMakeAddObjFile(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("\"");
+	WriteSrcFileObjPath();
+	WriteCStrToDestFile("\" \\");
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteMainRsrcObjMSCbuild(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("rc.exe ");
+	WriteRCexeFlags();
+	WriteCStrToDestFile(" /fo\"");
+	WriteMainRsrcObjPath();
+	WriteCStrToDestFile("\"");
+	WriteCStrToDestFile(" /i");
+	WriteQuoteToDestFile();
+	Write_src_d_ToDestFile();
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(" \"");
+	WriteMainRsrcSrcPath();
+	WriteCStrToDestFile("\"");
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteNMakeMakeFile(void)
+{
+	blnr WinCE = (gbk_targfam_wnce == gbo_targfam);
+
+	WriteDestFileLn("# make file generated by gryphel build system");
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("mk_COptions=");
+	WriteCLexeFlags();
+	WriteCStrToDestFile(" /I\"");
+	Write_cfg_d_ToDestFile();
+	WriteCStrToDestFile("\\\\\"");
+		/* yes, a double backslash is what is needed */
+	WriteCStrToDestFile(" /Fo\"");
+	Write_obj_d_ToDestFile();
+	WriteCStrToDestFile("\\\\\"");
+	WriteCStrToDestFile(" /Fd\"");
+	Write_obj_d_ToDestFile();
+	WriteCStrToDestFile("\\\\\"");
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("TheDefaultOutput :");
+	WriteMakeDependFile(WriteAppNamePath);
+	WriteEndDestFileLn();
+	WriteBlankLineToDestFile();
+	WriteBlankLineToDestFile();
+	DoAllSrcFilesWithSetup(DoSrcFileMakeCompile);
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("ObjFiles= \\");
+	++DestFileIndent;
+		DoAllSrcFilesSortWithSetup(DoSrcFileNMakeAddObjFile);
+	--DestFileIndent;
+	WriteBlankLineToDestFile();
+	WriteBlankLineToDestFile();
+	WriteBlankLineToDestFile();
+	WriteMakeRule(WriteMainRsrcObjPath,
+		WriteMainRsrcObjMSCdeps, WriteMainRsrcObjMSCbuild);
+	WriteBlankLineToDestFile();
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("\"");
+	WriteAppNamePath();
+	WriteCStrToDestFile("\" : $(ObjFiles) \"");
+	WriteMainRsrcObjPath();
+	WriteCStrToDestFile("\"");
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		WriteDestFileLn("link.exe @<<");
+		++DestFileIndent;
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("/out:\"");
+			WriteAppNamePath();
+			WriteCStrToDestFile("\"");
+			WriteEndDestFileLn();
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("/nologo");
+			if (WinCE) {
+				WriteCStrToDestFile(" /subsystem:windowsce,4.20");
+			} else {
+				WriteCStrToDestFile(" /subsystem:windows");
+			}
+			if (gbk_dbg_on == gbo_dbg) {
+				WriteCStrToDestFile(" /debug");
+			} else {
+				WriteCStrToDestFile(" /incremental:no");
+			}
+			WriteCStrToDestFile(" /opt:ref /opt:icf");
+				/*
+					more or less default, but putting this in
+					makes difference at least in visual studio 2005
+				*/
+			WriteEndDestFileLn();
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("/pdb:\"");
+			Write_obj_d_ToDestFile();
+			WriteCStrToDestFile("\\");
+			WriteStrAppAbbrev();
+			WriteCStrToDestFile(".pdb\"");
+			WriteCStrToDestFile(" /machine:");
+			if (gbk_cpufam_arm == gbo_cpufam) {
+				WriteCStrToDestFile("ARM");
+			} else if (gbk_cpufam_x64 == gbo_cpufam) {
+				if (ide_vers >= 7100) {
+					WriteCStrToDestFile("X64");
+				} else {
+					WriteCStrToDestFile("AMD64");
+				}
+			} else {
+				if (ide_vers >= 7100) {
+					WriteCStrToDestFile("X86");
+				} else {
+					WriteCStrToDestFile("I386");
+				}
+			}
+			WriteEndDestFileLn();
+			if (WinCE) {
+				WriteDestFileLn("/base:\"0x00010000\"");
+				WriteDestFileLn("/stack:0x10000,0x1000");
+				WriteDestFileLn("/entry:WinMainCRTStartup");
+				WriteDestFileLn("/align:4096");
+			}
+			if (ide_vers >= 9000) {
+				WriteDestFileLn("/dynamicbase:no");
+					/* smaller exe, maybe not as secure */
+			}
+			if (WinCE) {
+				WriteDestFileLn("commctrl.lib");
+				WriteDestFileLn("coredll.lib");
+				WriteDestFileLn("aygshell.lib");
+				WriteDestFileLn("Mmtimer.lib");
+				WriteDestFileLn("/nodefaultlib:libc.lib");
+				WriteDestFileLn("/nodefaultlib:libcd.lib");
+				WriteDestFileLn("/nodefaultlib:libcmt.lib");
+				WriteDestFileLn("/nodefaultlib:libcmtd.lib");
+				WriteDestFileLn("/nodefaultlib:msvcrt.lib");
+				WriteDestFileLn("/nodefaultlib:msvcrtd.lib");
+			} else {
+				WriteDestFileLn("winmm.lib");
+				WriteDestFileLn("kernel32.lib");
+				WriteDestFileLn("user32.lib");
+				WriteDestFileLn("gdi32.lib");
+				WriteDestFileLn("winspool.lib");
+				WriteDestFileLn("comdlg32.lib");
+				WriteDestFileLn("advapi32.lib");
+				WriteDestFileLn("shell32.lib");
+				WriteDestFileLn("ole32.lib");
+				WriteDestFileLn("oleaut32.lib");
+				WriteDestFileLn("uuid.lib");
+				if ((gbk_cpufam_x64 == gbo_cpufam)
+					&& (ide_vers >= 7000)
+					&& (ide_vers < 7100))
+				{
+					WriteDestFileLn("bufferoverflowU.lib");
+				}
+			}
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("\"");
+			WriteMainRsrcObjPath();
+			WriteCStrToDestFile("\"");
+			WriteEndDestFileLn();
+			WriteDestFileLn("$(ObjFiles)");
+		--DestFileIndent;
+	--DestFileIndent;
+	WriteDestFileLn("<<");
+	WriteBlankLineToDestFile();
+
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("CLEAN :");
+	++DestFileIndent;
+		DoAllSrcFilesStandardErase();
+		WriteRmFile(WriteMainRsrcObjPath);
+		WriteRmFile(WriteAppNamePath);
+	--DestFileIndent;
+}
+
+LOCALPROC WriteNMakeSpecificFiles(void)
+{
+	WriteADstFile1("my_project_d",
+		"MAKEFILE", "", "Make file",
+		WriteNMakeMakeFile);
+}
+
+LOCALPROC DoSrcFileMSVC10XMLAddFile(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("<ClCompile Include=\"");
+	WriteSrcFileFilePath();
+	WriteCStrToDestFile("\" />");
+	WriteEndDestFileLn();
+}
+
+LOCALPROC DoSrcFileMSVC10XMLAddHeaderFile(void)
+{
+	if ((DoSrcFile_gd()->Flgm & kCSrcFlgmNoHeader) == 0) {
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("<ClInclude Include=\"");
+		WriteSrcFileHeaderPath();
+		WriteCStrToDestFile("\" />");
+		WriteEndDestFileLn();
+	}
+}
+
+LOCALPROC DoMSVC10XMLAddAddExtraHeader(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("<ClInclude Include=\"");
+	WriteExtraHeaderFilePath();
+	WriteCStrToDestFile("\" />");
+	WriteEndDestFileLn();
+}
+
+LOCALPROC DoMSVC10XMLAddDocType(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("<None Include=\"");
+	WriteDocTypeIconFilePath();
+	WriteCStrToDestFile("\" />");
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteMSVC10OutDir(void)
+{
+	WriteCStrToDestFile(".\\");
+}
+
+LOCALPROC WriteMSVC10IntDir(void)
+{
+	Write_obj_d_ToDestFile();
+	WriteCStrToDestFile("\\");
+}
+
+LOCALPROC WriteMSVCXML10ProjectFile(void)
+{
+	WriteCStrToDestFile("\357\273\277"); /* UTF-8 byte-order mark */
+	WriteDestFileLn("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile(
+		"<Project DefaultTargets=\"Build\"");
+	if (ide_vers >= 15000) {
+		WriteCStrToDestFile(
+			" ToolsVersion=\"15.0\"");
+	} else if (ide_vers >= 14000) {
+		WriteCStrToDestFile(
+			" ToolsVersion=\"14.0\"");
+	} else if (ide_vers >= 12000) {
+		WriteCStrToDestFile(
+			" ToolsVersion=\"12.0\"");
+	} else {
+		WriteCStrToDestFile(
+			" ToolsVersion=\"4.0\"");
+	}
+	WriteCStrToDestFile(
+		" xmlns="
+		"\"http://schemas.microsoft.com/developer/msbuild/2003\">"
+		);
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		WriteDestFileLn("<ItemGroup Label=\"ProjectConfigurations\">");
+		++DestFileIndent;
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("<ProjectConfiguration Include=\"");
+			WriteMSVCXMLConfigurationName();
+			WriteCStrToDestFile("\">");
+			WriteEndDestFileLn();
+			++DestFileIndent;
+				WriteXMLtagBeginProcValEndLine("Configuration",
+					WriteMSVCdbgLevelName);
+				WriteXMLtagBeginProcValEndLine("Platform",
+					WriteMSVCPlatformName);
+			--DestFileIndent;
+			WriteDestFileLn("</ProjectConfiguration>");
+		--DestFileIndent;
+		WriteDestFileLn("</ItemGroup>");
+
+		WriteDestFileLn("<PropertyGroup Label=\"Globals\">");
+		++DestFileIndent;
+			WriteXMLtagBeginValEndLine("ProjectGuid",
+				"{00010000-0000-0000-0000-000000000000}");
+			WriteXMLtagBeginValEndLine("Keyword", "Win32Proj");
+			WriteXMLtagBeginProcValEndLine("RootNamespace",
+				WriteStrAppAbbrev);
+			if (ide_vers >= 15000) {
+				WriteXMLtagBeginValEndLine(
+					"WindowsTargetPlatformVersion", "10.0.14393.0");
+			}
+		--DestFileIndent;
+		WriteDestFileLn("</PropertyGroup>");
+
+		WriteDestFileLn("<Import Project=\""
+			"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />");
+
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("<PropertyGroup Condition=\""
+			"'$(Configuration)|$(Platform)'=='");
+		WriteMSVCXMLConfigurationName();
+		WriteCStrToDestFile("'\" Label=\"Configuration\">");
+		WriteEndDestFileLn();
+		++DestFileIndent;
+			WriteXMLtagBeginValEndLine("ConfigurationType",
+				"Application");
+			if (gbk_dbg_on != gbo_dbg) {
+				WriteXMLtagBeginValEndLine("WholeProgramOptimization",
+					"false");
+			}
+			if (ide_vers >= 11000) {
+				if (ide_vers >= 14000) {
+					WriteXMLtagBeginValEndLine("PlatformToolset",
+						"v141");
+				} else if (ide_vers >= 14000) {
+					WriteXMLtagBeginValEndLine("PlatformToolset",
+						"v140");
+				} else if (ide_vers >= 12000) {
+					WriteXMLtagBeginValEndLine("PlatformToolset",
+						"v120");
+				} else {
+					WriteXMLtagBeginValEndLine("PlatformToolset",
+						"v110");
+				}
+			}
+			WriteXMLtagBeginValEndLine("CharacterSet", "MultiByte");
+		--DestFileIndent;
+		WriteDestFileLn("</PropertyGroup>");
+
+		WriteDestFileLn("<Import Project=\""
+			"$(VCTargetsPath)\\Microsoft.Cpp.props\" />");
+		WriteDestFileLn("<ImportGroup Label=\"ExtensionSettings\">");
+		WriteDestFileLn("</ImportGroup>");
+
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("<ImportGroup");
+		WriteCStrToDestFile(" Label=\"PropertySheets\"");
+		WriteCStrToDestFile(
+			" Condition=\"'$(Configuration)|$(Platform)'=='");
+		WriteMSVCXMLConfigurationName();
+		WriteCStrToDestFile("'\">");
+		WriteEndDestFileLn();
+		++DestFileIndent;
+			WriteDestFileLn("<Import Project=\""
+				"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\""
+				" Condition=\"exists('$(UserRootDir)\\"
+					"Microsoft.Cpp.$(Platform).user.props')\""
+				" Label=\"LocalAppDataPlatform\" />");
+		--DestFileIndent;
+		WriteDestFileLn("</ImportGroup>");
+
+		WriteDestFileLn("<PropertyGroup Label=\"UserMacros\" />");
+
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("<PropertyGroup");
+		WriteCStrToDestFile(
+			" Condition=\"'$(Configuration)|$(Platform)'=='");
+		WriteMSVCXMLConfigurationName();
+		WriteCStrToDestFile("'\"");
+		WriteCStrToDestFile(">");
+		WriteEndDestFileLn();
+		++DestFileIndent;
+			WriteXMLtagBeginProcValEndLine("OutDir", WriteMSVC10OutDir);
+			WriteXMLtagBeginProcValEndLine("IntDir", WriteMSVC10IntDir);
+
+			if (gbk_dbg_on == gbo_dbg) {
+				WriteXMLtagBeginValEndLine("LinkIncremental", "true");
+			} else {
+				WriteXMLtagBeginValEndLine("LinkIncremental", "false");
+			}
+
+			WriteXMLtagBeginValEndLine("GenerateManifest", "false");
+		WriteEndXMLtagLine("PropertyGroup");
+
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("<ItemDefinitionGroup"
+			" Condition=\"'$(Configuration)|$(Platform)'=='");
+		WriteMSVCXMLConfigurationName();
+		WriteCStrToDestFile("'\">");
+		WriteEndDestFileLn();
+		++DestFileIndent;
+			WriteBeginXMLtagLine("ClCompile");
+				WriteXMLtagBeginValEndLine("WarningLevel", "Level4");
+				WriteXMLtagBeginValEndLine("PrecompiledHeader",
+					"NotUsing");
+
+#if 0
+				if (gbk_dbg_on != gbo_dbg) {
+					WriteXMLtagBeginValEndLine("Optimization",
+						"MinSpace");
+					WriteXMLtagBeginValEndLine("FavorSizeOrSpeed",
+						"Neither");
+					WriteXMLtagBeginValEndLine(
+						"WholeProgramOptimization", "false");
+					WriteXMLtagBeginValEndLine("OmitFramePointers",
+						"true");
+				} else
+#endif
+				{
+					/* Maximize chance of correct compile */
+					WriteXMLtagBeginValEndLine("Optimization",
+						"Disabled");
+				}
+
+				if (gbk_dbg_on == gbo_dbg) {
+					WriteDestFileLn("<PreprocessorDefinitions>"
+						"WIN32;_DEBUG;_WINDOWS;"
+						"%(PreprocessorDefinitions)"
+						"</PreprocessorDefinitions>");
+					if (gbk_targ_wx64 != cur_targ) {
+						WriteXMLtagBeginValEndLine("MinimalRebuild",
+							"true");
+					}
+					WriteXMLtagBeginValEndLine("BasicRuntimeChecks",
+						"EnableFastChecks");
+					WriteXMLtagBeginValEndLine("RuntimeLibrary",
+						"MultiThreadedDebug");
+					if (gbk_targ_wx64 == cur_targ) {
+						WriteXMLtagBeginValEndLine(
+							"DebugInformationFormat",
+							"ProgramDatabase");
+					} else {
+						WriteXMLtagBeginValEndLine(
+							"DebugInformationFormat",
+							"EditAndContinue");
+					}
+				} else {
+					WriteDestFileLn("<PreprocessorDefinitions>"
+						"WIN32;NDEBUG;_WINDOWS;"
+						"%(PreprocessorDefinitions)"
+						"</PreprocessorDefinitions>");
+					WriteXMLtagBeginValEndLine("StringPooling", "true");
+					WriteXMLtagBeginValEndLine("RuntimeLibrary",
+						"MultiThreaded");
+						/*
+							MultiThreadedDLL makes smaller exe,
+							maybe more compatibility issues
+						*/
+				}
+				WriteBgnDestFileLn();
+				WriteXMLtagBegin("AdditionalIncludeDirectories");
+				Write_cfg_d_ToDestFile();
+				WriteCStrToDestFile(";%(AdditionalIncludeDirectories)");
+				WriteXMLtagEnd("AdditionalIncludeDirectories");
+				WriteEndDestFileLn();
+
+				WriteXMLtagBeginValEndLine("FunctionLevelLinking",
+					"true");
+				WriteXMLtagBeginValEndLine("ExceptionHandling",
+					"false");
+			WriteEndXMLtagLine("ClCompile");
+
+			WriteBeginXMLtagLine("ResourceCompile");
+				WriteBgnDestFileLn();
+				WriteXMLtagBegin("AdditionalIncludeDirectories");
+				Write_src_d_ToDestFile();
+				WriteCStrToDestFile(";%(AdditionalIncludeDirectories)");
+				WriteXMLtagEnd("AdditionalIncludeDirectories");
+				WriteEndDestFileLn();
+			WriteEndXMLtagLine("ResourceCompile");
+
+			WriteBeginXMLtagLine("Link");
+				WriteXMLtagBeginValEndLine("SubSystem", "Windows");
+				if (gbk_dbg_on == gbo_dbg) {
+					WriteXMLtagBeginValEndLine(
+						"GenerateDebugInformation", "true");
+				} else {
+					WriteXMLtagBeginValEndLine(
+						"GenerateDebugInformation", "false");
+				}
+				if (gbk_dbg_on != gbo_dbg) {
+					WriteXMLtagBeginValEndLine("EnableCOMDATFolding",
+						"true");
+					WriteXMLtagBeginValEndLine("OptimizeReferences",
+						"true");
+				}
+				WriteDestFileLn("<AdditionalDependencies>"
+					"winmm.lib;%(AdditionalDependencies)"
+					"</AdditionalDependencies>");
+				WriteXMLtagBeginProcValEndLine("OutputFile",
+					WriteAppNamePath);
+				WriteXMLtagBeginValEndLine("RandomizedBaseAddress",
+					"false");
+			WriteEndXMLtagLine("Link");
+		--DestFileIndent;
+		WriteDestFileLn("</ItemDefinitionGroup>");
+
+		WriteBeginXMLtagLine("ItemGroup");
+			DoAllDocTypesWithSetup(DoMSVC10XMLAddDocType);
+		WriteEndXMLtagLine("ItemGroup");
+
+		WriteBeginXMLtagLine("ItemGroup");
+			DoAllSrcFilesWithSetup(
+				DoSrcFileMSVC10XMLAddHeaderFile);
+			DoAllExtraHeaders2WithSetup(
+				DoMSVC10XMLAddAddExtraHeader);
+		WriteEndXMLtagLine("ItemGroup");
+
+		WriteBeginXMLtagLine("ItemGroup");
+			DoAllSrcFilesWithSetup(
+				DoSrcFileMSVC10XMLAddFile);
+		WriteEndXMLtagLine("ItemGroup");
+
+		WriteBeginXMLtagLine("ItemGroup");
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("<ResourceCompile Include=\"");
+			WriteMainRsrcSrcPath();
+			WriteCStrToDestFile("\" />");
+			WriteEndDestFileLn();
+		WriteEndXMLtagLine("ItemGroup");
+
+		WriteDestFileLn("<Import Project=\""
+			"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />");
+		WriteDestFileLn("<ImportGroup Label=\"ExtensionTargets\">");
+		WriteDestFileLn("</ImportGroup>");
+	--DestFileIndent;
+	WriteDestFileLn("</Project>");
+}
+
+LOCALPROC DoSrcFileMSVC10XMLAddClCompile(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("<ClCompile Include=\"");
+	WriteSrcFileFilePath();
+	WriteCStrToDestFile("\">");
+	WriteEndDestFileLn();
+	++DestFileIndent;
+
+		WriteDestFileLn("<Filter>Source Files</Filter>");
+
+	--DestFileIndent;
+	WriteDestFileLn("</ClCompile>");
+}
+
+LOCALPROC DoSrcFileMSVC10XMLAddClInclude(void)
+{
+	if ((DoSrcFile_gd()->Flgm & kCSrcFlgmNoHeader) == 0) {
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("<ClInclude Include=\"");
+		WriteSrcFileHeaderPath();
+		WriteCStrToDestFile("\">");
+		WriteEndDestFileLn();
+		++DestFileIndent;
+
+			WriteDestFileLn("<Filter>Header Files</Filter>");
+
+		--DestFileIndent;
+		WriteDestFileLn("</ClInclude>");
+	}
+}
+
+LOCALPROC DoExtraHeaderMSVC10XMLAddClInclude(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("<ClInclude Include=\"");
+	WriteExtraHeaderFilePath();
+	WriteCStrToDestFile("\">");
+	WriteEndDestFileLn();
+	++DestFileIndent;
+
+		WriteDestFileLn("<Filter>Include Files</Filter>");
+
+	--DestFileIndent;
+	WriteDestFileLn("</ClInclude>");
+}
+
+LOCALPROC WriteDocTypeMSVC10resource(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("<None Include=\"");
+	WriteDocTypeIconFilePath();
+	WriteCStrToDestFile("\">");
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		WriteDestFileLn("<Filter>Resource Files</Filter>");
+	--DestFileIndent;
+	WriteDestFileLn("</None>");
+}
+
+LOCALPROC WriteMSVC10XMLProjectFiltersProps(void)
+{
+	WriteCStrToDestFile(" ToolsVersion=\"4.0\" xmlns="
+		"\"http://schemas.microsoft.com/developer/msbuild/2003\"");
+}
+
+LOCALPROC WriteMSVC10XMLProjectFiltersBodyFilters(void)
+{
+	WriteDestFileLn("<Filter Include=\"Header Files\">");
+	++DestFileIndent;
+		WriteDestFileLn("<UniqueIdentifier>"
+			"{00030000-0000-0000-0000-000000000000}"
+			"</UniqueIdentifier>");
+		WriteDestFileLn("<Extensions>"
+			"h;hpp;hxx;hm;inl;inc;xsd"
+			"</Extensions>");
+	--DestFileIndent;
+	WriteDestFileLn("</Filter>");
+
+	WriteDestFileLn("<Filter Include=\"Resource Files\">");
+	++DestFileIndent;
+		WriteDestFileLn("<UniqueIdentifier>"
+			"{00040000-0000-0000-0000-000000000000}"
+			"</UniqueIdentifier>");
+		WriteDestFileLn("<Extensions>"
+			"rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;"
+			"resx;tiff;tif;png;wav"
+			"</Extensions>");
+	--DestFileIndent;
+	WriteDestFileLn("</Filter>");
+
+	WriteDestFileLn("<Filter Include=\"Include Files\">");
+	++DestFileIndent;
+		WriteDestFileLn("<UniqueIdentifier>"
+			"{00050000-0000-0000-0000-000000000000}"
+			"</UniqueIdentifier>");
+		WriteDestFileLn("<Extensions>"
+			"h;hpp;hxx;hm;inl;inc;xsd"
+			"</Extensions>");
+	--DestFileIndent;
+	WriteDestFileLn("</Filter>");
+
+	WriteDestFileLn("<Filter Include=\"Source Files\">");
+	++DestFileIndent;
+		WriteDestFileLn("<UniqueIdentifier>"
+			"{00020000-0000-0000-0000-000000000000}"
+			"</UniqueIdentifier>");
+		WriteDestFileLn("<Extensions>"
+			"cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			"</Extensions>");
+	--DestFileIndent;
+	WriteDestFileLn("</Filter>");
+}
+
+LOCALPROC WriteMSVC10XMLProjectFiltersBodyClCompiles(void)
+{
+	DoAllSrcFilesWithSetup(
+		DoSrcFileMSVC10XMLAddClCompile);
+}
+
+LOCALPROC WriteMSVC10XMLProjectFiltersBodyClIncludes(void)
+{
+	DoAllSrcFilesWithSetup(
+		DoSrcFileMSVC10XMLAddClInclude);
+	DoAllExtraHeaders2WithSetup(
+		DoExtraHeaderMSVC10XMLAddClInclude);
+}
+
+LOCALPROC WriteMSVC10XMLProjectFiltersBodyResourceCompileProp(void)
+{
+	WriteCStrToDestFile(" Include=\"");
+	WriteMainRsrcSrcPath();
+	WriteCStrToDestFile("\"");
+}
+
+LOCALPROC WriteMSVC10XMLProjectFiltersBodyResourceCompileBody(void)
+{
+	WriteXMLtagBeginValEndLine("Filter", "Resource Files");
+}
+
+LOCALPROC WriteMSVC10XMLProjectFiltersBodyResourceCompiles(void)
+{
+	WriteXMLtaggedLinesWith1LnProps("ResourceCompile",
+		WriteMSVC10XMLProjectFiltersBodyResourceCompileProp,
+		WriteMSVC10XMLProjectFiltersBodyResourceCompileBody);
+}
+
+LOCALPROC WriteMSVC10XMLProjectFiltersBodyResourceFiles(void)
+{
+	DoAllDocTypesWithSetup(WriteDocTypeMSVC10resource);
+}
+
+LOCALPROC WriteMSVC10XMLProjectFiltersItemGroup(MyProc p)
+{
+	WriteXMLtaggedLines("ItemGroup", p);
+}
+
+LOCALPROC WriteMSVC10XMLProjectFiltersBody(void)
+{
+	WriteMSVC10XMLProjectFiltersItemGroup(
+		WriteMSVC10XMLProjectFiltersBodyFilters);
+	WriteMSVC10XMLProjectFiltersItemGroup(
+		WriteMSVC10XMLProjectFiltersBodyClCompiles);
+	WriteMSVC10XMLProjectFiltersItemGroup(
+		WriteMSVC10XMLProjectFiltersBodyClIncludes);
+	WriteMSVC10XMLProjectFiltersItemGroup(
+		WriteMSVC10XMLProjectFiltersBodyResourceCompiles);
+	WriteMSVC10XMLProjectFiltersItemGroup(
+		WriteMSVC10XMLProjectFiltersBodyResourceFiles);
+}
+
+LOCALPROC WriteMSVCXML10ProjectFiltersFile(void)
+{
+	WriteCStrToDestFile("\357\273\277"); /* UTF-8 byte-order mark */
+	WriteDestFileLn("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
+	WriteXMLtaggedLinesWith1LnProps("Project",
+		WriteMSVC10XMLProjectFiltersProps,
+		WriteMSVC10XMLProjectFiltersBody);
+}
+
+LOCALPROC WriteMSVCXML10SpecificFiles(void)
+{
+	WriteADstFile1("my_project_d",
+		vStrAppAbbrev, ".sln", "Solutions file",
+		WriteMSVCXMLSolutionFile);
+	WriteADstFile1("my_project_d",
+		vStrAppAbbrev, ".vcxproj", "Project file",
+		WriteMSVCXML10ProjectFile);
+	WriteADstFile1("my_project_d",
+		vStrAppAbbrev, ".vcxproj.filters", "Project Filters file",
+		WriteMSVCXML10ProjectFiltersFile);
+}
+
+LOCALPROC WriteMsvSpecificFiles(void)
+{
+	if (UseCmndLine) {
+		WriteNMakeSpecificFiles();
+	} else {
+		if (ide_vers >= 10000) {
+			WriteMSVCXML10SpecificFiles();
+		} else if (ide_vers >= 7000) {
+			WriteMSVCXMLSpecificFiles();
+		} else {
+			WriteMSVCSpecificFiles();
+		}
+	}
+}
--- /dev/null
+++ b/setup/WRMVCFLS.i
@@ -1,0 +1,595 @@
+/*
+	WRMVCFLS.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	WRite Mini vMac C specific FiLeS
+*/
+
+
+LOCALPROC WriteMVCCompileAsmLinkCommonOptions(void)
+{
+	{
+		switch (cur_targ) {
+			case gbk_targ_mach:
+			case gbk_targ_imch:
+			case gbk_targ_mc64:
+			case gbk_targ_mx11:
+			case gbk_targ_mi11:
+			case gbk_targ_mx64:
+				if (gbk_cpufam_x86 == gbo_cpufam) {
+					WriteCStrToDestFile(" -arch i386");
+				} else if (gbk_cpufam_x64 == gbo_cpufam) {
+					WriteCStrToDestFile(" -arch x86_64");
+				} else {
+					WriteCStrToDestFile(" -arch ppc");
+				}
+				break;
+			default:
+				break;
+		}
+	}
+
+	if ((gbk_apifam_osx == gbo_apifam)
+		|| (gbk_apifam_cco == gbo_apifam))
+	{
+		if (gbk_cpufam_ppc == gbo_cpufam) {
+			WriteCStrToDestFile(" -mmacosx-version-min=10.1");
+		} else
+		if (gbk_cpufam_x64 == gbo_cpufam) {
+			WriteCStrToDestFile(" -mmacosx-version-min=10.5");
+		} else
+		{
+			WriteCStrToDestFile(" -mmacosx-version-min=10.4");
+		}
+	}
+}
+
+LOCALPROC WriteMVCLinkOSGlucompileCommonOptions(void)
+{
+	if ((gbk_apifam_osx == gbo_apifam)
+		|| (gbk_apifam_cco == gbo_apifam))
+	{
+		WriteCStrToDestFile(" -isysroot");
+		if (ide_vers >= 3200) {
+			WriteCStrToDestFile(" /Developer/SDKs/MacOSX10.6.sdk");
+		} else if ((ide_vers >= 3100)
+			|| (gbk_cpufam_x64 == gbo_cpufam))
+		{
+			WriteCStrToDestFile(" /Developer/SDKs/MacOSX10.5.sdk");
+		} else {
+			WriteCStrToDestFile(" /Developer/SDKs/MacOSX10.4u.sdk");
+		}
+	}
+}
+
+LOCALPROC WriteMVCCompileLinkCommonOptions(void)
+{
+#if 0
+	WriteCStrToDestFile(" -Werror");
+#endif
+	if (gbk_dbg_on == gbo_dbg) {
+		WriteCStrToDestFile(" -g");
+	}
+}
+
+LOCALPROC WriteMVCCOptions(void)
+{
+	WriteCStrToDestFile(
+		" -Wall -Wmissing-prototypes -Wno-uninitialized");
+
+	WriteCStrToDestFile(" -Wundef -Wstrict-prototypes");
+
+	if (gbk_apifam_osx == gbo_apifam) {
+		WriteCStrToDestFile(" -Wno-deprecated-declarations");
+	}
+	WriteCStrToDestFile(" -fomit-frame-pointer");
+	WriteCStrToDestFile(" -fno-strict-aliasing");
+	WriteCStrToDestFile(" -fno-asynchronous-unwind-tables");
+	WriteCStrToDestFile(
+		" -Winline --param large-function-growth=1000");
+	if (gbk_targ_wcar == cur_targ) {
+		WriteCStrToDestFile(" -fno-leading-underscore");
+	}
+	switch (cur_targ) {
+		case gbk_targ_mach:
+		case gbk_targ_imch:
+		case gbk_targ_mc64:
+		case gbk_targ_mx11:
+		case gbk_targ_mi11:
+		case gbk_targ_mx64:
+			WriteCStrToDestFile(" -mdynamic-no-pic");
+			break;
+	}
+	WriteMVCCompileAsmLinkCommonOptions();
+	WriteMVCCompileLinkCommonOptions();
+
+	if (1 /* WantConfigDir */) {
+		WriteCStrToDestFile(" -I./");
+		Write_cfg_d_Name();
+		WriteCStrToDestFile(" -I./");
+		Write_src_d_Name();
+	}
+}
+
+LOCALPROC WriteMVCCOptOptions(void)
+{
+	if (gbk_dbg_on != gbo_dbg) {
+		WriteCStrToDestFile(" -Os");
+	} else {
+		WriteCStrToDestFile(" -O0");
+	}
+}
+
+LOCALPROC DoFrameWorkMVCaddFile(void)
+{
+	WriteCStrToDestFile(" -framework ");
+	WriteCStrToDestFile(DoFrameWork_gd()->s);
+}
+
+LOCALPROC Write_machoRsrcMVCDeps(void)
+{
+	WriteMakeDependFile(WriteMainRsrcSrcPath);
+	WriteMakeDependFile(Write_machoAppIconPath);
+}
+
+LOCALPROC Write_machoRsrcMVCBuild(void)
+{
+	WriteDestFileLn("/Developer/Tools/Rez \\");
+	++DestFileIndent;
+		WriteDestFileLn("-i /Developer/Headers/FlatCarbon \\");
+		WriteBgnDestFileLn();
+			WriteCStrToDestFile("\"");
+			WriteMainRsrcSrcPath();
+			WriteCStrToDestFile("\" \\");
+		WriteEndDestFileLn();
+		WriteBgnDestFileLn();
+			WriteCStrToDestFile("-o \"");
+			Write_machoRsrcPath();
+			WriteCStrToDestFile("\" \\");
+		WriteEndDestFileLn();
+		WriteDestFileLn("-useDF");
+	--DestFileIndent;
+}
+
+LOCALPROC WriteMVCSrcFileAsmName(void)
+{
+	WriteCStrToDestFile(DoSrcFile_gd()->s);
+	WriteCStrToDestFile(".s");
+}
+
+LOCALPROC WriteMVCSrcFileAsmPath(void)
+{
+	WriteFileInDirToDestFile0(Write_obj_d_ToDestFile,
+		WriteMVCSrcFileAsmName);
+}
+
+LOCALPROC DoMVCSrcFileMakeCompileBody(void)
+{
+	blnr UseAPI = (DoSrcFile_gd()->Flgm & kCSrcFlgmUseAPI) != 0;
+	blnr Fast = (DoSrcFile_gd()->Flgm & kCSrcFlgmSortFirst) != 0;
+
+	WriteBgnDestFileLn();
+
+	WriteCStrToDestFile("$(my_prefix)gcc -S");
+	WritePathArgInMakeCmnd(WriteSrcFileFilePath);
+	WriteCStrToDestFile(" -o");
+	WritePathArgInMakeCmnd(WriteMVCSrcFileAsmPath);
+	WriteSpaceToDestFile();
+	if (! UseAPI) {
+		if (Fast) {
+			WriteMakeVar("mk_COptionsFast");
+		} else {
+			WriteMakeVar("mk_COptions");
+		}
+	} else {
+		WriteMakeVar("mk_COptionsOSGLU");
+	}
+
+	WriteEndDestFileLn();
+}
+
+LOCALPROC DoMVCSrcFileMakeAsmBody(void)
+{
+	WriteBgnDestFileLn();
+
+	WriteCStrToDestFile("$(my_prefix)gcc -c");
+	WritePathArgInMakeCmnd(WriteMVCSrcFileAsmPath);
+	WriteCStrToDestFile(" -o");
+	WritePathArgInMakeCmnd(WriteSrcFileObjPath);
+
+	WriteEndDestFileLn();
+}
+
+LOCALPROC DoMVCSrcFileMakeAsmDeps(void)
+{
+	WriteMakeDependFile(WriteMVCSrcFileAsmPath);
+}
+
+LOCALPROC DoMVCSrcFileMakeCompile(void)
+{
+	WriteMakeRule(WriteMVCSrcFileAsmPath,
+		DoSrcFileMakeCompileDeps,
+		DoMVCSrcFileMakeCompileBody);
+}
+
+LOCALPROC DoMVCSrcFileMakeAsm(void)
+{
+	WriteMakeRule(WriteSrcFileObjPath,
+		DoMVCSrcFileMakeAsmDeps,
+		DoMVCSrcFileMakeAsmBody);
+}
+
+LOCALPROC DoMVCSrcFileStandardMakeAsms(void)
+{
+	WriteBgnDestFileLn();
+	WriteMVCSrcFileAsmPath();
+	WriteSpaceToDestFile();
+	WriteBackSlashToDestFile();
+	WriteEndDestFileLn();
+}
+
+LOCALPROC DoMVCAllSrcFilesStandardMakeAsms(void)
+{
+	DoAllSrcFilesSortWithSetup(DoMVCSrcFileStandardMakeAsms);
+}
+
+LOCALPROC WriteMVCMakeFile(void)
+{
+	WriteDestFileLn("# make file generated by gryphel build system");
+
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("mk_COptionsCommon =");
+	WriteMVCCOptions();
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("mk_COptionsOSGLU = $(mk_COptionsCommon)");
+	if (gbk_apifam_osx == gbo_apifam) {
+		WriteCStrToDestFile(" -Wno-multichar");
+	}
+	WriteMVCLinkOSGlucompileCommonOptions();
+	WriteMVCCOptOptions();
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("mk_COptionsNotOS = $(mk_COptionsCommon)");
+	if (gbk_cpufam_x86 == gbo_cpufam) {
+		WriteCStrToDestFile(" -mpreferred-stack-boundary=2");
+	}
+	WriteCStrToDestFile(" -fno-toplevel-reorder");
+	if (gbk_cpufam_x86 == gbo_cpufam) {
+		WriteCStrToDestFile(" -mtune=generic -march=i386");
+	}
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("mk_COptions = $(mk_COptionsNotOS)");
+	WriteMVCCOptOptions();
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("mk_COptionsFast = $(mk_COptionsNotOS)");
+	if (gbk_dbg_on != gbo_dbg) {
+		WriteCStrToDestFile(
+			" -O2 -fno-align-functions -fno-align-labels");
+	} else {
+		WriteMVCCOptOptions();
+	}
+	WriteEndDestFileLn();
+
+	switch (cur_targ) {
+		case gbk_targ_mach:
+			WriteDestFileLn("my_prefix = powerpc-apple-darwin9-");
+			break;
+		case gbk_targ_imch:
+			WriteDestFileLn("my_prefix = i686-apple-darwin11-");
+			break;
+		case gbk_targ_mc64:
+			WriteDestFileLn("my_prefix = x86_64-apple-darwin11-");
+			break;
+		case gbk_targ_wx86:
+			WriteDestFileLn("my_prefix = i686-w64-mingw32-");
+			break;
+		case gbk_targ_wx64:
+			WriteDestFileLn("my_prefix = x86_64-w64-mingw32-");
+			break;
+		case gbk_targ_lx86:
+			WriteDestFileLn("my_prefix = i386-pc-linux-");
+			break;
+		case gbk_targ_lx64:
+			WriteDestFileLn("my_prefix = x86_64-linux-gnu-");
+			break;
+		case gbk_targ_larm:
+			WriteDestFileLn("my_prefix = arm-linux-gnueabi-");
+			break;
+		case gbk_targ_lppc:
+			WriteDestFileLn("my_prefix = powerpc-linux-gnu-");
+			break;
+		case gbk_targ_lspr:
+			WriteDestFileLn("my_prefix = sparc-linux-gnu-");
+			break;
+		case gbk_targ_fbsd:
+			WriteDestFileLn("my_prefix = i386-pc-freebsd9-");
+			break;
+		case gbk_targ_fb64:
+			WriteDestFileLn("my_prefix = x86_64-pc-freebsd9-");
+			break;
+		case gbk_targ_nbsd:
+			WriteDestFileLn("my_prefix = i386-pc-netbsdelf-");
+			break;
+		case gbk_targ_nb64:
+			WriteDestFileLn("my_prefix = x86_64-pc-netbsdelf-");
+			break;
+		case gbk_targ_oind:
+			WriteDestFileLn("my_prefix = i386-pc-solaris2.11-");
+			break;
+		case gbk_targ_oi64:
+			WriteDestFileLn("my_prefix = x86_64-pc-solaris2.11-");
+			break;
+		case gbk_targ_wcar:
+			WriteDestFileLn("my_prefix = arm-wince-pe-");
+			break;
+	}
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn(".PHONY: TheDefaultOutput clean");
+
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("TheDefaultOutput :");
+	WriteMakeDependFile(Write_machobinpath_ToDestFile);
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+	DoAllSrcFilesWithSetup(DoMVCSrcFileMakeCompile);
+
+	WriteBlankLineToDestFile();
+	DoAllSrcFilesWithSetup(DoMVCSrcFileMakeAsm);
+
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("AsmFiles = ");
+	WriteBackSlashToDestFile();
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		DoMVCAllSrcFilesStandardMakeAsms();
+		WriteBlankLineToDestFile();
+	--DestFileIndent;
+
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("ObjFiles = ");
+	WriteBackSlashToDestFile();
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		DoAllSrcFilesStandardMakeObjects();
+		WriteBlankLineToDestFile();
+	--DestFileIndent;
+
+	if (HaveMacBundleApp) {
+		WriteBlankLineToDestFile();
+		WriteMakeRule(Write_machoAppIconPath,
+			Write_tmachoShellDeps,
+			Write_tmachoShell);
+	}
+	if (gbk_apifam_win == gbo_apifam) {
+		WriteBlankLineToDestFile();
+		WriteBgnDestFileLn();
+		WriteMainRsrcObjPath();
+		WriteCStrToDestFile(": ");
+		WriteMainRsrcSrcPath();
+		WriteEndDestFileLn();
+		++DestFileIndent;
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("$(my_prefix)windres");
+			WriteCStrToDestFile(" -i");
+			WritePathArgInMakeCmnd(WriteMainRsrcSrcPath);
+			WriteCStrToDestFile(" --input-format=rc -o");
+			WritePathArgInMakeCmnd(WriteMainRsrcObjPath);
+			WriteCStrToDestFile(" -O coff  --include-dir SRC");
+			WriteEndDestFileLn();
+		--DestFileIndent;
+		WriteBlankLineToDestFile();
+	}
+
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	Write_machobinpath_ToDestFile();
+	WriteCStrToDestFile(" : $(AsmFiles) $(ObjFiles)");
+	if (HaveMacBundleApp) {
+		WriteMakeDependFile(Write_machoAppIconPath);
+	}
+	if (HaveMacRrscs) {
+		WriteMakeDependFile(Write_machoRsrcPath);
+	}
+	if (gbk_apifam_win == gbo_apifam) {
+		WriteMakeDependFile(WriteMainRsrcObjPath);
+	}
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		WriteBgnDestFileLn();
+		switch (cur_targ) {
+			case gbk_targ_mach:
+			case gbk_targ_imch:
+			case gbk_targ_mc64:
+			case gbk_targ_mx11:
+			case gbk_targ_mi11:
+			case gbk_targ_mx64:
+				WriteCStrToDestFile("gcc");
+				break;
+			default:
+				WriteCStrToDestFile("$(my_prefix)gcc");
+				break;
+		}
+		WriteCStrToDestFile(" \\");
+		WriteEndDestFileLn();
+		++DestFileIndent;
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("-o");
+			WritePathArgInMakeCmnd(Write_machobinpath_ToDestFile);
+			WriteCStrToDestFile(" \\");
+			WriteEndDestFileLn();
+
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("$(ObjFiles)");
+			if ((gbk_apifam_osx == gbo_apifam)
+				|| (gbk_apifam_cco == gbo_apifam))
+			{
+				DoAllFrameWorksWithSetup(DoFrameWorkMVCaddFile);
+				if (gbk_targ_mach == cur_targ) {
+					WriteCStrToDestFile(
+						" /usr/local/mvmc/mach"
+						"/lib/darwin-gpsave.o");
+				}
+				if (ide_vers >= 4000) {
+					WriteCStrToDestFile(" -Wl,-no_pie");
+				}
+				WriteCStrToDestFile(" -nodefaultlibs -lSystem");
+				if ((gbk_targ_mach == cur_targ) && WantLocalTalk) {
+					WriteCStrToDestFile(" -lSystemStubs");
+				}
+			} else if (gbk_apifam_win == gbo_apifam) {
+				WritePathArgInMakeCmnd(WriteMainRsrcObjPath);
+				if (gbk_targ_wcar == cur_targ) {
+					WriteCStrToDestFile(
+						" /usr/local/mvmc/wcar/lib/divlib.o"
+						" -lmingw32");
+					WriteCStrToDestFile(
+						" -lcommctrl -lcoredll -laygshell -lmmtimer");
+					WriteCStrToDestFile(" -static-libgcc");
+				} else {
+					WriteCStrToDestFile(
+						" -mwindows -lwinmm -lole32 -luuid");
+				}
+			} else {
+				if (gbk_targfam_slrs == gbo_targfam) {
+					WriteCStrToDestFile(" -lposix4");
+				}
+#if MayUseSound
+				if (gbk_sndapi_alsa == gbo_sndapi) {
+					WriteCStrToDestFile(" -ldl");
+#if 0
+					WriteCStrToDestFile(" -lasound");
+#endif
+				} else if (gbk_sndapi_ddsp == gbo_sndapi) {
+					if ((gbk_targfam_nbsd == gbo_targfam)
+						|| (gbk_targfam_obsd == gbo_targfam))
+					{
+						WriteCStrToDestFile(" -lossaudio");
+					}
+				}
+#endif
+#if 0
+				WriteCStrToDestFile(" -lXext");
+#endif
+				if (gbk_targfam_nbsd == gbo_targfam) {
+					WriteCStrToDestFile(" -R/usr/X11R7/lib");
+				}
+				WriteCStrToDestFile(" -lX11");
+				switch (cur_targ) {
+					case gbk_targ_lx86:
+					case gbk_targ_lx64:
+					case gbk_targ_larm:
+					case gbk_targ_lppc:
+					case gbk_targ_lspr:
+					case gbk_targ_fbsd:
+					case gbk_targ_fb64:
+					case gbk_targ_nbsd:
+					case gbk_targ_nb64:
+					case gbk_targ_oind:
+					case gbk_targ_oi64:
+					case gbk_targ_wcar:
+						WriteCStrToDestFile(" -static-libgcc");
+						break;
+				}
+			}
+			WriteMVCCompileAsmLinkCommonOptions();
+			WriteMVCLinkOSGlucompileCommonOptions();
+			WriteMVCCompileLinkCommonOptions();
+			WriteEndDestFileLn();
+		--DestFileIndent;
+		if (gbk_dbg_on != gbo_dbg) {
+			WriteBgnDestFileLn();
+			switch (cur_targ) {
+				case gbk_targ_mach:
+				case gbk_targ_imch:
+				case gbk_targ_mc64:
+				case gbk_targ_mx11:
+				case gbk_targ_mi11:
+				case gbk_targ_mx64:
+					WriteCStrToDestFile("strip -u -r");
+					break;
+				default:
+					WriteCStrToDestFile("$(my_prefix)strip");
+					break;
+			}
+			WritePathArgInMakeCmnd(
+				Write_machobinpath_ToDestFile);
+			WriteEndDestFileLn();
+		}
+	--DestFileIndent;
+
+	if (HaveMacRrscs) {
+		WriteBlankLineToDestFile();
+		WriteMakeRule(Write_machoRsrcPath,
+			Write_machoRsrcMVCDeps,
+			Write_machoRsrcMVCBuild);
+	}
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("clean :");
+	++DestFileIndent;
+		WriteDestFileLn("rm -f $(AsmFiles) $(ObjFiles)");
+		if (HaveMacBundleApp) {
+			WriteRmDir(WriteAppNamePath);
+		} else {
+			if (gbk_apifam_win == gbo_apifam) {
+				WriteRmFile(WriteMainRsrcObjPath);
+			}
+			WriteRmFile(WriteAppNamePath);
+		}
+	--DestFileIndent;
+}
+
+LOCALPROC WriteWantSigningFlag(void)
+{
+	WriteOpenDestFile("my_config_d",
+		"codesign", ".txt", "code signing flag");
+
+	WriteDestFileLn("1");
+
+	WriteCloseDestFile();
+}
+
+LOCALPROC WriteMVCSpecificFiles(void)
+{
+	if (HaveMacBundleApp) {
+		WritePListData();
+	}
+
+	if (WantSigning) {
+		WriteWantSigningFlag();
+	}
+
+	if (WantSandbox) {
+		WriteEntitlementsData();
+	}
+
+	WriteADstFile1("my_project_d",
+		"Makefile", "", "Make file",
+		WriteMVCMakeFile);
+}
--- /dev/null
+++ b/setup/WRMW8FLS.i
@@ -1,0 +1,870 @@
+/*
+	WRMW8FLS.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	WRite MetroWerks 8 specific FiLeS
+*/
+
+
+
+static void WriteXMLtagSettingNameProcVal(char *n, MyProc v)
+{
+	WriteBgnDestFileLn();
+	WriteXMLtagBegin("SETTING");
+	WriteXMLtagBegin("NAME");
+	WriteCStrToDestFile(n);
+	WriteXMLtagEnd("NAME");
+	WriteXMLtagBegin("VALUE");
+	v();
+	WriteXMLtagEnd("VALUE");
+	WriteXMLtagEnd("SETTING");
+	WriteEndDestFileLn();
+}
+
+static void WriteXMLtagSettingNameVal(char *n, char *v)
+{
+	MyPtr SavepDt = pDt;
+
+	pDt = (MyPtr)v;
+	WriteXMLtagSettingNameProcVal(n, WritepDtString);
+	pDt = SavepDt;
+}
+
+static void WriteBeginNamedSettingXMLtagLine(char *s)
+{
+	WriteBgnDestFileLn();
+	WriteXMLtagBegin("SETTING");
+	WriteXMLtagBegin("NAME");
+	WriteCStrToDestFile(s);
+	WriteXMLtagEnd("NAME");
+	WriteEndDestFileLn();
+	++DestFileIndent;
+}
+
+static void WriteAllMWTargetName(void)
+{
+	WriteXMLtagBeginProcValEndLine("TARGETNAME", WriteAppVariationStr);
+}
+
+typedef void (*tWriteMWLib)(char *s);
+
+static void WriteMWLibs(tWriteMWLib p)
+{
+	if (gbk_targfam_mswn == gbo_targfam) {
+		p("kernel32.lib");
+		p("user32.lib");
+		p("gdi32.lib");
+		p("comdlg32.lib");
+		p("shell32.lib");
+		p("ole32.lib");
+		p("uuid.lib");
+		p("winmm.lib");
+		if (WantIconMaster) {
+			p("advapi32.lib");
+		}
+		p("MSL_All_x86.lib");
+	} else if (gbk_targfam_mach == gbo_targfam) {
+		p("crt1.o");
+		p("MSL_All_Mach-O_D.lib");
+	} else {
+		if (gbk_targfam_carb == gbo_targfam) {
+			p("CarbonLib");
+#if UseOpenGLinOSX
+				p("OpenGLLibraryStub");
+#endif
+		} else {
+			p("InterfaceLib");
+			p("MathLib");
+			p("AppearanceLib");
+			p("MenusLib");
+			p("NavigationLib");
+			p("DragLib");
+			p("WindowsLib");
+		}
+		p("MSL_Runtime_PPC.Lib");
+	}
+}
+
+static void WriteMWLibAddFile(char *s)
+{
+	WriteBeginXMLtagLine("FILE");
+		WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+		WriteXMLtagBeginValEndLine("PATH", s);
+		WriteXMLtagBeginValEndLine("PATHFORMAT", "MacOS");
+		if (gbk_targfam_mswn == gbo_targfam) {
+			WriteXMLtagBeginValEndLine("FILEKIND", "Unknown");
+		} else {
+			WriteXMLtagBeginValEndLine("FILEKIND", "Library");
+		}
+		WriteXMLtagBeginValEndLine("FILEFLAGS", "");
+	WriteEndXMLtagLine("FILE");
+}
+
+static void WriteMWLibMakeObjects(char *s)
+{
+	WriteBeginXMLtagLine("FILEREF");
+		WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+		WriteXMLtagBeginValEndLine("PATH", s);
+		WriteXMLtagBeginValEndLine("PATHFORMAT", "MacOS");
+	WriteEndXMLtagLine("FILEREF");
+}
+
+static void WriteMWLibGroupList(char *s)
+{
+	WriteBeginXMLtagLine("FILEREF");
+		WriteAllMWTargetName();
+		WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+		WriteXMLtagBeginValEndLine("PATH", s);
+		WriteXMLtagBeginValEndLine("PATHFORMAT", "MacOS");
+	WriteEndXMLtagLine("FILEREF");
+}
+
+static void WriteMWProjRelSearchPath(MyProc p)
+{
+	WriteBeginXMLtagLine("SETTING");
+		WriteBeginNamedSettingXMLtagLine("SearchPath");
+			WriteBgnDestFileLn();
+			WriteXMLtagBegin("SETTING");
+			WriteXMLtagBegin("NAME");
+			WriteCStrToDestFile("Path");
+			WriteXMLtagEnd("NAME");
+			WriteXMLtagBegin("VALUE");
+			p();
+			WriteXMLtagEnd("VALUE");
+			WriteXMLtagEnd("SETTING");
+			WriteEndDestFileLn();
+
+			WriteXMLtagSettingNameVal("PathFormat", "MacOS");
+			WriteXMLtagSettingNameVal("PathRoot", "Project");
+		WriteEndXMLtagLine("SETTING");
+		WriteXMLtagSettingNameVal("Recursive", "true");
+		WriteXMLtagSettingNameVal("FrameworkPath", "false");
+		WriteXMLtagSettingNameVal("HostFlags", "All");
+	WriteEndXMLtagLine("SETTING");
+}
+
+static void WriteMWDrvRelSearchPath(char *s)
+{
+	WriteBeginXMLtagLine("SETTING");
+		WriteBeginNamedSettingXMLtagLine("SearchPath");
+			WriteXMLtagSettingNameVal("Path", s);
+			WriteXMLtagSettingNameVal("PathFormat", "MacOS");
+			WriteXMLtagSettingNameVal("PathRoot", "Project");
+		WriteEndXMLtagLine("SETTING");
+		WriteXMLtagSettingNameVal("Recursive", "true");
+		WriteXMLtagSettingNameVal("FrameworkPath", "false");
+		WriteXMLtagSettingNameVal("HostFlags", "All");
+	WriteEndXMLtagLine("SETTING");
+}
+
+static void WriteBeginXMLMWGroup(char *s)
+{
+	WriteBgnDestFileLn();
+	WriteXMLtagBegin("GROUP");
+	WriteXMLtagBegin("NAME");
+	WriteCStrToDestFile(s);
+	WriteXMLtagEnd("NAME");
+	WriteEndDestFileLn();
+	++DestFileIndent;
+}
+
+static void WriteMWSettingsPanelComment(char *s)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("<!-- Settings for ");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(s);
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(" panel -->");
+	WriteEndDestFileLn();
+}
+
+static void WriteDocTypeMWAddFile(void)
+{
+	WriteBeginXMLtagLine("FILE");
+		WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+		WriteXMLtagBeginProcValEndLine("PATH",
+			WriteDocTypeIconFileName);
+		WriteXMLtagBeginValEndLine("PATHFORMAT", "MacOS");
+		WriteXMLtagBeginValEndLine("FILEKIND", "Unknown");
+		WriteXMLtagBeginValEndLine("FILEFLAGS", "");
+	WriteEndXMLtagLine("FILE");
+}
+
+static void WriteDocTypeMWMakeObjects(void)
+{
+	WriteBeginXMLtagLine("FILEREF");
+		WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+		WriteXMLtagBeginProcValEndLine("PATH",
+			WriteDocTypeIconFileName);
+		WriteXMLtagBeginValEndLine("PATHFORMAT", "MacOS");
+	WriteEndXMLtagLine("FILEREF");
+}
+
+static void WriteDocTypeMWGroupList(void)
+{
+	WriteBeginXMLtagLine("FILEREF");
+		WriteAllMWTargetName();
+		WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+		WriteXMLtagBeginProcValEndLine("PATH",
+			WriteDocTypeIconFileName);
+		WriteXMLtagBeginValEndLine("PATHFORMAT", "MacOS");
+	WriteEndXMLtagLine("FILEREF");
+}
+
+static void DoSrcFileMW8AddFile(void)
+{
+	WriteBeginXMLtagLine("FILE");
+		WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+		WriteXMLtagBeginProcValEndLine("PATH", WriteSrcFileFileName);
+		WriteXMLtagBeginValEndLine("PATHFORMAT", "MacOS");
+		WriteXMLtagBeginValEndLine("FILEKIND", "Text");
+		if (gbk_dbg_on == gbo_dbg) {
+			WriteXMLtagBeginValEndLine("FILEFLAGS", "Debug");
+		} else {
+			WriteXMLtagBeginValEndLine("FILEFLAGS", "");
+		}
+	WriteEndXMLtagLine("FILE");
+}
+
+static void DoSrcFileMW8sMakeObjects(void)
+{
+	WriteBeginXMLtagLine("FILEREF");
+		WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+		WriteXMLtagBeginProcValEndLine("PATH", WriteSrcFileFileName);
+		WriteXMLtagBeginValEndLine("PATHFORMAT", "MacOS");
+	WriteEndXMLtagLine("FILEREF");
+}
+
+LOCALPROC DoSrcFileMW8GroupList(void)
+{
+	WriteBeginXMLtagLine("FILEREF");
+		WriteAllMWTargetName();
+		WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+		WriteXMLtagBeginProcValEndLine("PATH", WriteSrcFileFileName);
+		WriteXMLtagBeginValEndLine("PATHFORMAT", "MacOS");
+	WriteEndXMLtagLine("FILEREF");
+}
+
+LOCALPROC WriteMetrowerksProjectFile(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("<?xml version=");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile("1.0");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(" encoding=");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile("UTF-8");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(" standalone=");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile("yes");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(" ?>");
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("<?codewarrior exportversion=");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile("1.0.1");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(" ideversion=");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile("5.0");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(" ?>");
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+	WriteBeginXMLtagLine("PROJECT");
+	WriteBeginXMLtagLine("TARGETLIST");
+	WriteBeginXMLtagLine("TARGET");
+		WriteXMLtagBeginProcValEndLine("NAME", WriteAppVariationStr);
+		WriteBeginXMLtagLine("SETTINGLIST");
+			WriteMWSettingsPanelComment("Access Paths");
+			if (gbk_targfam_mach == gbo_targfam) {
+				WriteXMLtagSettingNameVal(
+					"InterpretDOSAndUnixPaths", "true");
+				WriteXMLtagSettingNameVal(
+					"RequireFrameworkStyleIncludes", "true");
+			}
+			WriteBeginNamedSettingXMLtagLine("UserSearchPaths");
+				WriteMWProjRelSearchPath(Write_src_d_ToDestFile);
+				WriteMWProjRelSearchPath(Write_cfg_d_ToDestFile);
+				if (gbk_targfam_mach == gbo_targfam) {
+					/* seems to be wanted by property list compiler */
+					WriteMWDrvRelSearchPath(":");
+				}
+			WriteEndXMLtagLine("SETTING");
+			WriteBeginNamedSettingXMLtagLine("SystemSearchPaths");
+				if (gbk_targfam_mswn == gbo_targfam) {
+					WriteBeginXMLtagLine("SETTING");
+						WriteBeginNamedSettingXMLtagLine("SearchPath");
+							WriteXMLtagSettingNameVal("Path", ":MSL:");
+							WriteXMLtagSettingNameVal("PathFormat",
+								"MacOS");
+							WriteXMLtagSettingNameVal("PathRoot",
+								"CodeWarrior");
+						WriteEndXMLtagLine("SETTING");
+						WriteXMLtagSettingNameVal("Recursive", "true");
+						WriteXMLtagSettingNameVal("FrameworkPath",
+							"false");
+						WriteXMLtagSettingNameVal("HostFlags", "All");
+					WriteEndXMLtagLine("SETTING");
+
+					WriteBeginXMLtagLine("SETTING");
+						WriteBeginNamedSettingXMLtagLine("SearchPath");
+							WriteXMLtagSettingNameVal("Path",
+								":Win32-x86 Support:");
+							WriteXMLtagSettingNameVal("PathFormat",
+								"MacOS");
+							WriteXMLtagSettingNameVal("PathRoot",
+								"CodeWarrior");
+						WriteEndXMLtagLine("SETTING");
+						WriteXMLtagSettingNameVal("Recursive", "true");
+						WriteXMLtagSettingNameVal("FrameworkPath",
+							"false");
+						WriteXMLtagSettingNameVal("HostFlags", "All");
+					WriteEndXMLtagLine("SETTING");
+				} else {
+					WriteBeginXMLtagLine("SETTING");
+						WriteBeginNamedSettingXMLtagLine("SearchPath");
+							WriteXMLtagSettingNameVal("Path",
+								":MSL:MSL_C:");
+							WriteXMLtagSettingNameVal("PathFormat",
+								"MacOS");
+							WriteXMLtagSettingNameVal("PathRoot",
+								"CodeWarrior");
+						WriteEndXMLtagLine("SETTING");
+						WriteXMLtagSettingNameVal("Recursive", "true");
+						WriteXMLtagSettingNameVal("FrameworkPath",
+							"false");
+						WriteXMLtagSettingNameVal("HostFlags", "All");
+					WriteEndXMLtagLine("SETTING");
+
+					if (gbk_targfam_mach == gbo_targfam) {
+						WriteBeginXMLtagLine("SETTING");
+							WriteBeginNamedSettingXMLtagLine(
+								"SearchPath");
+								WriteXMLtagSettingNameVal("Path",
+									":MacOS X Support:");
+								WriteXMLtagSettingNameVal("PathFormat",
+									"MacOS");
+								WriteXMLtagSettingNameVal("PathRoot",
+									"CodeWarrior");
+							WriteEndXMLtagLine("SETTING");
+							WriteXMLtagSettingNameVal("Recursive",
+								"true");
+							WriteXMLtagSettingNameVal("FrameworkPath",
+								"false");
+							WriteXMLtagSettingNameVal("HostFlags",
+								"All");
+						WriteEndXMLtagLine("SETTING");
+
+						WriteBeginXMLtagLine("SETTING");
+							WriteBeginNamedSettingXMLtagLine(
+								"SearchPath");
+								WriteXMLtagSettingNameVal("Path",
+									"/usr/include");
+								WriteXMLtagSettingNameVal("PathFormat",
+									"Unix");
+								WriteXMLtagSettingNameVal("PathRoot",
+									"Absolute");
+							WriteEndXMLtagLine("SETTING");
+							WriteXMLtagSettingNameVal("Recursive",
+								"false");
+							WriteXMLtagSettingNameVal("FrameworkPath",
+								"false");
+							WriteXMLtagSettingNameVal("HostFlags",
+								"All");
+						WriteEndXMLtagLine("SETTING");
+
+						WriteBeginXMLtagLine("SETTING");
+							WriteBeginNamedSettingXMLtagLine(
+								"SearchPath");
+								WriteXMLtagSettingNameVal("Path",
+									"/usr/lib");
+								WriteXMLtagSettingNameVal("PathFormat",
+									"Unix");
+								WriteXMLtagSettingNameVal("PathRoot",
+									"Absolute");
+							WriteEndXMLtagLine("SETTING");
+							WriteXMLtagSettingNameVal("Recursive",
+								"false");
+							WriteXMLtagSettingNameVal("FrameworkPath",
+								"false");
+							WriteXMLtagSettingNameVal("HostFlags",
+								"All");
+						WriteEndXMLtagLine("SETTING");
+
+						WriteBeginXMLtagLine("SETTING");
+							WriteBeginNamedSettingXMLtagLine(
+								"SearchPath");
+								WriteXMLtagSettingNameVal("Path",
+									"System/Library/Frameworks");
+								WriteXMLtagSettingNameVal("PathFormat",
+									"Unix");
+								WriteXMLtagSettingNameVal("PathRoot",
+									"OS X Volume");
+							WriteEndXMLtagLine("SETTING");
+							WriteXMLtagSettingNameVal("Recursive",
+								"false");
+							WriteXMLtagSettingNameVal("FrameworkPath",
+								"true");
+							WriteXMLtagSettingNameVal("HostFlags",
+								"All");
+						WriteEndXMLtagLine("SETTING");
+					} else {
+						WriteBeginXMLtagLine("SETTING");
+							WriteBeginNamedSettingXMLtagLine(
+								"SearchPath");
+								WriteXMLtagSettingNameVal("Path",
+									":MacOS Support:");
+								WriteXMLtagSettingNameVal("PathFormat",
+									"MacOS");
+								WriteXMLtagSettingNameVal("PathRoot",
+									"CodeWarrior");
+							WriteEndXMLtagLine("SETTING");
+							WriteXMLtagSettingNameVal("Recursive",
+								"true");
+							WriteXMLtagSettingNameVal("FrameworkPath",
+								"false");
+							WriteXMLtagSettingNameVal("HostFlags",
+								"All");
+						WriteEndXMLtagLine("SETTING");
+					}
+				}
+
+			WriteEndXMLtagLine("SETTING");
+			WriteBlankLineToDestFile();
+			WriteMWSettingsPanelComment("Target Settings");
+			if (gbk_targ_wx86 == cur_targ) {
+				WriteXMLtagSettingNameVal("Linker",
+					"Win32 x86 Linker");
+			} else if (gbk_targ_mach == cur_targ) {
+				WriteXMLtagSettingNameVal("Linker",
+					"MacOS X PPC Linker");
+			} else {
+				WriteXMLtagSettingNameVal("Linker",
+					"MacOS PPC Linker");
+			}
+			WriteXMLtagSettingNameProcVal("Targetname",
+				WriteAppVariationStr);
+
+			WriteBeginNamedSettingXMLtagLine("OutputDirectory");
+				WriteXMLtagSettingNameVal("Path", ":");
+				WriteXMLtagSettingNameVal("PathFormat", "MacOS");
+				WriteXMLtagSettingNameVal("PathRoot", "Project");
+			WriteEndXMLtagLine("SETTING");
+
+			WriteBlankLineToDestFile();
+			WriteMWSettingsPanelComment("Build Extras");
+			WriteXMLtagSettingNameVal("BrowserGenerator", "0");
+
+			WriteBlankLineToDestFile();
+			WriteMWSettingsPanelComment("Debugger Target");
+			WriteXMLtagSettingNameVal("StopAtTempBPOnLaunch", "false");
+
+			WriteBlankLineToDestFile();
+			WriteMWSettingsPanelComment("C/C++ Compiler");
+			WriteXMLtagSettingNameVal("MWFrontEnd_C_checkprotos", "1");
+			WriteXMLtagSettingNameVal("MWFrontEnd_C_enableexceptions",
+				"0");
+			if ((gbk_dbg_on == gbo_dbg)
+				|| (gbk_targfam_mswn == gbo_targfam))
+			{
+				/* inlining seems to give bad code for x86 version */
+				WriteXMLtagSettingNameVal("MWFrontEnd_C_dontinline",
+					"1");
+			} else {
+				WriteXMLtagSettingNameVal("MWFrontEnd_C_dontinline",
+					"0");
+			}
+			WriteXMLtagSettingNameVal("MWFrontEnd_C_useRTTI", "0");
+			if (gbk_dbg_on == gbo_dbg) {
+				WriteXMLtagSettingNameVal("MWFrontEnd_C_autoinline",
+					"0");
+			} else {
+				WriteXMLtagSettingNameVal("MWFrontEnd_C_autoinline",
+					"1");
+			}
+
+			WriteBlankLineToDestFile();
+			WriteMWSettingsPanelComment("C/C++ Warnings");
+			WriteXMLtagSettingNameVal(
+				"MWWarning_C_warn_illpragma", "1");
+			WriteXMLtagSettingNameVal(
+				"MWWarning_C_warn_emptydecl", "1");
+			WriteXMLtagSettingNameVal(
+				"MWWarning_C_warn_possunwant", "1");
+			WriteXMLtagSettingNameVal(
+				"MWWarning_C_warn_unusedvar", "1");
+			WriteXMLtagSettingNameVal(
+				"MWWarning_C_warn_unusedarg", "1");
+			WriteXMLtagSettingNameVal(
+				"MWWarning_C_warn_extracomma", "1");
+			WriteXMLtagSettingNameVal(
+				"MWWarning_C_pedantic", "1");
+
+			WriteBlankLineToDestFile();
+			if (gbk_targfam_mswn == gbo_targfam) {
+				WriteMWSettingsPanelComment("x86 CodeGen");
+				if (gbk_dbg_on == gbo_dbg) {
+					WriteXMLtagSettingNameVal(
+						"MWCodeGen_X86_intrinsics", "0");
+				} else {
+					WriteXMLtagSettingNameVal(
+						"MWCodeGen_X86_intrinsics", "1");
+				}
+			} else if (gbk_targ_mach == cur_targ) {
+				WriteMWSettingsPanelComment("PPC CodeGen Mach-O");
+				WriteXMLtagSettingNameVal(
+					"MWCodeGen_MachO_structalignment", "PPC");
+				if (gbk_dbg_on == gbo_dbg) {
+					WriteXMLtagSettingNameVal(
+						"MWCodeGen_MachO_peephole", "0");
+					WriteXMLtagSettingNameVal(
+						"MWCodeGen_MachO_schedule", "0");
+				} else {
+					WriteXMLtagSettingNameVal(
+						"MWCodeGen_MachO_peephole", "1");
+					WriteXMLtagSettingNameVal(
+						"MWCodeGen_MachO_schedule", "1");
+				}
+			} else {
+				WriteMWSettingsPanelComment("PPC CodeGen");
+				if (gbk_dbg_on == gbo_dbg) {
+					WriteXMLtagSettingNameVal(
+						"MWCodeGen_PPC_tracebacktables", "Inline");
+				} else {
+					WriteXMLtagSettingNameVal(
+						"MWCodeGen_PPC_tracebacktables", "None");
+				}
+				WriteXMLtagSettingNameVal(
+					"MWCodeGen_PPC_vectortocdata", "0");
+				if (gbk_dbg_on == gbo_dbg) {
+					WriteXMLtagSettingNameVal(
+						"MWCodeGen_PPC_peephole", "0");
+					WriteXMLtagSettingNameVal(
+						"MWCodeGen_PPC_schedule", "0");
+				} else {
+					WriteXMLtagSettingNameVal(
+						"MWCodeGen_PPC_peephole", "1");
+					WriteXMLtagSettingNameVal(
+						"MWCodeGen_PPC_schedule", "1");
+				}
+			}
+
+			WriteBlankLineToDestFile();
+			if (gbk_targfam_mswn == gbo_targfam) {
+				WriteMWSettingsPanelComment("x86 Global Optimizer");
+				if (gbk_dbg_on == gbo_dbg) {
+					WriteXMLtagSettingNameVal(
+						"GlobalOptimizer_X86_optimizationlevel",
+						"Level0");
+				} else {
+					WriteXMLtagSettingNameVal(
+						"GlobalOptimizer_X86_optimizationlevel",
+						"Level1");
+					/*
+						Level4 (and Level3 and Level2)
+						generates bade code.
+					*/
+				}
+				WriteXMLtagSettingNameVal(
+					"GlobalOptimizer_X86_optfor", "Size");
+
+				/*
+					work around what is probably bug
+					in windows version of mw8
+				*/
+				if (gbk_dbg_on == gbo_dbg) {
+					WriteXMLtagSettingNameVal(
+						"GlobalOptimizer_X86__optimizationlevel",
+						"Level0");
+				} else {
+					WriteXMLtagSettingNameVal(
+						"GlobalOptimizer_X86__optimizationlevel",
+						"Level1");
+				}
+				WriteXMLtagSettingNameVal(
+					"GlobalOptimizer_X86__optfor", "Size");
+			} else {
+				WriteMWSettingsPanelComment("PPC Global Optimizer");
+				if (gbk_dbg_on == gbo_dbg) {
+					WriteXMLtagSettingNameVal(
+						"GlobalOptimizer_PPC_optimizationlevel",
+						"Level0");
+				} else {
+					WriteXMLtagSettingNameVal(
+						"GlobalOptimizer_PPC_optimizationlevel",
+						"Level4");
+				}
+				WriteXMLtagSettingNameVal(
+					"GlobalOptimizer_PPC_optfor", "Size");
+			}
+
+			WriteBlankLineToDestFile();
+			if (gbk_targfam_mswn == gbo_targfam) {
+				WriteMWSettingsPanelComment("x86 Linker");
+				WriteXMLtagSettingNameVal(
+					"MWLinker_X86_subsystem", "WinGUI");
+				if (gbk_dbg_on == gbo_dbg) {
+					WriteXMLtagSettingNameVal(
+						"MWLinker_X86_linkdebug", "true");
+				} else {
+					WriteXMLtagSettingNameVal(
+						"MWLinker_X86_linkdebug", "false");
+				}
+				WriteXMLtagSettingNameVal(
+					"MWLinker_X86_usedefaultlibs", "false");
+			} else if (gbk_targ_mach == cur_targ) {
+				WriteMWSettingsPanelComment("PPC Mac OS X Linker");
+				if (gbk_dbg_on == gbo_dbg) {
+					WriteXMLtagSettingNameVal(
+						"MWLinker_MacOSX_linksym", "1");
+				} else {
+					WriteXMLtagSettingNameVal(
+						"MWLinker_MacOSX_linksym", "0");
+				}
+				WriteXMLtagSettingNameVal(
+					"MWLinker_MacOSX_symfullpath", "1");
+				WriteXMLtagSettingNameVal(
+					"MWLinker_MacOSX_permitmultdefs", "0");
+				if (gbk_dbg_on != gbo_dbg) {
+					WriteXMLtagSettingNameVal(
+						"MWLinker_MacOSX_strip_debug_symbols", "1");
+				}
+			} else {
+				WriteMWSettingsPanelComment("PPC Linker");
+				if (gbk_dbg_on == gbo_dbg) {
+					WriteXMLtagSettingNameVal(
+						"MWLinker_PPC_linksym", "1");
+				} else {
+					WriteXMLtagSettingNameVal(
+						"MWLinker_PPC_linksym", "0");
+				}
+				WriteXMLtagSettingNameVal(
+					"MWLinker_PPC_linkmode", "Normal");
+			}
+
+			WriteBlankLineToDestFile();
+			if (gbk_targfam_mswn == gbo_targfam) {
+				WriteMWSettingsPanelComment("x86 Project");
+				WriteXMLtagSettingNameProcVal(
+					"MWProject_X86_outfile", WriteAppNameStr);
+			} else if (gbk_targ_mach == cur_targ) {
+				WriteMWSettingsPanelComment("PPC Mac OS X Project");
+				WriteXMLtagSettingNameVal(
+					"MWProject_MacOSX_type", "ApplicationPackage");
+				WriteXMLtagSettingNameProcVal(
+					"MWProject_MacOSX_outfile", WriteAppNameStr);
+				WriteXMLtagSettingNameVal(
+					"MWProject_MacOSX_filecreator", kMacCreatorSig);
+				WriteXMLtagSettingNameVal(
+					"MWProject_MacOSX_filetype", "APPL");
+				WriteXMLtagSettingNameVal(
+					"MWProject_MacOSX_vmaddress", "0");
+				WriteXMLtagSettingNameVal(
+					"MWProject_MacOSX_flatrsrc", "1");
+				WriteXMLtagSettingNameVal(
+					"MWProject_MacOSX_flatrsrcfilename", "");
+				WriteBeginNamedSettingXMLtagLine(
+					"MWProject_MacOSX_flatrsrcoutputdir");
+					WriteXMLtagSettingNameVal("Path", ":");
+					WriteXMLtagSettingNameVal("PathFormat", "MacOS");
+					WriteXMLtagSettingNameVal("PathRoot", "Project");
+				WriteEndXMLtagLine("SETTING");
+			} else {
+				WriteMWSettingsPanelComment("PPC Project");
+				WriteXMLtagSettingNameVal(
+					"MWProject_PPC_outfile", vStrAppAbbrev);
+				WriteXMLtagSettingNameVal(
+					"MWProject_PPC_filecreator", kMacCreatorSig);
+				WriteXMLtagSettingNameVal(
+					"MWProject_PPC_size", "6000");
+				WriteXMLtagSettingNameVal(
+					"MWProject_PPC_minsize", "3000");
+				WriteXMLtagSettingNameVal(
+					"MWProject_PPC_flags", "22768");
+			}
+		WriteEndXMLtagLine("SETTINGLIST");
+
+		WriteBeginXMLtagLine("FILELIST");
+			WriteMWLibs(WriteMWLibAddFile);
+
+			if (gbk_targfam_mswn == gbo_targfam) {
+				WriteBeginXMLtagLine("FILE");
+					WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+					WriteXMLtagBeginValEndLine("PATH", "main.RC");
+					WriteXMLtagBeginValEndLine("PATHFORMAT", "MacOS");
+					WriteXMLtagBeginValEndLine("FILEKIND", "Text");
+					WriteXMLtagBeginValEndLine("FILEFLAGS", "");
+				WriteEndXMLtagLine("FILE");
+			} else if (gbk_targfam_mach == gbo_targfam) {
+				WriteBeginXMLtagLine("FILE");
+					WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+					WriteXMLtagBeginValEndLine("PATH", "main.plc");
+					WriteXMLtagBeginValEndLine("PATHFORMAT", "MacOS");
+					WriteXMLtagBeginValEndLine("FILEKIND", "Text");
+					WriteXMLtagBeginValEndLine("FILEFLAGS", "Debug");
+				WriteEndXMLtagLine("FILE");
+				DoAllDocTypesWithSetup(WriteDocTypeMWAddFile);
+			} else {
+				WriteBeginXMLtagLine("FILE");
+					WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+					WriteXMLtagBeginValEndLine("PATH", "main.r");
+					WriteXMLtagBeginValEndLine("PATHFORMAT", "MacOS");
+					WriteXMLtagBeginValEndLine("FILEKIND", "Text");
+					WriteXMLtagBeginValEndLine("FILEFLAGS", "");
+				WriteEndXMLtagLine("FILE");
+			}
+
+			DoAllSrcFilesWithSetup(DoSrcFileMW8AddFile);
+		WriteEndXMLtagLine("FILELIST");
+
+		WriteBeginXMLtagLine("LINKORDER");
+			WriteMWLibs(WriteMWLibMakeObjects);
+			if (gbk_targfam_mswn == gbo_targfam) {
+				WriteBeginXMLtagLine("FILEREF");
+					WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+					WriteXMLtagBeginValEndLine("PATH", "main.RC");
+					WriteXMLtagBeginValEndLine("PATHFORMAT", "MacOS");
+				WriteEndXMLtagLine("FILEREF");
+			} else if (gbk_targfam_mach == gbo_targfam) {
+				WriteBeginXMLtagLine("FILEREF");
+					WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+					WriteXMLtagBeginValEndLine("PATH", "main.plc");
+					WriteXMLtagBeginValEndLine("PATHFORMAT", "MacOS");
+				WriteEndXMLtagLine("FILEREF");
+				DoAllDocTypesWithSetup(WriteDocTypeMWMakeObjects);
+			} else {
+				WriteBeginXMLtagLine("FILEREF");
+					WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+					WriteXMLtagBeginValEndLine("PATH", "main.r");
+					WriteXMLtagBeginValEndLine("PATHFORMAT", "MacOS");
+				WriteEndXMLtagLine("FILEREF");
+			}
+			DoAllSrcFilesSortWithSetup(DoSrcFileMW8sMakeObjects);
+		WriteEndXMLtagLine("LINKORDER");
+
+		if (gbk_targfam_mach == gbo_targfam) {
+			WriteBeginXMLtagLine("FRAMEWORKLIST");
+				WriteBeginXMLtagLine("FRAMEWORK");
+					WriteBeginXMLtagLine("FILEREF");
+						WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+						WriteXMLtagBeginValEndLine(
+							"PATH", "Carbon.framework");
+						WriteXMLtagBeginValEndLine(
+							"PATHFORMAT", "MacOS");
+					WriteEndXMLtagLine("FILEREF");
+					WriteXMLtagBeginValEndLine(
+						"DYNAMICLIBRARY", "Carbon");
+				WriteEndXMLtagLine("FRAMEWORK");
+
+#if UseOpenGLinOSX
+				WriteBeginXMLtagLine("FRAMEWORK");
+					WriteBeginXMLtagLine("FILEREF");
+						WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+						WriteXMLtagBeginValEndLine("PATH",
+							"OpenGL.framework");
+						WriteXMLtagBeginValEndLine(
+							"PATHFORMAT", "MacOS");
+					WriteEndXMLtagLine("FILEREF");
+					WriteXMLtagBeginValEndLine(
+						"DYNAMICLIBRARY", "OpenGL");
+				WriteEndXMLtagLine("FRAMEWORK");
+
+				WriteBeginXMLtagLine("FRAMEWORK");
+					WriteBeginXMLtagLine("FILEREF");
+						WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+						WriteXMLtagBeginValEndLine(
+							"PATH", "AGL.framework");
+						WriteXMLtagBeginValEndLine(
+							"PATHFORMAT", "MacOS");
+					WriteEndXMLtagLine("FILEREF");
+					WriteXMLtagBeginValEndLine("DYNAMICLIBRARY", "AGL");
+				WriteEndXMLtagLine("FRAMEWORK");
+#endif
+
+				WriteBeginXMLtagLine("FRAMEWORK");
+					WriteBeginXMLtagLine("FILEREF");
+						WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+						WriteXMLtagBeginValEndLine(
+							"PATH", "System.framework");
+						WriteXMLtagBeginValEndLine(
+							"PATHFORMAT", "MacOS");
+					WriteEndXMLtagLine("FILEREF");
+					WriteXMLtagBeginValEndLine(
+						"DYNAMICLIBRARY", "System");
+				WriteEndXMLtagLine("FRAMEWORK");
+			WriteEndXMLtagLine("FRAMEWORKLIST");
+		} /* (gbk_targfam_mach == gbo_targfam) */
+	WriteEndXMLtagLine("TARGET");
+	WriteEndXMLtagLine("TARGETLIST");
+
+	WriteBlankLineToDestFile();
+	WriteBeginXMLtagLine("TARGETORDER");
+		WriteBgnDestFileLn();
+		WriteXMLtagBegin("ORDEREDTARGET");
+		WriteXMLtagBegin("NAME");
+		WriteAppVariationStr();
+		WriteXMLtagEnd("NAME");
+		WriteXMLtagEnd("ORDEREDTARGET");
+		WriteEndDestFileLn();
+	WriteEndXMLtagLine("TARGETORDER");
+
+	WriteBlankLineToDestFile();
+	WriteBeginXMLtagLine("GROUPLIST");
+		WriteBeginXMLMWGroup("Libraries");
+			WriteMWLibs(WriteMWLibGroupList);
+		WriteEndXMLtagLine("GROUP");
+		WriteBeginXMLMWGroup("Resources");
+			WriteBeginXMLtagLine("FILEREF");
+				WriteAllMWTargetName();
+				WriteXMLtagBeginValEndLine("PATHTYPE", "Name");
+				if (gbk_targfam_mswn == gbo_targfam) {
+					WriteXMLtagBeginValEndLine("PATH", "main.RC");
+				} else {
+					if (HaveMacBundleApp) {
+						WriteXMLtagBeginValEndLine("PATH", "main.plc");
+					} else {
+						WriteXMLtagBeginValEndLine("PATH", "main.r");
+					}
+				}
+				WriteXMLtagBeginValEndLine("PATHFORMAT", "MacOS");
+			WriteEndXMLtagLine("FILEREF");
+			if (HaveMacBundleApp) {
+				DoAllDocTypesWithSetup(WriteDocTypeMWGroupList);
+			}
+		WriteEndXMLtagLine("GROUP");
+		DoAllSrcFilesWithSetup(DoSrcFileMW8GroupList);
+	WriteEndXMLtagLine("GROUPLIST");
+
+	WriteBlankLineToDestFile();
+	WriteEndXMLtagLine("PROJECT");
+}
+
+LOCALPROC WriteMetrowerksSpecificFiles(void)
+{
+	if (HaveMacBundleApp) {
+		WritePListData();
+	}
+
+	WriteADstFile1("my_project_d",
+		vStrAppAbbrev, ".mcp.xml", ".mcp.xml",
+		WriteMetrowerksProjectFile);
+}
--- /dev/null
+++ b/setup/WRPLCFLS.i
@@ -1,0 +1,289 @@
+/*
+	WRPLCFLS.i
+	Copyright (C) 2010 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	WRite Pelles C Compiler specific FiLeS
+*/
+
+
+LOCALPROC DoSrcFilePLCAddFile(void)
+{
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("# ");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("# Build ");
+	WriteSrcFileObjName();
+	WriteCStrToDestFile(".");
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("# ");
+
+	WriteBgnDestFileLn();
+	WriteSrcFileObjPath();
+	WriteCStrToDestFile(": \\");
+	WriteEndDestFileLn();
+
+	++DestFileIndent;
+
+		WriteBgnDestFileLn();
+		WriteSrcFileFilePath();
+		if ((DoSrcFile_gd()->Flgm & kCSrcFlgmNoHeader) == 0) {
+			WriteCStrToDestFile(" \\");
+			WriteEndDestFileLn();
+
+			WriteBgnDestFileLn();
+			WriteSrcFileHeaderPath();
+		}
+		WriteEndDestFileLn();
+
+		WriteDestFileLn("$(CC) $(CCFLAGS) \"$!\" -Fo\"$@\"");
+
+	--DestFileIndent;
+}
+
+
+LOCALPROC WritePLC_CCFLAGS(void)
+{
+	WriteCStrToDestFile(" -Tx86-coff");
+	if (gbk_dbg_on == gbo_dbg) {
+		WriteCStrToDestFile(" -Zi");
+	}
+	WriteCStrToDestFile(" -Ob1 -fp:precise -W1 -Gd -Ze");
+}
+
+LOCALPROC WritePLC_LINKFLAGS(void)
+{
+	if (gbk_dbg_on == gbo_dbg) {
+		WriteCStrToDestFile(" -debug -debugtype:cv");
+	}
+	WriteCStrToDestFile(" -subsystem:windows -machine:x86");
+}
+
+LOCALPROC WritePLCProjectFile(void)
+{
+	WriteDestFileLn("# ");
+	WriteDestFileLn(
+		"# PROJECT FILE generated by \"Pelles C for Windows,"
+		" version 6.00\".");
+	WriteDestFileLn("# WARNING! DO NOT EDIT THIS FILE.");
+	WriteDestFileLn("# ");
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("POC_PROJECT_VERSION = 6.00#");
+	WriteDestFileLn("POC_PROJECT_TYPE = 0#");
+	WriteDestFileLn("POC_PROJECT_OUTPUTDIR = bld#");
+	WriteDestFileLn("POC_PROJECT_RESULTDIR = .#");
+	WriteDestFileLn("POC_PROJECT_ARGUMENTS = #");
+	WriteDestFileLn("POC_PROJECT_WORKPATH = #");
+	WriteDestFileLn("POC_PROJECT_EXECUTOR = #");
+	WriteDestFileLn("CC = pocc.exe#");
+	WriteDestFileLn("AS = poasm.exe#");
+	WriteDestFileLn("RC = porc.exe#");
+	WriteDestFileLn("LINK = polink.exe#");
+	WriteDestFileLn("SIGN = posign.exe#");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("CCFLAGS =");
+	WritePLC_CCFLAGS();
+	WriteCStrToDestFile(" #");
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("ASFLAGS = -AIA32 -Gz #");
+	WriteDestFileLn("RCFLAGS = #");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("LINKFLAGS = ");
+	WritePLC_LINKFLAGS();
+	WriteCStrToDestFile(
+		"  shell32.lib winmm.lib ole32.lib uuid.lib kernel32.lib"
+		" user32.lib gdi32.lib comctl32.lib comdlg32.lib advapi32.lib"
+		" delayimp.lib#");
+	WriteEndDestFileLn();
+
+	WriteDestFileLn(
+		"SIGNFLAGS = -timeurl:http://"
+		"timestamp.verisign.com/scripts/timstamp.dll"
+		" -location:CU -store:MY -errkill#");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("INCLUDE = ");
+	WriteCStrToDestFile("$(PellesCDir)\\Include\\Win");
+	WriteCStrToDestFile(";");
+	WriteCStrToDestFile("$(PellesCDir)\\Include");
+	WriteCStrToDestFile(";");
+	Write_src_d_ToDestFile();
+	WriteCStrToDestFile(";");
+	Write_cfg_d_ToDestFile();
+	WriteCStrToDestFile("#");
+	WriteEndDestFileLn();
+
+	WriteDestFileLn(
+		"LIB = $(PellesCDir)\\Lib\\Win;$(PellesCDir)\\Lib#");
+	WriteDestFileLn("WizCreator = Pelle Orinius#");
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("# ");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("# Build ");
+	WriteAppNamePath();
+	WriteCStrToDestFile(".");
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("# ");
+
+	WriteBgnDestFileLn();
+	WriteAppNamePath();
+	WriteCStrToDestFile(": \\");
+	WriteEndDestFileLn();
+
+	++DestFileIndent;
+		DoAllSrcFilesStandardMakeObjects();
+
+		WriteBgnDestFileLn();
+		WriteMainRsrcObjPath();
+		WriteEndDestFileLn();
+	--DestFileIndent;
+
+	WriteDestFileLn("\t$(LINK) $(LINKFLAGS) -out:\"$@\" $**");
+
+	DoAllSrcFilesWithSetup(DoSrcFilePLCAddFile);
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("# ");
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("# Build ");
+	WriteMainRsrcObjName();
+	WriteCStrToDestFile(".");
+	WriteEndDestFileLn();
+
+	WriteDestFileLn("# ");
+
+	WriteBgnDestFileLn();
+	WriteMainRsrcObjPath();
+	WriteCStrToDestFile(": \\");
+	WriteEndDestFileLn();
+
+	++DestFileIndent;
+		WriteBgnDestFileLn();
+		WriteMainRsrcSrcPath();
+		WriteEndDestFileLn();
+
+		WriteDestFileLn("$(RC) $(RCFLAGS) \"$!\" -Fo\"$@\"");
+	--DestFileIndent;
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn(".SILENT:");
+	WriteBlankLineToDestFile();
+	WriteDestFileLn(".EXCLUDEDFILES:");
+}
+
+LOCALPROC WritePLCSpecificFiles(void)
+{
+	WriteADstFile1("my_project_d",
+		vStrAppAbbrev, ".ppj", "Project file",
+		WritePLCProjectFile);
+}
+
+LOCALPROC WriteMainRsrcObjPLCbuild(void)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("porc.exe ");
+	WriteMainRsrcSrcPath();
+	WriteCStrToDestFile(" -Fo\"");
+	WriteMainRsrcObjPath();
+	WriteCStrToDestFile("\"");
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WritePLCclMakeFile(void)
+{
+	WriteDestFileLn("# make file generated by gryphel build system");
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("mk_COptions =");
+	WritePLC_CCFLAGS();
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn(".phony: TheDefaultOutput clean");
+
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("TheDefaultOutput:");
+	WriteMakeDependFile(WriteAppNamePath);
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+	WriteBlankLineToDestFile();
+	DoAllSrcFilesWithSetup(DoSrcFileMakeCompile);
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("OBJFILES = \\");
+	++DestFileIndent;
+		DoAllSrcFilesStandardMakeObjects();
+		WriteBlankLineToDestFile();
+	--DestFileIndent;
+	WriteBlankLineToDestFile();
+
+	WriteBlankLineToDestFile();
+	WriteMakeRule(WriteMainRsrcObjPath,
+		WriteMainRsrcObjMSCdeps, WriteMainRsrcObjPLCbuild);
+
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteAppNamePath();
+	WriteCStrToDestFile(": $(OBJFILES) ");
+	WriteMainRsrcObjPath();
+	WriteEndDestFileLn();
+
+	++DestFileIndent;
+
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("polink.exe -out:\"");
+		WriteAppNamePath();
+		WriteCStrToDestFile("\"");
+		WritePLC_LINKFLAGS();
+		WriteCStrToDestFile(" \\");
+		WriteEndDestFileLn();
+
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("$(OBJFILES) ");
+		WriteMainRsrcObjPath();
+		WriteCStrToDestFile(" \\");
+		WriteEndDestFileLn();
+
+		WriteDestFileLn(
+			"user32.lib winmm.lib ole32.lib uuid.lib comdlg32.lib"
+			" shell32.lib gdi32.lib");
+
+	--DestFileIndent;
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("clean:");
+	++DestFileIndent;
+		DoAllSrcFilesStandardErase();
+		WriteRmFile(WriteMainRsrcObjPath);
+		WriteRmFile(WriteAppNamePath);
+	--DestFileIndent;
+}
+
+LOCALPROC WritePLCclSpecificFiles(void)
+{
+	WriteADstFile1("my_project_d",
+		"Makefile", "", "Make file",
+		WritePLCclMakeFile);
+}
--- /dev/null
+++ b/setup/WRSNCFLS.i
@@ -1,0 +1,115 @@
+/*
+	WRSNCFLS.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	WRite SuN C specific FiLeS
+*/
+
+LOCALPROC WriteSncCOptions(void)
+{
+	WriteCStrToDestFile(" -c -v -fd -xstrconst");
+	if (gbk_dbg_on != gbo_dbg) {
+		WriteCStrToDestFile(" -xO4 -xspace -Qn");
+	} else {
+		WriteCStrToDestFile(" -g");
+	}
+}
+
+LOCALPROC WriteSncMakeFile(void)
+{
+	WriteDestFileLn("# make file generated by gryphel build system");
+
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("mk_COptions =");
+	WriteSncCOptions();
+	WriteEndDestFileLn();
+	WriteBlankLineToDestFile();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("TheDefaultOutput : ");
+	Write_machobinpath_ToDestFile();
+	WriteEndDestFileLn();
+
+	WriteBlankLineToDestFile();
+	DoAllSrcFilesWithSetup(DoSrcFileMakeCompile);
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("ObjFiles = ");
+	WriteBackSlashToDestFile();
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		DoAllSrcFilesStandardMakeObjects();
+		WriteBlankLineToDestFile();
+	--DestFileIndent;
+	WriteBlankLineToDestFile();
+	WriteBgnDestFileLn();
+	Write_machobinpath_ToDestFile();
+	WriteCStrToDestFile(" : $(ObjFiles)");
+	WriteEndDestFileLn();
+	++DestFileIndent;
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("cc");
+		if (gbk_dbg_on != gbo_dbg) {
+			WriteCStrToDestFile(" -s -Qn -mr");
+		}
+		WriteCStrToDestFile(" \\");
+		WriteEndDestFileLn();
+		++DestFileIndent;
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("-o ");
+			WriteQuoteToDestFile();
+			Write_machobinpath_ToDestFile();
+			WriteQuoteToDestFile();
+
+			WriteCStrToDestFile(" -L/usr/X11R6/lib -lX11");
+#if 0
+			if (gbk_targfam_slrs == gbo_targfam) {
+				WriteCStrToDestFile(" -lposix4");
+			}
+			if (MySoundEnabled) {
+				WriteCStrToDestFile(" -lasound");
+			}
+#endif
+			WriteCStrToDestFile(" \\");
+			WriteEndDestFileLn();
+			WriteDestFileLn("$(ObjFiles)");
+		--DestFileIndent;
+		if (gbk_dbg_on != gbo_dbg) {
+			if (gbk_ide_xcd == cur_ide) {
+				WriteBgnDestFileLn();
+				WriteCStrToDestFile("strip -u -r \"");
+				Write_machobinpath_ToDestFile();
+				WriteCStrToDestFile("\"");
+				WriteEndDestFileLn();
+			}
+		}
+	--DestFileIndent;
+
+	WriteBlankLineToDestFile();
+	WriteDestFileLn("clean :");
+	++DestFileIndent;
+		WriteDestFileLn("rm -f $(ObjFiles)");
+		WriteRmFile(WriteAppNamePath);
+	--DestFileIndent;
+}
+
+LOCALPROC WriteSncSpecificFiles(void)
+{
+	WriteADstFile1("my_project_d",
+		"Makefile", "", "Make file",
+		WriteSncMakeFile);
+}
--- /dev/null
+++ b/setup/WRTEXTFL.i
@@ -1,0 +1,834 @@
+/*
+	WRTEXTFL.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	WRite TEXT FiLe
+*/
+
+
+
+/* --- routines for writing text files --- */
+
+
+#define WriteCharToOutput putchar
+
+LOCALPROC WriteCStrToOutput(char *s)
+{
+	printf("%s", s);
+}
+
+LOCALPROC WriteSignedLongToOutput(long int v)
+{
+	printf("%ld", v);
+}
+
+LOCALPROC WriteUnsignedToOutput(unsigned int v)
+{
+	printf("%u", v);
+}
+
+LOCALPROC WriteDec2CharToOutput(int v)
+{
+	printf("%02u", v);
+}
+
+LOCALPROC WriteHexByteToOutput(unsigned int v)
+{
+	printf("%02X", v);
+}
+
+LOCALPROC WriteHexWordToOutput(unsigned int v)
+{
+	printf("%04X", v);
+}
+
+LOCALPROC WriteHexLongToOutput(ui5r v)
+{
+	printf("%08lX", v);
+}
+
+LOCALPROC WriteEolToOutput(void)
+{
+	printf("\n");
+}
+
+LOCALPROC WriteLnCStrToOutput(char *s)
+{
+	WriteCStrToOutput(s);
+	WriteEolToOutput();
+}
+
+
+/* --- code specific to Scripting Language --- */
+
+GLOBALPROC WriteScriptLangExtension(void)
+{
+#if (gbo_script == gbk_script_mpw)
+	WriteCStrToOutput(".mpw");
+#endif
+#if (gbo_script == gbk_script_applescript)
+	WriteCStrToOutput(".scpt");
+#endif
+#if (gbo_script == gbk_script_bash)
+	WriteCStrToOutput(".sh");
+#endif
+#if (gbo_script == gbk_script_rc)
+	WriteCStrToOutput(".rc");
+#endif
+#if (gbo_script == gbk_script_vbscript)
+	WriteCStrToOutput(".vbs");
+#endif
+#if (gbo_script == gbk_script_xp)
+	WriteCStrToOutput(".bat");
+#endif
+}
+
+GLOBALPROC WriteScriptLangHeader(void)
+{
+#if (gbo_script == gbk_script_bash)
+	WriteLnCStrToOutput("#! /bin/bash");
+	WriteEolToOutput();
+#endif
+#if (gbo_script == gbk_script_xp)
+	WriteLnCStrToOutput("@echo off");
+	WriteEolToOutput();
+#endif
+#if (gbo_script == gbk_script_rc)
+	WriteLnCStrToOutput("#!/bin/rc");
+	WriteEolToOutput();
+#endif
+}
+
+#if (gbo_script == gbk_script_bash)
+#ifndef BashUsePrintf
+#define BashUsePrintf 1
+#endif
+#endif
+
+GLOBALPROC WriteSectionCommentDestFile(char * Description)
+{
+	WriteEolToOutput();
+	WriteEolToOutput();
+#if (gbo_script == gbk_script_mpw) || (gbo_script == gbk_script_bash) || (gbo_script == gbk_script_rc)
+	{
+		WriteCStrToOutput("# ----- ");
+		WriteCStrToOutput(Description);
+		WriteCStrToOutput(" -----");
+	}
+#endif
+#if (gbo_script == gbk_script_applescript)
+	{
+		WriteCStrToOutput("\t--- ");
+		WriteCStrToOutput(Description);
+		WriteCStrToOutput(" -----");
+	}
+#endif
+#if (gbo_script == gbk_script_vbscript)
+	{
+		WriteCStrToOutput("' ----- ");
+		WriteCStrToOutput(Description);
+		WriteCStrToOutput(" -----");
+	}
+#endif
+#if (gbo_script == gbk_script_xp)
+	{
+		WriteCStrToOutput("rem ----- ");
+		WriteCStrToOutput(Description);
+		WriteCStrToOutput(" -----");
+	}
+#endif
+
+	WriteEolToOutput();
+}
+
+LOCALPROC WriteOpenDestFile(char *DirVar, char *FileName, char *FileExt,
+	char * Description)
+{
+	WriteSectionCommentDestFile(Description);
+
+	WriteEolToOutput();
+
+#if (gbo_script == gbk_script_mpw)
+	{
+#if MPWOneEchoPerFile
+		WriteCStrToOutput("Echo -n > \"{");
+		WriteCStrToOutput(DirVar);
+		WriteCStrToOutput("}");
+		WriteCStrToOutput(FileName);
+		WriteCStrToOutput(FileExt);
+		WriteCStrToOutput("\" \266");
+		WriteEolToOutput();
+#else
+		WriteCStrToOutput("Set DestFile \"{");
+		WriteCStrToOutput(DirVar);
+		WriteCStrToOutput("}");
+		WriteCStrToOutput(FileName);
+		WriteCStrToOutput(FileExt);
+		WriteCStrToOutput("\"");
+		WriteEolToOutput();
+		WriteLnCStrToOutput("Echo -n > \"{DestFile}\"");
+		WriteEolToOutput();
+#endif
+	}
+#endif
+#if (gbo_script == gbk_script_applescript)
+	{
+		WriteCStrToOutput("\tset DestFile to open for access file (");
+		WriteCStrToOutput(DirVar);
+		WriteCStrToOutput(" & \"");
+		WriteCStrToOutput(FileName);
+		WriteCStrToOutput(FileExt);
+		WriteCStrToOutput("\") with write permission");
+		WriteEolToOutput();
+		WriteEolToOutput();
+		WriteLnCStrToOutput("\tset eof DestFile to 0");
+	}
+#endif
+#if (gbo_script == gbk_script_bash)
+	{
+		WriteCStrToOutput("DestFile=\"${");
+		WriteCStrToOutput(DirVar);
+		WriteCStrToOutput("}");
+		WriteCStrToOutput(FileName);
+		WriteCStrToOutput(FileExt);
+		WriteCStrToOutput("\"");
+		WriteEolToOutput();
+#if BashUsePrintf
+		WriteLnCStrToOutput("printf \"\" > \"${DestFile}\"");
+#else
+		/* WriteLnCStrToOutput("echo -n > \"${DestFile}\""); */
+		WriteLnCStrToOutput("true > \"${DestFile}\"");
+#endif
+		WriteEolToOutput();
+	}
+#endif
+#if (gbo_script == gbk_script_rc)
+	{
+		WriteCStrToOutput("DestFile=$");
+		WriteCStrToOutput(DirVar);
+		WriteCStrToOutput("^");
+		WriteCStrToOutput(FileName);
+		WriteCStrToOutput(FileExt);
+		WriteEolToOutput();
+		WriteLnCStrToOutput("echo -n > $DestFile");
+		WriteEolToOutput();
+	}
+#endif
+#if (gbo_script == gbk_script_xp)
+	{
+		WriteCStrToOutput("set DestFile=%");
+		WriteCStrToOutput(DirVar);
+		WriteCStrToOutput("%");
+		WriteCStrToOutput("\\");
+		WriteCStrToOutput(FileName);
+		WriteCStrToOutput(FileExt);
+		WriteEolToOutput();
+		WriteLnCStrToOutput("echo.>\"%DestFile%\"");
+		WriteLnCStrToOutput("del \"%DestFile%\"");
+	}
+#endif
+#if (gbo_script == gbk_script_vbscript)
+	{
+		WriteCStrToOutput("Set f = fso.CreateTextFile(");
+		WriteCStrToOutput(DirVar);
+		WriteCStrToOutput(" & \"\\");
+		WriteCStrToOutput(FileName);
+		WriteCStrToOutput(FileExt);
+		WriteCStrToOutput("\", True)");
+		WriteEolToOutput();
+		WriteEolToOutput();
+	}
+#endif
+}
+
+LOCALPROC WriteCloseDestFile(void)
+{
+#if (gbo_script == gbk_script_mpw)
+#if MPWOneEchoPerFile
+	WriteLnCStrToOutput("''");
+#endif
+#endif /* (gbo_script == gbk_script_mpw) */
+#if (gbo_script == gbk_script_applescript)
+	WriteEolToOutput();
+	WriteLnCStrToOutput("\tclose access DestFile");
+#endif
+#if (gbo_script == gbk_script_bash)
+#endif
+#if (gbo_script == gbk_script_vbscript)
+	WriteEolToOutput();
+	WriteLnCStrToOutput("f.Close");
+#endif
+#if (gbo_script == gbk_script_xp)
+#endif
+}
+
+TYPEDEFPROC (*MyProc)(void);
+
+LOCALPROC WriteADstFile1(char *DirVar,
+	char *FileName, char *FileExt, char * Description, MyProc p)
+{
+	WriteOpenDestFile(DirVar, FileName, FileExt, Description);
+	p();
+	WriteCloseDestFile();
+}
+
+LOCALPROC WriteBlankLineToDestFile(void)
+{
+#if (gbo_script == gbk_script_mpw)
+#if MPWOneEchoPerFile
+	WriteLnCStrToOutput("''\266n\266");
+#else
+	WriteLnCStrToOutput("Echo '' >> \"{DestFile}\"");
+#endif
+#endif /* (gbo_script == gbk_script_mpw) */
+#if (gbo_script == gbk_script_applescript)
+	WriteLnCStrToOutput("\twrite \"\" & return to DestFile");
+#endif
+#if (gbo_script == gbk_script_bash)
+#if BashUsePrintf
+	WriteLnCStrToOutput("printf \"\\n\" >> \"${DestFile}\"");
+#else
+	WriteLnCStrToOutput("echo '' >> \"${DestFile}\"");
+#endif
+#endif
+#if (gbo_script == gbk_script_rc)
+	WriteLnCStrToOutput("echo >> $DestFile");
+#endif
+#if (gbo_script == gbk_script_vbscript)
+	WriteLnCStrToOutput("f.WriteLine(\"\")");
+#endif
+#if (gbo_script == gbk_script_xp)
+	WriteLnCStrToOutput("echo.>>\"%DestFile%\"");
+#endif
+}
+
+LOCALVAR int DestFileIndent = 0;
+
+LOCALPROC WriteBgnDestFileLn(void)
+{
+	int i;
+
+#if (gbo_script == gbk_script_mpw)
+#if MPWOneEchoPerFile
+	WriteCStrToOutput("'");
+#else
+	WriteCStrToOutput("Echo '");
+#endif
+#endif /* (gbo_script == gbk_script_mpw) */
+#if (gbo_script == gbk_script_applescript)
+	WriteCStrToOutput("\twrite \"");
+#endif
+#if (gbo_script == gbk_script_rc)
+	WriteCStrToOutput("echo '");
+#endif
+#if (gbo_script == gbk_script_bash)
+#if BashUsePrintf
+	WriteCStrToOutput("printf \"%s\\n\" '");
+#else
+	WriteCStrToOutput("echo '");
+#endif
+#endif
+#if (gbo_script == gbk_script_vbscript)
+	WriteCStrToOutput("f.WriteLine(\"");
+#endif
+#if (gbo_script == gbk_script_xp)
+	WriteCStrToOutput("echo ");
+#endif
+
+	for (i = 0; i < DestFileIndent; ++i) {
+		WriteCStrToOutput("\t");
+	}
+}
+
+LOCALPROC WriteEndDestFileLn(void)
+{
+#if (gbo_script == gbk_script_mpw)
+#if MPWOneEchoPerFile
+	WriteCStrToOutput("'\266n\266");
+#else
+	WriteCStrToOutput("' >> \"{DestFile}\"");
+#endif
+#endif /* (gbo_script == gbk_script_mpw) */
+#if (gbo_script == gbk_script_applescript)
+	WriteCStrToOutput("\" & return to DestFile");
+#endif
+#if (gbo_script == gbk_script_rc)
+	WriteCStrToOutput("' >> $DestFile");
+#endif
+#if (gbo_script == gbk_script_bash)
+	WriteCStrToOutput("' >> \"${DestFile}\"");
+#endif
+#if (gbo_script == gbk_script_vbscript)
+	WriteCStrToOutput("\")");
+#endif
+#if (gbo_script == gbk_script_xp)
+	WriteCStrToOutput(">>\"%DestFile%\"");
+#endif
+
+	WriteEolToOutput();
+}
+
+LOCALPROC WriteCharToDestFile(char c)
+{
+	switch (c) {
+#if (gbo_script == gbk_script_mpw)
+		case '\'':
+			WriteCStrToOutput("'\266''");
+			break;
+#endif
+#if (gbo_script == gbk_script_bash)
+		case '\'':
+			WriteCStrToOutput("'\\''");
+			break;
+#endif
+#if (gbo_script == gbk_script_rc)
+		case '\'':
+			WriteCStrToOutput("''''");
+			break;
+#endif
+#if (gbo_script == gbk_script_applescript)
+		case '"':
+			WriteCStrToOutput("\\\"");
+			break;
+#endif
+#if (gbo_script == gbk_script_vbscript)
+		case '"':
+			WriteCStrToOutput("\"\"");
+			break;
+#endif
+#if (gbo_script == gbk_script_xp)
+		case '%':
+			WriteCStrToOutput("%%");
+			break;
+		case '^':
+		case '<':
+		case '>':
+		case '|':
+		case '"':
+
+			/*
+				digit preceeding redirection
+				modifies the redirection
+			*/
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+			WriteCStrToOutput("^");
+			WriteCharToOutput(c);
+			break;
+#endif
+		default:
+			WriteCharToOutput(c);
+			break;
+	}
+}
+
+LOCALPROC WriteCStrToDestFile(char *s)
+{
+	char c;
+
+	while ((c = *s++) != 0) {
+		WriteCharToDestFile(c);
+	}
+}
+
+LOCALPROC WriteScriptVarToDestFile(char *name)
+{
+#if (gbo_script == gbk_script_mpw)
+	WriteCStrToOutput("'\"{");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput("}\"'");
+#endif
+#if (gbo_script == gbk_script_applescript)
+	WriteCStrToOutput("* not implemented yet *");
+#endif
+#if (gbo_script == gbk_script_rc)
+	WriteCStrToOutput("$");
+	WriteCStrToOutput(name);
+#endif
+#if (gbo_script == gbk_script_bash)
+	WriteCStrToOutput("'\"${");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput("}\"'");
+#endif
+#if (gbo_script == gbk_script_vbscript)
+	WriteCStrToOutput("\" & ");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput(" & \"");
+#endif
+#if (gbo_script == gbk_script_xp)
+	WriteCStrToOutput("%");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput("%");
+#endif
+}
+
+LOCALPROC WriteBgnCommentBlock(void)
+{
+#if (gbo_script == gbk_script_applescript)
+	WriteLnCStrToOutput("(*");
+#endif
+}
+
+LOCALPROC WriteEndCommentBlock(void)
+{
+#if (gbo_script == gbk_script_applescript)
+	WriteLnCStrToOutput("*)");
+#endif
+}
+
+LOCALPROC WriteBgnCommentBlockLn(void)
+{
+#if (gbo_script == gbk_script_mpw) || (gbo_script == gbk_script_bash) || (gbo_script == gbk_script_rc)
+	WriteCStrToOutput("# ");
+#endif
+#if (gbo_script == gbk_script_applescript)
+	WriteCStrToOutput("\t");
+#endif
+#if (gbo_script == gbk_script_vbscript)
+	WriteCStrToOutput("' ");
+#endif
+#if (gbo_script == gbk_script_xp)
+	WriteCStrToOutput("rem ");
+#endif
+}
+
+LOCALPROC WriteEndCommentBlockLn(void)
+{
+#if (gbo_script == gbk_script_mpw) \
+	|| (gbo_script == gbk_script_applescript) \
+	|| (gbo_script == gbk_script_bash) \
+	|| (gbo_script == gbk_script_rc) \
+	|| (gbo_script == gbk_script_vbscript) \
+	|| (gbo_script == gbk_script_xp)
+	WriteEolToOutput();
+#endif
+}
+
+LOCALPROC WriteCommentBlockLn(char *s)
+{
+	WriteBgnCommentBlockLn();
+	WriteCStrToOutput(s);
+	WriteEndCommentBlockLn();
+}
+
+LOCALPROC FindSubDirectory(char *new_d, char *parent_d, char *name)
+{
+	WriteEolToOutput();
+
+#if (gbo_script == gbk_script_mpw)
+	WriteCStrToOutput("Set ");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput(" \"{");
+	WriteCStrToOutput(parent_d);
+	WriteCStrToOutput("}");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput(":\"");
+	WriteEolToOutput();
+
+
+	WriteCStrToOutput("IF not \"`exists -d -q \"{");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("}\"`\"");
+	WriteEolToOutput();
+
+	WriteCStrToOutput("\tEcho \"{");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("} is not an existing directory\"");
+	WriteEolToOutput();
+
+	WriteLnCStrToOutput("\tExit 1");
+
+	WriteLnCStrToOutput("END");
+#endif
+#if (gbo_script == gbk_script_applescript)
+	WriteCStrToOutput("\tset ");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput(" to ");
+	WriteCStrToOutput(parent_d);
+	WriteCStrToOutput(" & \"");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput(":\"");
+	WriteEolToOutput();
+
+	WriteCStrToOutput("\tif not (exists alias ");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput(") then");
+	WriteEolToOutput();
+
+	WriteCStrToOutput("\t\tdisplay dialog \"The folder '");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput("' is missing from '\" & ");
+	WriteCStrToOutput(parent_d);
+	WriteCStrToOutput(" & \"'.\" buttons {\"OK\"} default button 1");
+	WriteEolToOutput();
+
+	WriteLnCStrToOutput("\t\treturn");
+	WriteLnCStrToOutput("\tend if");
+#endif
+#if (gbo_script == gbk_script_bash)
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("=\"${");
+	WriteCStrToOutput(parent_d);
+	WriteCStrToOutput("}");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput("/\"");
+	WriteEolToOutput();
+
+	WriteCStrToOutput("if test ! -d \"${");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("}\" ; then");
+	WriteEolToOutput();
+
+	WriteCStrToOutput("\techo \"The folder '");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput("' is missing from ${");
+	WriteCStrToOutput(parent_d);
+	WriteCStrToOutput("}\"");
+	WriteEolToOutput();
+
+	WriteLnCStrToOutput("\texit 1");
+	WriteLnCStrToOutput("fi");
+#endif
+#if (gbo_script == gbk_script_rc)
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("=$");
+	WriteCStrToOutput(parent_d);
+	WriteCStrToOutput("^");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput("/");
+	WriteEolToOutput();
+
+	WriteCStrToOutput("if(test ! -d $");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput(") {");
+	WriteEolToOutput();
+
+	WriteCStrToOutput("\techo The folder '");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput("' is missing from $");
+	WriteCStrToOutput(parent_d);
+	WriteCStrToOutput("");
+	WriteEolToOutput();
+
+	WriteLnCStrToOutput("\texit fail");
+	WriteLnCStrToOutput("}");
+#endif
+#if (gbo_script == gbk_script_vbscript)
+	WriteCStrToOutput("dim ");
+	WriteCStrToOutput(new_d);
+	WriteEolToOutput();
+
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput(" = ");
+	WriteCStrToOutput(parent_d);
+	WriteCStrToOutput(" & \"\\");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput("\"");
+	WriteEolToOutput();
+#endif
+#if (gbo_script == gbk_script_xp)
+	WriteCStrToOutput("set ");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("=%");
+	WriteCStrToOutput(parent_d);
+	WriteCStrToOutput("%");
+	WriteCStrToOutput("\\");
+	WriteCStrToOutput(name);
+	WriteEolToOutput();
+
+	WriteCStrToOutput("if not exist \"%");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("%\" echo \"%");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("%\" is missing");
+	WriteEolToOutput();
+#endif
+}
+
+LOCALPROC MakeSubDirectory(char *new_d, char *parent_d, char *name,
+	char *FileExt)
+{
+	WriteEolToOutput();
+
+#if (gbo_script == gbk_script_mpw)
+	WriteCStrToOutput("Set ");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput(" \"{");
+	WriteCStrToOutput(parent_d);
+	WriteCStrToOutput("}");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput(FileExt);
+	WriteCStrToOutput(":\"");
+	WriteEolToOutput();
+
+	WriteCStrToOutput("IF not \"`exists -q \"{");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("}\"`\"");
+	WriteEolToOutput();
+
+	WriteCStrToOutput("\tNewFolder \"{");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("}\"");
+	WriteEolToOutput();
+
+	WriteLnCStrToOutput("END");
+#endif
+#if (gbo_script == gbk_script_applescript)
+	WriteCStrToOutput("\tset ");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput(" to ");
+	WriteCStrToOutput(parent_d);
+	WriteCStrToOutput(" & \"");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput(FileExt);
+	WriteCStrToOutput(":\"");
+	WriteEolToOutput();
+
+	WriteCStrToOutput("\tmake new folder at alias ");
+	WriteCStrToOutput(parent_d);
+	WriteCStrToOutput(" with properties {name:\"");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput(FileExt);
+	WriteCStrToOutput("\"}");
+	WriteEolToOutput();
+#endif
+#if (gbo_script == gbk_script_bash)
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("=\"${");
+	WriteCStrToOutput(parent_d);
+	WriteCStrToOutput("}");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput(FileExt);
+	WriteCStrToOutput("/\"");
+	WriteEolToOutput();
+
+	WriteCStrToOutput("if test ! -d \"${");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("}\" ; then");
+	WriteEolToOutput();
+
+	WriteCStrToOutput("\tmkdir \"${");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("}\"");
+	WriteEolToOutput();
+
+	WriteLnCStrToOutput("fi");
+#endif
+#if (gbo_script == gbk_script_rc)
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("=$");
+	WriteCStrToOutput(parent_d);
+	WriteCStrToOutput("^");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput(FileExt);
+	WriteCStrToOutput("/");
+	WriteEolToOutput();
+
+	WriteCStrToOutput("if(! test -d $");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput(") {");
+	WriteEolToOutput();
+
+	WriteCStrToOutput("\tmkdir $");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("");
+	WriteEolToOutput();
+
+	WriteLnCStrToOutput("}");
+#endif
+#if (gbo_script == gbk_script_vbscript)
+	WriteCStrToOutput("dim ");
+	WriteCStrToOutput(new_d);
+	WriteEolToOutput();
+
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput(" = ");
+	WriteCStrToOutput(parent_d);
+	WriteCStrToOutput(" & \"\\");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput(FileExt);
+	WriteCStrToOutput("\"");
+	WriteEolToOutput();
+
+	WriteCStrToOutput("if (NOT fso.FolderExists(");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput(")) Then");
+	WriteEolToOutput();
+
+	WriteCStrToOutput("\tfso.CreateFolder(");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput(")");
+	WriteEolToOutput();
+
+	WriteLnCStrToOutput("End If");
+#endif
+#if (gbo_script == gbk_script_xp)
+	WriteCStrToOutput("set ");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("=%");
+	WriteCStrToOutput(parent_d);
+	WriteCStrToOutput("%");
+	WriteCStrToOutput("\\");
+	WriteCStrToOutput(name);
+	WriteCStrToOutput(FileExt);
+	WriteEolToOutput();
+
+	WriteCStrToOutput("if not exist \"%");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("%\" mkdir \"%");
+	WriteCStrToOutput(new_d);
+	WriteCStrToOutput("%\"");
+	WriteEolToOutput();
+#endif
+}
+
+
+
+/* ------- utilities for writing to text files -------- */
+
+LOCALPROC WriteDestFileLn(char *s)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile(s);
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteSpaceToDestFile(void)
+{
+	WriteCharToDestFile(' ');
+}
+
+LOCALPROC WriteQuoteToDestFile(void)
+{
+	WriteCharToDestFile('\"');
+}
+
+LOCALPROC WriteSingleQuoteToDestFile(void)
+{
+	WriteCharToDestFile('\'');
+}
+
+LOCALPROC WriteBackSlashToDestFile(void)
+{
+	WriteCharToDestFile('\\');
+}
--- /dev/null
+++ b/setup/WRXCDFLS.i
@@ -1,0 +1,2082 @@
+/*
+	WRXCDFLS.i
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	WRite XCoDe specific FiLeS
+
+	(also support older Apple Project Builder)
+*/
+
+LOCALPROC WriteNextLineSameDent(void)
+{
+	WriteEndDestFileLn();
+	WriteBgnDestFileLn();
+}
+
+static void WriteAPBXCDObjectId(unsigned int theClass, unsigned int v)
+{
+	WriteHexWordToOutput(theClass);
+	WriteHexWordToOutput(v);
+	WriteCStrToDestFile("0000000000000000");
+}
+
+enum {
+	APBoclsSrcBld,
+	APBoclsIcnsBld,
+	APBoclsFramBld,
+	APBospcLibStdcBld,
+	APBospcMnRsrcBld, /* only if HaveMacRrscs */
+	APBospcLangDummyBld,
+
+	APBospcBuildStyle,
+
+	APBoclsSrcRf,
+	APBoclsHdr, /* only if gbk_ide_xcd == cur_ide */
+	APBoclsInc, /* only if gbk_ide_xcd == cur_ide */
+	APBoclsIcnsRf,
+	APBoclsFramRf,
+	APBospcLibStdcRf,
+	APBospcProductRef,
+	APBospcPlistRf,
+	APBospcMainRsrcRf, /* only if HaveMacRrscs */
+	APBospcLangRf,
+
+	APBospcPhaseLibs,
+	APBospcSources,
+	APBospcResources, /* only if HaveMacBundleApp */
+	APBospcLibraries,
+	APBospcProducts,
+	APBospcMainGroup,
+	APBospcSrcHeaders, /* only if gbk_ide_xcd == cur_ide */
+	APBospcIncludes, /* only if gbk_ide_xcd == cur_ide */
+
+	APBospcTarget,
+	APBospcRoot,
+	APBospcBunRsrcs, /* only if HaveMacBundleApp */
+	APBospcPhaseRsrc, /* only if HaveMacRrscs */
+	APBospcHeaders,
+	APBospcPhaseSrcs,
+
+	APBospcLangDummyRf,
+
+	APBospcNatCnfg, /* only if gbk_ide_xcd == cur_ide */
+	APBospcPrjCnfg, /* only if gbk_ide_xcd == cur_ide */
+	APBospcLstNatCnfg, /* only if gbk_ide_xcd == cur_ide */
+	APBospcLstPrjCnfg, /* only if gbk_ide_xcd == cur_ide */
+
+	kNumAPBocls
+};
+
+#define HaveAPBXCD_LangDummy (ide_vers >= 1000)
+#define HaveAPBXCD_PlistFile (ide_vers >= 1000)
+#define HaveAPBXCD_NameCmmnt (ide_vers >= 2100)
+#define HaveAPBXCD_Headers (ide_vers >= 1000)
+#define HaveAPBXCD_StdcLib (ide_vers < 1500)
+#define HaveAPBXCD_IsaFirst (ide_vers >= 2100)
+
+static void WriteAPBXCDBgnObjList(char *s)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile(s);
+	WriteCStrToDestFile(" = (");
+	WriteEndDestFileLn();
+	++DestFileIndent;
+}
+
+static void WriteAPBXCDEndObjList(void)
+{
+	--DestFileIndent;
+	WriteDestFileLn(");");
+}
+
+LOCALPROC WriteAPBXCDObjectIdAndComment(unsigned int theClass,
+	unsigned int v, MyProc comment)
+{
+	WriteAPBXCDObjectId(theClass, v);
+	if (HaveAPBXCD_NameCmmnt) {
+		WriteCStrToDestFile(" /* ");
+		comment();
+		WriteCStrToDestFile(" */");
+	}
+}
+
+static void WriteAPBXCDBeginObject(unsigned int theClass,
+	unsigned int v, MyProc comment)
+{
+	WriteBgnDestFileLn();
+	WriteAPBXCDObjectIdAndComment(theClass, v, comment);
+	WriteCStrToDestFile(" = {");
+	WriteEndDestFileLn();
+	++DestFileIndent;
+}
+
+static void WriteAPBXCDEndObject(void)
+{
+	--DestFileIndent;
+	WriteDestFileLn("};");
+}
+
+static void WriteAPBQuotedField(char *s, char *v)
+{
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile(s);
+	WriteCStrToDestFile(" = ");
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(v);
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(";");
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteAPBXCDobjlistelmp(unsigned int theClass, unsigned int v,
+	MyProc comment)
+{
+	WriteBgnDestFileLn();
+	WriteAPBXCDObjectIdAndComment(theClass, v, comment);
+	WriteCStrToDestFile(",");
+	WriteEndDestFileLn();
+}
+
+LOCALVAR int APBXCDForceSameLine = 0;
+
+LOCALPROC WriteAPBXCDSepA(void)
+{
+	if (0 == APBXCDForceSameLine) {
+		WriteNextLineSameDent();
+	} else {
+		WriteSpaceToDestFile();
+	}
+}
+
+LOCALPROC WriteAPBXCDDObjectAPropBgn(void)
+{
+	if (0 == APBXCDForceSameLine) {
+		WriteBgnDestFileLn();
+	}
+}
+
+LOCALPROC WriteAPBXCDDObjectAPropEnd(void)
+{
+	WriteCStrToDestFile(";");
+	if (0 == APBXCDForceSameLine) {
+		WriteEndDestFileLn();
+	} else {
+		WriteSpaceToDestFile();
+	}
+}
+
+LOCALPROC WriteAPBXCDObjectAp(unsigned int theClass, unsigned int v,
+	MyProc comment, MyProc body)
+{
+	WriteBgnDestFileLn();
+	WriteAPBXCDObjectIdAndComment(theClass, v, comment);
+	WriteCStrToDestFile(" = {");
+	if (ide_vers < 2100) {
+		WriteEndDestFileLn();
+		++DestFileIndent;
+			body();
+		--DestFileIndent;
+		WriteBgnDestFileLn();
+	} else {
+		++APBXCDForceSameLine;
+		body();
+		--APBXCDForceSameLine;
+	}
+	WriteCStrToDestFile("};");
+	WriteEndDestFileLn();
+}
+
+LOCALPROC WriteAPBXCDDObjAProp_SS(char *ns, char *vs)
+{
+	WriteAPBXCDDObjectAPropBgn();
+	WriteCStrToDestFile(ns);
+	WriteCStrToDestFile(" = ");
+	WriteCStrToDestFile(vs);
+	WriteAPBXCDDObjectAPropEnd();
+}
+
+LOCALPROC WriteAPBXCDDObjAProp_SP(char *ns, MyProc p)
+{
+	WriteAPBXCDDObjectAPropBgn();
+	WriteCStrToDestFile(ns);
+	WriteCStrToDestFile(" = ");
+	p();
+	WriteAPBXCDDObjectAPropEnd();
+}
+
+LOCALPROC WriteAPBXCDDObjAProp_SO(char *ns,
+	unsigned int theClass, unsigned int v,
+	MyProc comment)
+{
+	WriteAPBXCDDObjectAPropBgn();
+	WriteCStrToDestFile(ns);
+	WriteCStrToDestFile(" = ");
+	WriteAPBXCDObjectIdAndComment(theClass,
+		v, comment);
+	WriteAPBXCDDObjectAPropEnd();
+}
+
+LOCALPROC WriteAPBXCDDObjAPropIsa(char *s)
+{
+	WriteAPBXCDDObjAProp_SS("isa", s);
+}
+
+LOCALPROC WriteAPBXCDDObjAPropIsaBuildFile(void)
+{
+	WriteAPBXCDDObjAPropIsa("PBXBuildFile");
+}
+
+LOCALPROC WriteAPBXCDDObjAPropIsaFileReference(void)
+{
+	WriteAPBXCDDObjAPropIsa("PBXFileReference");
+}
+
+LOCALPROC WriteAPBXCDDObjAPropIsaGroup(void)
+{
+	WriteAPBXCDDObjAPropIsa("PBXGroup");
+}
+
+LOCALPROC WriteAPBXCDDObjAPropFileEncoding30(void)
+{
+	WriteAPBXCDDObjAProp_SS("fileEncoding", "30");
+}
+
+LOCALPROC WriteAPBXCDDObjAPropFileEncoding4(void)
+{
+	WriteAPBXCDDObjAProp_SS("fileEncoding", "4");
+}
+
+LOCALPROC WriteAPBXCDDObjAPropRefType(char *ns)
+{
+	if (ide_vers < 2100) {
+		WriteAPBXCDDObjAProp_SS("refType", ns);
+	}
+}
+
+LOCALPROC WriteAPBXCDDObjAPropRefType0(void)
+{
+	WriteAPBXCDDObjAPropRefType("0");
+}
+
+LOCALPROC WriteAPBXCDDObjAPropRefType2(void)
+{
+	WriteAPBXCDDObjAPropRefType("2");
+}
+
+LOCALPROC WriteAPBXCDDObjAPropRefType3(void)
+{
+	WriteAPBXCDDObjAPropRefType("3");
+}
+
+LOCALPROC WriteAPBXCDDObjAPropRefType4(void)
+{
+	WriteAPBXCDDObjAPropRefType("4");
+}
+
+LOCALPROC WriteAPBXCDDObjAPropName(MyProc p)
+{
+	WriteAPBXCDDObjAProp_SP("name", p);
+}
+
+LOCALPROC WriteAPBXCDDObjAPropPath(MyProc p)
+{
+	WriteAPBXCDDObjAProp_SP("path", p);
+}
+
+LOCALPROC WriteAPBXCDDObjAPropSourceTree(char *s)
+{
+	if (ide_vers >= 1000) {
+		WriteAPBXCDDObjAProp_SS("sourceTree", s);
+	}
+}
+
+LOCALPROC WriteAPBXCDDObjAPropSourceTreeRoot(void)
+{
+	WriteAPBXCDDObjAPropSourceTree("SOURCE_ROOT");
+}
+
+LOCALPROC WriteAPBXCDDObjAPropSourceTreeSDKRoot(void)
+{
+	WriteAPBXCDDObjAPropSourceTree("SDKROOT");
+}
+
+LOCALPROC WriteAPBXCDDObjAPropSourceTreeAbsolute(void)
+{
+	WriteAPBXCDDObjAPropSourceTree("\"<absolute>\"");
+}
+
+LOCALPROC WriteAPBXCDDObjAPropSourceTreeGroup(void)
+{
+	WriteAPBXCDDObjAPropSourceTree("\"<group>\"");
+}
+
+LOCALPROC WriteAPBXCDDObjAPropExpectedFileType(MyProc p)
+{
+	if ((ide_vers < 1500) && (ide_vers >= 1000)) {
+		WriteAPBXCDDObjAProp_SP("expectedFileType", p);
+	}
+}
+
+LOCALPROC WriteAPBXCDDObjAPropLastKnownFType(MyProc p)
+{
+	if (ide_vers >= 1500) {
+		WriteAPBXCDDObjAProp_SP("lastKnownFileType", p);
+	}
+}
+
+LOCALPROC WriteAPBXCDDObjAPropFileRef(
+	unsigned int theClass, unsigned int v,
+	MyProc comment)
+{
+	WriteAPBXCDDObjAProp_SO("fileRef",
+		theClass, v, comment);
+}
+
+LOCALPROC WriteAPBXCDDObjAPropIncludeII0(void)
+{
+	if (ide_vers >= 1000) {
+		WriteAPBXCDDObjAProp_SS("includeInIndex", "0");
+	}
+}
+
+LOCALPROC WriteAPBXCDDObjAPropSettingsNull(void)
+{
+	if (ide_vers < 2100) {
+		WriteAPBXCDDObjectAPropBgn();
+		WriteCStrToDestFile("settings = {");
+		WriteAPBXCDSepA();
+		WriteCStrToDestFile("}");
+		WriteAPBXCDDObjectAPropEnd();
+	}
+}
+
+LOCALPROC WriteSrcFileAPBXCDNameInSources(void)
+{
+	WriteSrcFileFileName();
+	WriteCStrToDestFile(" in Sources");
+}
+
+LOCALPROC DoSrcFileAPBXCDaddFileBody(void)
+{
+	if (HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaBuildFile();
+	}
+
+	WriteAPBXCDDObjAPropFileRef(APBoclsSrcRf,
+		FileCounter, WriteSrcFileFileName);
+	if (! HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaBuildFile();
+	}
+	WriteAPBXCDDObjAPropSettingsNull();
+}
+
+LOCALPROC DoSrcFileAPBXCDaddFile(void)
+{
+	WriteAPBXCDObjectAp(APBoclsSrcBld, FileCounter,
+		WriteSrcFileAPBXCDNameInSources, DoSrcFileAPBXCDaddFileBody);
+}
+
+LOCALPROC WriteSrcFileAPBXCDtype(void)
+{
+	char *s;
+	blnr UseObjc = ((DoSrcFile_gd()->Flgm & kCSrcFlgmOjbc) != 0);
+
+	if (UseObjc) {
+		s = "sourcecode.c.objc";
+	} else {
+		s = "sourcecode.c.c";
+	}
+	WriteCStrToDestFile(s);
+}
+
+LOCALPROC DoSrcFileAPBXCDaddFileRefBody(void)
+{
+	if (HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+
+	WriteAPBXCDDObjAPropExpectedFileType(WriteSrcFileAPBXCDtype);
+	WriteAPBXCDDObjAPropFileEncoding30();
+	if (! HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+	WriteAPBXCDDObjAPropLastKnownFType(WriteSrcFileAPBXCDtype);
+	WriteAPBXCDDObjAPropName(WriteSrcFileFileName);
+	WriteAPBXCDDObjAPropPath(WriteSrcFileFilePath);
+	WriteAPBXCDDObjAPropRefType2();
+	WriteAPBXCDDObjAPropSourceTreeRoot();
+}
+
+LOCALPROC DoSrcFileAPBXCDaddFileRef(void)
+{
+	WriteAPBXCDObjectAp(APBoclsSrcRf, FileCounter,
+		WriteSrcFileFileName,
+		DoSrcFileAPBXCDaddFileRefBody);
+}
+
+LOCALPROC DoSrcFileAPBXCDaddToGroup(void)
+{
+	WriteAPBXCDobjlistelmp(APBoclsSrcRf, FileCounter,
+		WriteSrcFileFileName);
+}
+
+LOCALPROC DoSrcFileAPBXCDaddToSources(void)
+{
+	WriteAPBXCDobjlistelmp(APBoclsSrcBld, FileCounter,
+		WriteSrcFileAPBXCDNameInSources);
+}
+
+LOCALPROC WriteHeaderFileAPBXCDtype(void)
+{
+	WriteCStrToDestFile("sourcecode.c.h");
+}
+
+LOCALPROC DoHeaderFileXCDaddFileRefBody(void)
+{
+	if (HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+
+	WriteAPBXCDDObjAPropExpectedFileType(WriteHeaderFileAPBXCDtype);
+	WriteAPBXCDDObjAPropFileEncoding30();
+	if (! HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+	WriteAPBXCDDObjAPropLastKnownFType(WriteHeaderFileAPBXCDtype);
+	WriteAPBXCDDObjAPropName(WriteSrcFileHeaderName);
+	WriteAPBXCDDObjAPropPath(WriteSrcFileHeaderPath);
+	WriteAPBXCDDObjAPropRefType2();
+	WriteAPBXCDDObjAPropSourceTreeRoot();
+}
+
+LOCALPROC DoHeaderFileXCDaddFileRef(void)
+{
+	if (0 == (DoSrcFile_gd()->Flgm & kCSrcFlgmNoHeader)) {
+		WriteAPBXCDObjectAp(APBoclsHdr, FileCounter,
+			WriteSrcFileHeaderName,
+			DoHeaderFileXCDaddFileRefBody);
+	}
+}
+
+LOCALPROC DoHeaderFileXCDaddToGroup(void)
+{
+	if (0 == (DoSrcFile_gd()->Flgm & kCSrcFlgmNoHeader)) {
+		WriteAPBXCDobjlistelmp(APBoclsHdr, FileCounter,
+			WriteSrcFileHeaderName);
+	}
+}
+
+LOCALPROC WriteDocTypeAPBXCDIconFileInResources(void)
+{
+	WriteDocTypeIconFileName();
+	WriteCStrToDestFile(" in Resources");
+}
+
+LOCALPROC DoDocTypeAPBXCDaddFileBody(void)
+{
+	if (HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaBuildFile();
+	}
+
+	WriteAPBXCDDObjAPropFileRef(APBoclsIcnsRf,
+		DocTypeCounter, WriteDocTypeIconFileName);
+	if (! HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaBuildFile();
+	}
+	WriteAPBXCDDObjAPropSettingsNull();
+}
+
+LOCALPROC DoDocTypeAPBXCDaddFile(void)
+{
+	WriteAPBXCDObjectAp(APBoclsIcnsBld, DocTypeCounter,
+		WriteDocTypeAPBXCDIconFileInResources,
+		DoDocTypeAPBXCDaddFileBody);
+}
+
+LOCALPROC WriteDocTypeAPBXCDtype(void)
+{
+	WriteCStrToDestFile("image.icns");
+}
+
+LOCALPROC DoDocTypeAPBXCDaddFileRefBody(void)
+{
+	if (HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+
+	WriteAPBXCDDObjAPropExpectedFileType(WriteDocTypeAPBXCDtype);
+	if (! HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+	WriteAPBXCDDObjAPropLastKnownFType(WriteDocTypeAPBXCDtype);
+	WriteAPBXCDDObjAPropName(WriteDocTypeIconFileName);
+	WriteAPBXCDDObjAPropPath(WriteDocTypeIconFilePath);
+	WriteAPBXCDDObjAPropRefType2();
+	WriteAPBXCDDObjAPropSourceTreeRoot();
+}
+
+LOCALPROC DoDocTypeAPBXCDaddFileRef(void)
+{
+	WriteAPBXCDObjectAp(APBoclsIcnsRf, DocTypeCounter,
+		WriteDocTypeIconFileName, DoDocTypeAPBXCDaddFileRefBody);
+}
+
+LOCALPROC DoDocTypeAPBXCDaddToGroup(void)
+{
+	WriteAPBXCDobjlistelmp(APBoclsIcnsRf, DocTypeCounter,
+		WriteDocTypeIconFileName);
+}
+
+LOCALPROC DoDocTypeAPBXCDaddToSources(void)
+{
+	WriteAPBXCDobjlistelmp(APBoclsIcnsBld, DocTypeCounter,
+		WriteDocTypeAPBXCDIconFileInResources);
+}
+
+LOCALPROC WriteFrameWorkAPBXCDFileName(void)
+{
+	WriteCStrToDestFile(DoFrameWork_gd()->s);
+	WriteCStrToDestFile(".framework");
+}
+
+LOCALPROC WriteFrameWorkAPBXCDFilePath(void)
+{
+	if (ide_vers < 4000) {
+		WriteCStrToDestFile("/");
+	}
+	WriteCStrToDestFile("System/Library/Frameworks/");
+	WriteFrameWorkAPBXCDFileName();
+}
+
+LOCALPROC WriteFrameWorkAPBXCDileInFrameworks(void)
+{
+	WriteFrameWorkAPBXCDFileName();
+	WriteCStrToDestFile(" in Frameworks");
+}
+
+LOCALPROC DoFrameWorkAPBXCDaddFileBody(void)
+{
+	if (HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaBuildFile();
+	}
+
+	WriteAPBXCDDObjAPropFileRef(APBoclsFramRf,
+		FileCounter, WriteFrameWorkAPBXCDFileName);
+	if (! HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaBuildFile();
+	}
+	WriteAPBXCDDObjAPropSettingsNull();
+}
+
+LOCALPROC DoFrameWorkAPBXCDaddFile(void)
+{
+	WriteAPBXCDObjectAp(APBoclsFramBld, FileCounter,
+		WriteFrameWorkAPBXCDileInFrameworks,
+		DoFrameWorkAPBXCDaddFileBody);
+}
+
+LOCALPROC WriteAPBXCDDObjAPropIsaFrameworkRef(void)
+{
+	if (ide_vers < 1000) {
+		WriteAPBXCDDObjAPropIsa("PBXFrameworkReference");
+	} else {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+}
+
+LOCALPROC WriteFrameWorkAPBXCDtype(void)
+{
+	WriteCStrToDestFile("wrapper.framework");
+}
+
+LOCALPROC DoFrameWorkAPBXCDaddFileRefBody(void)
+{
+	if (HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFrameworkRef();
+	}
+
+	WriteAPBXCDDObjAPropExpectedFileType(WriteFrameWorkAPBXCDtype);
+	if (! HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFrameworkRef();
+	}
+	WriteAPBXCDDObjAPropLastKnownFType(WriteFrameWorkAPBXCDtype);
+	WriteAPBXCDDObjAPropName(WriteFrameWorkAPBXCDFileName);
+	WriteAPBXCDDObjAPropPath(WriteFrameWorkAPBXCDFilePath);
+	WriteAPBXCDDObjAPropRefType0();
+	if (ide_vers >= 4000) {
+		WriteAPBXCDDObjAPropSourceTreeSDKRoot();
+	} else {
+		WriteAPBXCDDObjAPropSourceTreeAbsolute();
+	}
+}
+
+LOCALPROC DoFrameWorkAPBXCDaddFileRef(void)
+{
+	WriteAPBXCDObjectAp(APBoclsFramRf, FileCounter,
+		WriteFrameWorkAPBXCDFileName,
+		DoFrameWorkAPBXCDaddFileRefBody);
+}
+
+LOCALPROC DoFrameworkAPBXCDaddToBuild(void)
+{
+	WriteAPBXCDobjlistelmp(APBoclsFramBld, FileCounter,
+		WriteFrameWorkAPBXCDileInFrameworks);
+}
+
+LOCALPROC DoFrameworkAPBXCDaddToLibraries(void)
+{
+	WriteAPBXCDobjlistelmp(APBoclsFramRf, FileCounter,
+		WriteFrameWorkAPBXCDFileName);
+}
+
+LOCALPROC DoExtraHeaderFileXCDaddFileRefBody(void)
+{
+	if (HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+
+	WriteAPBXCDDObjAPropExpectedFileType(WriteHeaderFileAPBXCDtype);
+	WriteAPBXCDDObjAPropFileEncoding30();
+	if (! HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+	WriteAPBXCDDObjAPropLastKnownFType(WriteHeaderFileAPBXCDtype);
+	WriteAPBXCDDObjAPropName(WriteExtraHeaderFileName);
+	WriteAPBXCDDObjAPropPath(WriteExtraHeaderFilePath);
+	WriteAPBXCDDObjAPropRefType2();
+	WriteAPBXCDDObjAPropSourceTreeRoot();
+}
+
+LOCALPROC DoExtraHeaderFileXCDaddFileRef(void)
+{
+	WriteAPBXCDObjectAp(APBoclsInc, FileCounter,
+		WriteExtraHeaderFileName,
+		DoExtraHeaderFileXCDaddFileRefBody);
+}
+
+LOCALPROC DoExtraHeaderFileXCDaddToGroup(void)
+{
+	WriteAPBXCDobjlistelmp(APBoclsInc, FileCounter,
+		WriteExtraHeaderFileName);
+}
+
+LOCALPROC WriteMainAPBXCDRsrcNameinRez(void)
+{
+	WriteMainRsrcName();
+	WriteCStrToDestFile(" in Rez");
+}
+
+LOCALPROC DoRsrcAPBXCDaddFileBody(void)
+{
+	if (HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaBuildFile();
+	}
+
+	WriteAPBXCDDObjAPropFileRef(APBospcMainRsrcRf, 0,
+		WriteMainRsrcName);
+	if (! HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaBuildFile();
+	}
+	WriteAPBXCDDObjAPropSettingsNull();
+}
+
+LOCALPROC DoRsrcAPBXCDaddFile(void)
+{
+	WriteAPBXCDObjectAp(APBospcMnRsrcBld, 0,
+		WriteMainAPBXCDRsrcNameinRez,
+		DoRsrcAPBXCDaddFileBody);
+}
+
+LOCALPROC WriteRsrcAPBXCDtype(void)
+{
+	WriteCStrToDestFile("sourcecode.rez");
+}
+
+LOCALPROC DoRsrcAPBXCDaddFileRefBody(void)
+{
+	if (HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+
+	WriteAPBXCDDObjAPropExpectedFileType(WriteRsrcAPBXCDtype);
+	WriteAPBXCDDObjAPropFileEncoding30();
+	if (! HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+	WriteAPBXCDDObjAPropLastKnownFType(WriteRsrcAPBXCDtype);
+	WriteAPBXCDDObjAPropName(WriteMainRsrcName);
+	WriteAPBXCDDObjAPropPath(WriteMainRsrcSrcPath);
+	WriteAPBXCDDObjAPropRefType2();
+	WriteAPBXCDDObjAPropSourceTreeRoot();
+}
+
+LOCALPROC DoRsrcAPBXCDaddFileRef(void)
+{
+	WriteAPBXCDObjectAp(APBospcMainRsrcRf, 0,
+		WriteMainRsrcName,
+		DoRsrcAPBXCDaddFileRefBody);
+}
+
+LOCALPROC WriteLibStdcName(void)
+{
+	WriteCStrToDestFile("libstdc++.a");
+}
+
+LOCALPROC DoLibStdcAPBXCDaddFileBody(void)
+{
+	if (HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaBuildFile();
+	}
+
+	WriteAPBXCDDObjAPropFileRef(APBospcLibStdcRf, 0,
+		WriteLibStdcName);
+	if (! HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaBuildFile();
+	}
+	WriteAPBXCDDObjAPropSettingsNull();
+}
+
+LOCALPROC DoLibStdcAPBXCDaddFile(void)
+{
+	WriteAPBXCDObjectAp(APBospcLibStdcBld, 0,
+		WriteLibStdcName,
+		DoLibStdcAPBXCDaddFileBody);
+}
+
+LOCALPROC WriteLibStdcFileName(void)
+{
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile("libstdc++.a");
+	WriteQuoteToDestFile();
+}
+
+LOCALPROC WriteLibStdcFilePath(void)
+{
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile("/usr/lib/libstdc++.a");
+	WriteQuoteToDestFile();
+}
+
+LOCALPROC WriteLibStdcAPBXCDtype(void)
+{
+	WriteCStrToDestFile("archive.ar");
+}
+
+LOCALPROC DoLibStdcAPBXCDaddFileRefBody(void)
+{
+	if (HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+
+	WriteAPBXCDDObjAPropExpectedFileType(WriteLibStdcAPBXCDtype);
+	if (! HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+	WriteAPBXCDDObjAPropLastKnownFType(WriteLibStdcAPBXCDtype);
+	WriteAPBXCDDObjAPropName(WriteLibStdcFileName);
+	WriteAPBXCDDObjAPropPath(WriteLibStdcFilePath);
+	WriteAPBXCDDObjAPropRefType0();
+	WriteAPBXCDDObjAPropSourceTreeAbsolute();
+}
+
+LOCALPROC DoLibStdcAPBXCDaddFileRef(void)
+{
+	WriteAPBXCDObjectAp(APBospcLibStdcRf, 0,
+		WriteLibStdcName,
+		DoLibStdcAPBXCDaddFileRefBody);
+}
+
+LOCALPROC WriteDummyLangFileNameInResources(void)
+{
+	WriteDummyLangFileName();
+	WriteCStrToDestFile(" in Resources");
+}
+
+LOCALPROC DoDummyLangAPBXCDaddFileBody(void)
+{
+	if (HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaBuildFile();
+	}
+
+	WriteAPBXCDDObjAPropFileRef(APBospcLangDummyRf, 0,
+		WriteDummyLangFileName);
+	if (! HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaBuildFile();
+	}
+	WriteAPBXCDDObjAPropSettingsNull();
+}
+
+LOCALPROC DoDummyLangAPBXCDaddFile(void)
+{
+	WriteAPBXCDObjectAp(APBospcLangDummyBld, 0,
+		WriteDummyLangFileNameInResources,
+		DoDummyLangAPBXCDaddFileBody);
+}
+
+LOCALPROC WriteDummyLangFilePath(void)
+{
+	WriteFileInDirToDestFile0(WriteLProjFolderPath,
+		WriteDummyLangFileName);
+}
+
+LOCALPROC WriteLangDummyAPBXCDtype(void)
+{
+	WriteCStrToDestFile("text");
+}
+
+LOCALPROC DoLangDummyAPBXCDaddFileRefBody(void)
+{
+	if (HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+
+	WriteAPBXCDDObjAPropExpectedFileType(WriteLangDummyAPBXCDtype);
+	WriteAPBXCDDObjAPropFileEncoding30();
+	if (! HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+	WriteAPBXCDDObjAPropLastKnownFType(WriteLangDummyAPBXCDtype);
+	WriteAPBXCDDObjAPropName(WriteLProjName);
+	WriteAPBXCDDObjAPropPath(WriteDummyLangFilePath);
+	WriteAPBXCDDObjAPropRefType4();
+	WriteAPBXCDDObjAPropSourceTreeRoot();
+}
+
+LOCALPROC DoLangDummyAPBXCDaddFileRef(void)
+{
+	WriteAPBXCDObjectAp(APBospcLangRf, 0,
+		WriteLProjName,
+		DoLangDummyAPBXCDaddFileRefBody);
+}
+
+LOCALPROC DoLangDummyAPBXCDaddToSources(void)
+{
+	WriteAPBXCDobjlistelmp(APBospcLangDummyBld, 0,
+		WriteDummyLangFileNameInResources);
+}
+
+LOCALPROC DoLangDummyAPBXCDaddVariant(void)
+{
+	WriteAPBXCDBeginObject(APBospcLangDummyRf,
+		0, WriteDummyLangFileName);
+
+		if (HaveAPBXCD_IsaFirst) {
+			WriteAPBXCDDObjAPropIsa("PBXVariantGroup");
+		}
+
+		WriteAPBXCDBgnObjList("children");
+			WriteAPBXCDobjlistelmp(APBospcLangRf, 0, WriteLProjName);
+		WriteAPBXCDEndObjList();
+		if (! HaveAPBXCD_IsaFirst) {
+			WriteAPBXCDDObjAPropIsa("PBXVariantGroup");
+		}
+		WriteAPBXCDDObjAPropName(WriteDummyLangFileName);
+		WriteAPBXCDDObjAPropRefType4();
+		WriteAPBXCDDObjAPropSourceTreeGroup();
+	WriteAPBXCDEndObject();
+}
+
+static void DoBeginSectionAPBXCD(char *Name)
+{
+	if (ide_vers >= 2100) {
+		--DestFileIndent; --DestFileIndent;
+		WriteBlankLineToDestFile();
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("/* Begin ");
+		WriteCStrToDestFile(Name);
+		WriteCStrToDestFile(" section */");
+		WriteEndDestFileLn();
+		++DestFileIndent; ++DestFileIndent;
+	}
+}
+
+static void DoEndSectionAPBXCD(char *Name)
+{
+	if (ide_vers >= 2100) {
+		--DestFileIndent; --DestFileIndent;
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("/* End ");
+		WriteCStrToDestFile(Name);
+		WriteCStrToDestFile(" section */");
+		WriteEndDestFileLn();
+		++DestFileIndent; ++DestFileIndent;
+	}
+}
+
+LOCALPROC WriteXCDconfigname(void)
+{
+	char *s;
+
+	switch (gbo_dbg) {
+		case gbk_dbg_on:
+			if (ide_vers < 2100) {
+				s = "Development";
+			} else {
+				s = "Debug";
+			}
+			break;
+		case gbk_dbg_test:
+			s = "Test";
+			break;
+		case gbk_dbg_off:
+			if (ide_vers < 2100) {
+				s = "Deployment";
+			} else {
+				s = "Release";
+			}
+			break;
+		default:
+			s = "(unknown Debug Level)";
+			break;
+	}
+
+	WriteCStrToDestFile(s);
+}
+
+LOCALPROC WriteAPBXCDDObjAPropIsaApplicationRef(void)
+{
+	if (ide_vers < 1000) {
+		WriteAPBXCDDObjAPropIsa("PBXApplicationReference");
+	} else {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+}
+
+LOCALPROC WriteProductAPBXCDtype(void)
+{
+	if (HaveMacBundleApp) {
+		WriteCStrToDestFile("wrapper.application");
+	} else {
+		WriteCStrToDestFile("\"compiled.mach-o.executable\"");
+	}
+}
+
+LOCALPROC DoProductAPBXCDaddFileRefBody(void)
+{
+	if (HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaApplicationRef();
+	}
+
+	WriteAPBXCDDObjAPropExpectedFileType(WriteProductAPBXCDtype);
+	WriteAPBXCDDObjAPropIncludeII0();
+	if (! HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaApplicationRef();
+	}
+	WriteAPBXCDDObjAPropLastKnownFType(WriteProductAPBXCDtype);
+	WriteAPBXCDDObjAPropPath(WriteAppNameStr);
+	WriteAPBXCDDObjAPropRefType3();
+	WriteAPBXCDDObjAPropSourceTree("BUILT_PRODUCTS_DIR");
+}
+
+LOCALPROC DoProductAPBXCDaddFileRef(void)
+{
+	WriteAPBXCDObjectAp(APBospcProductRef, 0,
+		WriteAppNameStr,
+		DoProductAPBXCDaddFileRefBody);
+}
+
+LOCALPROC WritePlistAPBXCDtype(void)
+{
+	if (ide_vers >= 3100) {
+		WriteCStrToDestFile("text.plist.xml");
+	} else {
+		WriteCStrToDestFile("text.xml");
+	}
+}
+
+LOCALPROC DoPlistAPBXCDaddFileRefBody(void)
+{
+	if (HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+
+	WriteAPBXCDDObjAPropExpectedFileType(WritePlistAPBXCDtype);
+	WriteAPBXCDDObjAPropFileEncoding4();
+	if (! HaveAPBXCD_IsaFirst) {
+		WriteAPBXCDDObjAPropIsaFileReference();
+	}
+	WriteAPBXCDDObjAPropLastKnownFType(WritePlistAPBXCDtype);
+	WriteAPBXCDDObjAPropName(WriteInfoPlistFileName);
+	WriteAPBXCDDObjAPropPath(WriteInfoPlistFilePath);
+	WriteAPBXCDDObjAPropRefType2();
+	WriteAPBXCDDObjAPropSourceTreeRoot();
+}
+
+LOCALPROC DoPlistAPBXCDaddFileRef(void)
+{
+	WriteAPBXCDObjectAp(APBospcPlistRf, 0,
+		WriteInfoPlistFileName,
+		DoPlistAPBXCDaddFileRefBody);
+}
+
+LOCALPROC WriteAPBXCDBuildSettings(void)
+{
+	if (ide_vers >= 3100) {
+		WriteDestFileLn("ALWAYS_SEARCH_USER_PATHS = NO;");
+	}
+
+	if (ide_vers >= 2100) {
+		/* if (CrossCompile) */ {
+			if (gbk_cpufam_x86 == gbo_cpufam) {
+				WriteDestFileLn("ARCHS = i386;");
+				/*
+					may be preferred in later versions:
+					WriteDestFileLn(
+						"ARCHS = \"$(ARCHS_STANDARD_32_BIT)\";");
+				*/
+			} else if (gbk_cpufam_x64 == gbo_cpufam) {
+				WriteDestFileLn("ARCHS = x86_64;");
+			} else {
+				WriteDestFileLn("ARCHS = ppc;");
+			}
+		}
+	}
+	if (ide_vers >= 2100) { /*^*/
+		/*
+			seems to work in Xcode 2.1, but doesn't
+			really appear in settings user interface
+			until Xcode 2.2
+		*/
+		WriteDestFileLn(
+			"CONFIGURATION_BUILD_DIR = \"$(PROJECT_DIR)\";");
+	}
+	if (ide_vers >= 2200) { /*^*/
+		WriteDestFileLn("COPY_PHASE_STRIP = NO;");
+	} else {
+		if (gbk_dbg_on != gbo_dbg) {
+			WriteDestFileLn("COPY_PHASE_STRIP = YES;");
+		} else {
+			WriteDestFileLn("COPY_PHASE_STRIP = NO;");
+		}
+	}
+	if (ide_vers >= 1500) {
+		if (gbk_dbg_on != gbo_dbg) {
+			WriteDestFileLn("DEPLOYMENT_POSTPROCESSING = YES;");
+		}
+	}
+	if (ide_vers < 1500) {
+		if (gbk_dbg_on != gbo_dbg) {
+			WriteDestFileLn("DEBUGGING_SYMBOLS = NO;");
+		}
+	}
+	if (ide_vers >= 1500) {
+		WriteDestFileLn("GCC_CW_ASM_SYNTAX = NO;");
+	}
+	if (ide_vers >= 1000) {
+		WriteDestFileLn("GCC_DYNAMIC_NO_PIC = YES;");
+	}
+	if (ide_vers < 1500) {
+		WriteAPBQuotedField("FRAMEWORK_SEARCH_PATHS", "");
+	}
+	if ((ide_vers >= 1000) && (ide_vers < 4000)) {
+		WriteDestFileLn("GCC_ENABLE_FIX_AND_CONTINUE = NO;");
+	}
+	if (ide_vers >= 1000) {
+		if (gbk_dbg_on != gbo_dbg) {
+			WriteDestFileLn("GCC_GENERATE_DEBUGGING_SYMBOLS = NO;");
+		}
+	}
+	if ((ide_vers >= 1500) && (ide_vers < 4000)) {
+		WriteDestFileLn("GCC_MODEL_TUNING = \"\";");
+	}
+	if (ide_vers >= 1000) {
+		if (gbk_dbg_on == gbo_dbg) {
+			WriteDestFileLn("GCC_OPTIMIZATION_LEVEL = 0;");
+		} else {
+			WriteDestFileLn("GCC_OPTIMIZATION_LEVEL = s;");
+		}
+	}
+	if (ide_vers >= 2100) {
+		WriteDestFileLn("GCC_PRECOMPILE_PREFIX_HEADER = NO;");
+		WriteDestFileLn("GCC_PREFIX_HEADER = \"\";");
+		WriteDestFileLn("GCC_SYMBOLS_PRIVATE_EXTERN = NO;");
+	}
+	if (ide_vers >= 3100) {
+		if (ide_vers < 3200) {
+			WriteDestFileLn("GCC_VERSION = 4.0;");
+		}
+	}
+	if (ide_vers >= 1000) {
+		WriteDestFileLn("GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;");
+	}
+
+	if (HaveMacBundleApp) {
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("INFOPLIST_FILE = ");
+		WriteInfoPlistFilePath();
+		WriteCStrToDestFile(";");
+		WriteEndDestFileLn();
+	}
+	if (ide_vers >= 1000) {
+		WriteDestFileLn("INSTALL_PATH = \"$(HOME)/Applications\";");
+	}
+	if (ide_vers < 1500) {
+		WriteAPBQuotedField("LIBRARY_SEARCH_PATHS", "");
+	}
+	if (ide_vers >= 2100) {
+		if (gbk_cpufam_ppc == gbo_cpufam) {
+			WriteDestFileLn("MACOSX_DEPLOYMENT_TARGET = 10.1;");
+		} else {
+			if (ide_vers >= 9000) {
+				WriteDestFileLn("MACOSX_DEPLOYMENT_TARGET = 10.6;");
+			} else {
+				WriteDestFileLn("MACOSX_DEPLOYMENT_TARGET = 10.4;");
+			}
+		}
+	}
+	if (ide_vers < 1500) {
+		if (gbk_dbg_on == gbo_dbg) {
+			WriteAPBQuotedField("OPTIMIZATION_CFLAGS", "-O0");
+		}
+	}
+	if (ide_vers < 1500) {
+		WriteAPBQuotedField("OTHER_LDFLAGS", "");
+		WriteAPBQuotedField("OTHER_REZFLAGS", "");
+	} else {
+		if (! HaveMacBundleApp) {
+			WriteAPBXCDBgnObjList("OTHER_LDFLAGS");
+				WriteDestFileLn("\"-L/usr/X11R6/lib\",");
+#if 0
+				WriteDestFileLn("\"-lXext\",");
+#endif
+				WriteDestFileLn("\"-lX11\",");
+			WriteAPBXCDEndObjList();
+		}
+	}
+	if ((ide_vers >= 1500) && (ide_vers < 4000)) {
+		WriteDestFileLn("PREBINDING = NO;");
+	}
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("PRODUCT_NAME = ");
+	WriteStrAppAbbrev();
+	WriteCStrToDestFile(";");
+	WriteEndDestFileLn();
+	if (ide_vers >= 2200) {
+		if (ide_vers >= 4300) {
+			WriteDestFileLn("SDKROOT = macosx;");
+		} else if (ide_vers >= 3200) {
+			WriteDestFileLn("SDKROOT = macosx10.6;");
+		} else if (ide_vers >= 3100) {
+			WriteDestFileLn("SDKROOT = macosx10.5;");
+		} else {
+			WriteDestFileLn(
+				"SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk;");
+		}
+	}
+	if (ide_vers < 1500) {
+		WriteAPBQuotedField("SECTORDER_FLAGS", "");
+	}
+	if (ide_vers >= 2200) {
+		if (gbk_dbg_on != gbo_dbg) {
+			WriteDestFileLn("SEPARATE_STRIP = YES;");
+			WriteDestFileLn("STRIPFLAGS = \"-u -r\";");
+			WriteDestFileLn("STRIP_INSTALLED_PRODUCT = YES;");
+		}
+	}
+	if ((ide_vers >= 1500) && (ide_vers < 2100)) {
+		WriteDestFileLn("SYMROOT = \"$(PROJECT_DIR)\";");
+	}
+	WriteDestFileLn("USER_HEADER_SEARCH_PATHS = \"$(SRCROOT)/"
+		cfg_d_name
+		"\";");
+	if (ide_vers >= 2100) {
+		WriteAPBXCDBgnObjList("WARNING_CFLAGS");
+			WriteDestFileLn("\"-Wall\",");
+			WriteDestFileLn("\"-Wundef\",");
+			WriteDestFileLn("\"-Wstrict-prototypes\",");
+			WriteDestFileLn("\"-Wno-uninitialized\",");
+		WriteAPBXCDEndObjList();
+	} else {
+		WriteAPBQuotedField("WARNING_CFLAGS",
+			"-Wall -Wstrict-prototypes -Wno-uninitialized"
+			" -Wno-four-char-constants -Wno-unknown-pragmas");
+	}
+	if ((HaveMacBundleApp) && (ide_vers < 3100)) {
+		WriteDestFileLn("WRAPPER_EXTENSION = app;");
+	}
+	if ((ide_vers >= 1000) && (ide_vers < 3100)) {
+		WriteDestFileLn("ZERO_LINK = NO;");
+	}
+}
+
+LOCALPROC WriteAPBplist(void)
+{
+	int SaveDestFileIndent = DestFileIndent;
+
+	DestFileIndent = 0;
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("<!DOCTYPE plist PUBLIC ");
+	WriteBackSlashToDestFile();
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile("-//Apple Computer//DTD PLIST 1.0//EN");
+	WriteBackSlashToDestFile();
+	WriteQuoteToDestFile();
+	WriteSpaceToDestFile();
+	WriteBackSlashToDestFile();
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(
+		"http://www.apple.com/DTDs/PropertyList-1.0.dtd");
+	WriteBackSlashToDestFile();
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(">");
+	WriteEndDestFileLn();
+
+	WriteBgnDestFileLn();
+	WriteCStrToDestFile("<plist version=");
+	WriteBackSlashToDestFile();
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile("1.0");
+	WriteBackSlashToDestFile();
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(">");
+	WriteEndDestFileLn();
+
+	CurPListFormat = kPListRaw;
+
+	WriteMyInfoPListContents();
+
+	WriteDestFileLn("</plist>");
+	WriteBgnDestFileLn();
+	WriteQuoteToDestFile();
+	WriteCStrToDestFile(";");
+	WriteEndDestFileLn();
+
+	DestFileIndent = SaveDestFileIndent;
+}
+
+LOCALPROC WriteStrFrameworks(void)
+{
+	WriteCStrToDestFile("Frameworks");
+}
+
+LOCALPROC WriteStrSources(void)
+{
+	WriteCStrToDestFile("Sources");
+}
+
+LOCALPROC WriteStrResources(void)
+{
+	WriteCStrToDestFile("Resources");
+}
+
+LOCALPROC WriteStrRez(void)
+{
+	WriteCStrToDestFile("Rez");
+}
+
+LOCALPROC WriteStrFrameworksLibraries(void)
+{
+	WriteCStrToDestFile("External Frameworks and Libraries");
+}
+
+LOCALPROC WriteStrQuoteFrameworksLibraries(void)
+{
+	WriteQuoteToDestFile();
+	WriteStrFrameworksLibraries();
+	WriteQuoteToDestFile();
+}
+
+LOCALPROC WriteStrProducts(void)
+{
+	WriteCStrToDestFile("Products");
+}
+
+LOCALPROC WriteStrHeaders(void)
+{
+	WriteCStrToDestFile("Headers");
+}
+
+LOCALPROC WriteStrIncludes(void)
+{
+	WriteCStrToDestFile("Includes");
+}
+
+LOCALPROC WriteStrProjectObject(void)
+{
+	WriteCStrToDestFile("Project object");
+}
+
+LOCALPROC WriteStrEmptyQuote(void)
+{
+	WriteQuoteToDestFile();
+	WriteQuoteToDestFile();
+}
+
+LOCALPROC WriteAPBXCDDObjAPropPathNull(void)
+{
+	if (ide_vers < 2100) {
+		WriteAPBXCDDObjAPropPath(WriteStrEmptyQuote);
+	}
+}
+
+LOCALPROC WriteAPBXCDMainGroupName(void)
+{
+	if (ide_vers < 1000) {
+		WriteQuoteToDestFile();
+		WriteAppVariationStr();
+		WriteQuoteToDestFile();
+	} else {
+		WriteStrAppAbbrev();
+	}
+}
+
+LOCALPROC WriteAPBXCDDObjAPropIsaAppTarg(void)
+{
+	if (ide_vers < 1000) {
+		WriteAPBXCDDObjAPropIsa("PBXApplicationTarget");
+	} else {
+		WriteAPBXCDDObjAPropIsa("PBXNativeTarget");
+	}
+}
+
+LOCALPROC WriteStrConfListPBXProject(void)
+{
+	WriteCStrToDestFile("Build configuration list for PBXProject \"");
+	WriteStrAppAbbrev();
+	WriteCStrToDestFile("\"");
+}
+
+LOCALPROC WriteStrConfListPBXNativeTarget(void)
+{
+	WriteCStrToDestFile(
+		"Build configuration list for PBXNativeTarget \"");
+	WriteStrAppAbbrev();
+	WriteCStrToDestFile("\"");
+}
+
+#define HaveFrameworks HaveMacBundleApp
+
+LOCALPROC WriteXCDdummyfile(void)
+{
+	WriteDestFileLn("dummy");
+}
+
+LOCALPROC WriteXCDProjectFile(void)
+{
+	WriteDestFileLn("// !$*UTF8*$!");
+	WriteDestFileLn("{");
+	++DestFileIndent;
+		WriteDestFileLn("archiveVersion = 1;");
+		WriteDestFileLn("classes = {");
+		WriteDestFileLn("};");
+		if (ide_vers >= 3200) {
+			WriteDestFileLn("objectVersion = 46;");
+		} else if (ide_vers >= 3100) {
+			WriteDestFileLn("objectVersion = 45;");
+		} else if (ide_vers >= 2100) {
+			WriteDestFileLn("objectVersion = 42;");
+		} else if (ide_vers >= 1000) {
+			WriteDestFileLn("objectVersion = 39;");
+		} else {
+			WriteDestFileLn("objectVersion = 38;");
+		}
+		WriteDestFileLn("objects = {");
+	++DestFileIndent;
+
+	DoBeginSectionAPBXCD("PBXBuildFile");
+		DoAllSrcFilesWithSetup(DoSrcFileAPBXCDaddFile);
+		if (HaveMacBundleApp) {
+			DoAllDocTypesWithSetup(DoDocTypeAPBXCDaddFile);
+		}
+
+		if (HaveFrameworks) {
+			DoAllFrameWorksWithSetup(DoFrameWorkAPBXCDaddFile);
+		}
+		if (HaveAPBXCD_StdcLib) {
+			DoLibStdcAPBXCDaddFile();
+		}
+
+		if (HaveMacRrscs) {
+			DoRsrcAPBXCDaddFile();
+		}
+
+		if (HaveMacBundleApp) {
+			if (HaveAPBXCD_LangDummy) {
+				DoDummyLangAPBXCDaddFile();
+			}
+		}
+	DoEndSectionAPBXCD("PBXBuildFile");
+
+	if (ide_vers < 2300) {
+		DoBeginSectionAPBXCD("PBXBuildStyle");
+			WriteAPBXCDBeginObject(APBospcBuildStyle,
+				0, WriteXCDconfigname);
+
+				if (HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsa("PBXBuildStyle");
+				}
+
+				if (ide_vers < 1500) {
+					WriteAPBXCDBgnObjList("buildRules");
+					WriteAPBXCDEndObjList();
+				}
+				WriteDestFileLn("buildSettings = {");
+				WriteDestFileLn("};");
+				if (! HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsa("PBXBuildStyle");
+				}
+				WriteAPBXCDDObjAPropName(WriteXCDconfigname);
+			WriteAPBXCDEndObject();
+		DoEndSectionAPBXCD("PBXBuildStyle");
+	}
+
+	DoBeginSectionAPBXCD("PBXFileReference");
+		DoAllSrcFilesWithSetup(DoSrcFileAPBXCDaddFileRef);
+
+		if (HaveAPBXCD_Headers) {
+			DoAllSrcFilesWithSetup(DoHeaderFileXCDaddFileRef);
+			DoAllExtraHeaders2WithSetup(
+				DoExtraHeaderFileXCDaddFileRef);
+		}
+
+		if (HaveMacBundleApp) {
+			DoAllDocTypesWithSetup(DoDocTypeAPBXCDaddFileRef);
+		}
+
+		if (HaveFrameworks) {
+			DoAllFrameWorksWithSetup(DoFrameWorkAPBXCDaddFileRef);
+		}
+		if (HaveAPBXCD_StdcLib) {
+			DoLibStdcAPBXCDaddFileRef();
+		}
+
+		DoProductAPBXCDaddFileRef();
+
+		if (HaveMacBundleApp) {
+			if (HaveAPBXCD_PlistFile) {
+				DoPlistAPBXCDaddFileRef();
+			}
+		}
+		if (HaveMacRrscs) {
+			DoRsrcAPBXCDaddFileRef();
+		}
+		if (HaveMacBundleApp) {
+			if (HaveAPBXCD_LangDummy) {
+				DoLangDummyAPBXCDaddFileRef();
+			}
+		}
+	DoEndSectionAPBXCD("PBXFileReference");
+
+	DoBeginSectionAPBXCD("PBXFrameworksBuildPhase");
+		WriteAPBXCDBeginObject(APBospcPhaseLibs, 0, WriteStrFrameworks);
+			if (HaveAPBXCD_IsaFirst) {
+				WriteAPBXCDDObjAPropIsa("PBXFrameworksBuildPhase");
+			}
+
+			WriteDestFileLn("buildActionMask = 2147483647;");
+			WriteAPBXCDBgnObjList("files");
+				if (HaveFrameworks) {
+					DoAllFrameWorksWithSetup(
+						DoFrameworkAPBXCDaddToBuild);
+				}
+				if (HaveAPBXCD_StdcLib) {
+					WriteAPBXCDobjlistelmp(APBospcLibStdcBld,
+						0, WriteLibStdcName);
+				}
+			WriteAPBXCDEndObjList();
+			if (! HaveAPBXCD_IsaFirst) {
+				WriteAPBXCDDObjAPropIsa("PBXFrameworksBuildPhase");
+			}
+			WriteDestFileLn("runOnlyForDeploymentPostprocessing = 0;");
+		WriteAPBXCDEndObject();
+	DoEndSectionAPBXCD("PBXFrameworksBuildPhase");
+
+	DoBeginSectionAPBXCD("PBXGroup");
+		WriteAPBXCDBeginObject(APBospcSources, 0, WriteStrSources);
+			if (HaveAPBXCD_IsaFirst) {
+				WriteAPBXCDDObjAPropIsaGroup();
+			}
+
+			WriteAPBXCDBgnObjList("children");
+				DoAllSrcFilesWithSetup(DoSrcFileAPBXCDaddToGroup);
+				if (HaveMacRrscs) {
+					if (ide_vers >= 2100) {
+						WriteAPBXCDobjlistelmp(APBospcMainRsrcRf, 0,
+							WriteMainRsrcName);
+					}
+				}
+			WriteAPBXCDEndObjList();
+			if (! HaveAPBXCD_IsaFirst) {
+				WriteAPBXCDDObjAPropIsaGroup();
+			}
+			WriteAPBXCDDObjAPropName(WriteStrSources);
+			WriteAPBXCDDObjAPropPathNull();
+			WriteAPBXCDDObjAPropRefType4();
+			WriteAPBXCDDObjAPropSourceTreeGroup();
+		WriteAPBXCDEndObject();
+
+		if (HaveMacBundleApp) {
+			WriteAPBXCDBeginObject(APBospcResources,
+				0, WriteStrResources);
+
+				if (HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsaGroup();
+				}
+
+				WriteAPBXCDBgnObjList("children");
+					if (HaveMacRrscs) {
+						if (ide_vers < 2100) {
+							WriteAPBXCDobjlistelmp(APBospcMainRsrcRf,
+								0, WriteMainRsrcName);
+						}
+					}
+					DoAllDocTypesWithSetup(
+						DoDocTypeAPBXCDaddToGroup);
+					if (HaveAPBXCD_PlistFile) {
+						WriteAPBXCDobjlistelmp(APBospcPlistRf,
+							0, WriteInfoPlistFileName);
+					}
+					if (HaveAPBXCD_LangDummy) {
+#if 0
+						WriteAPBXCDobjlistelmp(APBospcLangRf,
+							0, WriteLProjFolderName);
+#endif
+						WriteAPBXCDobjlistelmp(APBospcLangDummyRf,
+							0, WriteDummyLangFileName);
+					}
+				WriteAPBXCDEndObjList();
+				if (! HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsaGroup();
+				}
+				WriteAPBXCDDObjAPropName(WriteStrResources);
+				WriteAPBXCDDObjAPropPathNull();
+				WriteAPBXCDDObjAPropRefType4();
+				WriteAPBXCDDObjAPropSourceTreeGroup();
+			WriteAPBXCDEndObject();
+		}
+
+		if (HaveFrameworks) {
+			WriteAPBXCDBeginObject(APBospcLibraries,
+				0, WriteStrFrameworksLibraries);
+
+				if (HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsaGroup();
+				}
+
+				WriteAPBXCDBgnObjList("children");
+					DoAllFrameWorksWithSetup(
+						DoFrameworkAPBXCDaddToLibraries);
+					if (HaveAPBXCD_StdcLib) {
+						WriteAPBXCDobjlistelmp(APBospcLibStdcRf,
+							0, WriteLibStdcName);
+					}
+				WriteAPBXCDEndObjList();
+				if (! HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsaGroup();
+				}
+				WriteAPBXCDDObjAPropName(
+					WriteStrQuoteFrameworksLibraries);
+				WriteAPBXCDDObjAPropPathNull();
+				WriteAPBXCDDObjAPropRefType4();
+				WriteAPBXCDDObjAPropSourceTreeGroup();
+			WriteAPBXCDEndObject();
+		}
+
+		WriteAPBXCDBeginObject(APBospcProducts, 0, WriteStrProducts);
+			if (HaveAPBXCD_IsaFirst) {
+				WriteAPBXCDDObjAPropIsaGroup();
+			}
+
+			WriteAPBXCDBgnObjList("children");
+				WriteAPBXCDobjlistelmp(APBospcProductRef,
+					0, WriteAppNameStr);
+			WriteAPBXCDEndObjList();
+			if (! HaveAPBXCD_IsaFirst) {
+				WriteAPBXCDDObjAPropIsaGroup();
+			}
+			WriteAPBXCDDObjAPropName(WriteStrProducts);
+			WriteAPBXCDDObjAPropRefType4();
+			WriteAPBXCDDObjAPropSourceTreeGroup();
+		WriteAPBXCDEndObject();
+
+		WriteAPBXCDBeginObject(APBospcMainGroup, 0, WriteStrAppAbbrev);
+			if (HaveAPBXCD_IsaFirst) {
+				WriteAPBXCDDObjAPropIsaGroup();
+			}
+
+			WriteAPBXCDBgnObjList("children");
+				WriteAPBXCDobjlistelmp(APBospcSources,
+					0, WriteStrSources);
+				if (HaveAPBXCD_Headers) {
+					WriteAPBXCDobjlistelmp(APBospcSrcHeaders,
+						0, WriteStrHeaders);
+					WriteAPBXCDobjlistelmp(APBospcIncludes,
+						0, WriteStrIncludes);
+				}
+				if (HaveMacBundleApp) {
+					WriteAPBXCDobjlistelmp(APBospcResources,
+						0, WriteStrResources);
+				}
+				if (HaveFrameworks) {
+					WriteAPBXCDobjlistelmp(APBospcLibraries,
+						0, WriteStrFrameworksLibraries);
+				}
+				WriteAPBXCDobjlistelmp(APBospcProducts,
+					0, WriteStrProducts);
+			WriteAPBXCDEndObjList();
+
+			if (! HaveAPBXCD_IsaFirst) {
+				WriteAPBXCDDObjAPropIsaGroup();
+			}
+			WriteAPBXCDDObjAPropName(WriteAPBXCDMainGroupName);
+			WriteAPBXCDDObjAPropPathNull();
+			WriteAPBXCDDObjAPropRefType4();
+			WriteAPBXCDDObjAPropSourceTreeGroup();
+		WriteAPBXCDEndObject();
+		if (HaveAPBXCD_Headers) {
+			WriteAPBXCDBeginObject(APBospcSrcHeaders,
+				0, WriteStrHeaders);
+
+				if (HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsaGroup();
+				}
+
+				WriteAPBXCDBgnObjList("children");
+					DoAllSrcFilesWithSetup(
+						DoHeaderFileXCDaddToGroup);
+				WriteAPBXCDEndObjList();
+				if (! HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsaGroup();
+				}
+				WriteAPBXCDDObjAPropName(WriteStrHeaders);
+				WriteAPBXCDDObjAPropRefType4();
+				WriteAPBXCDDObjAPropSourceTreeGroup();
+			WriteAPBXCDEndObject();
+			WriteAPBXCDBeginObject(APBospcIncludes,
+				0, WriteStrIncludes);
+
+				if (HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsaGroup();
+				}
+
+				WriteAPBXCDBgnObjList("children");
+					DoAllExtraHeaders2WithSetup(
+						DoExtraHeaderFileXCDaddToGroup);
+				WriteAPBXCDEndObjList();
+				if (! HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsaGroup();
+				}
+				WriteAPBXCDDObjAPropName(WriteStrIncludes);
+				WriteAPBXCDDObjAPropRefType4();
+				WriteAPBXCDDObjAPropSourceTreeGroup();
+			WriteAPBXCDEndObject();
+#if 0
+			WriteAPBXCDBeginObject(APBospcLangRf,
+				0, WriteLProjFolderName);
+
+				if (HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsaGroup();
+				}
+
+				WriteAPBXCDBgnObjList("children");
+					WriteAPBXCDobjlistelmp(APBospcLangDummyRf,
+						0, WriteDummyLangFileName);
+				WriteAPBXCDEndObjList();
+				if (! HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsaGroup();
+				}
+				WriteAPBXCDDObjAPropName(WriteLProjFolderName);
+				WriteAPBXCDDObjAPropPath(WriteLProjFolderPath);
+				WriteAPBXCDDObjAPropRefType4();
+				WriteAPBXCDDObjAPropSourceTreeGroup();
+			WriteAPBXCDEndObject();
+#endif
+		}
+	DoEndSectionAPBXCD("PBXGroup");
+
+	DoBeginSectionAPBXCD("PBXNativeTarget");
+		WriteAPBXCDBeginObject(APBospcTarget, 0, WriteStrAppAbbrev);
+			if (HaveAPBXCD_IsaFirst) {
+				WriteAPBXCDDObjAPropIsaAppTarg();
+			}
+
+			if (ide_vers >= 2100) {
+				WriteAPBXCDDObjAProp_SO("buildConfigurationList",
+					APBospcLstNatCnfg, 0,
+					WriteStrConfListPBXNativeTarget);
+			}
+			WriteAPBXCDBgnObjList("buildPhases");
+				if (ide_vers < 1500) {
+					WriteAPBXCDobjlistelmp(APBospcHeaders,
+						0, WriteStrHeaders);
+				}
+				if (HaveMacBundleApp) {
+					WriteAPBXCDobjlistelmp(APBospcBunRsrcs,
+						0, WriteStrResources);
+				}
+				WriteAPBXCDobjlistelmp(APBospcPhaseSrcs,
+					0, WriteStrSources);
+				WriteAPBXCDobjlistelmp(APBospcPhaseLibs,
+					0, WriteStrFrameworks);
+				if (HaveMacRrscs) {
+					WriteAPBXCDobjlistelmp(APBospcPhaseRsrc,
+						0, WriteStrRez);
+				}
+			WriteAPBXCDEndObjList();
+			if (ide_vers >= 1000) {
+				WriteAPBXCDBgnObjList("buildRules");
+				WriteAPBXCDEndObjList();
+			}
+			if (ide_vers < 2300) {
+				WriteDestFileLn("buildSettings = {");
+				++DestFileIndent;
+				if (ide_vers < 2100) {
+					WriteAPBXCDBuildSettings();
+				}
+				--DestFileIndent;
+				WriteDestFileLn("};");
+			}
+			WriteAPBXCDBgnObjList("dependencies");
+			WriteAPBXCDEndObjList();
+
+			if (! HaveAPBXCD_IsaFirst) {
+				WriteAPBXCDDObjAPropIsaAppTarg();
+			}
+
+			WriteAPBXCDDObjAPropName(WriteStrAppAbbrev);
+
+			if (ide_vers >= 1000) {
+				WriteDestFileLn(
+					"productInstallPath = \"$(HOME)/Applications\";");
+			}
+
+			WriteBgnDestFileLn();
+			WriteCStrToDestFile("productName = ");
+			if (ide_vers < 1000) {
+				WriteQuoteToDestFile();
+			}
+			WriteStrAppAbbrev();
+			if (ide_vers < 1000) {
+				WriteQuoteToDestFile();
+			}
+			WriteCStrToDestFile(";");
+			WriteEndDestFileLn();
+
+			WriteAPBXCDDObjAProp_SO("productReference",
+				APBospcProductRef, 0,
+				WriteAppNameStr);
+
+			if (ide_vers >= 1000) {
+				if (HaveMacBundleApp) {
+					WriteDestFileLn(
+						"productType = "
+						"\"com.apple.product-type.application\";");
+				} else {
+					WriteDestFileLn(
+						"productType = "
+						"\"com.apple.product-type.tool\";");
+				}
+			}
+			if ((! HaveAPBXCD_PlistFile) && HaveMacBundleApp) {
+				WriteBgnDestFileLn();
+				WriteCStrToDestFile("productSettingsXML = ");
+				WriteQuoteToDestFile();
+				WriteCStrToDestFile("<?xml version=");
+				WriteBackSlashToDestFile();
+				WriteQuoteToDestFile();
+				WriteCStrToDestFile("1.0");
+				WriteBackSlashToDestFile();
+				WriteQuoteToDestFile();
+				WriteCStrToDestFile(" encoding=\\\"UTF-8\\\"?>");
+				WriteEndDestFileLn();
+
+				WriteAPBplist();
+			}
+		WriteAPBXCDEndObject();
+	DoEndSectionAPBXCD("PBXNativeTarget");
+
+	DoBeginSectionAPBXCD("PBXProject");
+		WriteAPBXCDBeginObject(APBospcRoot, 0, WriteStrProjectObject);
+			if (HaveAPBXCD_IsaFirst) {
+				WriteAPBXCDDObjAPropIsa("PBXProject");
+			}
+			if (ide_vers >= 4300) {
+				WriteDestFileLn("attributes = {");
+				++DestFileIndent;
+					WriteBgnDestFileLn();
+					WriteCStrToDestFile("LastUpgradeCheck = ");
+					WriteCharToDestFile('0'
+						+ ((ide_vers / 10000) % 10));
+					WriteCharToDestFile('0' + ((ide_vers / 1000) % 10));
+					WriteCharToDestFile('0' + ((ide_vers / 100) % 10));
+					WriteCStrToDestFile("0;");
+					WriteEndDestFileLn();
+				--DestFileIndent;
+				WriteDestFileLn("};");
+			}
+			if (ide_vers >= 2100) {
+				WriteAPBXCDDObjAProp_SO("buildConfigurationList",
+					APBospcLstPrjCnfg, 0,
+					WriteStrConfListPBXProject);
+			}
+			if (ide_vers < 2300) {
+				if (ide_vers >= 1000) {
+					WriteDestFileLn("buildSettings = {");
+					WriteDestFileLn("};");
+				}
+				WriteAPBXCDBgnObjList("buildStyles");
+					WriteAPBXCDobjlistelmp(APBospcBuildStyle,
+						0, WriteXCDconfigname);
+				WriteAPBXCDEndObjList();
+			}
+			if (ide_vers >= 3200) {
+				WriteDestFileLn(
+					"compatibilityVersion = \"Xcode 3.2\";");
+			} else if (ide_vers >= 3100) {
+				WriteDestFileLn(
+					"compatibilityVersion = \"Xcode 3.1\";");
+			}
+			WriteDestFileLn("hasScannedForEncodings = 1;");
+
+			if (! HaveAPBXCD_IsaFirst) {
+				WriteAPBXCDDObjAPropIsa("PBXProject");
+			}
+
+			WriteAPBXCDDObjAProp_SO("mainGroup",
+				APBospcMainGroup, 0,
+				WriteStrAppAbbrev);
+
+			if (ide_vers >= 4000) {
+				WriteAPBXCDDObjAProp_SO("productRefGroup",
+					APBospcProducts, 0,
+					WriteStrProducts);
+			}
+
+			WriteDestFileLn("projectDirPath = \"\";");
+
+			if (ide_vers >= 3100) {
+				WriteDestFileLn("projectRoot = \"\";");
+			}
+
+			WriteAPBXCDBgnObjList("targets");
+				WriteAPBXCDobjlistelmp(APBospcTarget,
+					0, WriteStrAppAbbrev);
+			WriteAPBXCDEndObjList();
+		WriteAPBXCDEndObject();
+	DoEndSectionAPBXCD("PBXProject");
+
+	if (HaveMacBundleApp) {
+		DoBeginSectionAPBXCD("PBXResourcesBuildPhase");
+			WriteAPBXCDBeginObject(APBospcBunRsrcs,
+				0, WriteStrResources);
+
+				if (HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsa("PBXResourcesBuildPhase");
+				}
+
+				WriteDestFileLn("buildActionMask = 2147483647;");
+				WriteAPBXCDBgnObjList("files");
+					DoAllDocTypesWithSetup(
+						DoDocTypeAPBXCDaddToSources);
+					if (HaveAPBXCD_LangDummy) {
+						DoLangDummyAPBXCDaddToSources();
+					}
+				WriteAPBXCDEndObjList();
+				if (! HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsa("PBXResourcesBuildPhase");
+				}
+				WriteDestFileLn(
+					"runOnlyForDeploymentPostprocessing = 0;");
+			WriteAPBXCDEndObject();
+		DoEndSectionAPBXCD("PBXResourcesBuildPhase");
+	}
+	if (HaveMacRrscs) {
+		DoBeginSectionAPBXCD("PBXRezBuildPhase");
+			WriteAPBXCDBeginObject(APBospcPhaseRsrc, 0, WriteStrRez);
+				if (HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsa("PBXRezBuildPhase");
+				}
+
+				WriteDestFileLn("buildActionMask = 2147483647;");
+				WriteAPBXCDBgnObjList("files");
+					WriteAPBXCDobjlistelmp(APBospcMnRsrcBld, 0,
+						WriteMainAPBXCDRsrcNameinRez);
+				WriteAPBXCDEndObjList();
+				if (! HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsa("PBXRezBuildPhase");
+				}
+				WriteDestFileLn(
+					"runOnlyForDeploymentPostprocessing = 0;");
+			WriteAPBXCDEndObject();
+		DoEndSectionAPBXCD("PBXRezBuildPhase");
+	}
+
+	if (ide_vers < 1500) {
+		WriteAPBXCDBeginObject(APBospcHeaders, 0, WriteStrHeaders);
+			if (HaveAPBXCD_IsaFirst) {
+				WriteAPBXCDDObjAPropIsa("PBXHeadersBuildPhase");
+			}
+
+			WriteDestFileLn("buildActionMask = 2147483647;");
+			WriteAPBXCDBgnObjList("files");
+			WriteAPBXCDEndObjList();
+			if (! HaveAPBXCD_IsaFirst) {
+				WriteAPBXCDDObjAPropIsa("PBXHeadersBuildPhase");
+			}
+			WriteDestFileLn("runOnlyForDeploymentPostprocessing = 0;");
+		WriteAPBXCDEndObject();
+	}
+
+	DoBeginSectionAPBXCD("PBXSourcesBuildPhase");
+		WriteAPBXCDBeginObject(APBospcPhaseSrcs, 0, WriteStrSources);
+			if (HaveAPBXCD_IsaFirst) {
+				WriteAPBXCDDObjAPropIsa("PBXSourcesBuildPhase");
+			}
+
+			WriteDestFileLn("buildActionMask = 2147483647;");
+			WriteAPBXCDBgnObjList("files");
+				DoAllSrcFilesSortWithSetup(
+					DoSrcFileAPBXCDaddToSources);
+			WriteAPBXCDEndObjList();
+			if (! HaveAPBXCD_IsaFirst) {
+				WriteAPBXCDDObjAPropIsa("PBXSourcesBuildPhase");
+			}
+			WriteDestFileLn("runOnlyForDeploymentPostprocessing = 0;");
+		WriteAPBXCDEndObject();
+	DoEndSectionAPBXCD("PBXSourcesBuildPhase");
+
+	if (HaveMacBundleApp) {
+		if (HaveAPBXCD_LangDummy) {
+			DoBeginSectionAPBXCD("PBXVariantGroup");
+				DoLangDummyAPBXCDaddVariant();
+			DoEndSectionAPBXCD("PBXVariantGroup");
+		}
+	}
+
+	if (ide_vers >= 2100) {
+		DoBeginSectionAPBXCD("XCBuildConfiguration");
+			WriteAPBXCDBeginObject(APBospcNatCnfg,
+				0, WriteXCDconfigname);
+
+				if (HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsa("XCBuildConfiguration");
+				}
+
+				WriteDestFileLn("buildSettings = {");
+				++DestFileIndent;
+					WriteAPBXCDBuildSettings();
+				--DestFileIndent;
+				WriteDestFileLn("};");
+				if (! HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsa("XCBuildConfiguration");
+				}
+				WriteAPBXCDDObjAPropName(WriteXCDconfigname);
+			WriteAPBXCDEndObject();
+			WriteAPBXCDBeginObject(APBospcPrjCnfg,
+				0, WriteXCDconfigname);
+
+				if (HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsa("XCBuildConfiguration");
+				}
+
+				WriteDestFileLn("buildSettings = {");
+				WriteDestFileLn("};");
+				if (! HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsa("XCBuildConfiguration");
+				}
+				WriteAPBXCDDObjAPropName(WriteXCDconfigname);
+			WriteAPBXCDEndObject();
+		DoEndSectionAPBXCD("XCBuildConfiguration");
+	}
+
+	if (ide_vers >= 2100) {
+		DoBeginSectionAPBXCD("XCConfigurationList");
+			WriteAPBXCDBeginObject(APBospcLstNatCnfg, 0,
+				WriteStrConfListPBXNativeTarget);
+
+				if (HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsa("XCConfigurationList");
+				}
+
+				WriteAPBXCDBgnObjList("buildConfigurations");
+					WriteAPBXCDobjlistelmp(APBospcNatCnfg,
+						0, WriteXCDconfigname);
+				WriteAPBXCDEndObjList();
+				WriteAPBXCDDObjAProp_SS(
+					"defaultConfigurationIsVisible", "0");
+				WriteAPBXCDDObjAProp_SP(
+					"defaultConfigurationName", WriteXCDconfigname);
+				if (! HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsa("XCConfigurationList");
+				}
+			WriteAPBXCDEndObject();
+			WriteAPBXCDBeginObject(APBospcLstPrjCnfg, 0,
+				WriteStrConfListPBXProject);
+
+				if (HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsa("XCConfigurationList");
+				}
+
+				WriteAPBXCDBgnObjList("buildConfigurations");
+					WriteAPBXCDobjlistelmp(APBospcPrjCnfg,
+						0, WriteXCDconfigname);
+				WriteAPBXCDEndObjList();
+				WriteAPBXCDDObjAProp_SS(
+					"defaultConfigurationIsVisible", "0");
+				WriteAPBXCDDObjAProp_SP(
+					"defaultConfigurationName", WriteXCDconfigname);
+				if (! HaveAPBXCD_IsaFirst) {
+					WriteAPBXCDDObjAPropIsa("XCConfigurationList");
+				}
+			WriteAPBXCDEndObject();
+		DoEndSectionAPBXCD("XCConfigurationList");
+	}
+
+	--DestFileIndent;
+		WriteDestFileLn("};");
+		WriteBgnDestFileLn();
+		WriteCStrToDestFile("rootObject = ");
+		WriteAPBXCDObjectIdAndComment(APBospcRoot,
+			0, WriteStrProjectObject);
+		WriteCStrToDestFile(";");
+		WriteEndDestFileLn();
+	--DestFileIndent;
+	WriteDestFileLn("}");
+}
+
+LOCALPROC WriteOutDummyLangContents(void)
+{
+	WriteDestFileLn(
+		"This file is here because some archive extraction");
+	WriteDestFileLn("software will not create an empty directory.");
+}
+
+LOCALPROC WriteXCDSpecificFiles(void)
+{
+	MakeSubDirectory("my_proj_d", "my_project_d", vStrAppAbbrev,
+		(ide_vers >= 2100) ? ".xcodeproj" : ".pbproj");
+
+	WriteADstFile1("my_proj_d",
+		"project", ".pbxproj", "project file",
+		WriteXCDProjectFile);
+
+	if (HaveMacBundleApp) {
+		if (HaveAPBXCD_PlistFile) {
+			WritePListData();
+		}
+
+		MakeSubDirectory("my_lang_d", "my_config_d",
+			GetLProjName(gbo_lang), ".lproj");
+
+		WriteADstFile1("my_lang_d",
+			"dummy", ".txt", "Dummy",
+			WriteOutDummyLangContents);
+	}
+
+	if (WantSandbox) {
+		WriteEntitlementsData();
+	}
+}
--- /dev/null
+++ b/setup/mkfile
@@ -1,0 +1,8 @@
+</$objtype/mkfile
+
+CFLAGS=-p -D__plan9__ $CFLAGS
+TARG=setup
+OFILES=tool.$O
+default:V: all
+
+</sys/src/cmd/mkone
--- /dev/null
+++ b/setup/tool.c
@@ -1,0 +1,175 @@
+/*
+	app.c
+	Copyright (C) 2009 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef __plan9__
+#include <u.h>
+#include <libc.h>
+#else
+#include <stdlib.h>
+#include <string.h>
+#endif
+#include <stdio.h>
+
+#include "COREDEFS.i"
+
+#include "CNFGOPTS.i"
+#include "CONFIGUR.i"
+#include "CNFGDLFT.i"
+
+
+#define MyMoveBytes(src, dst, n) \
+	(void) memmove((void *)(dst), (void *)(src), n)
+
+#define kMyErr_noErr 0 /* no error */
+
+#define kMyErrReported 1029
+	/* already notified user, no further report needed */
+#define kMyErrNoMatch 1030
+	/* (so try something else) always should be handled, not reported */
+
+#if NeedSegmenting
+#pragma segment Utilities
+#endif
+
+#include "STRUTILS.i"
+
+#include "CMDARGT1.i"
+
+#include "WRTEXTFL.i"
+
+#if NeedSegmenting
+#pragma segment Body
+#endif
+
+#include "SPBASDEF.i"
+
+#include "GNBLDOPT.i"
+#ifdef Have_SPBLDOPT
+#include "SPBLDOPT.i"
+#endif
+
+#if NeedSegmenting
+#pragma segment Body1
+#endif
+
+#include "BLDUTIL3.i"
+
+#include "DFFILDEF.i"
+#include "SPFILDEF.i"
+
+#if NeedSegmenting
+#pragma segment Body2
+#endif
+
+#include "USFILDEF.i"
+#include "WRMACRES.i"
+#include "WRMPLIST.i"
+#include "WRCNFGGL.i"
+#include "WRCNFGAP.i"
+
+#if NeedSegmenting
+#pragma segment Body3
+#endif
+
+#if gbk_ide_mpw == cur_ide
+#include "WRMPWFLS.i"
+#endif
+
+#if gbk_ide_mw8 == cur_ide
+#include "WRMW8FLS.i"
+#endif
+
+#if gbk_ide_mvc == cur_ide
+#include "WRMVCFLS.i"
+#endif
+
+#if (gbk_ide_bgc == cur_ide) \
+	|| (gbk_ide_cyg == cur_ide) \
+	|| (gbk_ide_mgw == cur_ide) \
+	|| (gbk_ide_dkp == cur_ide) \
+	|| (gbk_ide_dvc == cur_ide) \
+	|| (gbk_ide_xcd == cur_ide)
+#include "WRBGCFLS.i"
+#endif
+
+#if gbk_ide_snc == cur_ide
+#include "WRSNCFLS.i"
+#endif
+
+#if gbk_ide_msv == cur_ide
+#include "WRMSCFLS.i"
+#endif
+
+#if gbk_ide_lcc == cur_ide
+#include "WRLCCFLS.i"
+#endif
+
+#if gbk_ide_dvc == cur_ide
+#include "WRDVCFLS.i"
+#endif
+
+#if gbk_ide_xcd == cur_ide
+#include "WRXCDFLS.i"
+#endif
+
+#if gbk_ide_dmc == cur_ide
+#include "WRDMCFLS.i"
+#endif
+
+#if gbk_ide_plc == cur_ide
+#include "WRPLCFLS.i"
+#endif
+
+#if gbk_ide_ccc == cur_ide || gbk_ide_9pc == cur_ide
+#include "WRCCCFLS.i"
+#endif
+
+#if NeedSegmenting
+#pragma segment Body4
+#endif
+
+#ifdef Have_SPCNFGGL
+#include "SPCNFGGL.i"
+#endif
+#ifdef Have_SPCNFGAP
+#include "SPCNFGAP.i"
+#endif
+#include "SPOTHRCF.i"
+
+#if NeedSegmenting
+#pragma segment Main
+#endif
+
+#include "BLDUTIL4.i"
+
+int main(int argc, char *argv[])
+{
+	tMyErr err;
+	int return_code = 1;
+
+	BeginParseCommandLineArguments(argc, argv);
+
+	err = DoTheCommand();
+
+	if (kMyErr_noErr == err) {
+		return_code = 0;
+	} else {
+		if (kMyErrReported != err) {
+			fprintf(stderr, "Unknown Error in %s", argv[0]);
+		}
+	}
+
+	return return_code;
+}
--- /dev/null
+++ b/src/ACTVCODE.h
@@ -1,0 +1,373 @@
+/*
+	ACTVCODE.h
+
+	Copyright (C) 2009 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	ACTiVation CODE
+*/
+
+LOCALFUNC uimr KeyFun0(uimr x, uimr y, uimr m)
+{
+	uimr r = x + y;
+
+	if ((r >= m) || (r < x)) {
+		r -= m;
+	}
+
+	return r;
+}
+
+LOCALFUNC uimr KeyFun1(uimr x, uimr y, uimr m)
+{
+	uimr r = 0;
+	uimr t = x;
+	uimr s = y;
+
+	while (s > 0) {
+		if (0 != (s & 1)) {
+			r = KeyFun0(r, t, m);
+		}
+		t = KeyFun0(t, t, m);
+		s >>= 1;
+	}
+
+	return r;
+}
+
+LOCALFUNC uimr KeyFun2(uimr x, uimr y, uimr m)
+{
+	uimr r = 1;
+	uimr t = x;
+	uimr s = y;
+
+	while (s > 0) {
+		if (0 != (s & 1)) {
+			r = KeyFun1(r, t, m);
+		}
+		t = KeyFun1(t, t, m);
+		s >>= 1;
+	}
+
+	return r;
+}
+
+LOCALFUNC blnr CheckActvCode(ui3p p, blnr *Trial)
+{
+	blnr IsOk = falseblnr;
+	uimr v0 = do_get_mem_long(p);
+	uimr v1 = do_get_mem_long(p + 4);
+
+	if (v0 > KeyCon2) {
+		/* v0 too big */
+	} else if (v1 > KeyCon4) {
+		/* v1 too big */
+	} else {
+		uimr t0 = KeyFun0(v0, KeyCon0, KeyCon2);
+		uimr t1 = KeyFun2(KeyCon1, t0, KeyCon2);
+		uimr t2 = KeyFun2(v1, KeyCon3, KeyCon4);
+		uimr t3 = KeyFun0(t2, KeyCon4 - t1, KeyCon4);
+		uimr t4 = KeyFun0(t3, KeyCon4 - KeyCon5, KeyCon4);
+		if ((0 == (t4 >> 8)) && (t4 >= KeyCon6)) {
+			*Trial = falseblnr;
+			IsOk = trueblnr;
+		} else if (0 == t4) {
+			*Trial = trueblnr;
+			IsOk = trueblnr;
+		}
+	}
+
+	return IsOk;
+}
+
+/* user interface */
+
+LOCALFUNC blnr Key2Digit(ui3r key, ui3r *r)
+{
+	ui3r v;
+
+	switch (key) {
+		case MKC_0:
+		case MKC_KP0:
+			v = 0;
+			break;
+		case MKC_1:
+		case MKC_KP1:
+			v = 1;
+			break;
+		case MKC_2:
+		case MKC_KP2:
+			v = 2;
+			break;
+		case MKC_3:
+		case MKC_KP3:
+			v = 3;
+			break;
+		case MKC_4:
+		case MKC_KP4:
+			v = 4;
+			break;
+		case MKC_5:
+		case MKC_KP5:
+			v = 5;
+			break;
+		case MKC_6:
+		case MKC_KP6:
+			v = 6;
+			break;
+		case MKC_7:
+		case MKC_KP7:
+			v = 7;
+			break;
+		case MKC_8:
+		case MKC_KP8:
+			v = 8;
+			break;
+		case MKC_9:
+		case MKC_KP9:
+			v = 9;
+			break;
+		default:
+			return falseblnr;
+			break;
+	}
+
+	*r = v;
+	return trueblnr;
+}
+
+#define ActvCodeMaxLen 20
+LOCALVAR ui4r ActvCodeLen = 0;
+LOCALVAR ui3b ActvCodeDigits[ActvCodeMaxLen];
+
+#define ActvCodeFileLen 8
+
+#if UseActvFile
+FORWARDFUNC tMacErr ActvCodeFileSave(ui3p p);
+FORWARDFUNC tMacErr ActvCodeFileLoad(ui3p p);
+#endif
+
+LOCALVAR ui3b CurActvCode[ActvCodeFileLen];
+
+LOCALPROC DoActvCodeModeKey(ui3r key)
+{
+	ui3r digit;
+	ui3r L;
+	int i;
+	blnr Trial;
+
+	if (MKC_BackSpace == key) {
+		if (ActvCodeLen > 0) {
+			--ActvCodeLen;
+			NeedWholeScreenDraw = trueblnr;
+		}
+	} else if (Key2Digit(key, &digit)) {
+		if (ActvCodeLen < (ActvCodeMaxLen - 1)) {
+			ActvCodeDigits[ActvCodeLen] = digit;
+			++ActvCodeLen;
+			NeedWholeScreenDraw = trueblnr;
+			L = ActvCodeDigits[0] + (1 + 9);
+			if (ActvCodeLen == L) {
+				uimr v0 = 0;
+				uimr v1 = 0;
+
+				for (i = 1; i < (ActvCodeDigits[0] + 1); ++i) {
+					v0 = v0 * 10 + ActvCodeDigits[i];
+				}
+				for (; i < ActvCodeLen; ++i) {
+					v1 = v1 * 10 + ActvCodeDigits[i];
+				}
+
+				do_put_mem_long(&CurActvCode[0], v0);
+				do_put_mem_long(&CurActvCode[4], v1);
+
+				if (CheckActvCode(CurActvCode, &Trial)) {
+					SpecialModeClr(SpclModeActvCode);
+					NeedWholeScreenDraw = trueblnr;
+#if UseActvFile
+					if (Trial) {
+						MacMsg(
+							"Using temporary code.",
+							"Thank you for trying Mini vMac!",
+							falseblnr);
+					} else {
+						if (mnvm_noErr != ActvCodeFileSave(CurActvCode))
+						{
+							MacMsg("Oops",
+								"I could not save the activation code"
+								" to disk.",
+								falseblnr);
+						} else {
+							MacMsg("Activation succeeded.",
+								"Thank you!", falseblnr);
+						}
+					}
+#else
+					MacMsg(
+						"Thank you for trying Mini vMac!",
+						"sample variation : ^v",
+						falseblnr);
+#endif
+				}
+			} else if (ActvCodeLen > L) {
+				--ActvCodeLen;
+			}
+		}
+	}
+}
+
+LOCALPROC DrawCellsActvCodeModeBody(void)
+{
+#if UseActvFile
+	DrawCellsOneLineStr("Please enter your activation code:");
+	DrawCellsBlankLine();
+#else
+	DrawCellsOneLineStr(
+		"To try this variation of ^p, please type these numbers:");
+	DrawCellsBlankLine();
+	DrawCellsOneLineStr("281 953 822 340");
+	DrawCellsBlankLine();
+#endif
+
+	if (0 == ActvCodeLen) {
+		DrawCellsOneLineStr("?");
+	} else {
+		int i;
+		ui3r L = ActvCodeDigits[0] + (1 + 9);
+
+		DrawCellsBeginLine();
+		for (i = 0; i < L; ++i) {
+			if (0 == ((L - i) % 3)) {
+				if (0 != i) {
+					DrawCellAdvance(kCellSpace);
+				}
+			}
+			if (i < ActvCodeLen) {
+				DrawCellAdvance(kCellDigit0 + ActvCodeDigits[i]);
+			} else if (i == ActvCodeLen) {
+				DrawCellAdvance(kCellQuestion);
+			} else {
+				DrawCellAdvance(kCellHyphen);
+			}
+		}
+		DrawCellsEndLine();
+		if (L == ActvCodeLen) {
+			DrawCellsBlankLine();
+			DrawCellsOneLineStr(
+				"Sorry, this is not a valid activation code.");
+		}
+	}
+
+#if UseActvFile
+	DrawCellsBlankLine();
+	DrawCellsOneLineStr(
+		"If you haven;}t obtained an activation code yet,"
+		" here is a temporary one:");
+	DrawCellsBlankLine();
+	DrawCellsOneLineStr("281 953 822 340");
+#else
+	DrawCellsBlankLine();
+	DrawCellsOneLineStr(kStrForMoreInfo);
+	DrawCellsOneLineStr("http://www.gryphel.com/c/var/");
+#endif
+}
+
+LOCALPROC DrawActvCodeMode(void)
+{
+	DrawSpclMode0(
+#if UseActvFile
+		"Activation Code",
+#else
+		"sample variation : ^v",
+#endif
+		DrawCellsActvCodeModeBody);
+}
+
+#if UseActvFile
+LOCALPROC ClStrAppendHexLong(int *L0, ui3b *r, ui5r v)
+{
+	ClStrAppendHexWord(L0, r, (v >> 16) & 0xFFFF);
+	ClStrAppendHexWord(L0, r, v & 0xFFFF);
+}
+#endif
+
+LOCALPROC CopyRegistrationStr(void)
+{
+	ui3b ps[ClStrMaxLength];
+	int i;
+	int L;
+	tPbuf j;
+#if UseActvFile
+	int L0;
+	ui5r sum;
+
+	ClStrFromSubstCStr(&L0, ps, "^v ");
+
+	for (i = 0; i < L0; ++i) {
+		ps[i] = Cell2MacAsciiMap[ps[i]];
+	}
+	L = L0;
+
+	sum = 0;
+	for (i = 0; i < L; ++i) {
+		sum += ps[i];
+		sum = (sum << 5) | ((sum >> (32 - 5)) & 0x1F);
+		sum += (sum << 8);
+	}
+
+	sum &= 0x1FFFFFFF;
+
+	sum = KeyFun0(sum, do_get_mem_long(&CurActvCode[0]), KeyCon4);
+
+	ClStrAppendHexLong(&L, ps, sum);
+
+	sum = KeyFun0(sum, do_get_mem_long(&CurActvCode[4]), KeyCon4);
+	sum = KeyFun2(sum, KeyCon3, KeyCon4);
+
+	ClStrAppendHexLong(&L, ps, sum);
+
+	for (i = L0; i < L; ++i) {
+		ps[i] = Cell2MacAsciiMap[ps[i]];
+	}
+#else
+	ClStrFromSubstCStr(&L, ps, "^v");
+
+	for (i = 0; i < L; ++i) {
+		ps[i] = Cell2MacAsciiMap[ps[i]];
+	}
+#endif
+
+	if (mnvm_noErr == PbufNew(L, &j)) {
+		PbufTransfer(ps, j, 0, L, trueblnr);
+		HTCEexport(j);
+	}
+}
+
+LOCALFUNC blnr ActvCodeInit(void)
+{
+#if UseActvFile
+	blnr Trial;
+
+	if ((mnvm_noErr != ActvCodeFileLoad(CurActvCode))
+		|| (! CheckActvCode(CurActvCode, &Trial))
+		|| Trial
+		)
+#endif
+	{
+		SpecialModeSet(SpclModeActvCode);
+		NeedWholeScreenDraw = trueblnr;
+	}
+
+	return trueblnr;
+}
--- /dev/null
+++ b/src/ADBEMDEV.c
@@ -1,0 +1,214 @@
+/*
+	ADBEMDEV.c
+
+	Copyright (C) 2008 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Apple Desktop Bus EMulated DEVice
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+#include "MYOSGLUE.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+#endif
+
+#include "ADBEMDEV.h"
+
+#ifdef _VIA_Debug
+#include <stdio.h>
+#endif
+
+/*
+	ReportAbnormalID unused 0x0C06 - 0x0CFF
+*/
+
+IMPORTPROC ADB_ShiftOutData(ui3b v);
+IMPORTFUNC ui3b ADB_ShiftInData(void);
+
+#include "ADBSHARE.h"
+
+LOCALVAR blnr ADB_ListenDatBuf;
+LOCALVAR ui3b ADB_IndexDatBuf;
+
+GLOBALPROC ADB_DoNewState(void)
+{
+	ui3b state = ADB_st1 * 2 + ADB_st0;
+#ifdef _VIA_Debug
+	fprintf(stderr, "ADB_DoNewState: %d\n", state);
+#endif
+	{
+		ADB_Int = 1;
+		switch (state) {
+			case 0: /* Start a new command */
+				if (ADB_ListenDatBuf) {
+					ADB_ListenDatBuf = falseblnr;
+					ADB_SzDatBuf = ADB_IndexDatBuf;
+					ADB_EndListen();
+				}
+				ADB_TalkDatBuf = falseblnr;
+				ADB_IndexDatBuf = 0;
+				ADB_CurCmd = ADB_ShiftInData();
+					/* which sets interrupt, acknowleding command */
+#ifdef _VIA_Debug
+				fprintf(stderr, "in: %d\n", ADB_CurCmd);
+#endif
+				switch ((ADB_CurCmd >> 2) & 3) {
+					case 0: /* reserved */
+						switch (ADB_CurCmd & 3) {
+							case 0: /* Send Reset */
+								ADB_DoReset();
+								break;
+							case 1: /* Flush */
+								ADB_Flush();
+								break;
+							case 2: /* reserved */
+							case 3: /* reserved */
+								ReportAbnormalID(0x0C01,
+									"Reserved ADB command");
+								break;
+						}
+						break;
+					case 1: /* reserved */
+						ReportAbnormalID(0x0C02,
+							"Reserved ADB command");
+						break;
+					case 2: /* listen */
+						ADB_ListenDatBuf = trueblnr;
+#ifdef _VIA_Debug
+						fprintf(stderr, "*** listening\n");
+#endif
+						break;
+					case 3: /* talk */
+						ADB_DoTalk();
+						break;
+				}
+				break;
+			case 1: /* Transfer date byte (even) */
+			case 2: /* Transfer date byte (odd) */
+				if (! ADB_ListenDatBuf) {
+					/*
+						will get here even if no pending talk data,
+						when there is pending event from device
+						other than the one polled by the last talk
+						command. this probably indicates a bug.
+					*/
+					if ((! ADB_TalkDatBuf)
+						|| (ADB_IndexDatBuf >= ADB_SzDatBuf))
+					{
+						ADB_ShiftOutData(0xFF);
+						ADB_Data = 1;
+						ADB_Int = 0;
+					} else {
+#ifdef _VIA_Debug
+						fprintf(stderr, "*** talk one\n");
+#endif
+						ADB_ShiftOutData(ADB_DatBuf[ADB_IndexDatBuf]);
+						ADB_Data = 1;
+						ADB_IndexDatBuf += 1;
+					}
+				} else {
+					if (ADB_IndexDatBuf >= ADB_MaxSzDatBuf) {
+						ReportAbnormalID(0x0C03, "ADB listen too much");
+							/* ADB_MaxSzDatBuf isn't big enough */
+						(void) ADB_ShiftInData();
+					} else {
+#ifdef _VIA_Debug
+						fprintf(stderr, "*** listen one\n");
+#endif
+						ADB_DatBuf[ADB_IndexDatBuf] = ADB_ShiftInData();
+						ADB_IndexDatBuf += 1;
+					}
+				}
+				break;
+			case 3: /* idle */
+				if (ADB_ListenDatBuf) {
+					ReportAbnormalID(0x0C04, "ADB idle follows listen");
+					/* apparently doesn't happen */
+				}
+				if (ADB_TalkDatBuf) {
+					if (ADB_IndexDatBuf != 0) {
+						ReportAbnormalID(0x0C05,
+							"idle when not done talking");
+					}
+					ADB_ShiftOutData(0xFF);
+					/* ADB_Int = 0; */
+				} else if (CheckForADBanyEvt()) {
+					if (((ADB_CurCmd >> 2) & 3) == 3) {
+						ADB_DoTalk();
+					}
+					ADB_ShiftOutData(0xFF);
+					/* ADB_Int = 0; */
+				}
+				break;
+		}
+	}
+}
+
+GLOBALPROC ADBstate_ChangeNtfy(void)
+{
+#ifdef _VIA_Debug
+	fprintf(stderr, "ADBstate_ChangeNtfy: %d, %d, %d\n",
+		ADB_st1, ADB_st0, GetCuriCount());
+#endif
+	ICT_add(kICT_ADB_NewState,
+		348160UL * kCycleScale / 64 * kMyClockMult);
+		/*
+			Macintosh Family Hardware Reference say device "must respond
+			to talk command within 260 microseconds", which translates
+			to about 190 instructions. But haven't seen much problems
+			even for very large values (tens of thousands), and do see
+			problems for small values. 50 is definitely too small,
+			mouse doesn't move smoothly. There may still be some
+			signs of this problem with 150.
+
+			On the other hand, how fast the device must respond may
+			not be related to how fast the ADB transceiver responds.
+		*/
+}
+
+GLOBALPROC ADB_DataLineChngNtfy(void)
+{
+#ifdef _VIA_Debug
+	fprintf(stderr, "ADB_DataLineChngNtfy: %d\n", ADB_Data);
+#endif
+}
+
+GLOBALPROC ADB_Update(void)
+{
+	ui3b state = ADB_st1 * 2 + ADB_st0;
+
+	if (state == 3) { /* idle */
+		if (ADB_TalkDatBuf) {
+			/* ignore, presumably being taken care of */
+		} else if (CheckForADBanyEvt())
+		{
+			if (((ADB_CurCmd >> 2) & 3) == 3) {
+				ADB_DoTalk();
+			}
+			ADB_ShiftOutData(0xFF);
+				/*
+					Wouldn't expect this would be needed unless
+					there is actually talk data. But without it,
+					ADB never polls the other devices. Clearing
+					ADB_Int has no effect.
+				*/
+			/*
+				ADB_Int = 0;
+				seems to have no effect, which probably indicates a bug
+			*/
+		}
+	}
+}
--- /dev/null
+++ b/src/ADBEMDEV.h
@@ -1,0 +1,27 @@
+/*
+	ADBEMDEV.h
+
+	Copyright (C) 2008 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef ADBEMDEV_H
+#error "header already included"
+#else
+#define ADBEMDEV_H
+#endif
+
+
+EXPORTPROC ADBstate_ChangeNtfy(void);
+EXPORTPROC ADB_DoNewState(void);
+EXPORTPROC ADB_DataLineChngNtfy(void);
+EXPORTPROC ADB_Update(void);
--- /dev/null
+++ b/src/ADBSHARE.h
@@ -1,0 +1,290 @@
+/*
+	ADBSHARE.h
+
+	Copyright (C) 2008 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Apple Desktop Bus SHAREd code
+	shared by emulation of different implementations of ADB
+*/
+
+#ifdef ADBSHARE_H
+#error "header already included"
+#else
+#define ADBSHARE_H
+#endif
+
+
+/*
+	ReportAbnormalID unused 0x0D08 - 0x0DFF
+*/
+
+#define ADB_MaxSzDatBuf 8
+
+LOCALVAR ui3b ADB_SzDatBuf;
+LOCALVAR blnr ADB_TalkDatBuf = falseblnr;
+LOCALVAR ui3b ADB_DatBuf[ADB_MaxSzDatBuf];
+LOCALVAR ui3b ADB_CurCmd = 0;
+LOCALVAR ui3b NotSoRandAddr = 1;
+
+LOCALVAR ui3b MouseADBAddress;
+LOCALVAR blnr SavedCurMouseButton = falseblnr;
+LOCALVAR ui4r MouseADBDeltaH = 0;
+LOCALVAR ui4r MouseADBDeltaV = 0;
+
+LOCALPROC ADB_DoMouseTalk(void)
+{
+	switch (ADB_CurCmd & 3) {
+		case 0:
+			{
+				MyEvtQEl *p;
+				ui4b partH;
+				ui4b partV;
+				blnr overflow = falseblnr;
+				blnr MouseButtonChange = falseblnr;
+
+				if (nullpr != (p = MyEvtQOutP())) {
+					if (MyEvtQElKindMouseDelta == p->kind) {
+						MouseADBDeltaH += p->u.pos.h;
+						MouseADBDeltaV += p->u.pos.v;
+						MyEvtQOutDone();
+					}
+				}
+				partH = MouseADBDeltaH;
+				partV = MouseADBDeltaV;
+
+				if ((si4b)MouseADBDeltaH < 0) {
+					partH = - partH;
+				}
+				if ((si4b)MouseADBDeltaV < 0) {
+					partV = - partV;
+				}
+				if ((partH >> 6) > 0) {
+					overflow = trueblnr;
+					partH = (1 << 6) - 1;
+				}
+				if ((partV >> 6) > 0) {
+					overflow = trueblnr;
+					partV = (1 << 6) - 1;
+				}
+				if ((si4b)MouseADBDeltaH < 0) {
+					partH = - partH;
+				}
+				if ((si4b)MouseADBDeltaV < 0) {
+					partV = - partV;
+				}
+				MouseADBDeltaH -= partH;
+				MouseADBDeltaV -= partV;
+				if (! overflow) {
+					if (nullpr != (p = MyEvtQOutP())) {
+						if (MyEvtQElKindMouseButton == p->kind) {
+							SavedCurMouseButton = p->u.press.down;
+							MouseButtonChange = trueblnr;
+							MyEvtQOutDone();
+						}
+					}
+				}
+				if ((0 != partH) || (0 != partV) || MouseButtonChange) {
+					ADB_SzDatBuf = 2;
+					ADB_TalkDatBuf = trueblnr;
+					ADB_DatBuf[0] = (SavedCurMouseButton ? 0x00 : 0x80)
+						| (partV & 127);
+					ADB_DatBuf[1] = /* 0x00 */ 0x80 | (partH & 127);
+				}
+			}
+			ADBMouseDisabled = 0;
+			break;
+		case 3:
+			ADB_SzDatBuf = 2;
+			ADB_TalkDatBuf = trueblnr;
+			ADB_DatBuf[0] = 0x60 | (NotSoRandAddr & 0x0f);
+			ADB_DatBuf[1] = 0x01;
+			NotSoRandAddr += 1;
+			break;
+		default:
+			ReportAbnormalID(0x0D01, "Talk to unknown mouse register");
+			break;
+	}
+}
+
+LOCALPROC ADB_DoMouseListen(void)
+{
+	switch (ADB_CurCmd & 3) {
+		case 3:
+			if (ADB_DatBuf[1] == 0xFE) {
+				/* change address */
+				MouseADBAddress = (ADB_DatBuf[0] & 0x0F);
+			} else {
+				ReportAbnormalID(0x0D02,
+					"unknown listen op to mouse register 3");
+			}
+			break;
+		default:
+			ReportAbnormalID(0x0D03,
+				"listen to unknown mouse register");
+			break;
+	}
+}
+
+LOCALVAR ui3b KeyboardADBAddress;
+
+LOCALFUNC blnr CheckForADBkeyEvt(ui3b *NextADBkeyevt)
+{
+	int i;
+	blnr KeyDown;
+
+	if (! FindKeyEvent(&i, &KeyDown)) {
+		return falseblnr;
+	} else {
+#if dbglog_HAVE && 0
+		if (KeyDown) {
+			dbglog_WriteNote("Got a KeyDown");
+		}
+#endif
+		switch (i) {
+			case MKC_Control:
+				i = 0x36;
+				break;
+			case MKC_Left:
+				i = 0x3B;
+				break;
+			case MKC_Right:
+				i = 0x3C;
+				break;
+			case MKC_Down:
+				i = 0x3D;
+				break;
+			case MKC_Up:
+				i = 0x3E;
+				break;
+			default:
+				/* unchanged */
+				break;
+		}
+		*NextADBkeyevt = (KeyDown ? 0x00 : 0x80) | i;
+		return trueblnr;
+	}
+}
+
+LOCALPROC ADB_DoKeyboardTalk(void)
+{
+	switch (ADB_CurCmd & 3) {
+		case 0:
+			{
+				ui3b NextADBkeyevt;
+
+				if (CheckForADBkeyEvt(&NextADBkeyevt)) {
+					ADB_SzDatBuf = 2;
+					ADB_TalkDatBuf = trueblnr;
+					ADB_DatBuf[0] = NextADBkeyevt;
+					if (! CheckForADBkeyEvt(&NextADBkeyevt)) {
+						ADB_DatBuf[1] = 0xFF;
+					} else {
+						ADB_DatBuf[1] = NextADBkeyevt;
+					}
+				}
+			}
+			break;
+		case 3:
+			ADB_SzDatBuf = 2;
+			ADB_TalkDatBuf = trueblnr;
+			ADB_DatBuf[0] = 0x60 | (NotSoRandAddr & 0x0f);
+			ADB_DatBuf[1] = 0x01;
+			NotSoRandAddr += 1;
+			break;
+		default:
+			ReportAbnormalID(0x0D04,
+				"Talk to unknown keyboard register");
+			break;
+	}
+}
+
+LOCALPROC ADB_DoKeyboardListen(void)
+{
+	switch (ADB_CurCmd & 3) {
+		case 3:
+			if (ADB_DatBuf[1] == 0xFE) {
+				/* change address */
+				KeyboardADBAddress = (ADB_DatBuf[0] & 0x0F);
+			} else {
+				ReportAbnormalID(0x0D05,
+					"unknown listen op to keyboard register 3");
+			}
+			break;
+		default:
+			ReportAbnormalID(0x0D06,
+				"listen to unknown keyboard register");
+			break;
+	}
+}
+
+LOCALFUNC blnr CheckForADBanyEvt(void)
+{
+	MyEvtQEl *p = MyEvtQOutP();
+	if (nullpr != p) {
+		switch (p->kind) {
+			case MyEvtQElKindMouseButton:
+			case MyEvtQElKindMouseDelta:
+			case MyEvtQElKindKey:
+				return trueblnr;
+				break;
+			default:
+				break;
+		}
+	}
+
+	return (0 != MouseADBDeltaH) && (0 != MouseADBDeltaV);
+}
+
+LOCALPROC ADB_DoTalk(void)
+{
+	ui3b Address = ADB_CurCmd >> 4;
+	if (Address == MouseADBAddress) {
+		ADB_DoMouseTalk();
+	} else if (Address == KeyboardADBAddress) {
+		ADB_DoKeyboardTalk();
+	}
+}
+
+LOCALPROC ADB_EndListen(void)
+{
+	ui3b Address = ADB_CurCmd >> 4;
+	if (Address == MouseADBAddress) {
+		ADB_DoMouseListen();
+	} else if (Address == KeyboardADBAddress) {
+		ADB_DoKeyboardListen();
+	}
+}
+
+LOCALPROC ADB_DoReset(void)
+{
+	MouseADBAddress = 3;
+	KeyboardADBAddress = 2;
+}
+
+LOCALPROC ADB_Flush(void)
+{
+	ui3b Address = ADB_CurCmd >> 4;
+
+	if ((Address == KeyboardADBAddress)
+		|| (Address == MouseADBAddress))
+	{
+		ADB_SzDatBuf = 2;
+		ADB_TalkDatBuf = trueblnr;
+		ADB_DatBuf[0] = 0x00;
+		ADB_DatBuf[1] = 0x00;
+	} else {
+		ReportAbnormalID(0x0D07, "Unhandled ADB Flush");
+	}
+}
--- /dev/null
+++ b/src/ALTKEYSM.h
@@ -1,0 +1,209 @@
+/*
+	ALTKEYSM.h
+
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	ALTernate KEYs Mode
+*/
+
+#ifdef ALTKEYSM_H
+#error "header already included"
+#else
+#define ALTKEYSM_H
+#endif
+
+LOCALVAR blnr AltKeysLockText = falseblnr;
+LOCALVAR blnr AltKeysTrueCmnd = falseblnr;
+LOCALVAR blnr AltKeysTrueOption = falseblnr;
+LOCALVAR blnr AltKeysTrueShift = falseblnr;
+LOCALVAR blnr AltKeysModOn = falseblnr;
+LOCALVAR blnr AltKeysTextOn = falseblnr;
+
+LOCALPROC CheckAltKeyUseMode(void)
+{
+	blnr NewAltKeysTextOn;
+
+	AltKeysModOn = AltKeysTrueCmnd
+		|| AltKeysTrueOption || AltKeysTrueShift;
+	NewAltKeysTextOn = AltKeysLockText || AltKeysModOn;
+	if (NewAltKeysTextOn != AltKeysTextOn) {
+		DisconnectKeyCodes(kKeepMaskControl | kKeepMaskCapsLock
+			| (AltKeysTrueCmnd ? kKeepMaskCommand : 0)
+			| (AltKeysTrueOption ? kKeepMaskOption : 0)
+			| (AltKeysTrueShift ? kKeepMaskShift : 0));
+		AltKeysTextOn = NewAltKeysTextOn;
+	}
+}
+
+LOCALPROC Keyboard_UpdateKeyMap1(ui3r key, blnr down)
+{
+	if (MKC_Command == key) {
+		AltKeysTrueCmnd = down;
+		CheckAltKeyUseMode();
+		Keyboard_UpdateKeyMap(key, down);
+	} else if (MKC_Option == key) {
+		AltKeysTrueOption = down;
+		CheckAltKeyUseMode();
+		Keyboard_UpdateKeyMap(key, down);
+	} else if (MKC_Shift == key) {
+		AltKeysTrueShift = down;
+		CheckAltKeyUseMode();
+		Keyboard_UpdateKeyMap(key, down);
+	} else if (MKC_SemiColon == key) {
+		if (down && ! AltKeysModOn) {
+			if (AltKeysLockText) {
+				AltKeysLockText = falseblnr;
+				NeedWholeScreenDraw = trueblnr;
+				SpecialModeClr(SpclModeAltKeyText);
+
+				CheckAltKeyUseMode();
+			}
+		} else {
+			Keyboard_UpdateKeyMap(key, down);
+		}
+	} else if (AltKeysTextOn) {
+		Keyboard_UpdateKeyMap(key, down);
+	} else if (MKC_M == key) {
+		if (down) {
+			if (! AltKeysLockText) {
+				AltKeysLockText = trueblnr;
+				SpecialModeSet(SpclModeAltKeyText);
+				NeedWholeScreenDraw = trueblnr;
+				CheckAltKeyUseMode();
+			}
+		}
+	} else {
+		switch (key) {
+			case MKC_A:
+				key = MKC_SemiColon;
+				break;
+			case MKC_B:
+				key = MKC_BackSlash;
+				break;
+			case MKC_C:
+				key = MKC_F3;
+				break;
+			case MKC_D:
+				key = MKC_Option;
+				break;
+			case MKC_E:
+				key = MKC_BackSpace;
+				break;
+			case MKC_F:
+				key = MKC_Command;
+				break;
+			case MKC_G:
+				key = MKC_Enter;
+				break;
+			case MKC_H:
+				key = MKC_Equal;
+				break;
+			case MKC_I:
+				key = MKC_Up;
+				break;
+			case MKC_J:
+				key = MKC_Left;
+				break;
+			case MKC_K:
+				key = MKC_Down;
+				break;
+			case MKC_L:
+				key = MKC_Right;
+				break;
+			case MKC_M:
+				/* handled above */
+				break;
+			case MKC_N:
+				key = MKC_Minus;
+				break;
+			case MKC_O:
+				key = MKC_RightBracket;
+				break;
+			case MKC_P:
+				return; /* none */
+				break;
+			case MKC_Q:
+				key = MKC_Grave;
+				break;
+			case MKC_R:
+				key = MKC_Return;
+				break;
+			case MKC_S:
+				key = MKC_Shift;
+				break;
+			case MKC_T:
+				key = MKC_Tab;
+				break;
+			case MKC_U:
+				key = MKC_LeftBracket;
+				break;
+			case MKC_V:
+				key = MKC_F4;
+				break;
+			case MKC_W:
+				return; /* none */
+				break;
+			case MKC_X:
+				key = MKC_F2;
+				break;
+			case MKC_Y:
+				key = MKC_Escape;
+				break;
+			case MKC_Z:
+				key = MKC_F1;
+				break;
+			default:
+				break;
+		}
+		Keyboard_UpdateKeyMap(key, down);
+	}
+}
+
+LOCALPROC DisconnectKeyCodes1(ui5b KeepMask)
+{
+	DisconnectKeyCodes(KeepMask);
+
+	if (! (0 != (KeepMask & kKeepMaskCommand))) {
+		AltKeysTrueCmnd = falseblnr;
+	}
+	if (! (0 != (KeepMask & kKeepMaskOption))) {
+		AltKeysTrueOption = falseblnr;
+	}
+	if (! (0 != (KeepMask & kKeepMaskShift))) {
+		AltKeysTrueShift = falseblnr;
+	}
+	AltKeysModOn = AltKeysTrueCmnd
+		|| AltKeysTrueOption || AltKeysTrueShift;
+	AltKeysTextOn = AltKeysLockText || AltKeysModOn;
+}
+
+LOCALPROC DrawAltKeyMode(void)
+{
+	int i;
+
+	CurCellv0 = ControlBoxv0;
+	CurCellh0 = ControlBoxh0;
+
+	DrawCellAdvance(kInsertText00);
+	for (i = (ControlBoxw - 4) / 2; --i >= 0; ) {
+		DrawCellAdvance(kInsertText04);
+	}
+	DrawCellAdvance(kInsertText01);
+	DrawCellAdvance(kInsertText02);
+	for (i = (ControlBoxw - 4) / 2; --i >= 0; ) {
+		DrawCellAdvance(kInsertText04);
+	}
+	DrawCellAdvance(kInsertText03);
+}
--- /dev/null
+++ b/src/ASCEMDEV.c
@@ -1,0 +1,868 @@
+/*
+	ASCEMDEV.c
+
+	Copyright (C) 2008 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Apple Sound Chip EMulated DEVice
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+#include "ENDIANAC.h"
+#include "MYOSGLUE.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+#include "VIAEMDEV.h"
+#endif
+
+#include "ASCEMDEV.h"
+
+/*
+	ReportAbnormalID unused 0x0F0E, 0x0F1E - 0x0FFF
+*/
+
+LOCALVAR ui3r SoundReg801 = 0;
+LOCALVAR ui3r SoundReg802 = 0;
+LOCALVAR ui3r SoundReg803 = 0;
+LOCALVAR ui3r SoundReg804 = 0;
+LOCALVAR ui3r SoundReg805 = 0;
+LOCALVAR ui3r SoundReg_Volume = 0; /* 0x806 */
+/* LOCALVAR ui3r SoundReg807 = 0; */
+
+LOCALVAR ui3b ASC_SampBuff[0x800];
+
+struct ASC_ChanR {
+	ui3b freq[4];
+	ui3b phase[4];
+};
+typedef struct ASC_ChanR ASC_ChanR;
+
+LOCALVAR ASC_ChanR ASC_ChanA[4];
+
+LOCALVAR ui4b ASC_FIFO_Out = 0;
+LOCALVAR ui4b ASC_FIFO_InA = 0;
+LOCALVAR ui4b ASC_FIFO_InB = 0;
+LOCALVAR blnr ASC_Playing = falseblnr;
+
+#define ASC_dolog (dbglog_HAVE && 0)
+
+#ifdef ASC_interrupt_PulseNtfy
+IMPORTPROC ASC_interrupt_PulseNtfy(void);
+#endif
+
+LOCALPROC ASC_RecalcStatus(void)
+{
+	if ((1 == SoundReg801) && ASC_Playing) {
+		if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) {
+			SoundReg804 &= ~ 0x01;
+		} else {
+			SoundReg804 |= 0x01;
+		}
+		if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x400) {
+			SoundReg804 |= 0x02;
+		} else {
+			SoundReg804 &= ~ 0x02;
+		}
+		if (0 != (SoundReg802 & 2)) {
+			if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x200) {
+				SoundReg804 &= ~ 0x04;
+			} else {
+				SoundReg804 |= 0x04;
+			}
+			if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x400) {
+				SoundReg804 |= 0x08;
+			} else {
+				SoundReg804 &= ~ 0x08;
+			}
+		}
+	}
+}
+
+LOCALPROC ASC_ClearFIFO(void)
+{
+	ASC_FIFO_Out = 0;
+	ASC_FIFO_InA = 0;
+	ASC_FIFO_InB = 0;
+	ASC_Playing = falseblnr;
+	ASC_RecalcStatus();
+}
+
+GLOBALFUNC ui5b ASC_Access(ui5b Data, blnr WriteMem, CPTR addr)
+{
+	if (addr < 0x800) {
+		if (WriteMem) {
+			if (1 == SoundReg801) {
+				if (0 == (addr & 0x400)) {
+					if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x400)
+					{
+#if 0 /* seems to happen in tetris */
+						ReportAbnormalID(0x0F01,
+							"ASC - Channel A Overflow");
+#endif
+						SoundReg804 |= 0x02;
+					} else {
+
+					ASC_SampBuff[ASC_FIFO_InA & 0x3FF] = Data;
+
+					++ASC_FIFO_InA;
+					if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200)
+					{
+						if (0 != (SoundReg804 & 0x01)) {
+							/* happens normally */
+							SoundReg804 &= ~ 0x01;
+						}
+					} else {
+#if 0 /* doesn't seem to be necessary, but doesn't hurt either */
+						SoundReg804 |= 0x01;
+#endif
+					}
+					if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x400)
+					{
+						SoundReg804 |= 0x02;
+#if ASC_dolog
+						dbglog_WriteNote("ASC : setting full flag A");
+#endif
+					} else {
+						if (0 != (SoundReg804 & 0x02)) {
+							ReportAbnormalID(0x0F02, "ASC_Access : "
+								"full flag A not already clear");
+							SoundReg804 &= ~ 0x02;
+						}
+					}
+
+					}
+				} else {
+					if (0 == (SoundReg802 & 2)) {
+						ReportAbnormalID(0x0F03,
+							"ASC - Channel B for Mono");
+					}
+					if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x400)
+					{
+						ReportAbnormalID(0x0F04,
+							"ASC - Channel B Overflow");
+						SoundReg804 |= 0x08;
+					} else {
+
+					ASC_SampBuff[0x400 + (ASC_FIFO_InB & 0x3FF)] = Data;
+
+					++ASC_FIFO_InB;
+					if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x200)
+					{
+						if (0 != (SoundReg804 & 0x04)) {
+							/* happens normally */
+							SoundReg804 &= ~ 0x04;
+						}
+					} else {
+#if 0 /* doesn't seem to be necessary, but doesn't hurt either */
+						SoundReg804 |= 0x04;
+#endif
+					}
+					if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x400)
+					{
+						SoundReg804 |= 0x08;
+#if ASC_dolog
+						dbglog_WriteNote("ASC : setting full flag B");
+#endif
+					} else {
+						if (0 != (SoundReg804 & 0x08)) {
+							ReportAbnormalID(0x0F05, "ASC_Access : "
+								"full flag B not already clear");
+							SoundReg804 &= ~ 0x08;
+						}
+					}
+
+					}
+				}
+#if ASC_dolog && 0
+				dbglog_writeCStr("ASC_InputIndex =");
+				dbglog_writeNum(ASC_InputIndex);
+				dbglog_writeReturn();
+#endif
+			} else {
+				ASC_SampBuff[addr] = Data;
+			}
+		} else {
+			Data = ASC_SampBuff[addr];
+		}
+
+#if ASC_dolog && 1
+#if 0
+		if (((addr & 0x1FF) >= 0x04)
+			&& ((addr & 0x1FF) < (0x200 - 0x04)))
+		{
+			/* don't report them all */
+		} else
+#endif
+		{
+			dbglog_AddrAccess("ASC_Access SampBuff",
+				Data, WriteMem, addr);
+		}
+#endif
+	} else if (addr < 0x810) {
+		switch (addr) {
+			case 0x800: /* VERSION */
+				if (WriteMem) {
+					ReportAbnormalID(0x0F06, "ASC - writing VERSION");
+				} else {
+					Data = 0;
+				}
+#if ASC_dolog && 1
+				dbglog_AddrAccess("ASC_Access Control (VERSION)",
+					Data, WriteMem, addr);
+#endif
+				break;
+			case 0x801: /* ENABLE */
+				if (WriteMem) {
+					if (1 == Data) {
+						if (1 != SoundReg801) {
+							ASC_ClearFIFO();
+						}
+					} else {
+						if (Data > 2) {
+							ReportAbnormalID(0x0F07,
+								"ASC - unexpected ENABLE");
+						}
+					}
+					SoundReg801 = Data;
+				} else {
+					Data = SoundReg801;
+					/* happens in LodeRunner */
+				}
+#if ASC_dolog && 1
+				dbglog_AddrAccess("ASC_Access Control (ENABLE)",
+					Data, WriteMem, addr);
+#endif
+				break;
+			case 0x802: /* CONTROL */
+				if (WriteMem) {
+#if 1
+					if (0 != SoundReg801) {
+						if (SoundReg802 == Data) {
+							/*
+								this happens normally,
+								such as in Lunar Phantom
+							*/
+						} else {
+							if (1 == SoundReg801) {
+/*
+	happens in dark castle, if play other sound first,
+	such as by changing beep sound in sound control panel.
+*/
+								ASC_ClearFIFO();
+							}
+
+#if 0
+							ReportAbnormalID(0x0F08,
+								"ASC - changing CONTROL while ENABLEd");
+#endif
+						}
+					}
+#endif
+					if (0 != (Data & ~ 2)) {
+						ReportAbnormalID(0x0F09,
+							"ASC - unexpected CONTROL value");
+					}
+					SoundReg802 = Data;
+				} else {
+					Data = SoundReg802;
+					ReportAbnormalID(0x0F0A,
+						"ASC - reading CONTROL value");
+				}
+#if ASC_dolog && 1
+				dbglog_AddrAccess("ASC_Access Control (CONTROL)",
+					Data, WriteMem, addr);
+#endif
+				break;
+			case 0x803:
+				if (WriteMem) {
+					if (0 != (Data & ~ 0x80)) {
+						ReportAbnormalID(0x0F0B,
+							"ASC - unexpected FIFO MODE");
+					}
+					if (0 != (Data & 0x80)) {
+						if (0 != (SoundReg803 & 0x80)) {
+							ReportAbnormalID(0x0F0C,
+								"ASC - set clear FIFO again");
+						} else
+						if (1 != SoundReg801) {
+#if 0 /* happens in system 6, such as with Lunar Phantom */
+							ReportAbnormalID(0x0F0D,
+								"ASC - clear FIFO when not FIFO mode");
+#endif
+						} else
+						{
+							ASC_ClearFIFO();
+							/*
+								ASC_interrupt_PulseNtfy();
+									Doesn't seem to be needed,
+									but doesn't hurt either.
+							*/
+						}
+					}
+					SoundReg803 = Data;
+				} else {
+					Data = SoundReg803;
+				}
+#if ASC_dolog && 1
+				dbglog_AddrAccess("ASC_Access Control (FIFO MODE)",
+					Data, WriteMem, addr);
+#endif
+				break;
+			case 0x804:
+				if (WriteMem) {
+#if 0
+					if ((0 != SoundReg804) && (0 != Data)) {
+						ReportAbnormalID(0x0F0F,
+							"ASC - set FIFO IRQ STATUS when not 0");
+					}
+#endif
+					SoundReg804 = Data;
+					if (0 != SoundReg804) {
+						ASC_interrupt_PulseNtfy();
+						/*
+							Generating this interrupt seems
+							to be the point of writing to
+							this register.
+						*/
+					}
+#if ASC_dolog && 1
+					dbglog_AddrAccess(
+						"ASC_Access Control (FIFO IRQ STATUS)",
+						Data, WriteMem, addr);
+#endif
+				} else {
+					Data = SoundReg804;
+#if 0
+					if (1 != SoundReg801) {
+						/* no, ok, part of normal interrupt handling */
+						ReportAbnormalID(0x0F10,
+							"ASC - read STATUS when not FIFO");
+					}
+#endif
+					/* SoundReg804 = 0; */
+					SoundReg804 &= ~ 0x01;
+					SoundReg804 &= ~ 0x04;
+						/*
+							In lunar phantom, observe checking
+							full flag before first write, but
+							status was read previous.
+						*/
+#if ASC_dolog && 1
+#if 0
+					if (0 != Data)
+#endif
+					{
+						dbglog_AddrAccess(
+							"ASC_Access Control (FIFO IRQ STATUS)",
+							Data, WriteMem, addr);
+					}
+#endif
+				}
+				break;
+			case 0x805:
+				if (WriteMem) {
+					SoundReg805 = Data;
+					/* cleared in LodeRunner */
+				} else {
+					Data = SoundReg805;
+					ReportAbnormalID(0x0F11,
+						"ASC - reading WAVE CONTROL register");
+				}
+#if ASC_dolog && 1
+				dbglog_AddrAccess("ASC_Access Control (WAVE CONTROL)",
+					Data, WriteMem, addr);
+#endif
+				break;
+			case 0x806: /* VOLUME */
+				if (WriteMem) {
+					SoundReg_Volume = Data >> 5;
+					if (0 != (Data & 0x1F)) {
+						ReportAbnormalID(0x0F12,
+							"ASC - unexpected volume value");
+					}
+				} else {
+					Data = SoundReg_Volume << 5;
+					ReportAbnormalID(0x0F13,
+						"ASC - reading volume register");
+				}
+#if ASC_dolog && 1
+				dbglog_AddrAccess("ASC_Access Control (VOLUME)",
+					Data, WriteMem, addr);
+#endif
+				break;
+			case 0x807: /* CLOCK RATE */
+				if (WriteMem) {
+					/* SoundReg807 = Data; */
+					if (0 != Data) {
+						ReportAbnormalID(0x0F14,
+							"ASC - nonstandard CLOCK RATE");
+					}
+				} else {
+					/* Data = SoundReg807; */
+					ReportAbnormalID(0x0F15,
+						"ASC - reading CLOCK RATE");
+				}
+#if ASC_dolog && 1
+				dbglog_AddrAccess("ASC_Access Control (CLOCK RATE)",
+					Data, WriteMem, addr);
+#endif
+				break;
+			case 0x808: /* CONTROL */
+				if (WriteMem) {
+					ReportAbnormalID(0x0F16, "ASC - write to 808");
+				} else {
+					/* happens on boot System 7.5.5 */
+					Data = 0;
+				}
+#if ASC_dolog && 1
+				dbglog_AddrAccess("ASC_Access Control (CONTROL)",
+					Data, WriteMem, addr);
+#endif
+				break;
+			case 0x80A: /* ? */
+				if (WriteMem) {
+					ReportAbnormalID(0x0F17, "ASC - write to 80A");
+				} else {
+					/*
+						happens in system 6, Lunar Phantom,
+							soon after new game.
+					*/
+					Data = 0;
+				}
+#if ASC_dolog && 1
+				dbglog_AddrAccess("ASC_Access Control (80A)",
+					Data, WriteMem, addr);
+#endif
+				break;
+			default:
+				if (WriteMem) {
+				} else {
+					Data = 0;
+				}
+				ReportAbnormalID(0x0F18, "ASC - unknown ASC reg");
+#if ASC_dolog && 1
+				dbglog_AddrAccess("ASC_Access Control (?)",
+					Data, WriteMem, addr);
+#endif
+				break;
+		}
+	} else if (addr < 0x830) {
+		ui3r b = addr & 3;
+		ui3r chan = ((addr - 0x810) >> 3) & 3;
+
+		if (0 != (addr & 4)) {
+
+			if (WriteMem) {
+				ASC_ChanA[chan].freq[b] = Data;
+			} else {
+				Data = ASC_ChanA[chan].freq[b];
+			}
+#if ASC_dolog && 1
+			dbglog_AddrAccess("ASC_Access Control (frequency)",
+				Data, WriteMem, addr);
+#endif
+#if ASC_dolog && 0
+			dbglog_writeCStr("freq b=");
+			dbglog_writeNum(WriteMem);
+			dbglog_writeCStr(", chan=");
+			dbglog_writeNum(chan);
+			dbglog_writeReturn();
+#endif
+		} else {
+
+			if (WriteMem) {
+				ASC_ChanA[chan].phase[b] = Data;
+			} else {
+				Data = ASC_ChanA[chan].phase[b];
+			}
+#if ASC_dolog && 1
+			dbglog_AddrAccess("ASC_Access Control (phase)",
+				Data, WriteMem, addr);
+#endif
+		}
+	} else if (addr < 0x838) {
+#if ASC_dolog && 1
+		dbglog_AddrAccess("ASC_Access Control *** unknown reg",
+			Data, WriteMem, addr);
+#endif
+	} else {
+#if ASC_dolog && 1
+		dbglog_AddrAccess("ASC_Access Control ? *** unknown reg",
+			Data, WriteMem, addr);
+#endif
+
+		ReportAbnormalID(0x0F19, "unknown ASC reg");
+	}
+
+	return Data;
+}
+
+/*
+	approximate volume levels of vMac, so:
+
+	x * vol_mult[SoundVolume] >> 16
+		+ vol_offset[SoundVolume]
+	= {approx} (x - kCenterSound) / (8 - SoundVolume) + kCenterSound;
+*/
+
+LOCALVAR const ui4b vol_mult[] = {
+	8192, 9362, 10922, 13107, 16384, 21845, 32768
+};
+
+LOCALVAR const trSoundSamp vol_offset[] = {
+#if 3 == kLn2SoundSampSz
+	112, 110, 107, 103, 96, 86, 64, 0
+#elif 4 == kLn2SoundSampSz
+	28672, 28087, 27307, 26215, 24576, 21846, 16384, 0
+#else
+#error "unsupported kLn2SoundSampSz"
+#endif
+};
+
+LOCALVAR const ui3r SubTick_n[kNumSubTicks] = {
+	23,  23,  23,  23,  23,  23,  23,  24,
+	23,  23,  23,  23,  23,  23,  23,  24
+};
+
+GLOBALPROC ASC_SubTick(int SubTick)
+{
+	ui4r actL;
+#if MySoundEnabled
+	tpSoundSamp p;
+#endif
+	ui4r i;
+	ui4r n = SubTick_n[SubTick];
+#if MySoundEnabled
+	ui3b SoundVolume = SoundReg_Volume;
+#endif
+
+#if MySoundEnabled
+label_retry:
+	p = MySound_BeginWrite(n, &actL);
+#else
+	actL = n;
+#endif
+	if (actL > 0) {
+
+		if (1 == SoundReg801) {
+#if MySoundEnabled
+			ui3p addr;
+#endif
+
+			if (0 != (SoundReg802 & 2)) {
+
+			if (! ASC_Playing) {
+				if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) {
+					if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x200)
+					{
+						SoundReg804 &= ~ 0x01;
+						SoundReg804 &= ~ 0x04;
+						ASC_Playing = trueblnr;
+#if ASC_dolog
+						dbglog_WriteNote("ASC : start stereo playing");
+#endif
+					} else {
+						if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) == 0)
+						if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out))
+							>= 370)
+						{
+#if ASC_dolog
+							dbglog_WriteNote("ASC : switch to mono");
+#endif
+							SoundReg802 &= ~ 2;
+							/*
+								cludge to get Tetris to work,
+								may not actually work on real machine.
+							*/
+						}
+					}
+				}
+			}
+
+			for (i = 0; i < actL; i++) {
+				if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) == 0) {
+					ASC_Playing = falseblnr;
+				}
+				if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) == 0) {
+					ASC_Playing = falseblnr;
+				}
+				if (! ASC_Playing) {
+#if MySoundEnabled
+					*p++ = 0x80;
+#endif
+				} else
+				{
+
+#if MySoundEnabled
+				addr = ASC_SampBuff + (ASC_FIFO_Out & 0x3FF);
+
+#if ASC_dolog && 1
+				dbglog_StartLine();
+				dbglog_writeCStr("out sound ");
+				dbglog_writeCStr("[");
+				dbglog_writeHex(ASC_FIFO_Out);
+				dbglog_writeCStr("]");
+				dbglog_writeCStr(" = ");
+				dbglog_writeHex(*addr);
+				dbglog_writeCStr(" , ");
+				dbglog_writeHex(addr[0x400]);
+				dbglog_writeReturn();
+#endif
+
+				*p++ = ((addr[0] + addr[0x400])
+#if 4 == kLn2SoundSampSz
+					<< 8
+#endif
+					) >> 1;
+#endif /* MySoundEnabled */
+
+				ASC_FIFO_Out += 1;
+
+				}
+			}
+
+			} else {
+
+			/* mono */
+
+			if (! ASC_Playing) {
+				if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200)
+				{
+					SoundReg804 &= ~ 0x01;
+					ASC_Playing = trueblnr;
+#if ASC_dolog
+					dbglog_WriteNote("ASC : start mono playing");
+#endif
+				}
+			}
+
+			for (i = 0; i < actL; i++) {
+				if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) == 0) {
+					ASC_Playing = falseblnr;
+				}
+				if (! ASC_Playing) {
+#if MySoundEnabled
+					*p++ = 0x80;
+#endif
+				} else
+				{
+
+#if MySoundEnabled
+				addr = ASC_SampBuff + (ASC_FIFO_Out & 0x3FF);
+
+#if ASC_dolog && 1
+				dbglog_StartLine();
+				dbglog_writeCStr("out sound ");
+				dbglog_writeCStr("[");
+				dbglog_writeHex(ASC_FIFO_Out);
+				dbglog_writeCStr("]");
+				dbglog_writeCStr(" = ");
+				dbglog_writeHex(*addr);
+				dbglog_writeCStr(", in buff: ");
+				dbglog_writeHex((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out));
+				dbglog_writeReturn();
+#endif
+
+				*p++ = (addr[0])
+#if 4 == kLn2SoundSampSz
+					<< 8
+#endif
+					;
+#endif /* MySoundEnabled */
+
+				/* Move the address on */
+				/* *addr = 0x80; */
+				/* addr += 2; */
+				ASC_FIFO_Out += 1;
+
+				}
+			}
+
+			}
+		} else if (2 == SoundReg801) {
+#if MySoundEnabled
+			ui4r v;
+			ui4r i0;
+			ui4r i1;
+			ui4r i2;
+			ui4r i3;
+#endif
+			ui5r freq0 = do_get_mem_long(ASC_ChanA[0].freq);
+			ui5r freq1 = do_get_mem_long(ASC_ChanA[1].freq);
+			ui5r freq2 = do_get_mem_long(ASC_ChanA[2].freq);
+			ui5r freq3 = do_get_mem_long(ASC_ChanA[3].freq);
+			ui5r phase0 = do_get_mem_long(ASC_ChanA[0].phase);
+			ui5r phase1 = do_get_mem_long(ASC_ChanA[1].phase);
+			ui5r phase2 = do_get_mem_long(ASC_ChanA[2].phase);
+			ui5r phase3 = do_get_mem_long(ASC_ChanA[3].phase);
+#if ASC_dolog && 1
+			dbglog_writeCStr("freq0=");
+			dbglog_writeNum(freq0);
+			dbglog_writeCStr(", freq1=");
+			dbglog_writeNum(freq1);
+			dbglog_writeCStr(", freq2=");
+			dbglog_writeNum(freq2);
+			dbglog_writeCStr(", freq3=");
+			dbglog_writeNum(freq3);
+			dbglog_writeReturn();
+#endif
+			for (i = 0; i < actL; i++) {
+
+				phase0 += freq0;
+				phase1 += freq1;
+				phase2 += freq2;
+				phase3 += freq3;
+
+#if MySoundEnabled
+
+#if 1
+				i0 = ((phase0 + 0x4000) >> 15) & 0x1FF;
+				i1 = ((phase1 + 0x4000) >> 15) & 0x1FF;
+				i2 = ((phase2 + 0x4000) >> 15) & 0x1FF;
+				i3 = ((phase3 + 0x4000) >> 15) & 0x1FF;
+#else
+				i0 = ((phase0 + 0x8000) >> 16) & 0x1FF;
+				i1 = ((phase1 + 0x8000) >> 16) & 0x1FF;
+				i2 = ((phase2 + 0x8000) >> 16) & 0x1FF;
+				i3 = ((phase3 + 0x8000) >> 16) & 0x1FF;
+#endif
+
+				v = ASC_SampBuff[i0]
+					+ ASC_SampBuff[0x0200 + i1]
+					+ ASC_SampBuff[0x0400 + i2]
+					+ ASC_SampBuff[0x0600 + i3];
+
+#if ASC_dolog && 1
+				dbglog_StartLine();
+				dbglog_writeCStr("i0=");
+				dbglog_writeNum(i0);
+				dbglog_writeCStr(", i1=");
+				dbglog_writeNum(i1);
+				dbglog_writeCStr(", i2=");
+				dbglog_writeNum(i2);
+				dbglog_writeCStr(", i3=");
+				dbglog_writeNum(i3);
+				dbglog_writeCStr(", output sound v=");
+				dbglog_writeNum(v);
+				dbglog_writeReturn();
+#endif
+
+				*p++ = (v >> 2);
+#endif /* MySoundEnabled */
+			}
+
+			do_put_mem_long(ASC_ChanA[0].phase, phase0);
+			do_put_mem_long(ASC_ChanA[1].phase, phase1);
+			do_put_mem_long(ASC_ChanA[2].phase, phase2);
+			do_put_mem_long(ASC_ChanA[3].phase, phase3);
+		} else {
+#if MySoundEnabled
+			for (i = 0; i < actL; i++) {
+				*p++ = kCenterSound;
+			}
+#endif
+		}
+
+
+#if MySoundEnabled
+		if (SoundVolume < 7) {
+			/*
+				Usually have volume at 7, so this
+				is just for completeness.
+			*/
+			ui5b mult = (ui5b)vol_mult[SoundVolume];
+			trSoundSamp offset = vol_offset[SoundVolume];
+
+			p -= actL;
+			for (i = 0; i < actL; i++) {
+				*p = (trSoundSamp)((ui5b)(*p) * mult >> 16) + offset;
+				++p;
+			}
+		}
+
+		MySound_EndWrite(actL);
+		n -= actL;
+		if (n > 0) {
+			goto label_retry;
+		}
+#endif
+	}
+
+#if 1
+	if ((1 == SoundReg801) && ASC_Playing) {
+		if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) {
+			if (0 != (SoundReg804 & 0x01)) {
+				ReportAbnormalID(0x0F1A,
+					"half flag A not already clear");
+				SoundReg804 &= ~ 0x01;
+			}
+		} else {
+			if (0 != (SoundReg804 & 0x01)) {
+				/* happens in lode runner */
+			} else {
+#if ASC_dolog
+				dbglog_WriteNote("setting half flag A");
+#endif
+				ASC_interrupt_PulseNtfy();
+				SoundReg804 |= 0x01;
+			}
+		}
+		if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x400) {
+			if (0 == (SoundReg804 & 0x02)) {
+				ReportAbnormalID(0x0F1B, "full flag A not already set");
+				SoundReg804 |= 0x02;
+			}
+		} else {
+			if (0 != (SoundReg804 & 0x02)) {
+				/* ReportAbnormal("full flag A not already clear"); */
+				SoundReg804 &= ~ 0x02;
+			}
+		}
+		if (0 != (SoundReg802 & 2)) {
+			if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x200) {
+				if (0 != (SoundReg804 & 0x04)) {
+					ReportAbnormalID(0x0F1C,
+						"half flag B not already clear");
+					SoundReg804 &= ~ 0x04;
+				}
+			} else {
+				if (0 != (SoundReg804 & 0x04)) {
+					/* happens in Lunar Phantom */
+				} else {
+#if ASC_dolog
+					dbglog_WriteNote("setting half flag B");
+#endif
+					ASC_interrupt_PulseNtfy();
+					SoundReg804 |= 0x04;
+				}
+			}
+			if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x400) {
+				if (0 == (SoundReg804 & 0x08)) {
+					ReportAbnormalID(0x0F1D,
+						"full flag B not already set");
+					SoundReg804 |= 0x08;
+				}
+			} else {
+				if (0 != (SoundReg804 & 0x08)) {
+					/*
+						ReportAbnormal("full flag B not already clear");
+					*/
+					SoundReg804 &= ~ 0x08;
+				}
+			}
+		}
+	}
+#endif
+}
--- /dev/null
+++ b/src/ASCEMDEV.h
@@ -1,0 +1,24 @@
+/*
+	ASCEMDEV.h
+
+	Copyright (C) 2008 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef ASCEMDEV_H
+#error "header already included"
+#else
+#define ASCEMDEV_H
+#endif
+
+EXPORTFUNC ui5b ASC_Access(ui5b Data, blnr WriteMem, CPTR addr);
+EXPORTPROC ASC_SubTick(int SubTick);
--- /dev/null
+++ b/src/BPFILTER.h
@@ -1,0 +1,365 @@
+/*
+	BPFILTER.h
+
+	Copyright (C) 2012 Michael Fort, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Berkeley Packet Filter for localtalk emulation
+*/
+
+/* BPF and devices */
+static unsigned char device_address[6] = {
+	0
+};
+static unsigned int device_buffer_size = 0;
+static int fd = -1; /* BPF file descriptor */
+static struct bpf_version bpf_version;
+static struct bpf_program bpf_program;
+static struct bpf_insn insns[] =
+{
+	/* Program for BPF to filter out non-LTOE packets */
+	BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12),
+	BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x809B, 0, 1),
+	BPF_STMT(BPF_RET + BPF_K, 65535),
+	BPF_STMT(BPF_RET + BPF_K, 0),
+};
+
+GLOBALVAR ui3p LT_TxBuffer = NULL;
+
+/* Transmit state */
+GLOBALVAR ui4r LT_TxBuffSz = 0;
+
+/*
+	Transmit buffer that is reused from tx packet to tx packet.
+	The 's' byte represents the source mac address (ours) and we don't
+	have to initialize it because the MAC device will automatically
+	fill it in for us.  The four 'p' bytes represent the process number
+	of this Mini vMac application.  It helps differentiate packets
+	between two applications running on the same machine.  It is not
+	used at this time.  There is a small chance two applications could
+	get the same LLAP/SDLC address to start with and would not work
+	correctly (1 in 254). The 'S' bytes are the size of the LLAP packet
+	since it can be smaller than the minimum sized Ethernet frame.
+	The process number is replaced at initialization.  The size is
+	updated just before sending to BPF.  All LLAP data is inserted
+	starting at byte 20.
+*/
+static unsigned char tx_buffer[20 + LT_TxBfMxSz] =
+	"\xFF\xFF\xFF\xFF\xFF\xFFssssss\x80\x9BppppSS";
+
+/* Receive state */
+GLOBALVAR ui3p LT_RxBuffer = NULL;
+	/* When data pending, this is used */
+GLOBALVAR ui5r LT_RxBuffSz = 0;
+	/* When data pending, this is used */
+
+/* Macro used by only the get_sockaddrs function for readability. */
+#define ROUNDUP(a, size) \
+	(((a) & ((size) - 1)) ? (1 + ((a) | ((size) - 1))) : (a))
+
+/*
+	Utility function needed for walking the addresses of the
+	kernel route lookup
+*/
+LOCALPROC get_sockaddrs(int addrs, struct sockaddr* sa,
+	struct sockaddr** rti_info)
+{
+	int loop;
+	int incr;
+
+	for (loop = 0; loop < RTAX_MAX; loop++) {
+		if (addrs & (1 << loop)) {
+			rti_info[loop] = sa;
+			incr = sa->sa_len ? ROUNDUP(sa->sa_len, sizeof(uint32_t))
+				: sizeof(uint32_t);
+			sa = (struct sockaddr*)((unsigned long int)sa + incr);
+		} else {
+			rti_info[loop] = NULL;
+		}
+	}
+}
+
+/*
+	This ugly function does a lot of steps to prepare the BPF
+	for our use.
+	1. Find the ethernet interface that the default route uses.
+	2. Determine the maximum number of BPF devices can exist.
+	3. Search for a usable BPF device and open it.
+	4. Set the BPF device to use our ethernet interface.
+	5. Get the proper buffer size to use with the BPF device.
+	6. Set some useful modes of operation on the BPF device.
+	7. Install a program on the device that filters out non-LTOE
+	packets.
+*/
+
+LOCALFUNC int get_ethernet(void)
+{
+	int result;
+	int size;
+	struct rt_msghdr* message;
+	struct sockaddr_in* addrs;
+	struct sockaddr* sa_list[RTAX_MAX];
+	int loop;
+	char filename[64];
+	struct ifreq ifreq;
+	int enable = 1;
+	struct kinfo_proc kp;
+	size_t len = sizeof(kp);
+	int max = 4;
+
+	char device[32];
+
+	/* Get a socket to routed for IPv4 */
+	fd = socket(PF_ROUTE, SOCK_RAW, AF_INET);
+	if (fd == -1) {
+		return falseblnr;
+	}
+
+	/* Allocate a message */
+	size = sizeof(struct rt_msghdr) + 16 * sizeof(struct sockaddr_in);
+	message = (struct rt_msghdr*)malloc(size);
+	if (! message) {
+		close(fd);
+		return falseblnr;
+	}
+	memset(message, 0, size);
+	addrs = (struct sockaddr_in*)(message + 1);
+
+	/* Fill in the request */
+	message->rtm_msglen    = size;
+	message->rtm_version   = RTM_VERSION;
+	message->rtm_type      = RTM_GET;
+	message->rtm_addrs
+		= RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_IFP | RTA_IFA;
+	addrs->sin_len         = sizeof(struct sockaddr_in);
+	addrs->sin_family      = AF_INET;
+	addrs->sin_addr.s_addr = 0; /* 0.0.0.0 is default route */
+
+	/* Send the message to the kernel */
+	result = write(fd, message, size);
+	if (result < 0) {
+		close(fd);
+		free(message);
+		return falseblnr;
+	}
+
+	/* Read the result from the kernel */
+	result = read(fd, message, size);
+	if (result < 0) {
+		close(fd);
+		free(message);
+		return falseblnr;
+	}
+
+	/* Close the route socket */
+	close(fd);
+
+	/* Get pointer to the result then parse it */
+	struct sockaddr* sa = (struct sockaddr*)
+		((unsigned long int)message + sizeof(struct rt_msghdr));
+	get_sockaddrs(message->rtm_addrs, sa, sa_list);
+
+	/* Must have a LINK (Ethernet) */
+	if ((! sa_list[RTAX_IFP])
+		|| (sa_list[RTAX_IFP]->sa_family != AF_LINK))
+	{
+		return falseblnr;
+	}
+
+	int namelen = ((struct sockaddr_dl*)sa_list[RTAX_IFP])->sdl_nlen;
+#if 0
+	int addrlen = ((struct sockaddr_dl*)sa_list[RTAX_IFP])->sdl_alen;
+#endif
+
+	strncpy(device,
+		&((struct sockaddr_dl*)sa_list[RTAX_IFP])->sdl_data[0],
+		namelen);
+	device[namelen] = 0;
+	memcpy(device_address,
+		&((struct sockaddr_dl*)sa_list[RTAX_IFP])->sdl_data[namelen],
+		6);
+	memcpy(&(tx_buffer[6]),
+		&((struct sockaddr_dl*)sa_list[RTAX_IFP])->sdl_data[namelen],
+		6);
+
+	result = sysctlbyname("debug.bpf_maxdevices", &kp, &len, NULL, 0);
+	if (result == -1) {
+		return falseblnr;
+	}
+	max = *((int *)&kp);
+
+	for (loop = 0; loop < max; loop++) {
+		sprintf(filename, "/dev/bpf%d", loop);
+		fd = open(filename, O_RDWR | O_NONBLOCK | O_EXLOCK);
+		if (fd >= 0) {
+			/* sprintf(buffer, "using %s\n", filename); */
+			break;
+		}
+	}
+
+	if (fd <= 0) {
+		return falseblnr;
+	}
+
+	memset(&ifreq, 0, sizeof(struct ifreq));
+	strncpy(ifreq.ifr_name, device, IFNAMSIZ);
+	result = ioctl(fd, BIOCSETIF, &ifreq);
+	if (result) {
+		return falseblnr;
+	}
+
+	result = ioctl(fd, BIOCGBLEN, &device_buffer_size);
+	if (result) {
+		return falseblnr;
+	}
+
+	result = ioctl(fd, BIOCPROMISC, &enable);
+	if (result) {
+		return falseblnr;
+	}
+
+	result = ioctl(fd, BIOCSSEESENT, &enable);
+	if (result) {
+		return falseblnr;
+	}
+
+	result = ioctl(fd, BIOCSHDRCMPLT, &enable);
+	if (result) {
+		return falseblnr;
+	}
+
+	result = ioctl(fd, BIOCIMMEDIATE, &enable);
+	if (result) {
+		return falseblnr;
+	}
+
+	result = ioctl(fd, BIOCVERSION, &bpf_version);
+	if (result) {
+		return falseblnr;
+	}
+
+	bpf_program.bf_len = 4;
+	bpf_program.bf_insns = insns;
+
+	result = ioctl(fd, BIOCSETF, &bpf_program);
+	if (result) {
+		return falseblnr;
+	}
+
+	return trueblnr;
+}
+
+LOCALVAR unsigned char *MyRxBuffer = NULL;
+
+/*
+	External function needed at startup to initialize the LocalTalk
+	functionality.
+*/
+LOCALFUNC int InitLocalTalk(void)
+{
+	/* Perform a lot of stuff to get access to the Ethernet */
+	get_ethernet();
+
+	/*
+		Save the process id in the transmit buffer as it may be used
+		later to uniquely identify the sender to identify collisions
+		in dynamic llap node address assignment.
+	*/
+	*((uint32_t*)(&tx_buffer[14])) = htonl(getpid());
+
+	LT_TxBuffer = (ui3p)&tx_buffer[20];
+
+	MyRxBuffer = malloc(device_buffer_size);
+	if (NULL == MyRxBuffer) {
+		return falseblnr;
+	}
+
+	/* Initialized properly */
+	return trueblnr;
+}
+
+GLOBALOSGLUPROC LT_TransmitPacket(void)
+{
+	int count;
+
+	/*
+		Write the length in the packet.  This is needed because
+		Ethernet has a minimum 60 bytes length, which the MAC chip
+		will enforce on TX.  Without the size, a simple 3 byte LLAP
+		packet would look like a (60 - 14 =) 46 byte LLAP packet.
+	*/
+	*((uint16_t*)(&tx_buffer[18])) = htons(LT_TxBuffSz);
+
+	/* Send the packet to Ethernet */
+	count = write(fd, tx_buffer, 20 + LT_TxBuffSz);
+
+	(void)count; /* unused */
+}
+
+LOCALVAR unsigned char* NextPacket = NULL;
+LOCALVAR unsigned char* EndPackets = NULL;
+
+LOCALPROC LocalTalkTick0(void)
+{
+	/* Get a single buffer worth of packets from BPF */
+	unsigned char* device_buffer = MyRxBuffer;
+	int bytes = read(fd, device_buffer, device_buffer_size);
+	if (bytes > 0) {
+		/* Maybe multiple packets in this buffer */
+#if 0
+		dbglog_WriteNote("SCC founds packets from BPF");
+#endif
+		NextPacket = device_buffer;
+		EndPackets = device_buffer + bytes;
+	}
+}
+
+GLOBALOSGLUPROC LT_ReceivePacket(void)
+{
+label_retry:
+	if (NextPacket == NULL) {
+		LocalTalkTick0();
+		if (NextPacket != NULL) {
+			goto label_retry;
+		}
+	} else if (NextPacket >= EndPackets) {
+#if 0
+		dbglog_WriteNote("SCC finished set of packets from BPF");
+#endif
+		NextPacket = NULL;
+		goto label_retry;
+	} else {
+		unsigned char* packet = NextPacket;
+		/* Get pointer to BPF header */
+		struct bpf_hdr* header = (struct bpf_hdr *)packet;
+
+		/* Advance to next packet in buffer */
+		NextPacket += BPF_WORDALIGN(header->bh_hdrlen
+			+ header->bh_caplen);
+
+		/* Get clean references to data */
+		int ethernet_length = header->bh_caplen - 14;
+		int llap_length = htons(*((uint16_t*)(packet
+			+ header->bh_hdrlen + 18)));
+		unsigned char* start = packet + header->bh_hdrlen + 20;
+
+		if (llap_length <= ethernet_length) {
+			/* Start the receiver */
+			LT_RxBuffer    = (ui3p)start;
+			LT_RxBuffSz    = llap_length;
+		} else {
+			goto label_retry;
+		}
+	}
+}
--- /dev/null
+++ b/src/COMOSGLU.h
@@ -1,0 +1,1219 @@
+/*
+	COMOSGLU.h
+
+	Copyright (C) 2009 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	COMmon code for Operating System GLUe
+*/
+
+#if EnableMouseMotion && MayFullScreen
+#define EnableFSMouseMotion 1
+#else
+#define EnableFSMouseMotion 0
+#endif
+
+#if EnableMagnify || VarFullScreen
+#define EnableRecreateW 1
+#else
+#define EnableRecreateW 0
+#endif
+
+#if EnableRecreateW || EnableFSMouseMotion
+#define EnableMoveMouse 1
+#else
+#define EnableMoveMouse 0
+#endif
+
+GLOBALVAR ui3p ROM = nullpr;
+LOCALVAR blnr ROM_loaded = falseblnr;
+
+GLOBALVAR ui5b vSonyWritableMask = 0;
+GLOBALVAR ui5b vSonyInsertedMask = 0;
+
+#if IncludeSonyRawMode
+GLOBALVAR blnr vSonyRawMode = falseblnr;
+#endif
+
+#if IncludeSonyNew
+GLOBALVAR blnr vSonyNewDiskWanted = falseblnr;
+GLOBALVAR ui5b vSonyNewDiskSize;
+#endif
+
+#if IncludeSonyNameNew
+GLOBALVAR tPbuf vSonyNewDiskName = NotAPbuf;
+#endif
+
+GLOBALVAR ui5b CurMacDateInSeconds = 0;
+#if AutoLocation
+GLOBALVAR ui5b CurMacLatitude = 0;
+GLOBALVAR ui5b CurMacLongitude = 0;
+#endif
+#if AutoTimeZone
+GLOBALVAR ui5b CurMacDelta = 0;
+#endif
+
+#if 0 != vMacScreenDepth
+GLOBALVAR blnr UseColorMode = falseblnr;
+GLOBALVAR blnr ColorModeWorks = falseblnr;
+#endif
+
+#if 0 != vMacScreenDepth
+GLOBALVAR blnr ColorMappingChanged = falseblnr;
+#endif
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+GLOBALVAR ui4r CLUT_reds[CLUT_size];
+GLOBALVAR ui4r CLUT_greens[CLUT_size];
+GLOBALVAR ui4r CLUT_blues[CLUT_size];
+#endif
+
+LOCALVAR blnr RequestMacOff = falseblnr;
+
+GLOBALVAR blnr ForceMacOff = falseblnr;
+
+GLOBALVAR blnr WantMacInterrupt = falseblnr;
+
+GLOBALVAR blnr WantMacReset = falseblnr;
+
+GLOBALVAR ui3b SpeedValue = WantInitSpeedValue;
+
+#if EnableAutoSlow
+GLOBALVAR blnr WantNotAutoSlow = (WantInitNotAutoSlow != 0);
+#endif
+
+GLOBALVAR ui4b CurMouseV = 0;
+GLOBALVAR ui4b CurMouseH = 0;
+
+#if EnableFSMouseMotion
+LOCALVAR blnr HaveMouseMotion = falseblnr;
+#endif
+
+#if EnableAutoSlow
+GLOBALVAR ui5r QuietTime = 0;
+GLOBALVAR ui5r QuietSubTicks = 0;
+#endif
+
+#ifndef GrabKeysFullScreen
+#define GrabKeysFullScreen 1
+#endif
+
+#ifndef GrabKeysMaxFullScreen
+#define GrabKeysMaxFullScreen 0
+#endif
+
+#if IncludePbufs
+LOCALVAR ui5b PbufAllocatedMask;
+LOCALVAR ui5b PbufSize[NumPbufs];
+#endif
+
+#if IncludePbufs
+#define PbufIsAllocated(i) ((PbufAllocatedMask & ((ui5b)1 << (i))) != 0)
+#endif
+
+#if IncludePbufs
+LOCALFUNC blnr FirstFreePbuf(tPbuf *r)
+{
+	tPbuf i;
+
+	for (i = 0; i < NumPbufs; ++i) {
+		if (! PbufIsAllocated(i)) {
+			*r = i;
+			return trueblnr;
+		}
+	}
+	return falseblnr;
+}
+#endif
+
+#if IncludePbufs
+LOCALPROC PbufNewNotify(tPbuf Pbuf_No, ui5b count)
+{
+	PbufSize[Pbuf_No] = count;
+	PbufAllocatedMask |= ((ui5b)1 << Pbuf_No);
+}
+#endif
+
+#if IncludePbufs
+LOCALPROC PbufDisposeNotify(tPbuf Pbuf_No)
+{
+	PbufAllocatedMask &= ~ ((ui5b)1 << Pbuf_No);
+}
+#endif
+
+#if IncludePbufs
+GLOBALOSGLUFUNC tMacErr CheckPbuf(tPbuf Pbuf_No)
+{
+	tMacErr result;
+
+	if (Pbuf_No >= NumPbufs) {
+		result = mnvm_nsDrvErr;
+	} else if (! PbufIsAllocated(Pbuf_No)) {
+		result = mnvm_offLinErr;
+	} else {
+		result = mnvm_noErr;
+	}
+
+	return result;
+}
+#endif
+
+#if IncludePbufs
+GLOBALOSGLUFUNC tMacErr PbufGetSize(tPbuf Pbuf_No, ui5r *Count)
+{
+	tMacErr result = CheckPbuf(Pbuf_No);
+
+	if (mnvm_noErr == result) {
+		*Count = PbufSize[Pbuf_No];
+	}
+
+	return result;
+}
+#endif
+
+LOCALFUNC blnr FirstFreeDisk(tDrive *Drive_No)
+{
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		if (! vSonyIsInserted(i)) {
+			if (nullpr != Drive_No) {
+				*Drive_No = i;
+			}
+			return trueblnr;
+		}
+	}
+	return falseblnr;
+}
+
+GLOBALOSGLUFUNC blnr AnyDiskInserted(void)
+{
+#if 0
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		if (vSonyIsInserted(i)) {
+			return trueblnr;
+		}
+	}
+	return falseblnr;
+#endif
+	return 0 != vSonyInsertedMask;
+}
+
+GLOBALOSGLUPROC DiskRevokeWritable(tDrive Drive_No)
+{
+	vSonyWritableMask &= ~ ((ui5b)1 << Drive_No);
+}
+
+LOCALPROC DiskInsertNotify(tDrive Drive_No, blnr locked)
+{
+	vSonyInsertedMask |= ((ui5b)1 << Drive_No);
+	if (! locked) {
+		vSonyWritableMask |= ((ui5b)1 << Drive_No);
+	}
+
+	QuietEnds();
+}
+
+LOCALPROC DiskEjectedNotify(tDrive Drive_No)
+{
+	vSonyWritableMask &= ~ ((ui5b)1 << Drive_No);
+	vSonyInsertedMask &= ~ ((ui5b)1 << Drive_No);
+}
+
+/*
+	block type - for operating on multiple ui3b elements
+		at a time.
+*/
+
+#if LittleEndianUnaligned || BigEndianUnaligned
+
+#define uibb ui5b
+#define uibr ui5r
+#define ln2uiblockn 2
+
+#if 0
+#define uibb long long
+#define uibr long long
+#define ln2uiblockn 3
+#endif
+
+#else
+
+#define uibb ui3b
+#define uibr ui3r
+#define ln2uiblockn 0
+
+#endif
+
+#define uiblockn (1 << ln2uiblockn)
+#define ln2uiblockbitsn (3 + ln2uiblockn)
+#define uiblockbitsn (8 * uiblockn)
+
+LOCALFUNC blnr FindFirstChangeInLVecs(uibb *ptr1, uibb *ptr2,
+					uimr L, uimr *j)
+{
+/*
+	find index of first difference
+*/
+	uibb *p1 = ptr1;
+	uibb *p2 = ptr2;
+	uimr i;
+
+	for (i = L; i != 0; --i) {
+		if (*p1++ != *p2++) {
+			--p1;
+			*j = p1 - ptr1;
+			return trueblnr;
+		}
+	}
+	return falseblnr;
+}
+
+LOCALPROC FindLastChangeInLVecs(uibb *ptr1, uibb *ptr2,
+					uimr L, uimr *j)
+{
+/*
+	find index of last difference, assuming there is one
+*/
+	uibb *p1 = ptr1 + L;
+	uibb *p2 = ptr2 + L;
+
+	while (*--p1 == *--p2) {
+	}
+	*j = p1 - ptr1;
+}
+
+LOCALPROC FindLeftRightChangeInLMat(uibb *ptr1, uibb *ptr2,
+	uimr width, uimr top, uimr bottom,
+	uimr *LeftMin0, uibr *LeftMask0,
+	uimr *RightMax0, uibr *RightMask0)
+{
+	uimr i;
+	uimr j;
+	uibb *p1;
+	uibb *p2;
+	uibr x;
+	ui5r offset = top * width;
+	uibb *p10 = (uibb *)ptr1 + offset;
+	uibb *p20 = (uibb *)ptr2 + offset;
+	uimr LeftMin = *LeftMin0;
+	uimr RightMax = *RightMax0;
+	uibr LeftMask = 0;
+	uibr RightMask = 0;
+	for (i = top; i < bottom; ++i) {
+		p1 = p10;
+		p2 = p20;
+		for (j = 0; j < LeftMin; ++j) {
+			x = *p1++ ^ *p2++;
+			if (0 != x) {
+				LeftMin = j;
+				LeftMask = x;
+				goto Label_3;
+			}
+		}
+		LeftMask |= (*p1 ^ *p2);
+Label_3:
+		p1 = p10 + RightMax;
+		p2 = p20 + RightMax;
+		RightMask |= (*p1++ ^ *p2++);
+		for (j = RightMax + 1; j < width; ++j) {
+			x = *p1++ ^ *p2++;
+			if (0 != x) {
+				RightMax = j;
+				RightMask = x;
+			}
+		}
+
+		p10 += width;
+		p20 += width;
+	}
+	*LeftMin0 = LeftMin;
+	*RightMax0 = RightMax;
+	*LeftMask0 = LeftMask;
+	*RightMask0 = RightMask;
+}
+
+LOCALVAR ui3p screencomparebuff = nullpr;
+
+LOCALVAR uimr NextDrawRow = 0;
+
+
+#if BigEndianUnaligned
+
+#define FlipCheckMonoBits (uiblockbitsn - 1)
+
+#else
+
+#define FlipCheckMonoBits 7
+
+#endif
+
+#define FlipCheckBits (FlipCheckMonoBits >> vMacScreenDepth)
+
+#ifndef WantColorTransValid
+#define WantColorTransValid 0
+#endif
+
+#if WantColorTransValid
+LOCALVAR blnr ColorTransValid = falseblnr;
+#endif
+
+LOCALFUNC blnr ScreenFindChanges(ui3p screencurrentbuff,
+	si3b TimeAdjust, si4b *top, si4b *left, si4b *bottom, si4b *right)
+{
+	uimr j0;
+	uimr j1;
+	uimr j0h;
+	uimr j1h;
+	uimr j0v;
+	uimr j1v;
+	uimr copysize;
+	uimr copyoffset;
+	uimr copyrows;
+	uimr LimitDrawRow;
+	uimr MaxRowsDrawnPerTick;
+	uimr LeftMin;
+	uimr RightMax;
+	uibr LeftMask;
+	uibr RightMask;
+	int j;
+
+	if (TimeAdjust < 4) {
+		MaxRowsDrawnPerTick = vMacScreenHeight;
+	} else if (TimeAdjust < 6) {
+		MaxRowsDrawnPerTick = vMacScreenHeight / 2;
+	} else {
+		MaxRowsDrawnPerTick = vMacScreenHeight / 4;
+	}
+
+#if 0 != vMacScreenDepth
+	if (UseColorMode) {
+		if (ColorMappingChanged) {
+			ColorMappingChanged = falseblnr;
+			j0h = 0;
+			j1h = vMacScreenWidth;
+			j0v = 0;
+			j1v = vMacScreenHeight;
+#if WantColorTransValid
+			ColorTransValid = falseblnr;
+#endif
+		} else {
+			if (! FindFirstChangeInLVecs(
+				(uibb *)screencurrentbuff
+					+ NextDrawRow * (vMacScreenBitWidth / uiblockbitsn),
+				(uibb *)screencomparebuff
+					+ NextDrawRow * (vMacScreenBitWidth / uiblockbitsn),
+				((uimr)(vMacScreenHeight - NextDrawRow)
+					* (uimr)vMacScreenBitWidth) / uiblockbitsn,
+				&j0))
+			{
+				NextDrawRow = 0;
+				return falseblnr;
+			}
+			j0v = j0 / (vMacScreenBitWidth / uiblockbitsn);
+			j0h = j0 - j0v * (vMacScreenBitWidth / uiblockbitsn);
+			j0v += NextDrawRow;
+			LimitDrawRow = j0v + MaxRowsDrawnPerTick;
+			if (LimitDrawRow >= vMacScreenHeight) {
+				LimitDrawRow = vMacScreenHeight;
+				NextDrawRow = 0;
+			} else {
+				NextDrawRow = LimitDrawRow;
+			}
+			FindLastChangeInLVecs((uibb *)screencurrentbuff,
+				(uibb *)screencomparebuff,
+				((uimr)LimitDrawRow
+					* (uimr)vMacScreenBitWidth) / uiblockbitsn,
+				&j1);
+			j1v = j1 / (vMacScreenBitWidth / uiblockbitsn);
+			j1h = j1 - j1v * (vMacScreenBitWidth / uiblockbitsn);
+			j1v++;
+
+			if (j0h < j1h) {
+				LeftMin = j0h;
+				RightMax = j1h;
+			} else {
+				LeftMin = j1h;
+				RightMax = j0h;
+			}
+
+			FindLeftRightChangeInLMat((uibb *)screencurrentbuff,
+				(uibb *)screencomparebuff,
+				(vMacScreenBitWidth / uiblockbitsn),
+				j0v, j1v, &LeftMin, &LeftMask, &RightMax, &RightMask);
+
+#if vMacScreenDepth > ln2uiblockbitsn
+			j0h =  (LeftMin >> (vMacScreenDepth - ln2uiblockbitsn));
+#elif ln2uiblockbitsn > vMacScreenDepth
+			for (j = 0; j < (1 << (ln2uiblockbitsn - vMacScreenDepth));
+				++j)
+			{
+				if (0 != (LeftMask
+					& (((((uibr)1) << (1 << vMacScreenDepth)) - 1)
+						<< ((j ^ FlipCheckBits) << vMacScreenDepth))))
+				{
+					goto Label_1c;
+				}
+			}
+Label_1c:
+			j0h =  (LeftMin << (ln2uiblockbitsn - vMacScreenDepth)) + j;
+#else
+			j0h =  LeftMin;
+#endif
+
+#if vMacScreenDepth > ln2uiblockbitsn
+			j1h = (RightMax >> (vMacScreenDepth - ln2uiblockbitsn)) + 1;
+#elif ln2uiblockbitsn > vMacScreenDepth
+			for (j = (uiblockbitsn >> vMacScreenDepth); --j >= 0; ) {
+				if (0 != (RightMask
+					& (((((uibr)1) << (1 << vMacScreenDepth)) - 1)
+						<< ((j ^ FlipCheckBits) << vMacScreenDepth))))
+				{
+					goto Label_2c;
+				}
+			}
+Label_2c:
+			j1h = (RightMax << (ln2uiblockbitsn - vMacScreenDepth))
+				+ j + 1;
+#else
+			j1h = RightMax + 1;
+#endif
+		}
+
+		copyrows = j1v - j0v;
+		copyoffset = j0v * vMacScreenByteWidth;
+		copysize = copyrows * vMacScreenByteWidth;
+	} else
+#endif
+	{
+#if 0 != vMacScreenDepth
+		if (ColorMappingChanged) {
+			ColorMappingChanged = falseblnr;
+			j0h = 0;
+			j1h = vMacScreenWidth;
+			j0v = 0;
+			j1v = vMacScreenHeight;
+#if WantColorTransValid
+			ColorTransValid = falseblnr;
+#endif
+		} else
+#endif
+		{
+			if (! FindFirstChangeInLVecs(
+				(uibb *)screencurrentbuff
+					+ NextDrawRow * (vMacScreenWidth / uiblockbitsn),
+				(uibb *)screencomparebuff
+					+ NextDrawRow * (vMacScreenWidth / uiblockbitsn),
+				((uimr)(vMacScreenHeight - NextDrawRow)
+					* (uimr)vMacScreenWidth) / uiblockbitsn,
+				&j0))
+			{
+				NextDrawRow = 0;
+				return falseblnr;
+			}
+			j0v = j0 / (vMacScreenWidth / uiblockbitsn);
+			j0h = j0 - j0v * (vMacScreenWidth / uiblockbitsn);
+			j0v += NextDrawRow;
+			LimitDrawRow = j0v + MaxRowsDrawnPerTick;
+			if (LimitDrawRow >= vMacScreenHeight) {
+				LimitDrawRow = vMacScreenHeight;
+				NextDrawRow = 0;
+			} else {
+				NextDrawRow = LimitDrawRow;
+			}
+			FindLastChangeInLVecs((uibb *)screencurrentbuff,
+				(uibb *)screencomparebuff,
+				((uimr)LimitDrawRow
+					* (uimr)vMacScreenWidth) / uiblockbitsn,
+				&j1);
+			j1v = j1 / (vMacScreenWidth / uiblockbitsn);
+			j1h = j1 - j1v * (vMacScreenWidth / uiblockbitsn);
+			j1v++;
+
+			if (j0h < j1h) {
+				LeftMin = j0h;
+				RightMax = j1h;
+			} else {
+				LeftMin = j1h;
+				RightMax = j0h;
+			}
+
+			FindLeftRightChangeInLMat((uibb *)screencurrentbuff,
+				(uibb *)screencomparebuff,
+				(vMacScreenWidth / uiblockbitsn),
+				j0v, j1v, &LeftMin, &LeftMask, &RightMax, &RightMask);
+
+			for (j = 0; j < uiblockbitsn; ++j) {
+				if (0 != (LeftMask
+					& (((uibr)1) << (j ^ FlipCheckMonoBits))))
+				{
+					goto Label_1;
+				}
+			}
+Label_1:
+			j0h = LeftMin * uiblockbitsn + j;
+
+			for (j = uiblockbitsn; --j >= 0; ) {
+				if (0 != (RightMask
+					& (((uibr)1) << (j ^ FlipCheckMonoBits))))
+				{
+					goto Label_2;
+				}
+			}
+Label_2:
+			j1h = RightMax * uiblockbitsn + j + 1;
+		}
+
+		copyrows = j1v - j0v;
+		copyoffset = j0v * vMacScreenMonoByteWidth;
+		copysize = copyrows * vMacScreenMonoByteWidth;
+	}
+
+	MyMoveBytes((anyp)screencurrentbuff + copyoffset,
+		(anyp)screencomparebuff + copyoffset,
+		copysize);
+
+	*top = j0v;
+	*left = j0h;
+	*bottom = j1v;
+	*right = j1h;
+
+	return trueblnr;
+}
+
+GLOBALVAR blnr EmVideoDisable = falseblnr;
+GLOBALVAR si3b EmLagTime = 0;
+
+GLOBALVAR ui5b OnTrueTime = 0;
+	/*
+		The time slice we are currently dealing
+		with, in the same units as TrueEmulatedTime.
+	*/
+
+LOCALVAR si4b ScreenChangedTop;
+LOCALVAR si4b ScreenChangedLeft;
+LOCALVAR si4b ScreenChangedBottom;
+LOCALVAR si4b ScreenChangedRight;
+
+LOCALPROC ScreenClearChanges(void)
+{
+	ScreenChangedTop = vMacScreenHeight;
+	ScreenChangedBottom = 0;
+	ScreenChangedLeft = vMacScreenWidth;
+	ScreenChangedRight = 0;
+}
+
+LOCALPROC ScreenChangedAll(void)
+{
+	ScreenChangedTop = 0;
+	ScreenChangedBottom = vMacScreenHeight;
+	ScreenChangedLeft = 0;
+	ScreenChangedRight = vMacScreenWidth;
+}
+
+#if EnableAutoSlow
+LOCALVAR si4b ScreenChangedQuietTop = vMacScreenHeight;
+LOCALVAR si4b ScreenChangedQuietLeft = vMacScreenWidth;
+LOCALVAR si4b ScreenChangedQuietBottom = 0;
+LOCALVAR si4b ScreenChangedQuietRight = 0;
+#endif
+
+GLOBALOSGLUPROC Screen_OutputFrame(ui3p screencurrentbuff)
+{
+	si4b top;
+	si4b left;
+	si4b bottom;
+	si4b right;
+
+	if (! EmVideoDisable) {
+		if (ScreenFindChanges(screencurrentbuff, EmLagTime,
+			&top, &left, &bottom, &right))
+		{
+			if (top < ScreenChangedTop) {
+				ScreenChangedTop = top;
+			}
+			if (bottom > ScreenChangedBottom) {
+				ScreenChangedBottom = bottom;
+			}
+			if (left < ScreenChangedLeft) {
+				ScreenChangedLeft = left;
+			}
+			if (right > ScreenChangedRight) {
+				ScreenChangedRight = right;
+			}
+
+#if EnableAutoSlow
+			if (top < ScreenChangedQuietTop) {
+				ScreenChangedQuietTop = top;
+			}
+			if (bottom > ScreenChangedQuietBottom) {
+				ScreenChangedQuietBottom = bottom;
+			}
+			if (left < ScreenChangedQuietLeft) {
+				ScreenChangedQuietLeft = left;
+			}
+			if (right > ScreenChangedQuietRight) {
+				ScreenChangedQuietRight = right;
+			}
+
+			if (((ScreenChangedQuietRight - ScreenChangedQuietLeft) > 1)
+				|| ((ScreenChangedQuietBottom
+					- ScreenChangedQuietTop) > 32))
+			{
+				ScreenChangedQuietTop = vMacScreenHeight;
+				ScreenChangedQuietLeft = vMacScreenWidth;
+				ScreenChangedQuietBottom = 0;
+				ScreenChangedQuietRight = 0;
+
+				QuietEnds();
+			}
+#endif
+		}
+	}
+}
+
+#if MayFullScreen
+LOCALVAR ui4r ViewHSize;
+LOCALVAR ui4r ViewVSize;
+LOCALVAR ui4r ViewHStart = 0;
+LOCALVAR ui4r ViewVStart = 0;
+#if EnableFSMouseMotion
+LOCALVAR si4b SavedMouseH;
+LOCALVAR si4b SavedMouseV;
+#endif
+#endif
+
+#ifndef WantAutoScrollBorder
+#define WantAutoScrollBorder 0
+#endif
+
+#if EnableFSMouseMotion
+LOCALPROC AutoScrollScreen(void)
+{
+	si4b Shift;
+	si4b Limit;
+
+	/*
+		Scroll in multiples of two pixels, so as to
+		work better with the common gray pattern.
+		ViewHSize and ViewVSize are constrained
+		to a multiple of two.
+
+		Mac OS (some versions at least) constrains
+		the mouse position to be less than the screen
+		height and width, not allowing equal to it.
+		Can still scroll to see last pixel because
+		scroll in multiples of two pixels.
+	*/
+
+	if (vMacScreenWidth != ViewHSize) {
+		Shift = 0;
+		Limit = ViewHStart
+#if WantAutoScrollBorder
+			+ (ViewHSize / 16)
+#endif
+			;
+		if (CurMouseH < Limit) {
+			Shift = (Limit - CurMouseH + 1) & (~ 1);
+			Limit = ViewHStart;
+			if (Shift >= Limit) {
+				Shift = Limit;
+			}
+			Shift = - Shift;
+		} else {
+			Limit = ViewHStart + ViewHSize
+#if WantAutoScrollBorder
+				- (ViewHSize / 16)
+#endif
+				;
+			if (CurMouseH > Limit) {
+				Shift = (CurMouseH - Limit + 1) & (~ 1);
+				Limit = vMacScreenWidth - ViewHSize - ViewHStart;
+				if (Shift >= Limit) {
+					Shift = Limit;
+				}
+			}
+		}
+
+		if (Shift != 0) {
+			ViewHStart += Shift;
+			SavedMouseH += Shift;
+			ScreenChangedAll();
+		}
+	}
+
+	if (vMacScreenHeight != ViewVSize) {
+		Shift = 0;
+		Limit = ViewVStart
+#if WantAutoScrollBorder
+			+ (ViewVSize / 16)
+#endif
+			;
+		if (CurMouseV < Limit) {
+			Shift = (Limit - CurMouseV + 1) & (~ 1);
+			Limit = ViewVStart;
+			if (Shift >= Limit) {
+				Shift = Limit;
+			}
+			Shift = - Shift;
+		} else {
+			Limit = ViewVStart + ViewVSize
+#if WantAutoScrollBorder
+				- (ViewVSize / 16)
+#endif
+				;
+			if (CurMouseV > Limit) {
+				Shift = (CurMouseV - Limit + 1) & (~ 1);
+				Limit = vMacScreenHeight - ViewVSize - ViewVStart;
+				if (Shift >= Limit) {
+					Shift = Limit;
+				}
+			}
+		}
+
+		if (Shift != 0) {
+			ViewVStart += Shift;
+			SavedMouseV += Shift;
+			ScreenChangedAll();
+		}
+	}
+}
+#endif
+
+LOCALPROC SetLongs(ui5b *p, long n)
+{
+	long i;
+
+	for (i = n; --i >= 0; ) {
+		*p++ = (ui5b) -1;
+	}
+}
+
+LOCALVAR uimr ReserveAllocOffset;
+LOCALVAR ui3p ReserveAllocBigBlock = nullpr;
+
+#define PowOf2(p) ((uimr)1 << (p))
+#define Pow2Mask(p) (PowOf2(p) - 1)
+#define ModPow2(i, p) ((i) & Pow2Mask(p))
+#define FloorDivPow2(i, p) ((i) >> (p))
+#define FloorPow2Mult(i, p) ((i) & (~ Pow2Mask(p)))
+#define CeilPow2Mult(i, p) FloorPow2Mult((i) + Pow2Mask(p), (p))
+	/* warning - CeilPow2Mult evaluates p twice */
+
+GLOBALOSGLUPROC ReserveAllocOneBlock(ui3p *p, uimr n,
+	ui3r align, blnr FillOnes)
+{
+	ReserveAllocOffset = CeilPow2Mult(ReserveAllocOffset, align);
+	if (nullpr == ReserveAllocBigBlock) {
+		*p = nullpr;
+	} else {
+		*p = ReserveAllocBigBlock + ReserveAllocOffset;
+		if (FillOnes) {
+			SetLongs((ui5b *)*p, n / 4);
+		}
+	}
+	ReserveAllocOffset += n;
+}
+
+/* --- sending debugging info to file --- */
+
+#if dbglog_HAVE
+
+#define dbglog_bufsz PowOf2(dbglog_buflnsz)
+LOCALVAR uimr dbglog_bufpos = 0;
+
+LOCALVAR char *dbglog_bufp = nullpr;
+
+LOCALPROC dbglog_ReserveAlloc(void)
+{
+	ReserveAllocOneBlock((ui3p *)&dbglog_bufp, dbglog_bufsz,
+		5, falseblnr);
+}
+
+#define dbglog_open dbglog_open0
+
+LOCALPROC dbglog_close(void)
+{
+	uimr n = ModPow2(dbglog_bufpos, dbglog_buflnsz);
+	if (n != 0) {
+		dbglog_write0(dbglog_bufp, n);
+	}
+
+	dbglog_close0();
+}
+
+LOCALPROC dbglog_write(char *p, uimr L)
+{
+	uimr r;
+	uimr bufposmod;
+	uimr curbufdiv;
+	uimr newbufpos = dbglog_bufpos + L;
+	uimr newbufdiv = FloorDivPow2(newbufpos, dbglog_buflnsz);
+
+label_retry:
+	curbufdiv = FloorDivPow2(dbglog_bufpos, dbglog_buflnsz);
+	bufposmod = ModPow2(dbglog_bufpos, dbglog_buflnsz);
+	if (newbufdiv != curbufdiv) {
+		r = dbglog_bufsz - bufposmod;
+		MyMoveBytes((anyp)p, (anyp)(dbglog_bufp + bufposmod), r);
+		dbglog_write0(dbglog_bufp, dbglog_bufsz);
+		L -= r;
+		p += r;
+		dbglog_bufpos += r;
+		goto label_retry;
+	}
+	MyMoveBytes((anyp)p, (anyp)dbglog_bufp + bufposmod, L);
+	dbglog_bufpos = newbufpos;
+}
+
+LOCALFUNC uimr CStrLength(char *s)
+{
+	char *p = s;
+
+	while (*p++ != 0) {
+	}
+	return p - s - 1;
+}
+
+GLOBALOSGLUPROC dbglog_writeCStr(char *s)
+{
+	/* fprintf(DumpFile, "%s", s); */
+	dbglog_write(s, CStrLength(s));
+}
+
+GLOBALOSGLUPROC dbglog_writeReturn(void)
+{
+	dbglog_writeCStr("\n");
+	/* fprintf(DumpFile, "\n"); */
+}
+
+GLOBALOSGLUPROC dbglog_writeHex(uimr x)
+{
+	ui3r v;
+	char s[16];
+	char *p = s + 16;
+	uimr n = 0;
+
+	do {
+		v = x & 0x0F;
+		if (v < 10) {
+			*--p = '0' + v;
+		} else {
+			*--p = 'A' + v - 10;
+		}
+		x >>= 4;
+		++n;
+	} while (x != 0);
+
+	dbglog_write(p, n);
+	/* fprintf(DumpFile, "%d", (int)x); */
+}
+
+GLOBALOSGLUPROC dbglog_writeNum(uimr x)
+{
+	uimr newx;
+	char s[16];
+	char *p = s + 16;
+	uimr n = 0;
+
+	do {
+		newx = x / (uimr)10;
+		*--p = '0' + (x - newx * 10);
+		x = newx;
+		++n;
+	} while (x != 0);
+
+	dbglog_write(p, n);
+	/* fprintf(DumpFile, "%d", (int)x); */
+}
+
+GLOBALOSGLUPROC dbglog_writeMacChar(ui3r x)
+{
+	char s;
+
+	if ((x > 32) && (x < 127)) {
+		s = x;
+	} else {
+		s = '?';
+	}
+
+	dbglog_write(&s, 1);
+}
+
+LOCALPROC dbglog_writeSpace(void)
+{
+	dbglog_writeCStr(" ");
+}
+
+GLOBALOSGLUPROC dbglog_writeln(char *s)
+{
+	dbglog_writeCStr(s);
+	dbglog_writeReturn();
+}
+
+GLOBALOSGLUPROC dbglog_writelnNum(char *s, simr v)
+{
+	dbglog_writeCStr(s);
+	dbglog_writeSpace();
+	dbglog_writeNum(v);
+	dbglog_writeReturn();
+}
+
+#endif
+
+/* my event queue */
+
+#define MyEvtQLg2Sz 4
+#define MyEvtQSz (1 << MyEvtQLg2Sz)
+#define MyEvtQIMask (MyEvtQSz - 1)
+
+LOCALVAR MyEvtQEl MyEvtQA[MyEvtQSz];
+LOCALVAR ui4r MyEvtQIn = 0;
+LOCALVAR ui4r MyEvtQOut = 0;
+
+GLOBALOSGLUFUNC MyEvtQEl * MyEvtQOutP(void)
+{
+	MyEvtQEl *p = nullpr;
+	if (MyEvtQIn != MyEvtQOut) {
+		p = &MyEvtQA[MyEvtQOut & MyEvtQIMask];
+	}
+	return p;
+}
+
+GLOBALOSGLUPROC MyEvtQOutDone(void)
+{
+	++MyEvtQOut;
+}
+
+LOCALVAR blnr MyEvtQNeedRecover = falseblnr;
+	/* events lost because of full queue */
+
+LOCALFUNC MyEvtQEl * MyEvtQElPreviousIn(void)
+{
+	MyEvtQEl *p = NULL;
+	if (MyEvtQIn - MyEvtQOut != 0) {
+		p = &MyEvtQA[(MyEvtQIn - 1) & MyEvtQIMask];
+	}
+
+	return p;
+}
+
+LOCALFUNC MyEvtQEl * MyEvtQElAlloc(void)
+{
+	MyEvtQEl *p = NULL;
+	if (MyEvtQIn - MyEvtQOut >= MyEvtQSz) {
+		MyEvtQNeedRecover = trueblnr;
+	} else {
+		p = &MyEvtQA[MyEvtQIn & MyEvtQIMask];
+
+		++MyEvtQIn;
+	}
+
+	return p;
+}
+
+LOCALVAR ui5b theKeys[4];
+
+LOCALPROC Keyboard_UpdateKeyMap(ui3r key, blnr down)
+{
+	ui3r k = key & 127; /* just for safety */
+	ui3r bit = 1 << (k & 7);
+	ui3b *kp = (ui3b *)theKeys;
+	ui3b *kpi = &kp[k / 8];
+	blnr CurDown = ((*kpi & bit) != 0);
+	if (CurDown != down) {
+		MyEvtQEl *p = MyEvtQElAlloc();
+		if (NULL != p) {
+			p->kind = MyEvtQElKindKey;
+			p->u.press.key = k;
+			p->u.press.down = down;
+
+			if (down) {
+				*kpi |= bit;
+			} else {
+				*kpi &= ~ bit;
+			}
+		}
+
+		QuietEnds();
+	}
+}
+
+LOCALVAR blnr MyMouseButtonState = falseblnr;
+
+LOCALPROC MyMouseButtonSet(blnr down)
+{
+	if (MyMouseButtonState != down) {
+		MyEvtQEl *p = MyEvtQElAlloc();
+		if (NULL != p) {
+			p->kind = MyEvtQElKindMouseButton;
+			p->u.press.down = down;
+
+			MyMouseButtonState = down;
+		}
+
+		QuietEnds();
+	}
+}
+
+#if EnableFSMouseMotion
+LOCALPROC MyMousePositionSetDelta(ui4r dh, ui4r dv)
+{
+	if ((dh != 0) || (dv != 0)) {
+		MyEvtQEl *p = MyEvtQElPreviousIn();
+		if ((NULL != p) && (MyEvtQElKindMouseDelta == p->kind)) {
+			p->u.pos.h += dh;
+			p->u.pos.v += dv;
+		} else {
+			p = MyEvtQElAlloc();
+			if (NULL != p) {
+				p->kind = MyEvtQElKindMouseDelta;
+				p->u.pos.h = dh;
+				p->u.pos.v = dv;
+			}
+		}
+
+		QuietEnds();
+	}
+}
+#endif
+
+LOCALVAR ui4b MyMousePosCurV = 0;
+LOCALVAR ui4b MyMousePosCurH = 0;
+
+LOCALPROC MyMousePositionSet(ui4r h, ui4r v)
+{
+	if ((h != MyMousePosCurH) || (v != MyMousePosCurV)) {
+		MyEvtQEl *p = MyEvtQElPreviousIn();
+		if ((NULL == p) || (MyEvtQElKindMousePos != p->kind)) {
+			p = MyEvtQElAlloc();
+		}
+		if (NULL != p) {
+			p->kind = MyEvtQElKindMousePos;
+			p->u.pos.h = h;
+			p->u.pos.v = v;
+
+			MyMousePosCurH = h;
+			MyMousePosCurV = v;
+		}
+
+		QuietEnds();
+	}
+}
+
+#if 0
+#define Keyboard_TestKeyMap(key) \
+	((((ui3b *)theKeys)[(key) / 8] & (1 << ((key) & 7))) != 0)
+#endif
+
+LOCALPROC InitKeyCodes(void)
+{
+	theKeys[0] = 0;
+	theKeys[1] = 0;
+	theKeys[2] = 0;
+	theKeys[3] = 0;
+}
+
+#define kKeepMaskControl  (1 << 0)
+#define kKeepMaskCapsLock (1 << 1)
+#define kKeepMaskCommand  (1 << 2)
+#define kKeepMaskOption   (1 << 3)
+#define kKeepMaskShift    (1 << 4)
+
+LOCALPROC DisconnectKeyCodes(ui5b KeepMask)
+{
+	/*
+		Called when may miss key ups,
+		so act is if all pressed keys have been released,
+		except maybe for control, caps lock, command,
+		option and shift.
+	*/
+
+	int j;
+	int b;
+	int key;
+	ui5b m;
+
+	for (j = 0; j < 16; ++j) {
+		ui3b k1 = ((ui3b *)theKeys)[j];
+		if (0 != k1) {
+			ui3b bit = 1;
+			for (b = 0; b < 8; ++b) {
+				if (0 != (k1 & bit)) {
+					key = j * 8 + b;
+					switch (key) {
+						case MKC_Control: m = kKeepMaskControl; break;
+						case MKC_CapsLock: m = kKeepMaskCapsLock; break;
+						case MKC_Command: m = kKeepMaskCommand; break;
+						case MKC_Option: m = kKeepMaskOption; break;
+						case MKC_Shift: m = kKeepMaskShift; break;
+						default: m = 0; break;
+					}
+					if (0 == (KeepMask & m)) {
+						Keyboard_UpdateKeyMap(key, falseblnr);
+					}
+				}
+				bit <<= 1;
+			}
+		}
+	}
+}
+
+LOCALPROC MyEvtQTryRecoverFromFull(void)
+{
+	MyMouseButtonSet(falseblnr);
+	DisconnectKeyCodes(0);
+}
+
+/* MacMsg */
+
+LOCALVAR char *SavedBriefMsg = nullpr;
+LOCALVAR char *SavedLongMsg;
+#if WantAbnormalReports
+LOCALVAR ui4r SavedIDMsg = 0;
+#endif
+LOCALVAR blnr SavedFatalMsg;
+
+LOCALPROC MacMsg(char *briefMsg, char *longMsg, blnr fatal)
+{
+	if (nullpr != SavedBriefMsg) {
+		/*
+			ignore the new message, only display the
+			first error.
+		*/
+	} else {
+		SavedBriefMsg = briefMsg;
+		SavedLongMsg = longMsg;
+		SavedFatalMsg = fatal;
+	}
+}
+
+#if WantAbnormalReports
+GLOBALOSGLUPROC WarnMsgAbnormalID(ui4r id)
+{
+	MacMsg(kStrReportAbnormalTitle,
+		kStrReportAbnormalMessage, falseblnr);
+
+	if (0 != SavedIDMsg) {
+		/*
+			ignore the new message, only display the
+			first error.
+		*/
+	} else {
+		SavedIDMsg = id;
+	}
+}
+#endif
--- /dev/null
+++ b/src/CONTROLM.h
@@ -1,0 +1,1395 @@
+/*
+	CONTROLM.h
+
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	CONTROL Mode
+*/
+
+#ifdef CONTROLM_H
+#error "header already included"
+#else
+#define CONTROLM_H
+#endif
+
+enum {
+#if EnableDemoMsg
+	SpclModeDemo,
+#endif
+#if EnableAltKeysMode
+	SpclModeAltKeyText,
+#endif
+#if UseActvCode
+	SpclModeActvCode,
+#endif
+	SpclModeNoRom,
+	SpclModeMessage,
+#if UseControlKeys
+	SpclModeControl,
+#endif
+
+	kNumSpclModes
+};
+
+LOCALVAR uimr SpecialModes = 0;
+
+LOCALVAR blnr NeedWholeScreenDraw = falseblnr;
+
+#define SpecialModeSet(i) SpecialModes |= (1 << (i))
+#define SpecialModeClr(i) SpecialModes &= ~ (1 << (i))
+#define SpecialModeTst(i) (0 != (SpecialModes & (1 << (i))))
+
+#define MacMsgDisplayed SpecialModeTst(SpclModeMessage)
+
+LOCALVAR ui3p CntrlDisplayBuff = nullpr;
+
+LOCALPROC DrawCell(unsigned int h, unsigned int v, int x)
+{
+#if 1
+	/* safety check */
+	if ((h < ((long)vMacScreenWidth / 8 - 2))
+		&& (v < (vMacScreenHeight / 16 - 1)))
+#endif
+	{
+		int i;
+		ui3p p0 = ((ui3p)CellData) + 16 * x;
+
+#if 0 != vMacScreenDepth
+		if (UseColorMode) {
+			ui3p p = CntrlDisplayBuff
+				+ ((h + 1) << vMacScreenDepth)
+				+ (v * 16 + 11) * vMacScreenByteWidth;
+
+			for (i = 16; --i >= 0; ) {
+#if 1 == vMacScreenDepth
+				int k;
+				ui3b t0 = *p0;
+				ui3p p2 = p;
+				for (k = 2; --k >= 0; ) {
+					*p2++ = (((t0) & 0x80) ? 0xC0 : 0x00)
+						| (((t0) & 0x40) ? 0x30 : 0x00)
+						| (((t0) & 0x20) ? 0x0C : 0x00)
+						| (((t0) & 0x10) ? 0x03 : 0x00);
+						/* black RRGGBBAA, white RRGGBBAA */
+					t0 <<= 4;
+				}
+#elif 2 == vMacScreenDepth
+				int k;
+				ui3b t0 = *p0;
+				ui3p p2 = p;
+				for (k = 4; --k >= 0; ) {
+					*p2++ = (((t0) & 0x40) ? 0x0F : 0x00)
+						| (((t0) & 0x80) ? 0xF0 : 0x00);
+						/* black RRGGBBAA, white RRGGBBAA */
+					t0 <<= 2;
+				}
+#elif 3 == vMacScreenDepth
+				int k;
+				ui3b t0 = *p0;
+				ui3p p2 = p;
+				for (k = 8; --k >= 0; ) {
+					*p2++ = ((t0 >> k) & 0x01) ? 0xFF : 0x00;
+						/* black RRGGBBAA, white RRGGBBAA */
+				}
+#elif 4 == vMacScreenDepth
+				int k;
+				ui4r v;
+				ui3b t0 = *p0;
+				ui3p p2 = p;
+				for (k = 8; --k >= 0; ) {
+					v = ((t0 >> k) & 0x01) ? 0x0000 : 0x7FFF;
+						/* black RRGGBBAA, white RRGGBBAA */
+					/* *((ui4b *)p2)++ = v; need big endian, so : */
+					*p2++ = v >> 8;
+					*p2++ = v;
+				}
+#elif 5 == vMacScreenDepth
+				int k;
+				ui5r v;
+				ui3b t0 = *p0;
+				ui3p p2 = p;
+				for (k = 8; --k >= 0; ) {
+					v = ((t0 >> k) & 0x01) ? 0x00000000 : 0x00FFFFFF;
+						/* black RRGGBBAA, white RRGGBBAA */
+					/* *((ui5b *)p2)++ = v; need big endian, so : */
+					*p2++ = v >> 24;
+					*p2++ = v >> 16;
+					*p2++ = v >> 8;
+					*p2++ = v;
+				}
+#endif
+				p += vMacScreenByteWidth;
+				p0 ++;
+			}
+		} else
+#endif
+		{
+			ui3p p = CntrlDisplayBuff + (h + 1)
+				+ (v * 16 + 11) * vMacScreenMonoByteWidth;
+
+			for (i = 16; --i >= 0; ) {
+				*p = *p0;
+				p += vMacScreenMonoByteWidth;
+				p0 ++;
+			}
+		}
+	}
+}
+
+#define ControlBoxh0 0
+#define ControlBoxw 62
+#define ControlBoxv0 0
+
+#define hLimit (ControlBoxh0 + ControlBoxw - 1)
+#define hStart (ControlBoxh0 + 1)
+
+
+LOCALVAR int CurCellh0;
+LOCALVAR int CurCellv0;
+
+LOCALPROC DrawCellsBeginLine(void)
+{
+	DrawCell(ControlBoxh0, CurCellv0, kCellMiddleLeft);
+	CurCellh0 = hStart;
+}
+
+LOCALPROC DrawCellsEndLine(void)
+{
+	int i;
+
+	for (i = CurCellh0; i < hLimit; ++i) {
+		DrawCell(i, CurCellv0, kCellSpace);
+	}
+	DrawCell(hLimit, CurCellv0, kCellMiddleRight);
+	CurCellv0++;
+}
+
+LOCALPROC DrawCellsBottomLine(void)
+{
+	int i;
+
+	DrawCell(ControlBoxh0 + 0, CurCellv0, kCellLowerLeft);
+	for (i = hStart; i < hLimit; ++i) {
+		DrawCell(i, CurCellv0, kCellLowerMiddle);
+	}
+	DrawCell(hLimit, CurCellv0, kCellLowerRight);
+}
+
+LOCALPROC DrawCellAdvance(int x)
+{
+	DrawCell(CurCellh0, CurCellv0, x);
+	CurCellh0++;
+}
+
+LOCALPROC DrawCellsBlankLine(void)
+{
+	DrawCellsBeginLine();
+	DrawCellsEndLine();
+}
+
+LOCALPROC DrawCellsFromStr(char *s)
+{
+	ui3b ps[ClStrMaxLength];
+	ui3b cs;
+	int L;
+	int i;
+	int j;
+	int w;
+
+	ClStrFromSubstCStr(&L, ps, s);
+
+	i = 0;
+
+	while (i < L) {
+		cs = ps[i];
+		i++;
+		if (CurCellh0 < hLimit) {
+			DrawCellAdvance(cs);
+		} else {
+			/* line is too wide, wrap */
+			if (kCellSpace != cs) {
+				--i; /* back up one char, at least */
+
+				/* now try backing up to beginning of word */
+				j = i;
+				w = CurCellh0 - hStart;
+
+				while ((w > 0) && (j > 0)
+					&& (ps[j - 1] != kCellSpace))
+				{
+					--j;
+					--w;
+				}
+				if (w != 0) {
+					i = j;
+					CurCellh0 = hStart + w;
+				}
+				/*
+					else if w == 0, then have backed up to
+					beginning of line, so just let the word
+					be split.
+				*/
+			}
+			/*
+				else if cs == kCellSpace, just lose the space.
+			*/
+			DrawCellsEndLine();
+				/*
+					draw white space over the part of
+					the word that have already drawn
+				*/
+			DrawCellsBeginLine();
+		}
+	}
+}
+
+LOCALPROC DrawCellsOneLineStr(char *s)
+{
+	DrawCellsBeginLine();
+	DrawCellsFromStr(s);
+	DrawCellsEndLine();
+}
+
+LOCALPROC DrawCellsKeyCommand(char *k, char *s)
+{
+	DrawCellsBeginLine();
+	DrawCellsFromStr(" ");
+	DrawCellsFromStr(k);
+	DrawCellsFromStr(" - ");
+	DrawCellsFromStr(s);
+	DrawCellsEndLine();
+}
+
+typedef void (*SpclModeBody) (void);
+
+LOCALPROC DrawSpclMode0(char *Title, SpclModeBody Body)
+{
+	int i;
+	int k;
+
+	CurCellv0 = ControlBoxv0 + 0;
+	DrawCell(ControlBoxh0 + 0, CurCellv0, kCellUpperLeft);
+	k = kCellIcon00;
+	for (i = hStart; i < hStart + 4; ++i) {
+		DrawCell(i, CurCellv0, k);
+		k++;
+	}
+	for (i = hStart + 4; i < hLimit; ++i) {
+		DrawCell(i, CurCellv0, kCellUpperMiddle);
+	}
+	DrawCell(hLimit, CurCellv0, kCellUpperRight);
+	++CurCellv0;
+
+	DrawCellsBeginLine();
+	for (i = hStart; i < hStart + 4; ++i) {
+		DrawCellAdvance(k);
+		k++;
+	}
+	DrawCellAdvance(kCellSpace);
+	DrawCellsFromStr(Title);
+	DrawCellsEndLine();
+
+	DrawCellsBeginLine();
+	for (i = hStart; i < hStart + 4; ++i) {
+		DrawCellAdvance(k);
+		k++;
+	}
+	for (i = hStart + 4; i < hLimit; ++i) {
+		DrawCellAdvance(kCellGraySep);
+	}
+	DrawCellsEndLine();
+
+	if (nullpr != Body) {
+		Body();
+	}
+
+	DrawCellsBottomLine();
+}
+
+#if EnableAltKeysMode
+#include "ALTKEYSM.h"
+#else
+#define Keyboard_UpdateKeyMap1 Keyboard_UpdateKeyMap
+#define DisconnectKeyCodes1 DisconnectKeyCodes
+#endif
+
+#if WantAbnormalReports || UseActvFile
+LOCALPROC ClStrAppendHexNib(int *L0, ui3b *r, ui3r v)
+{
+	if (v < 10) {
+		ClStrAppendChar(L0, r, kCellDigit0 + v);
+	} else {
+		ClStrAppendChar(L0, r, kCellUpA + (v - 10));
+	}
+}
+#endif
+
+#if WantAbnormalReports || UseActvFile
+LOCALPROC ClStrAppendHexByte(int *L0, ui3b *r, ui3r v)
+{
+	ClStrAppendHexNib(L0, r, (v >> 4) & 0x0F);
+	ClStrAppendHexNib(L0, r, v & 0x0F);
+}
+#endif
+
+#if WantAbnormalReports || UseActvFile
+LOCALPROC ClStrAppendHexWord(int *L0, ui3b *r, ui4r v)
+{
+	ClStrAppendHexByte(L0, r, (v >> 8) & 0xFF);
+	ClStrAppendHexByte(L0, r, v & 0xFF);
+}
+#endif
+
+#if WantAbnormalReports
+LOCALPROC DrawCellsOneLineHexWord(ui4r v)
+{
+	ui3b ps[ClStrMaxLength];
+	int L = 0;
+	int i;
+
+	ClStrAppendHexWord(&L, ps, v);
+
+	DrawCellsBeginLine();
+	for (i = 0; i < L; ++i) {
+		DrawCellAdvance(ps[i]);
+	}
+	DrawCellsEndLine();
+}
+#endif
+
+LOCALPROC DrawCellsMessageModeBody(void)
+{
+	DrawCellsOneLineStr(SavedBriefMsg);
+	DrawCellsBlankLine();
+	DrawCellsOneLineStr(SavedLongMsg);
+#if WantAbnormalReports
+	if (0 != SavedIDMsg) {
+		DrawCellsBlankLine();
+		DrawCellsOneLineHexWord(SavedIDMsg);
+	}
+#endif
+}
+
+LOCALPROC DrawMessageMode(void)
+{
+	DrawSpclMode0(kStrModeMessage, DrawCellsMessageModeBody);
+}
+
+LOCALPROC MacMsgDisplayOff(void)
+{
+	SpecialModeClr(SpclModeMessage);
+	SavedBriefMsg = nullpr;
+#if WantAbnormalReports
+	SavedIDMsg = 0;
+#endif
+	NeedWholeScreenDraw = trueblnr;
+}
+
+LOCALPROC MacMsgDisplayOn(void)
+{
+	NeedWholeScreenDraw = trueblnr;
+	DisconnectKeyCodes1(kKeepMaskControl | kKeepMaskCapsLock);
+		/* command */
+	SpecialModeSet(SpclModeMessage);
+}
+
+LOCALPROC DoMessageModeKey(ui3r key)
+{
+	if (MKC_C == key) {
+		MacMsgDisplayOff();
+	}
+}
+
+LOCALPROC MacMsgOverride(char *briefMsg, char *longMsg)
+{
+	if (MacMsgDisplayed) {
+		MacMsgDisplayOff();
+	}
+	MacMsg(briefMsg, longMsg, falseblnr);
+}
+
+#if NeedDoMoreCommandsMsg
+LOCALPROC DoMoreCommandsMsg(void)
+{
+	MacMsgOverride(kStrMoreCommandsTitle,
+		kStrMoreCommandsMessage);
+}
+#endif
+
+#if NeedDoAboutMsg
+LOCALPROC DoAboutMsg(void)
+{
+	MacMsgOverride(kStrAboutTitle,
+		kStrAboutMessage);
+}
+#endif
+
+LOCALPROC NoRomMsgDisplayOff(void)
+{
+	SpecialModeClr(SpclModeNoRom);
+	NeedWholeScreenDraw = trueblnr;
+}
+
+LOCALPROC NoRomMsgDisplayOn(void)
+{
+	NeedWholeScreenDraw = trueblnr;
+	SpecialModeSet(SpclModeNoRom);
+}
+
+LOCALPROC DrawCellsNoRomModeBody(void)
+{
+	DrawCellsOneLineStr(kStrNoROMMessage);
+}
+
+LOCALPROC DrawNoRomMode(void)
+{
+	DrawSpclMode0(kStrNoROMTitle, DrawCellsNoRomModeBody);
+}
+
+#if UseControlKeys
+
+LOCALVAR blnr LastControlKey = falseblnr;
+LOCALVAR int CurControlMode = 0;
+LOCALVAR int ControlMessage = 0;
+
+enum {
+	kCntrlModeOff,
+	kCntrlModeBase,
+#if WantEnblCtrlRst
+	kCntrlModeConfirmReset,
+#endif
+#if WantEnblCtrlInt
+	kCntrlModeConfirmInterrupt,
+#endif
+	kCntrlModeConfirmQuit,
+	kCntrlModeSpeedControl,
+
+	kNumCntrlModes
+};
+
+enum {
+	kCntrlMsgBaseStart,
+#if EnableMagnify
+	kCntrlMsgMagnify,
+#endif
+#if VarFullScreen
+	kCntrlMsgFullScreen,
+#endif
+#if WantEnblCtrlRst
+	kCntrlMsgConfirmResetStart,
+	kCntrlMsgHaveReset,
+	kCntrlMsgResetCancelled,
+#endif
+#if WantEnblCtrlInt
+	kCntrlMsgConfirmInterruptStart,
+	kCntrlMsgHaveInterrupted,
+	kCntrlMsgInterruptCancelled,
+#endif
+	kCntrlMsgConfirmQuitStart,
+	kCntrlMsgQuitCancelled,
+#if WantEnblCtrlKtg
+	kCntrlMsgEmCntrl,
+#endif
+	kCntrlMsgSpeedControlStart,
+	kCntrlMsgNewSpeed,
+	kCntrlMsgNewStopped,
+	kCntrlMsgNewRunInBack,
+#if EnableAutoSlow
+	kCntrlMsgNewAutoSlow,
+#endif
+	kCntrlMsgAbout,
+	kCntrlMsgHelp,
+#if IncludePbufs
+	kCntrlMsgOptionsStrCopied,
+#endif
+#if 0 && (UseActvCode || EnableDemoMsg)
+	kCntrlMsgRegStrCopied,
+#endif
+
+	kNumCntrlMsgs
+};
+
+LOCALPROC DoEnterControlMode(void)
+{
+	CurControlMode = kCntrlModeBase;
+	ControlMessage = kCntrlMsgBaseStart;
+	NeedWholeScreenDraw = trueblnr;
+	DisconnectKeyCodes1(kKeepMaskControl | kKeepMaskCapsLock);
+	SpecialModeSet(SpclModeControl);
+}
+
+LOCALPROC DoLeaveControlMode(void)
+{
+	SpecialModeClr(SpclModeControl);
+	CurControlMode = kCntrlModeOff;
+	NeedWholeScreenDraw = trueblnr;
+}
+
+LOCALPROC Keyboard_UpdateControlKey(blnr down)
+{
+	if (down != LastControlKey) {
+		LastControlKey = down;
+		if (down) {
+			DoEnterControlMode();
+		} else {
+			DoLeaveControlMode();
+		}
+	}
+}
+
+LOCALPROC SetSpeedValue(ui3b i)
+{
+	SpeedValue = i;
+	CurControlMode = kCntrlModeBase;
+	ControlMessage = kCntrlMsgNewSpeed;
+}
+
+#if VarFullScreen
+FORWARDPROC ToggleWantFullScreen(void);
+#endif
+
+#if IncludeHostTextClipExchange
+LOCALPROC HTCEexportSubstCStr(char *s)
+{
+	int i;
+	int L;
+	tPbuf j;
+#ifdef PbufHaveLock
+	int n = ClStrSizeSubstCStr(s);
+
+	if (mnvm_noErr == PbufNew(n, &j)) {
+		blnr IsOk = falseblnr;
+		ui3p p = PbufLock(j);
+
+		if (nullpr != p) {
+			L = 0;
+			ClStrAppendSubstCStr(&L, p, s);
+
+			if (L == n) {
+				for (i = 0; i < n; ++i) {
+					p[i] = Cell2MacAsciiMap[p[i]];
+				}
+				IsOk = trueblnr;
+			}
+
+			PbufUnlock(j);
+		}
+
+		if (IsOk) {
+			HTCEexport(j);
+		} else {
+			PbufDispose(j);
+		}
+	}
+#else
+	ui3b ps[ClStrMaxLength];
+
+	ClStrFromSubstCStr(&L, ps, s);
+
+	for (i = 0; i < L; ++i) {
+		ps[i] = Cell2MacAsciiMap[ps[i]];
+	}
+
+	if (mnvm_noErr == PbufNew(L, &j)) {
+		PbufTransfer(ps, j, 0, L, trueblnr);
+		HTCEexport(j);
+	}
+#endif
+}
+#endif
+
+#if IncludeHostTextClipExchange
+LOCALPROC CopyOptionsStr(void)
+{
+	HTCEexportSubstCStr(kBldOpts);
+}
+#endif
+
+#if 0
+#if UseActvCode
+FORWARDPROC CopyRegistrationStr(void);
+#elif EnableDemoMsg
+LOCALPROC CopyRegistrationStr(void)
+{
+	HTCEexportSubstCStr("^v");
+}
+#endif
+#endif
+
+
+LOCALPROC DoControlModeKey(ui3r key)
+{
+	switch (CurControlMode) {
+		case kCntrlModeBase:
+			switch (key) {
+#if WantEnblCtrlKtg
+				case MKC_K:
+					ControlKeyPressed = ! ControlKeyPressed;
+					ControlMessage = kCntrlMsgEmCntrl;
+					Keyboard_UpdateKeyMap1(MKC_UnMappedKey,
+						ControlKeyPressed);
+					break;
+#endif
+				case MKC_S:
+					CurControlMode = kCntrlModeSpeedControl;
+					ControlMessage = kCntrlMsgSpeedControlStart;
+					break;
+#if WantEnblCtrlInt
+				case MKC_I:
+					CurControlMode = kCntrlModeConfirmInterrupt;
+					ControlMessage = kCntrlMsgConfirmInterruptStart;
+					break;
+#endif
+#if WantEnblCtrlRst
+				case MKC_R:
+					if (! AnyDiskInserted()) {
+						WantMacReset = trueblnr;
+						ControlMessage = kCntrlMsgHaveReset;
+					} else {
+						CurControlMode = kCntrlModeConfirmReset;
+						ControlMessage = kCntrlMsgConfirmResetStart;
+					}
+					break;
+#endif
+				case MKC_Q:
+					if (! AnyDiskInserted()) {
+						ForceMacOff = trueblnr;
+					} else {
+						CurControlMode = kCntrlModeConfirmQuit;
+						ControlMessage = kCntrlMsgConfirmQuitStart;
+					}
+					break;
+				case MKC_A:
+					ControlMessage = kCntrlMsgAbout;
+					break;
+				case MKC_H:
+					ControlMessage = kCntrlMsgHelp;
+					break;
+#if NeedRequestInsertDisk
+				case MKC_O:
+					RequestInsertDisk = trueblnr;
+					break;
+#endif
+#if EnableMagnify
+				case MKC_M:
+					WantMagnify = ! WantMagnify;
+					ControlMessage = kCntrlMsgMagnify;
+					break;
+#endif
+#if VarFullScreen
+				case MKC_F:
+					ToggleWantFullScreen();
+					ControlMessage = kCntrlMsgFullScreen;
+					break;
+#endif
+#if IncludeHostTextClipExchange
+				case MKC_P:
+					CopyOptionsStr();
+					ControlMessage = kCntrlMsgOptionsStrCopied;
+					break;
+#endif
+#if 0 && (UseActvCode || EnableDemoMsg)
+				case MKC_P:
+					CopyRegistrationStr();
+					ControlMessage = kCntrlMsgRegStrCopied;
+					break;
+#endif
+#if NeedRequestIthDisk
+				case MKC_1:
+					RequestIthDisk = 1;
+					break;
+				case MKC_2:
+					RequestIthDisk = 2;
+					break;
+				case MKC_3:
+					RequestIthDisk = 3;
+					break;
+				case MKC_4:
+					RequestIthDisk = 4;
+					break;
+				case MKC_5:
+					RequestIthDisk = 5;
+					break;
+				case MKC_6:
+					RequestIthDisk = 6;
+					break;
+				case MKC_7:
+					RequestIthDisk = 7;
+					break;
+				case MKC_8:
+					RequestIthDisk = 8;
+					break;
+				case MKC_9:
+					RequestIthDisk = 9;
+					break;
+#endif
+			}
+			break;
+#if WantEnblCtrlRst
+		case kCntrlModeConfirmReset:
+			switch (key) {
+				case MKC_Y:
+					WantMacReset = trueblnr;
+					CurControlMode = kCntrlModeBase;
+					ControlMessage = kCntrlMsgHaveReset;
+					break;
+				case MKC_R:
+					/* ignore, in case of repeat */
+					break;
+				case MKC_N:
+				default:
+					CurControlMode = kCntrlModeBase;
+					ControlMessage = kCntrlMsgResetCancelled;
+					break;
+			}
+			break;
+#endif
+#if WantEnblCtrlInt
+		case kCntrlModeConfirmInterrupt:
+			switch (key) {
+				case MKC_Y:
+					WantMacInterrupt = trueblnr;
+					CurControlMode = kCntrlModeBase;
+					ControlMessage = kCntrlMsgHaveInterrupted;
+					break;
+				case MKC_I:
+					/* ignore, in case of repeat */
+					break;
+				case MKC_N:
+				default:
+					CurControlMode = kCntrlModeBase;
+					ControlMessage = kCntrlMsgInterruptCancelled;
+					break;
+			}
+			break;
+#endif
+		case kCntrlModeConfirmQuit:
+			switch (key) {
+				case MKC_Y:
+					ForceMacOff = trueblnr;
+					CurControlMode = kCntrlModeBase;
+					ControlMessage = kCntrlMsgBaseStart;
+						/* shouldn't see this message since quitting */
+					break;
+				case MKC_Q:
+					/* ignore, in case of repeat */
+					break;
+				case MKC_N:
+				default:
+					CurControlMode = kCntrlModeBase;
+					ControlMessage = kCntrlMsgQuitCancelled;
+					break;
+			}
+			break;
+		case kCntrlModeSpeedControl:
+			switch (key) {
+				case MKC_E:
+					CurControlMode = kCntrlModeBase;
+					ControlMessage = kCntrlMsgBaseStart;
+					break;
+				case MKC_B:
+					RunInBackground = ! RunInBackground;
+					CurControlMode = kCntrlModeBase;
+					ControlMessage = kCntrlMsgNewRunInBack;
+					break;
+				case MKC_D:
+					if (ROM_loaded) {
+						SpeedStopped = ! SpeedStopped;
+						CurControlMode = kCntrlModeBase;
+						ControlMessage = kCntrlMsgNewStopped;
+					}
+					break;
+#if EnableAutoSlow
+				case MKC_W:
+					WantNotAutoSlow = ! WantNotAutoSlow;
+					CurControlMode = kCntrlModeBase;
+					ControlMessage = kCntrlMsgNewAutoSlow;
+					break;
+#endif
+				case MKC_Z:
+					SetSpeedValue(0);
+					break;
+				case MKC_1:
+					SetSpeedValue(1);
+					break;
+				case MKC_2:
+					SetSpeedValue(2);
+					break;
+				case MKC_3:
+					SetSpeedValue(3);
+					break;
+				case MKC_4:
+					SetSpeedValue(4);
+					break;
+				case MKC_5:
+					SetSpeedValue(5);
+					break;
+				case MKC_A:
+					SetSpeedValue((ui3b) -1);
+					break;
+			}
+			break;
+	}
+	NeedWholeScreenDraw = trueblnr;
+}
+
+LOCALFUNC char * ControlMode2TitleStr(void)
+{
+	char *s;
+
+	switch (CurControlMode) {
+#if WantEnblCtrlRst
+		case kCntrlModeConfirmReset:
+			s = kStrModeConfirmReset;
+			break;
+#endif
+#if WantEnblCtrlInt
+		case kCntrlModeConfirmInterrupt:
+			s = kStrModeConfirmInterrupt;
+			break;
+#endif
+		case kCntrlModeConfirmQuit:
+			s = kStrModeConfirmQuit;
+			break;
+		case kCntrlModeSpeedControl:
+			s = kStrModeSpeedControl;
+			break;
+		case kCntrlModeBase:
+		default:
+			if (kCntrlMsgHelp == ControlMessage) {
+				s = kStrModeControlHelp;
+			} else {
+				s = kStrModeControlBase;
+			}
+			break;
+	}
+
+	return s;
+}
+
+LOCALPROC DrawCellsControlModeBody(void)
+{
+	switch (ControlMessage) {
+		case kCntrlMsgAbout:
+			DrawCellsOneLineStr(kStrProgramInfo);
+
+			DrawCellsBlankLine();
+
+			DrawCellsOneLineStr(kStrWorkOfMany);
+			DrawCellsOneLineStr(kMaintainerName);
+			DrawCellsOneLineStr(kStrForMoreInfo);
+			DrawCellsOneLineStr("^w");
+
+			DrawCellsBlankLine();
+
+			DrawCellsBeginLine();
+			DrawCellsFromStr(kStrLicense);
+			DrawCellsFromStr(kStrDisclaimer);
+			DrawCellsEndLine();
+
+			break;
+
+		case kCntrlMsgHelp:
+			DrawCellsOneLineStr(kStrHowToLeaveControl);
+			DrawCellsOneLineStr(kStrHowToPickACommand);
+			DrawCellsBlankLine();
+			DrawCellsKeyCommand("A", kStrCmdAbout);
+#if NeedRequestInsertDisk
+			DrawCellsKeyCommand("O", kStrCmdOpenDiskImage);
+#endif
+			DrawCellsKeyCommand("Q", kStrCmdQuit);
+			DrawCellsKeyCommand("S", kStrCmdSpeedControl);
+#if EnableMagnify
+			DrawCellsKeyCommand("M", kStrCmdMagnifyToggle);
+#endif
+#if VarFullScreen
+			DrawCellsKeyCommand("F", kStrCmdFullScrnToggle);
+#endif
+#if WantEnblCtrlKtg
+			DrawCellsKeyCommand("K", kStrCmdCtrlKeyToggle);
+#endif
+#if WantEnblCtrlRst
+			DrawCellsKeyCommand("R", kStrCmdReset);
+#endif
+#if WantEnblCtrlInt
+			DrawCellsKeyCommand("I", kStrCmdInterrupt);
+#endif
+			DrawCellsKeyCommand("P", kStrCmdCopyOptions);
+			DrawCellsKeyCommand("H", kStrCmdHelp);
+			break;
+		case kCntrlMsgSpeedControlStart:
+			DrawCellsOneLineStr(kStrCurrentSpeed);
+			DrawCellsKeyCommand("Z", "1x");
+			DrawCellsKeyCommand("1", "2x");
+			DrawCellsKeyCommand("2", "4x");
+			DrawCellsKeyCommand("3", "8x");
+			DrawCellsKeyCommand("4", "16x");
+			DrawCellsKeyCommand("5", "32x");
+			DrawCellsKeyCommand("A", kStrSpeedAllOut);
+			DrawCellsBlankLine();
+			DrawCellsKeyCommand("D", kStrSpeedStopped);
+			DrawCellsKeyCommand("B", kStrSpeedBackToggle);
+#if EnableAutoSlow
+			DrawCellsKeyCommand("W", kStrSpeedAutoSlowToggle);
+#endif
+			DrawCellsBlankLine();
+			DrawCellsKeyCommand("E", kStrSpeedExit);
+			break;
+		case kCntrlMsgNewSpeed:
+			DrawCellsOneLineStr(kStrNewSpeed);
+			break;
+		case kCntrlMsgNewRunInBack:
+			DrawCellsOneLineStr(kStrNewRunInBack);
+			break;
+		case kCntrlMsgNewStopped:
+			DrawCellsOneLineStr(kStrNewStopped);
+			break;
+#if EnableAutoSlow
+		case kCntrlMsgNewAutoSlow:
+			DrawCellsOneLineStr(kStrNewAutoSlow);
+			break;
+#endif
+#if EnableMagnify
+		case kCntrlMsgMagnify:
+			DrawCellsOneLineStr(kStrNewMagnify);
+			break;
+#endif
+#if VarFullScreen
+		case kCntrlMsgFullScreen:
+			DrawCellsOneLineStr(kStrNewFullScreen);
+			break;
+#endif
+#if IncludeHostTextClipExchange
+		case kCntrlMsgOptionsStrCopied:
+			DrawCellsOneLineStr(kStrHaveCopiedOptions);
+			break;
+#endif
+#if 0
+#if UseActvCode
+		case kCntrlMsgRegStrCopied:
+			DrawCellsOneLineStr("Registration String copied.");
+			break;
+#elif EnableDemoMsg
+		case kCntrlMsgRegStrCopied:
+			DrawCellsOneLineStr("Variation name copied.");
+			break;
+#endif
+#endif
+#if WantEnblCtrlRst
+		case kCntrlMsgConfirmResetStart:
+			DrawCellsOneLineStr(kStrConfirmReset);
+			DrawCellsBlankLine();
+			DrawCellsKeyCommand("Y", kStrResetDo);
+			DrawCellsKeyCommand("N", kStrResetNo);
+			break;
+		case kCntrlMsgHaveReset:
+			DrawCellsOneLineStr(kStrHaveReset);
+			break;
+		case kCntrlMsgResetCancelled:
+			DrawCellsOneLineStr(kStrCancelledReset);
+			break;
+#endif
+#if WantEnblCtrlInt
+		case kCntrlMsgConfirmInterruptStart:
+			DrawCellsOneLineStr(kStrConfirmInterrupt);
+			DrawCellsBlankLine();
+			DrawCellsKeyCommand("Y", kStrInterruptDo);
+			DrawCellsKeyCommand("N", kStrInterruptNo);
+			break;
+		case kCntrlMsgHaveInterrupted:
+			DrawCellsOneLineStr(kStrHaveInterrupted);
+			break;
+		case kCntrlMsgInterruptCancelled:
+			DrawCellsOneLineStr(kStrCancelledInterrupt);
+			break;
+#endif
+		case kCntrlMsgConfirmQuitStart:
+			DrawCellsOneLineStr(kStrConfirmQuit);
+			DrawCellsBlankLine();
+			DrawCellsKeyCommand("Y", kStrQuitDo);
+			DrawCellsKeyCommand("N", kStrQuitNo);
+			break;
+		case kCntrlMsgQuitCancelled:
+			DrawCellsOneLineStr(kStrCancelledQuit);
+			break;
+#if WantEnblCtrlKtg
+		case kCntrlMsgEmCntrl:
+			DrawCellsOneLineStr(kStrNewCntrlKey);
+			break;
+#endif
+		case kCntrlMsgBaseStart:
+		default:
+			DrawCellsOneLineStr(kStrHowToLeaveControl);
+			break;
+	}
+}
+
+LOCALPROC DrawControlMode(void)
+{
+	DrawSpclMode0(ControlMode2TitleStr(), DrawCellsControlModeBody);
+}
+
+#endif /* UseControlKeys */
+
+#if EnableDemoMsg
+
+LOCALPROC DrawDemoMode(void)
+{
+	CurCellv0 = ControlBoxv0 + ((9 * CurMacDateInSeconds) & 0x0F);
+	CurCellh0 = ControlBoxh0 + ((15 * CurMacDateInSeconds) & 0x1F);
+
+	DrawCellAdvance(kCellDemo0);
+	DrawCellAdvance(kCellDemo6);
+	DrawCellAdvance(kCellDemo6);
+	DrawCellAdvance(kCellDemo7);
+	DrawCellAdvance(kCellDemo1);
+	DrawCellAdvance(kCellDemo2);
+	DrawCellAdvance(kCellDemo3);
+	DrawCellAdvance(kCellDemo4);
+	DrawCellAdvance(kCellDemo7);
+	DrawCellAdvance(kCellDemo6);
+	DrawCellAdvance(kCellDemo6);
+	DrawCellAdvance(kCellDemo5);
+}
+
+LOCALPROC DemoModeSecondNotify(void)
+{
+	NeedWholeScreenDraw = trueblnr;
+	SpecialModeSet(SpclModeDemo);
+}
+
+#endif /* EnableDemoMsg */
+
+#if UseActvCode
+#include "ACTVCODE.h"
+#endif
+
+LOCALPROC DrawSpclMode(void)
+{
+#if UseControlKeys
+	if (SpecialModeTst(SpclModeControl)) {
+		DrawControlMode();
+	} else
+#endif
+	if (SpecialModeTst(SpclModeMessage)) {
+		DrawMessageMode();
+	} else
+	if (SpecialModeTst(SpclModeNoRom)) {
+		DrawNoRomMode();
+	} else
+#if UseActvCode
+	if (SpecialModeTst(SpclModeActvCode)) {
+		DrawActvCodeMode();
+	} else
+#endif
+#if EnableAltKeysMode
+	if (SpecialModeTst(SpclModeAltKeyText)) {
+		DrawAltKeyMode();
+	} else
+#endif
+#if EnableDemoMsg
+	if (SpecialModeTst(SpclModeDemo)) {
+		DrawDemoMode();
+	} else
+#endif
+	{
+		/* should not get here */
+	}
+}
+
+LOCALFUNC ui3p GetCurDrawBuff(void)
+{
+	ui3p p = screencomparebuff;
+
+	if (0 != SpecialModes) {
+		MyMoveBytes((anyp)p, (anyp)CntrlDisplayBuff,
+#if 0 != vMacScreenDepth
+			UseColorMode ? vMacScreenNumBytes :
+#endif
+				vMacScreenMonoNumBytes
+			);
+		p = CntrlDisplayBuff;
+
+		DrawSpclMode();
+	}
+
+	return p;
+}
+
+#ifdef WantKeyboard_RemapMac
+LOCALFUNC ui3r Keyboard_RemapMac(ui3r key)
+{
+	switch (key) {
+#if MKC_formac_Control != MKC_Control
+		case MKC_Control:
+			key = MKC_formac_Control;
+			break;
+#endif
+#if MKC_formac_Command != MKC_Command
+		case MKC_Command:
+			key = MKC_formac_Command;
+			break;
+#endif
+#if MKC_formac_Option != MKC_Option
+		case MKC_Option:
+			key = MKC_formac_Option;
+			break;
+#endif
+#if MKC_formac_Shift != MKC_Shift
+		case MKC_Shift:
+			key = MKC_formac_Shift;
+			break;
+#endif
+#if MKC_formac_CapsLock != MKC_CapsLock
+		case MKC_CapsLock:
+			key = MKC_formac_CapsLock;
+			break;
+#endif
+#if MKC_formac_F1 != MKC_F1
+		case MKC_F1:
+			key = MKC_formac_F1;
+			break;
+#endif
+#if MKC_formac_F2 != MKC_F2
+		case MKC_F2:
+			key = MKC_formac_F2;
+			break;
+#endif
+#if MKC_formac_F3 != MKC_F3
+		case MKC_F3:
+			key = MKC_formac_F3;
+			break;
+#endif
+#if MKC_formac_F4 != MKC_F4
+		case MKC_F4:
+			key = MKC_formac_F4;
+			break;
+#endif
+#if MKC_formac_F5 != MKC_F5
+		case MKC_F5:
+			key = MKC_formac_F5;
+			break;
+#endif
+#if MKC_formac_Escape != MKC_Escape
+		case MKC_Escape:
+			key = MKC_formac_Escape;
+			break;
+#endif
+#if MKC_formac_BackSlash != MKC_BackSlash
+		case MKC_BackSlash:
+			key = MKC_formac_BackSlash;
+			break;
+#endif
+#if MKC_formac_Slash != MKC_Slash
+		case MKC_Slash:
+			key = MKC_formac_Slash;
+			break;
+#endif
+#if MKC_formac_Grave != MKC_Grave
+		case MKC_Grave:
+			key = MKC_formac_Grave;
+			break;
+#endif
+#if MKC_formac_Enter != MKC_Enter
+		case MKC_Enter:
+			key = MKC_formac_Enter;
+			break;
+#endif
+#if MKC_formac_PageUp != MKC_PageUp
+		case MKC_PageUp:
+			key = MKC_formac_PageUp;
+			break;
+#endif
+#if MKC_formac_PageDown != MKC_PageDown
+		case MKC_PageDown:
+			key = MKC_formac_PageDown;
+			break;
+#endif
+#if MKC_formac_Home != MKC_Home
+		case MKC_Home:
+			key = MKC_formac_Home;
+			break;
+#endif
+#if MKC_formac_End != MKC_End
+		case MKC_End:
+			key = MKC_formac_End;
+			break;
+#endif
+#if MKC_formac_Help != MKC_Help
+		case MKC_Help:
+			key = MKC_formac_Help;
+			break;
+#endif
+#if MKC_formac_ForwardDel != MKC_ForwardDel
+		case MKC_ForwardDel:
+			key = MKC_formac_ForwardDel;
+			break;
+#endif
+		default:
+			break;
+	}
+
+	return key;
+}
+#endif /* WantKeyboard_RemapMac */
+
+LOCALPROC Keyboard_UpdateKeyMap2(ui3r key, blnr down)
+{
+#if UseControlKeys
+	if (MKC_CM == key) {
+		Keyboard_UpdateControlKey(down);
+	} else
+#endif
+	if ((0 == SpecialModes)
+#if EnableAltKeysMode || EnableDemoMsg
+			|| (0 == (SpecialModes & ~ (
+				0
+#if EnableAltKeysMode
+				| (1 << SpclModeAltKeyText)
+#endif
+#if EnableDemoMsg
+				| (1 << SpclModeDemo)
+#endif
+				)))
+#endif
+			|| (MKC_CapsLock == key)
+		)
+	{
+		/* pass through */
+		Keyboard_UpdateKeyMap1(key, down);
+	} else {
+		if (down) {
+#if UseControlKeys
+			if (SpecialModeTst(SpclModeControl)) {
+				DoControlModeKey(key);
+			} else
+#endif
+			if (SpecialModeTst(SpclModeMessage)) {
+				DoMessageModeKey(key);
+			} else
+#if UseActvCode
+			if (SpecialModeTst(SpclModeActvCode)) {
+				DoActvCodeModeKey(key);
+			} else
+#endif
+			{
+			}
+		} /* else if not down ignore */
+	}
+}
+
+LOCALPROC DisconnectKeyCodes2(void)
+{
+	DisconnectKeyCodes1(kKeepMaskControl | kKeepMaskCapsLock);
+#if UseControlKeys
+	Keyboard_UpdateControlKey(falseblnr);
+#endif
+}
+
+#ifndef CheckRomCheckSum
+#define CheckRomCheckSum 1
+#endif
+
+#if CheckRomCheckSum
+LOCALFUNC ui5r Calc_Checksum(void)
+{
+	long int i;
+	ui5b CheckSum = 0;
+	ui3p p = 4 + ROM;
+
+	for (i = (kCheckSumRom_Size - 4) >> 1; --i >= 0; ) {
+		CheckSum += do_get_mem_word(p);
+		p += 2;
+	}
+
+	return CheckSum;
+}
+#endif
+
+#if CheckRomCheckSum && RomStartCheckSum
+LOCALPROC WarnMsgCorruptedROM(void)
+{
+	MacMsgOverride(kStrCorruptedROMTitle, kStrCorruptedROMMessage);
+}
+#endif
+
+#if CheckRomCheckSum
+LOCALPROC WarnMsgUnsupportedROM(void)
+{
+	MacMsgOverride(kStrUnsupportedROMTitle,
+		kStrUnsupportedROMMessage);
+}
+#endif
+
+LOCALFUNC tMacErr ROM_IsValid(void)
+{
+#if CheckRomCheckSum
+	ui5r CheckSum = Calc_Checksum();
+
+#if RomStartCheckSum
+	if (CheckSum != do_get_mem_long(ROM)) {
+		WarnMsgCorruptedROM();
+		return mnvm_miscErr;
+	} else
+#endif
+#ifdef kRomCheckSum1
+	if (CheckSum == kRomCheckSum1) {
+	} else
+#endif
+#ifdef kRomCheckSum2
+	if (CheckSum == kRomCheckSum2) {
+	} else
+#endif
+#ifdef kRomCheckSum3
+	if (CheckSum == kRomCheckSum3) {
+	} else
+#endif
+	{
+		WarnMsgUnsupportedROM();
+		return mnvm_miscErr;
+	}
+	/*
+		Even if ROM is corrupt or unsupported, go ahead and
+		try to run anyway. It shouldn't do any harm.
+		[update: no, don't]
+	*/
+
+#endif /* CheckRomCheckSum */
+
+	ROM_loaded = trueblnr;
+	SpeedStopped = falseblnr;
+
+	return mnvm_noErr;
+}
+
+LOCALFUNC blnr WaitForRom(void)
+{
+	if (! ROM_loaded) {
+		NoRomMsgDisplayOn();
+
+		SpeedStopped = trueblnr;
+		do {
+			WaitForNextTick();
+
+			if (ForceMacOff) {
+				return falseblnr;
+			}
+		} while (SpeedStopped);
+
+		NoRomMsgDisplayOff();
+	}
+
+	return trueblnr;
+}
--- /dev/null
+++ b/src/DATE2SEC.h
@@ -1,0 +1,117 @@
+/*
+	DATE2SEC.h
+	Copyright (C) 2003 Bradford L. Barrett, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	DATE 2(to) SEConds
+
+	convert year/month/day/hour/minute/second
+	to number of seconds since the beginning
+	of 1904, the format for storing dates
+	on the Macintosh.
+
+	The function jdate is from the program Webalizer
+	by Bradford L. Barrett.
+*/
+
+#ifdef DATE2SEC_H
+#error "header already included"
+#else
+#define DATE2SEC_H
+#endif
+
+/*
+	The function jdate was found at the end of the file
+	webalizer.c in the program webalizer at
+	"www.mrunix.net/webalizer/".
+	Here is copyright info from the top of that file:
+
+	webalizer - a web server log analysis program
+
+	Copyright (C) 1997-2000  Bradford L. Barrett ([email protected])
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version, and provided that the above
+	copyright and permission notice is included with all distributed
+	copies of this or derived software.
+*/
+
+/* ************************************************************* */
+/*                                                               */
+/* JDATE  - Julian date calculator                               */
+/*                                                               */
+/* Calculates the number of days since Jan 1, 0000.              */
+/*                                                               */
+/* Originally written by Bradford L. Barrett (03/17/1988)        */
+/* Returns an unsigned long value representing the number of     */
+/* days since January 1, 0000.                                   */
+/*                                                               */
+/* Note: Due to the changes made by Pope Gregory XIII in the     */
+/*       16th Centyry (Feb 24, 1582), dates before 1583 will     */
+/*       not return a truely accurate number (will be at least   */
+/*       10 days off).  Somehow, I don't think this will         */
+/*       present much of a problem for most situations :)        */
+/*                                                               */
+/* Usage: days = jdate(day, month, year)                         */
+/*                                                               */
+/* The number returned is adjusted by 5 to facilitate day of     */
+/* week calculations.  The mod of the returned value gives the   */
+/* day of the week the date is.  (ie: dow = days % 7) where      */
+/* dow will return 0=Sunday, 1=Monday, 2=Tuesday, etc...         */
+/*                                                               */
+/* ************************************************************* */
+
+LOCALFUNC ui5b jdate(int day, int month, int year)
+{
+	ui5b days;                      /* value returned */
+	int mtable[] = {
+		0,    31,  59,  90, 120, 151,
+		181, 212, 243, 273, 304, 334
+	};
+
+	/*
+		First, calculate base number including leap
+		and Centenial year stuff
+	*/
+
+	days = (((ui5b)year * 365) + day + mtable[month - 1]
+		+ ((year + 4) / 4) - ((year / 100) - (year / 400)));
+
+	/* now adjust for leap year before March 1st */
+
+	if ((year % 4 == 0)
+		&& (! ((year % 100 == 0) && (year % 400 != 0)))
+		&& (month < 3))
+	{
+		--days;
+	}
+
+	/* done, return with calculated value */
+
+	return (days + 5);
+}
+
+LOCALFUNC ui5b Date2MacSeconds(int second, int minute, int hour,
+	int day, int month, int year)
+{
+	ui5b curjdate;
+	ui5b basejdate;
+
+	curjdate = jdate(day, month, year);
+	basejdate = jdate(1, 1, 1904);
+	return (((curjdate - basejdate) * 24 + hour) * 60
+		+ minute) * 60 + second;
+}
--- /dev/null
+++ b/src/DISAM68K.c
@@ -1,0 +1,2940 @@
+/*
+	DISAM68K.c
+
+	Copyright (C) 2010 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	DISAssemble Motorola 68K instructions.
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+
+#include "ENDIANAC.h"
+#include "MYOSGLUE.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+
+#include "M68KITAB.h"
+#endif
+
+#include "DISAM68K.h"
+
+LOCALVAR ui5r Disasm_pc;
+
+/*
+	don't use get_vm_byte/get_vm_word/get_vm_long
+		so as to be sure of no side effects
+		(if pc points to memory mapped device)
+*/
+
+LOCALVAR ui3p Disasm_pcp;
+LOCALVAR ui5r Disasm_pc_blockmask;
+LOCALVAR ui3b Disasm_pcp_dummy[2] = {
+	0, 0
+};
+
+IMPORTFUNC ATTep FindATTel(CPTR addr);
+
+LOCALPROC Disasm_Find_pcp(void)
+{
+	ATTep p;
+
+	p = FindATTel(Disasm_pc);
+	if (0 == (p->Access & kATTA_readreadymask)) {
+		Disasm_pcp = Disasm_pcp_dummy;
+		Disasm_pc_blockmask = 0;
+	} else {
+		Disasm_pc_blockmask = p->usemask & ~ p->cmpmask;
+		Disasm_pc_blockmask = Disasm_pc_blockmask
+			& ~ (Disasm_pc_blockmask + 1);
+		Disasm_pcp = p->usebase + (Disasm_pc & p->usemask);
+	}
+}
+
+LOCALFUNC ui4r Disasm_nextiword(void)
+/* NOT sign extended */
+{
+	ui4r r = do_get_mem_word(Disasm_pcp);
+	Disasm_pcp += 2;
+	Disasm_pc += 2;
+	if (0 == (Disasm_pc_blockmask & Disasm_pc)) {
+		Disasm_Find_pcp();
+	}
+	return r;
+}
+
+LOCALINLINEFUNC ui3r Disasm_nextibyte(void)
+{
+	return (ui3b) Disasm_nextiword();
+}
+
+LOCALFUNC ui5r Disasm_nextilong(void)
+{
+	ui5r hi = Disasm_nextiword();
+	ui5r lo = Disasm_nextiword();
+	ui5r r = ((hi << 16) & 0xFFFF0000)
+		| (lo & 0x0000FFFF);
+
+	return r;
+}
+
+LOCALPROC Disasm_setpc(CPTR newpc)
+{
+	if (newpc != Disasm_pc) {
+		Disasm_pc = newpc;
+
+		Disasm_Find_pcp();
+	}
+}
+
+LOCALVAR ui5b Disasm_opcode;
+
+LOCALVAR ui5b Disasm_opsize;
+
+#define Disasm_b76 ((Disasm_opcode >> 6) & 3)
+#define Disasm_b8 ((Disasm_opcode >> 8) & 1)
+#define Disasm_mode ((Disasm_opcode >> 3) & 7)
+#define Disasm_reg (Disasm_opcode & 7)
+#define Disasm_md6 ((Disasm_opcode >> 6) & 7)
+#define Disasm_rg9 ((Disasm_opcode >> 9) & 7)
+
+LOCALPROC DisasmOpSizeFromb76(void)
+{
+	Disasm_opsize = 1 << Disasm_b76;
+	switch (Disasm_opsize) {
+		case 1 :
+			dbglog_writeCStr(".B");
+			break;
+		case 2 :
+			dbglog_writeCStr(".W");
+			break;
+		case 4 :
+			dbglog_writeCStr(".L");
+			break;
+	}
+}
+
+LOCALPROC DisasmModeRegister(ui5b themode, ui5b thereg)
+{
+	switch (themode) {
+		case 0 :
+			dbglog_writeCStr("D");
+			dbglog_writeHex(thereg);
+			break;
+		case 1 :
+			dbglog_writeCStr("A");
+			dbglog_writeHex(thereg);
+			break;
+		case 2 :
+			dbglog_writeCStr("(A");
+			dbglog_writeHex(thereg);
+			dbglog_writeCStr(")");
+			break;
+		case 3 :
+			dbglog_writeCStr("(A");
+			dbglog_writeHex(thereg);
+			dbglog_writeCStr(")+");
+			break;
+		case 4 :
+			dbglog_writeCStr("-(A");
+			dbglog_writeHex(thereg);
+			dbglog_writeCStr(")");
+			break;
+		case 5 :
+			dbglog_writeHex(Disasm_nextiword());
+			dbglog_writeCStr("(A");
+			dbglog_writeHex(thereg);
+			dbglog_writeCStr(")");
+			break;
+		case 6 :
+			dbglog_writeCStr("???");
+#if 0
+			ArgKind = AKMemory;
+			ArgAddr.mem = get_disp_ea(m68k_areg(thereg));
+#endif
+			break;
+		case 7 :
+			switch (thereg) {
+				case 0 :
+					dbglog_writeCStr("(");
+					dbglog_writeHex(Disasm_nextiword());
+					dbglog_writeCStr(")");
+					break;
+				case 1 :
+					dbglog_writeCStr("(");
+					dbglog_writeHex(Disasm_nextilong());
+					dbglog_writeCStr(")");
+					break;
+				case 2 :
+					{
+						ui5r s = Disasm_pc;
+						s += ui5r_FromSWord(Disasm_nextiword());
+						dbglog_writeCStr("(");
+						dbglog_writeHex(s);
+						dbglog_writeCStr(")");
+					}
+					break;
+				case 3 :
+					dbglog_writeCStr("???");
+#if 0
+					ArgKind = AKMemory;
+					s = get_disp_ea(Disasm_pc);
+#endif
+					break;
+				case 4 :
+					dbglog_writeCStr("#");
+					if (Disasm_opsize == 2) {
+						dbglog_writeHex(Disasm_nextiword());
+					} else if (Disasm_opsize < 2) {
+						dbglog_writeHex(Disasm_nextibyte());
+					} else {
+						dbglog_writeHex(Disasm_nextilong());
+					}
+					break;
+			}
+			break;
+		case 8 :
+			dbglog_writeCStr("#");
+			dbglog_writeHex(thereg);
+			break;
+	}
+}
+
+LOCALPROC DisasmStartOne(char *s)
+{
+	dbglog_writeCStr(s);
+}
+
+LOCALPROC Disasm_xxxxxxxxssmmmrrr(char *s)
+{
+	DisasmStartOne(s);
+	DisasmOpSizeFromb76();
+	dbglog_writeCStr(" ");
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROC DisasmEaD_xxxxdddxssmmmrrr(char *s)
+{
+	DisasmStartOne(s);
+	DisasmOpSizeFromb76();
+	dbglog_writeCStr(" ");
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeCStr(", ");
+	dbglog_writeCStr("D");
+	dbglog_writeHex(Disasm_rg9);
+	dbglog_writeReturn();
+}
+
+LOCALPROC DisasmI_xxxxxxxxssmmmrrr(char *s)
+{
+	DisasmStartOne(s);
+	DisasmOpSizeFromb76();
+	dbglog_writeCStr(" #");
+	if (Disasm_opsize == 2) {
+		dbglog_writeHex(ui5r_FromSWord(Disasm_nextiword()));
+	} else if (Disasm_opsize < 2) {
+		dbglog_writeHex(ui5r_FromSByte(Disasm_nextibyte()));
+	} else {
+		dbglog_writeHex(ui5r_FromSLong(Disasm_nextilong()));
+	}
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROC DisasmsAA_xxxxdddxssxxxrrr(char *s)
+{
+	DisasmStartOne(s);
+	DisasmOpSizeFromb76();
+	DisasmModeRegister(3, Disasm_reg);
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(3, Disasm_rg9);
+	dbglog_writeReturn();
+}
+
+LOCALFUNC ui5r Disasm_octdat(ui5r x)
+{
+	if (x == 0) {
+		return 8;
+	} else {
+		return x;
+	}
+}
+
+LOCALPROC Disasm_xxxxnnnxssmmmrrr(char *s)
+{
+	DisasmStartOne(s);
+	DisasmOpSizeFromb76();
+	dbglog_writeCStr(" #");
+
+	dbglog_writeHex(Disasm_octdat(Disasm_rg9));
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROC DisasmDEa_xxxxdddxssmmmrrr(char *s)
+{
+	DisasmStartOne(s);
+	DisasmOpSizeFromb76();
+	dbglog_writeCStr(" D");
+	dbglog_writeHex(Disasm_rg9);
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROC DisasmEaA_xxxxdddsxxmmmrrr(char *s)
+{
+	DisasmStartOne(s);
+
+	Disasm_opsize = Disasm_b8 * 2 + 2;
+	if (Disasm_opsize == 2) {
+		dbglog_writeCStr(".W");
+	} else {
+		dbglog_writeCStr(".L");
+	}
+	dbglog_writeCStr(" ");
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeCStr(", A");
+	dbglog_writeHex(Disasm_rg9);
+	dbglog_writeReturn();
+}
+
+LOCALPROC DisasmDD_xxxxdddxssxxxrrr(char *s)
+{
+	DisasmStartOne(s);
+	DisasmOpSizeFromb76();
+	dbglog_writeCStr(" ");
+	DisasmModeRegister(0, Disasm_reg);
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(0, Disasm_rg9);
+	dbglog_writeReturn();
+}
+
+LOCALPROC DisasmAAs_xxxxdddxssxxxrrr(char *s)
+{
+	DisasmStartOne(s);
+	DisasmOpSizeFromb76();
+	dbglog_writeCStr(" ");
+	DisasmModeRegister(4, Disasm_reg);
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(4, Disasm_rg9);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmTst(void)
+{
+	/* Tst 01001010ssmmmrrr */
+	Disasm_xxxxxxxxssmmmrrr("TST");
+}
+
+LOCALPROCUSEDONCE DisasmCompare(void)
+{
+	/* Cmp 1011ddd0ssmmmrrr */
+	DisasmEaD_xxxxdddxssmmmrrr("CMP");
+}
+
+LOCALPROCUSEDONCE DisasmCmpI(void)
+{
+	/* CMPI 00001100ssmmmrrr */
+	DisasmI_xxxxxxxxssmmmrrr("CMP");
+}
+
+LOCALPROCUSEDONCE DisasmCmpM(void)
+{
+	/* CmpM 1011ddd1ss001rrr */
+	DisasmsAA_xxxxdddxssxxxrrr("CMP");
+}
+
+LOCALPROC DisasmCC(void)
+{
+	switch ((Disasm_opcode >> 8) & 15) {
+		case 0:  dbglog_writeCStr("T"); break;
+		case 1:  dbglog_writeCStr("F"); break;
+		case 2:  dbglog_writeCStr("HI"); break;
+		case 3:  dbglog_writeCStr("LS"); break;
+		case 4:  dbglog_writeCStr("CC"); break;
+		case 5:  dbglog_writeCStr("CS"); break;
+		case 6:  dbglog_writeCStr("NE"); break;
+		case 7:  dbglog_writeCStr("EQ"); break;
+		case 8:  dbglog_writeCStr("VC"); break;
+		case 9:  dbglog_writeCStr("VS"); break;
+		case 10: dbglog_writeCStr("P"); break;
+		case 11: dbglog_writeCStr("MI"); break;
+		case 12: dbglog_writeCStr("GE"); break;
+		case 13: dbglog_writeCStr("LT"); break;
+		case 14: dbglog_writeCStr("GT"); break;
+		case 15: dbglog_writeCStr("LE"); break;
+		default: break; /* shouldn't get here */
+	}
+}
+
+LOCALPROCUSEDONCE DisasmBcc(void)
+{
+	/* Bcc 0110ccccnnnnnnnn */
+	ui5b src = ((ui5b)Disasm_opcode) & 255;
+	ui5r s = Disasm_pc;
+
+	if (0 == ((Disasm_opcode >> 8) & 15)) {
+		DisasmStartOne("BRA");
+	} else {
+		DisasmStartOne("B");
+		DisasmCC();
+	}
+	dbglog_writeCStr(" ");
+
+	if (src == 0) {
+		s += ui5r_FromSWord(Disasm_nextiword());
+	} else
+#if Use68020
+	if (src == 255) {
+		s += ui5r_FromSLong(Disasm_nextilong());
+		/* ReportAbnormal("long branch in DoCode6"); */
+		/* Used by various Apps */
+	} else
+#endif
+	{
+		s += ui5r_FromSByte(src);
+	}
+	dbglog_writeHex(s);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmDBcc(void)
+{
+	/* DBcc 0101cccc11001ddd */
+
+	ui5r s = Disasm_pc;
+
+	DisasmStartOne("DB");
+	DisasmCC();
+
+	dbglog_writeCStr(" D");
+	dbglog_writeHex(Disasm_reg);
+	dbglog_writeCStr(", ");
+
+	s += (si5b)(si4b)Disasm_nextiword();
+	dbglog_writeHex(s);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmSwap(void)
+{
+	/* Swap 0100100001000rrr */
+
+	DisasmStartOne("SWAP D");
+	dbglog_writeHex(Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROC DisasmMove(void) /* MOVE */
+{
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(Disasm_md6, Disasm_rg9);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmMoveL(void)
+{
+	DisasmStartOne("MOVE.L ");
+	Disasm_opsize = 4;
+	DisasmMove();
+}
+
+LOCALPROCUSEDONCE DisasmMoveW(void)
+{
+	DisasmStartOne("MOVE.W ");
+	Disasm_opsize = 2;
+	DisasmMove();
+}
+
+LOCALPROCUSEDONCE DisasmMoveB(void)
+{
+	DisasmStartOne("MOVE.B ");
+	Disasm_opsize = 1;
+	DisasmMove();
+}
+
+LOCALPROCUSEDONCE DisasmMoveAL(void)
+{
+	DisasmStartOne("MOVEA.L ");
+	Disasm_opsize = 4;
+	DisasmMove();
+}
+
+LOCALPROCUSEDONCE DisasmMoveAW(void)
+{
+	DisasmStartOne("MOVEA.W ");
+	Disasm_opsize = 2;
+	DisasmMove();
+}
+
+LOCALPROCUSEDONCE DisasmMoveQ(void)
+{
+	/* MoveQ 0111ddd0nnnnnnnn */
+	DisasmStartOne("MOVEQ #");
+	dbglog_writeHex(ui5r_FromSByte(Disasm_opcode));
+	dbglog_writeCStr(", D");
+	dbglog_writeHex(Disasm_rg9);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmAddEaR(void)
+{
+	DisasmEaD_xxxxdddxssmmmrrr("ADD");
+}
+
+LOCALPROCUSEDONCE DisasmAddQ(void)
+{
+	/* AddQ 0101nnn0ssmmmrrr */
+	Disasm_xxxxnnnxssmmmrrr("ADDQ");
+}
+
+LOCALPROCUSEDONCE DisasmAddI(void)
+{
+	DisasmI_xxxxxxxxssmmmrrr("ADDI");
+}
+
+LOCALPROCUSEDONCE DisasmAddREa(void)
+{
+	DisasmDEa_xxxxdddxssmmmrrr("ADD");
+}
+
+LOCALPROCUSEDONCE DisasmSubEaR(void)
+{
+	DisasmEaD_xxxxdddxssmmmrrr("SUB");
+}
+
+LOCALPROCUSEDONCE DisasmSubQ(void)
+{
+	/* SubQ 0101nnn1ssmmmrrr */
+	Disasm_xxxxnnnxssmmmrrr("SUBQ");
+}
+
+LOCALPROCUSEDONCE DisasmSubI(void)
+{
+	DisasmI_xxxxxxxxssmmmrrr("SUBI");
+}
+
+LOCALPROCUSEDONCE DisasmSubREa(void)
+{
+	DisasmDEa_xxxxdddxssmmmrrr("SUB");
+}
+
+LOCALPROCUSEDONCE DisasmLea(void)
+{
+	/* Lea 0100aaa111mmmrrr */
+	DisasmStartOne("LEA ");
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeCStr(", A");
+	dbglog_writeHex(Disasm_rg9);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmPEA(void)
+{
+	/* PEA 0100100001mmmrrr */
+	DisasmStartOne("PEA ");
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmALine(void)
+{
+	DisasmStartOne("$");
+	dbglog_writeHex(Disasm_opcode);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmBsr(void)
+{
+	ui5b src = ((ui5b)Disasm_opcode) & 255;
+	ui5r s = Disasm_pc;
+
+	DisasmStartOne("BSR ");
+	if (src == 0) {
+		s += (si5b)(si4b)Disasm_nextiword();
+	} else
+#if Use68020
+	if (src == 255) {
+		s += (si5b)Disasm_nextilong();
+		/* ReportAbnormal("long branch in DoCode6"); */
+		/* Used by various Apps */
+	} else
+#endif
+	{
+		s += (si5b)(si3b)src;
+	}
+	dbglog_writeHex(s);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmJsr(void)
+{
+	/* Jsr 0100111010mmmrrr */
+	DisasmStartOne("JSR ");
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmLinkA6(void)
+{
+	DisasmStartOne("LINK A6, ");
+	dbglog_writeHex(Disasm_nextiword());
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmMOVEMRmM(void)
+{
+	/* MOVEM reg to mem 0100100011s100rrr */
+	si4b z;
+	ui5r regmask;
+
+	DisasmStartOne("MOVEM");
+	if (Disasm_b76 == 2) {
+		dbglog_writeCStr(".W");
+	} else {
+		dbglog_writeCStr(".L");
+	}
+	dbglog_writeCStr(" ");
+	regmask = Disasm_nextiword();
+
+	for (z = 16; --z >= 0; ) {
+		if ((regmask & (1 << (15 - z))) != 0) {
+			if (z >= 8) {
+				dbglog_writeCStr("A");
+				dbglog_writeHex(z - 8);
+			} else {
+				dbglog_writeCStr("D");
+				dbglog_writeHex(z);
+			}
+		}
+	}
+	dbglog_writeCStr(", -(A");
+	dbglog_writeHex(Disasm_reg);
+	dbglog_writeCStr(")");
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmMOVEMApR(void)
+{
+	/* MOVEM mem to reg 0100110011s011rrr */
+	si4b z;
+	ui5r regmask;
+
+	regmask = Disasm_nextiword();
+
+	DisasmStartOne("MOVEM");
+	if (Disasm_b76 == 2) {
+		dbglog_writeCStr(".W");
+	} else {
+		dbglog_writeCStr(".L");
+	}
+	dbglog_writeCStr(" (A");
+	dbglog_writeHex(Disasm_reg);
+	dbglog_writeCStr(")+, ");
+
+	for (z = 0; z < 16; ++z) {
+		if ((regmask & (1 << z)) != 0) {
+			if (z >= 8) {
+				dbglog_writeCStr("A");
+				dbglog_writeHex(z - 8);
+			} else {
+				dbglog_writeCStr("D");
+				dbglog_writeHex(z);
+			}
+		}
+	}
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmUnlkA6(void)
+{
+	DisasmStartOne("UNLINK A6");
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmRts(void)
+{
+	/* Rts 0100111001110101 */
+	DisasmStartOne("RTS");
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmJmp(void)
+{
+	/* JMP 0100111011mmmrrr */
+	DisasmStartOne("JMP ");
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmClr(void)
+{
+	/* Clr 01000010ssmmmrrr */
+	Disasm_xxxxxxxxssmmmrrr("CLR");
+}
+
+LOCALPROCUSEDONCE DisasmAddA(void)
+{
+	/* ADDA 1101dddm11mmmrrr */
+	DisasmEaA_xxxxdddsxxmmmrrr("ADDA");
+}
+
+LOCALPROCUSEDONCE DisasmAddQA(void)
+{
+	/* 0101nnn0ss001rrr */
+	DisasmStartOne("ADDQA #");
+	dbglog_writeHex(Disasm_octdat(Disasm_rg9));
+	dbglog_writeCStr(", A");
+	dbglog_writeHex(Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmSubQA(void)
+{
+	/* 0101nnn1ss001rrr */
+	DisasmStartOne("SUBQA #");
+	dbglog_writeHex(Disasm_octdat(Disasm_rg9));
+	dbglog_writeCStr(", A");
+	dbglog_writeHex(Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmSubA(void)
+{
+	/* SUBA 1001dddm11mmmrrr */
+	DisasmEaA_xxxxdddsxxmmmrrr("SUBA");
+}
+
+LOCALPROCUSEDONCE DisasmCmpA(void)
+{
+	DisasmStartOne("CMPA ");
+	Disasm_opsize = Disasm_b8 * 2 + 2;
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeCStr(", A");
+	dbglog_writeHex(Disasm_rg9);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmAddXd(void)
+{
+	DisasmDD_xxxxdddxssxxxrrr("ADDX");
+}
+
+LOCALPROCUSEDONCE DisasmAddXm(void)
+{
+	DisasmAAs_xxxxdddxssxxxrrr("ADDX");
+}
+
+LOCALPROCUSEDONCE DisasmSubXd(void)
+{
+	DisasmDD_xxxxdddxssxxxrrr("SUBX");
+}
+
+LOCALPROCUSEDONCE DisasmSubXm(void)
+{
+	DisasmAAs_xxxxdddxssxxxrrr("SUBX");
+}
+
+LOCALPROC DisasmBinOp1(ui5r x)
+{
+	if (! Disasm_b8) {
+		switch (x) {
+			case 0:
+				DisasmStartOne("ASR");
+				break;
+			case 1:
+				DisasmStartOne("LSR");
+				break;
+			case 2:
+				DisasmStartOne("RXR");
+				break;
+			case 3:
+				DisasmStartOne("ROR");
+				break;
+			default:
+				/* should not get here */
+				break;
+		}
+	} else {
+		switch (x) {
+			case 0:
+				DisasmStartOne("ASL");
+				break;
+			case 1:
+				DisasmStartOne("LSL");
+				break;
+			case 2:
+				DisasmStartOne("RXL");
+				break;
+			case 3:
+				DisasmStartOne("ROL");
+				break;
+			default:
+				/* should not get here */
+				break;
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DisasmRolopNM(void)
+{
+	DisasmBinOp1(Disasm_rg9);
+	dbglog_writeCStr(" ");
+	Disasm_opsize = 2;
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmRolopND(void)
+{
+	/* 1110cccdss0ttddd */
+	DisasmBinOp1(Disasm_mode & 3);
+	DisasmOpSizeFromb76();
+	dbglog_writeCStr(" #");
+	dbglog_writeHex(Disasm_octdat(Disasm_rg9));
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(0, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmRolopDD(void)
+{
+	/* 1110rrrdss1ttddd */
+	DisasmBinOp1(Disasm_mode & 3);
+	DisasmOpSizeFromb76();
+	dbglog_writeCStr(" ");
+	DisasmModeRegister(0, Disasm_rg9);
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(0, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROC DisasmBinBitOp1(void)
+{
+	switch (Disasm_b76) {
+		case 0:
+			DisasmStartOne("BTST");
+			break;
+		case 1:
+			DisasmStartOne("BCHG");
+			break;
+		case 2:
+			DisasmStartOne("BCLR");
+			break;
+		case 3:
+			DisasmStartOne("BSET");
+			break;
+		default:
+			/* should not get here */
+			break;
+	}
+}
+
+LOCALPROCUSEDONCE DisasmBitOpDD(void)
+{
+	/* dynamic bit, Opcode = 0000ddd1tt000rrr */
+	DisasmBinBitOp1();
+	Disasm_opsize = 4;
+	dbglog_writeCStr(" ");
+	DisasmModeRegister(0, Disasm_rg9);
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(0, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmBitOpDM(void)
+{
+	/* dynamic bit, Opcode = 0000ddd1ttmmmrrr */
+	DisasmBinBitOp1();
+	Disasm_opsize = 1;
+	dbglog_writeCStr(" ");
+	DisasmModeRegister(0, Disasm_rg9);
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(Disasm_mode, Disasm_rg9);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmBitOpND(void)
+{
+	/* static bit 00001010tt000rrr */
+	DisasmBinBitOp1();
+	Disasm_opsize = 4;
+	dbglog_writeCStr(" #");
+	dbglog_writeHex(ui5r_FromSByte(Disasm_nextibyte()));
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(0, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmBitOpNM(void)
+{
+	/* static bit 00001010ttmmmrrr */
+	DisasmBinBitOp1();
+	Disasm_opsize = 1;
+	dbglog_writeCStr(" #");
+	dbglog_writeHex(ui5r_FromSByte(Disasm_nextibyte()));
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(Disasm_mode, Disasm_rg9);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmAndI(void)
+{
+	DisasmI_xxxxxxxxssmmmrrr("ANDI");
+}
+
+LOCALPROCUSEDONCE DisasmAndDEa(void)
+{
+	/* And 1100ddd1ssmmmrrr */
+	DisasmDEa_xxxxdddxssmmmrrr("AND");
+}
+
+LOCALPROCUSEDONCE DisasmAndEaD(void)
+{
+	/* And 1100ddd0ssmmmrrr */
+	DisasmEaD_xxxxdddxssmmmrrr("AND");
+}
+
+LOCALPROCUSEDONCE DisasmOrI(void)
+{
+	DisasmI_xxxxxxxxssmmmrrr("ORI");
+}
+
+LOCALPROCUSEDONCE DisasmOrDEa(void)
+{
+	/* OR 1000ddd1ssmmmrrr */
+	DisasmDEa_xxxxdddxssmmmrrr("OR");
+}
+
+LOCALPROCUSEDONCE DisasmOrEaD(void)
+{
+	/* OR 1000ddd0ssmmmrrr */
+	DisasmEaD_xxxxdddxssmmmrrr("OR");
+}
+
+LOCALPROCUSEDONCE DisasmEorI(void)
+{
+	DisasmI_xxxxxxxxssmmmrrr("EORI");
+}
+
+LOCALPROCUSEDONCE DisasmEor(void)
+{
+	/* Eor 1011ddd1ssmmmrrr */
+	DisasmDEa_xxxxdddxssmmmrrr("EOR");
+}
+
+LOCALPROCUSEDONCE DisasmNot(void)
+{
+	/* Not 01000110ssmmmrrr */
+	Disasm_xxxxxxxxssmmmrrr("NOT");
+}
+
+LOCALPROCUSEDONCE DisasmScc(void)
+{
+	/* Scc 0101cccc11mmmrrr */
+	Disasm_opsize = 1;
+	DisasmStartOne("S");
+	DisasmCC();
+	dbglog_writeCStr(" ");
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmEXTL(void)
+{
+	DisasmStartOne("EXT.L D");
+	dbglog_writeHex(Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmEXTW(void)
+{
+	DisasmStartOne("EXT.W D");
+	dbglog_writeHex(Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmNeg(void)
+{
+	/* Neg 01000100ssmmmrrr */
+	Disasm_xxxxxxxxssmmmrrr("NEG");
+}
+
+LOCALPROCUSEDONCE DisasmNegX(void)
+{
+	/* NegX 01000000ssmmmrrr */
+	Disasm_xxxxxxxxssmmmrrr("NEGX");
+}
+
+LOCALPROCUSEDONCE DisasmMulU(void)
+{
+	/* MulU 1100ddd011mmmrrr */
+	Disasm_opsize = 2;
+	DisasmStartOne("MULU ");
+
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(0, Disasm_rg9);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmMulS(void)
+{
+	/* MulS 1100ddd111mmmrrr */
+	Disasm_opsize = 2;
+	DisasmStartOne("MULS ");
+
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(0, Disasm_rg9);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmDivU(void)
+{
+	/* DivU 1000ddd011mmmrrr */
+
+	Disasm_opsize = 2;
+	DisasmStartOne("DIVU ");
+
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(0, Disasm_rg9);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmDivS(void)
+{
+	/* DivS 1000ddd111mmmrrr */
+
+	Disasm_opsize = 2;
+	DisasmStartOne("DIVS ");
+
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(0, Disasm_rg9);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmExgdd(void)
+{
+	/* Exg 1100ddd101000rrr */
+
+	Disasm_opsize = 4;
+	DisasmStartOne("EXG ");
+	DisasmModeRegister(0, Disasm_rg9);
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(0, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmExgaa(void)
+{
+	/* Exg 1100ddd101001rrr */
+
+	Disasm_opsize = 4;
+	DisasmStartOne("EXG ");
+	DisasmModeRegister(1, Disasm_rg9);
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(1, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmExgda(void)
+{
+	/* Exg 1100ddd110001rrr */
+
+	Disasm_opsize = 4;
+	DisasmStartOne("EXG ");
+	DisasmModeRegister(0, Disasm_rg9);
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(1, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmMoveCCREa(void)
+{
+	/* Move from CCR 0100001011mmmrrr */
+	Disasm_opsize = 2;
+	DisasmStartOne("MOVE CCR, ");
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmMoveEaCR(void)
+{
+	/* 0100010011mmmrrr */
+	Disasm_opsize = 2;
+	DisasmStartOne("MOVE ");
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeCStr(", CCR");
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmMoveSREa(void)
+{
+	/* Move from SR 0100000011mmmrrr */
+	Disasm_opsize = 2;
+	DisasmStartOne("MOVE SR, ");
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmMoveEaSR(void)
+{
+	/* 0100011011mmmrrr */
+	Disasm_opsize = 2;
+	DisasmStartOne("MOVE ");
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeCStr(", SR");
+	dbglog_writeReturn();
+}
+
+LOCALPROC DisasmBinOpStatusCCR(void)
+{
+	switch (Disasm_rg9) {
+		case 0 :
+			DisasmStartOne("OR");
+			break;
+		case 1 :
+			DisasmStartOne("AND");
+			break;
+		case 5 :
+			DisasmStartOne("EOR");
+			break;
+		default: /* should not happen */
+			break;
+	}
+	DisasmOpSizeFromb76();
+	dbglog_writeCStr(" #");
+	dbglog_writeHex(ui5r_FromSWord(Disasm_nextiword()));
+	if (Disasm_b76 != 0) {
+		dbglog_writeCStr(", SR");
+	} else {
+		dbglog_writeCStr(", CCR");
+	}
+	dbglog_writeReturn();
+}
+
+LOCALPROC disasmreglist(si4b direction, ui5b m1, ui5b r1)
+{
+	si4b z;
+	ui5r regmask;
+
+	DisasmStartOne("MOVEM");
+
+	regmask = Disasm_nextiword();
+	Disasm_opsize = 2 * Disasm_b76 - 2;
+
+	if (Disasm_opsize == 2) {
+		dbglog_writeCStr(".W");
+	} else {
+		dbglog_writeCStr(".L");
+	}
+
+	dbglog_writeCStr(" ");
+
+	if (direction != 0) {
+		DisasmModeRegister(m1, r1);
+		dbglog_writeCStr(", ");
+	}
+
+	for (z = 0; z < 16; ++z) {
+		if ((regmask & (1 << z)) != 0) {
+			if (z >= 8) {
+				dbglog_writeCStr("A");
+				dbglog_writeHex(z - 8);
+			} else {
+				dbglog_writeCStr("D");
+				dbglog_writeHex(z);
+			}
+		}
+	}
+
+	if (direction == 0) {
+		dbglog_writeCStr(", ");
+		DisasmModeRegister(m1, r1);
+	}
+
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmMOVEMrm(void)
+{
+	/* MOVEM reg to mem 010010001ssmmmrrr */
+	disasmreglist(0, Disasm_mode, Disasm_reg);
+}
+
+LOCALPROCUSEDONCE DisasmMOVEMmr(void)
+{
+	/* MOVEM mem to reg 0100110011smmmrrr */
+	disasmreglist(1, Disasm_mode, Disasm_reg);
+}
+
+LOCALPROC DisasmByteBinOp(char *s, ui5b m1, ui5b r1, ui5b m2, ui5b r2)
+{
+	DisasmStartOne(s);
+	dbglog_writeCStr(" ");
+	DisasmOpSizeFromb76();
+	DisasmModeRegister(m1, r1);
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(m2, r2);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmAbcdr(void)
+{
+	/* ABCD 1100ddd100000rrr */
+	DisasmByteBinOp("ABCD", 0, Disasm_reg, 0, Disasm_rg9);
+}
+
+LOCALPROCUSEDONCE DisasmAbcdm(void)
+{
+	/* ABCD 1100ddd100001rrr */
+	DisasmByteBinOp("ABCD", 4, Disasm_reg, 4, Disasm_rg9);
+}
+
+LOCALPROCUSEDONCE DisasmSbcdr(void)
+{
+	/* SBCD 1000xxx100000xxx */
+	DisasmByteBinOp("ABCD", 0, Disasm_reg, 0, Disasm_rg9);
+}
+
+LOCALPROCUSEDONCE DisasmSbcdm(void)
+{
+	/* SBCD 1000xxx100001xxx */
+	DisasmByteBinOp("ABCD", 4, Disasm_reg, 4, Disasm_rg9);
+}
+
+LOCALPROCUSEDONCE DisasmNbcd(void)
+{
+	/* Nbcd 0100100000mmmrrr */
+	Disasm_xxxxxxxxssmmmrrr("NBCD");
+}
+
+LOCALPROCUSEDONCE DisasmRte(void)
+{
+	/* Rte 0100111001110011 */
+	DisasmStartOne("RTE");
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmNop(void)
+{
+	/* Nop 0100111001110001 */
+	DisasmStartOne("NOP");
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmMoveP(void)
+{
+	/* MoveP 0000ddd1mm001aaa */
+
+	DisasmStartOne("MOVEP");
+	if (0 == (Disasm_b76 & 1)) {
+		Disasm_opsize = 2;
+		dbglog_writeCStr(".W");
+	} else {
+		Disasm_opsize = 4;
+		dbglog_writeCStr(".L");
+	}
+	dbglog_writeCStr(" ");
+	if (Disasm_b76 < 2) {
+		DisasmModeRegister(5, Disasm_reg);
+		dbglog_writeCStr(", ");
+		DisasmModeRegister(0, Disasm_rg9);
+	} else {
+		DisasmModeRegister(0, Disasm_rg9);
+		dbglog_writeCStr(", ");
+		DisasmModeRegister(5, Disasm_reg);
+	}
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmIllegal(void)
+{
+	DisasmStartOne("ILLEGAL");
+	dbglog_writeReturn();
+}
+
+LOCALPROC DisasmCheck(void)
+{
+	DisasmStartOne("CHK");
+	if (2 == Disasm_opsize) {
+		dbglog_writeCStr(".W");
+	} else {
+		dbglog_writeCStr(".L");
+	}
+	dbglog_writeCStr(" ");
+
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(0, Disasm_rg9);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmChkW(void)
+{
+	/* Chk.W 0100ddd110mmmrrr */
+	Disasm_opsize = 2;
+	DisasmCheck();
+}
+
+LOCALPROCUSEDONCE DisasmTrap(void)
+{
+	/* Trap 010011100100vvvv */
+	DisasmStartOne("TRAP ");
+	dbglog_writeHex(Disasm_opcode & 15);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmTrapV(void)
+{
+	/* TrapV 0100111001110110 */
+	DisasmStartOne("TRAPV");
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmRtr(void)
+{
+	/* Rtr 0100111001110111 */
+	DisasmStartOne("RTR");
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmLink(void)
+{
+	DisasmStartOne("LINK A");
+	dbglog_writeHex(Disasm_reg);
+	dbglog_writeCStr(", ");
+	dbglog_writeHex(Disasm_nextiword());
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmUnlk(void)
+{
+	DisasmStartOne("UNLINK A");
+	dbglog_writeHex(Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmMoveRUSP(void)
+{
+	/* MOVE USP 0100111001100aaa */
+	DisasmStartOne("MOVE A");
+	dbglog_writeHex(Disasm_reg);
+	dbglog_writeCStr(", USP");
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmMoveUSPR(void)
+{
+	/* MOVE USP 0100111001101aaa */
+	DisasmStartOne("MOVE USP, A");
+	dbglog_writeHex(Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmTas(void)
+{
+	/* Tas 0100101011mmmrrr */
+	Disasm_opsize = 1;
+	DisasmStartOne("TAS");
+	dbglog_writeCStr(" ");
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmFLine(void)
+{
+	DisasmStartOne("$");
+	dbglog_writeHex(Disasm_opcode);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmCallMorRtm(void)
+{
+	DisasmStartOne("CALLM #");
+	dbglog_writeHex(Disasm_nextibyte());
+	dbglog_writeCStr(", ");
+	DisasmModeRegister(Disasm_mode, Disasm_reg);
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmStop(void)
+{
+	/* Stop 0100111001110010 */
+	DisasmStartOne("STOP #");
+	dbglog_writeHex(Disasm_nextiword());
+	dbglog_writeReturn();
+}
+
+LOCALPROCUSEDONCE DisasmReset(void)
+{
+	/* Reset 0100111001100000 */
+	DisasmStartOne("RESET");
+	dbglog_writeReturn();
+}
+
+#if Use68020
+LOCALPROCUSEDONCE DisasmEXTBL(void)
+{
+	/* EXTB.L */
+	DisasmStartOne("EXTB.L D");
+	dbglog_writeHex(Disasm_reg);
+	dbglog_writeReturn();
+}
+#endif
+
+#if Use68020
+LOCALPROCUSEDONCE DisasmTRAPcc(void)
+{
+	/* TRAPcc 0101cccc11111sss */
+
+	DisasmStartOne("TRAP");
+	DisasmCC();
+
+	switch (Disasm_reg) {
+		case 2:
+			dbglog_writeCStr(" ");
+			dbglog_writeHex(Disasm_nextiword());
+			break;
+		case 3:
+			dbglog_writeCStr(" ");
+			dbglog_writeHex(Disasm_nextilong());
+			break;
+		case 4:
+			/* no optional data */
+			break;
+		default:
+			/* illegal format */
+			break;
+	}
+
+	dbglog_writeReturn();
+}
+#endif
+
+#if Use68020
+LOCALPROCUSEDONCE DisasmChkL(void)
+{
+	/* Chk.L 0100ddd100mmmrrr */
+	Disasm_opsize = 4;
+	DisasmCheck();
+}
+#endif
+
+#if Use68020
+LOCALPROCUSEDONCE DisasmBkpt(void)
+{
+	/* BKPT 0100100001001rrr */
+	DisasmStartOne("BKPT #");
+	dbglog_writeHex(Disasm_reg);
+	dbglog_writeReturn();
+}
+#endif
+
+#if Use68020
+LOCALPROCUSEDONCE DisasmDivL(void)
+{
+	/* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */
+	/* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */
+	Disasm_opsize = 4;
+	DisasmStartOne("DIV");
+
+	{
+		ui4b extra = Disasm_nextiword();
+		ui5b rDr = extra & 7;
+		ui5b rDq = (extra >> 12) & 7;
+
+		if (extra & 0x0800) {
+			dbglog_writeCStr("S");
+		} else {
+			dbglog_writeCStr("U");
+		}
+		if (extra & 0x0400) {
+			dbglog_writeCStr("L");
+		}
+		dbglog_writeCStr(".L ");
+
+		DisasmModeRegister(Disasm_mode, Disasm_reg);
+
+		dbglog_writeCStr(", ");
+
+		if (rDr != rDq) {
+			dbglog_writeCStr("D");
+			dbglog_writeHex(rDr);
+			dbglog_writeCStr(":");
+		}
+		dbglog_writeCStr("D");
+		dbglog_writeHex(rDq);
+	}
+
+	dbglog_writeReturn();
+}
+#endif
+
+#if Use68020
+LOCALPROCUSEDONCE DisasmMulL(void)
+{
+	/* MULU 0100110000mmmrrr 0rrr0s0000000rrr */
+	/* MULS 0100110000mmmrrr 0rrr1s0000000rrr */
+
+	Disasm_opsize = 4;
+	DisasmStartOne("MUL");
+
+	{
+		ui4b extra = Disasm_nextiword();
+		ui5b rhi = extra & 7;
+		ui5b rlo = (extra >> 12) & 7;
+
+		if (extra & 0x0800) {
+			dbglog_writeCStr("S");
+		} else {
+			dbglog_writeCStr("U");
+		}
+
+		dbglog_writeCStr(".L ");
+
+		DisasmModeRegister(Disasm_mode, Disasm_reg);
+
+		dbglog_writeCStr(", ");
+
+		if (extra & 0x400) {
+			dbglog_writeCStr("D");
+			dbglog_writeHex(rhi);
+			dbglog_writeCStr(":");
+		}
+		dbglog_writeCStr("D");
+		dbglog_writeHex(rlo);
+	}
+
+	dbglog_writeReturn();
+}
+#endif
+
+#if Use68020
+LOCALPROCUSEDONCE DisasmRtd(void)
+{
+	/* Rtd 0100111001110100 */
+	DisasmStartOne("RTD #");
+	dbglog_writeHex((si5b)(si4b)Disasm_nextiword());
+	dbglog_writeReturn();
+}
+#endif
+
+#if Use68020
+LOCALPROC DisasmControlReg(ui4r i)
+{
+	switch (i) {
+		case 0x0000:
+			dbglog_writeCStr("SFC");
+			break;
+		case 0x0001:
+			dbglog_writeCStr("DFC");
+			break;
+		case 0x0002:
+			dbglog_writeCStr("CACR");
+			break;
+		case 0x0800:
+			dbglog_writeCStr("USP");
+			break;
+		case 0x0801:
+			dbglog_writeCStr("VBR");
+			break;
+		case 0x0802:
+			dbglog_writeCStr("CAAR");
+			break;
+		case 0x0803:
+			dbglog_writeCStr("MSP");
+			break;
+		case 0x0804:
+			dbglog_writeCStr("ISP");
+			break;
+		default:
+			dbglog_writeCStr("???");
+			break;
+	}
+}
+#endif
+
+#if Use68020
+LOCALPROCUSEDONCE DisasmMoveC(void)
+{
+	/* MOVEC 010011100111101m */
+	DisasmStartOne("MOVEC ");
+
+	{
+		ui4b src = Disasm_nextiword();
+		int regno = (src >> 12) & 0x0F;
+		switch (Disasm_reg) {
+			case 2:
+				DisasmControlReg(src & 0x0FFF);
+				dbglog_writeCStr(", ");
+				if (regno < 8) {
+					dbglog_writeCStr("D");
+				} else {
+					dbglog_writeCStr("A");
+				}
+				dbglog_writeHex(regno & 7);
+				break;
+			case 3:
+				if (regno < 8) {
+					dbglog_writeCStr("D");
+				} else {
+					dbglog_writeCStr("A");
+				}
+				dbglog_writeHex(regno & 7);
+
+				dbglog_writeCStr(", ");
+
+				DisasmControlReg(src & 0x0FFF);
+				break;
+			default:
+				/* illegal */
+				break;
+		}
+	}
+
+	dbglog_writeReturn();
+}
+#endif
+
+#if Use68020
+LOCALPROCUSEDONCE DisasmLinkL(void)
+{
+	/* Link.L 0100100000001rrr */
+	DisasmStartOne("LINK.L A");
+	dbglog_writeHex(Disasm_reg);
+	dbglog_writeCStr(", ");
+	dbglog_writeHex(Disasm_nextilong());
+	dbglog_writeReturn();
+}
+#endif
+
+#if Use68020
+LOCALPROCUSEDONCE DisasmPack(void)
+{
+	DisasmStartOne("PACK ???");
+	dbglog_writeReturn();
+	/* DoCodePack */
+}
+#endif
+
+#if Use68020
+LOCALPROCUSEDONCE DisasmUnpk(void)
+{
+	DisasmStartOne("UNPK ???");
+	dbglog_writeReturn();
+	/* DoCodeUnpk */
+}
+#endif
+
+#if Use68020
+LOCALPROCUSEDONCE DisasmCHK2orCMP2(void)
+{
+	DisasmStartOne("CHK2/CMP2 ???");
+	dbglog_writeReturn();
+	/* DoCHK2orCMP2 */
+}
+#endif
+
+#if Use68020
+LOCALPROCUSEDONCE DisasmCAS2(void)
+{
+	DisasmStartOne("CAS2 ???");
+	dbglog_writeReturn();
+	/* DoCAS2 */
+}
+#endif
+
+#if Use68020
+LOCALPROCUSEDONCE DisasmCAS(void)
+{
+	DisasmStartOne("CAS ???");
+	dbglog_writeReturn();
+	/* DoDoCAS */
+}
+#endif
+
+#if Use68020
+LOCALPROCUSEDONCE DisasmMOVES(void)
+{
+	DisasmStartOne("MOVES ???");
+	dbglog_writeReturn();
+	/* DoMOVES */
+}
+#endif
+
+#if Use68020
+LOCALPROCUSEDONCE DisasmBitField(void)
+{
+	DisasmStartOne("BitField ???");
+	dbglog_writeReturn();
+	/* DoBitField */
+}
+#endif
+
+LOCALFUNC blnr IsValidAddrMode(void)
+{
+	return (Disasm_mode != 7) || (Disasm_reg < 5);
+}
+
+LOCALFUNC blnr IsValidDstAddrMode(void)
+{
+	return (Disasm_md6 != 7) || (Disasm_rg9 < 2);
+}
+
+LOCALFUNC blnr IsValidDataAltAddrMode(void)
+{
+	blnr IsOk;
+
+	switch (Disasm_mode) {
+		case 1:
+		default: /* keep compiler happy */
+			IsOk = falseblnr;
+			break;
+		case 0:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+			IsOk = trueblnr;
+			break;
+		case 7:
+			IsOk = Disasm_reg < 2;
+			break;
+	}
+
+	return IsOk;
+}
+
+LOCALFUNC blnr IsValidDataAddrMode(void)
+{
+	blnr IsOk;
+
+	switch (Disasm_mode) {
+		case 1:
+		default: /* keep compiler happy */
+			IsOk = falseblnr;
+			break;
+		case 0:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+			IsOk = trueblnr;
+			break;
+		case 7:
+			IsOk = Disasm_reg < 5;
+			break;
+	}
+
+	return IsOk;
+}
+
+LOCALFUNC blnr IsValidControlAddrMode(void)
+{
+	blnr IsOk;
+
+	switch (Disasm_mode) {
+		case 0:
+		case 1:
+		case 3:
+		case 4:
+		default: /* keep compiler happy */
+			IsOk = falseblnr;
+			break;
+		case 2:
+		case 5:
+		case 6:
+			IsOk = trueblnr;
+			break;
+		case 7:
+			IsOk = Disasm_reg < 4;
+			break;
+	}
+
+	return IsOk;
+}
+
+LOCALFUNC blnr IsValidControlAltAddrMode(void)
+{
+	blnr IsOk;
+
+	switch (Disasm_mode) {
+		case 0:
+		case 1:
+		case 3:
+		case 4:
+		default: /* keep compiler happy */
+			IsOk = falseblnr;
+			break;
+		case 2:
+		case 5:
+		case 6:
+			IsOk = trueblnr;
+			break;
+		case 7:
+			IsOk = Disasm_reg < 2;
+			break;
+	}
+
+	return IsOk;
+}
+
+LOCALFUNC blnr IsValidAltMemAddrMode(void)
+{
+	blnr IsOk;
+
+	switch (Disasm_mode) {
+		case 0:
+		case 1:
+		default: /* keep compiler happy */
+			IsOk = falseblnr;
+			break;
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+			IsOk = trueblnr;
+			break;
+		case 7:
+			IsOk = Disasm_reg < 2;
+			break;
+	}
+
+	return IsOk;
+}
+
+LOCALPROCUSEDONCE DisasmCode0(void)
+{
+	if (Disasm_b8 == 1) {
+		if (Disasm_mode == 1) {
+			/* MoveP 0000ddd1mm001aaa */
+			DisasmMoveP();
+		} else {
+			/* dynamic bit, Opcode = 0000ddd1ttmmmrrr */
+			if (Disasm_mode == 0) {
+				DisasmBitOpDD();
+			} else {
+				if (Disasm_b76 == 0) {
+					if (IsValidDataAddrMode()) {
+						DisasmBitOpDM();
+					} else {
+						DisasmIllegal();
+					}
+				} else {
+					if (IsValidDataAltAddrMode()) {
+						DisasmBitOpDM();
+					} else {
+						DisasmIllegal();
+					}
+				}
+			}
+		}
+	} else {
+		if (Disasm_rg9 == 4) {
+			/* static bit 00001010ssmmmrrr */
+			if (Disasm_mode == 0) {
+				DisasmBitOpND();
+			} else {
+				if (Disasm_b76 == 0) {
+					if ((Disasm_mode == 7) && (Disasm_reg == 4)) {
+						DisasmIllegal();
+					} else {
+						if (IsValidDataAddrMode()) {
+							DisasmBitOpNM();
+						} else {
+							DisasmIllegal();
+						}
+					}
+				} else {
+					if (IsValidDataAltAddrMode()) {
+						DisasmBitOpNM();
+					} else {
+						DisasmIllegal();
+					}
+				}
+			}
+		} else
+		if (Disasm_b76 == 3) {
+#if Use68020
+			if (Disasm_rg9 < 3) {
+				/* CHK2 or CMP2 00000ss011mmmrrr */
+				if (IsValidControlAddrMode()) {
+					DisasmCHK2orCMP2();
+				} else {
+					DisasmIllegal();
+				}
+			} else
+			if (Disasm_rg9 >= 5) {
+				if ((Disasm_mode == 7) && (Disasm_reg == 4)) {
+					/* CAS2 00001ss011111100 */
+					DisasmCAS2();
+				} else {
+					/* CAS 00001ss011mmmrrr */
+					DisasmCAS2();
+				}
+			} else
+			if (Disasm_rg9 == 3) {
+				/* CALLM or RTM 0000011011mmmrrr */
+				DisasmCallMorRtm();
+			} else
+#endif
+			{
+				DisasmIllegal();
+			}
+		} else
+		if (Disasm_rg9 == 6) {
+			/* CMPI 00001100ssmmmrrr */
+			if (IsValidDataAltAddrMode()) {
+				DisasmCmpI();
+			} else {
+				DisasmIllegal();
+			}
+		} else if (Disasm_rg9 == 7) {
+#if Use68020
+			/* MoveS 00001110ssmmmrrr */
+			if (IsValidAltMemAddrMode()) {
+				DisasmMoveSREa();
+			} else {
+				DisasmIllegal();
+			}
+#else
+			DisasmIllegal();
+#endif
+		} else {
+			if ((Disasm_mode == 7) && (Disasm_reg == 4)) {
+				switch (Disasm_rg9) {
+					case 0:
+					case 1:
+					case 5:
+						DisasmBinOpStatusCCR();
+						break;
+					default:
+						DisasmIllegal();
+						break;
+				}
+			} else {
+				if (! IsValidDataAltAddrMode()) {
+					DisasmIllegal();
+				} else {
+					switch (Disasm_rg9) {
+						case 0:
+							DisasmOrI();
+							break;
+						case 1:
+							DisasmAndI();
+							break;
+						case 2:
+							DisasmSubI();
+							break;
+						case 3:
+							DisasmAddI();
+							break;
+						case 5:
+							DisasmEorI();
+							break;
+						default:
+							/*
+								for compiler.
+								should be 0, 1, 2, 3, or 5
+							*/
+							DisasmIllegal();
+							break;
+					}
+				}
+			}
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DisasmCode1(void)
+{
+	if ((Disasm_mode == 1) || ! IsValidAddrMode()) {
+		DisasmIllegal();
+	} else if (Disasm_md6 == 1) { /* MOVEA */
+		DisasmIllegal();
+	} else if (! IsValidDstAddrMode()) {
+		DisasmIllegal();
+	} else {
+		DisasmMoveB();
+	}
+}
+
+LOCALPROCUSEDONCE DisasmCode2(void)
+{
+	if (Disasm_md6 == 1) { /* MOVEA */
+		if (IsValidAddrMode()) {
+			DisasmMoveAL();
+		} else {
+			DisasmIllegal();
+		}
+	} else if (! IsValidAddrMode()) {
+		DisasmIllegal();
+	} else if (! IsValidDstAddrMode()) {
+		DisasmIllegal();
+	} else {
+		DisasmMoveL();
+	}
+}
+
+LOCALPROCUSEDONCE DisasmCode3(void)
+{
+	if (Disasm_md6 == 1) { /* MOVEA */
+		if (IsValidAddrMode()) {
+			DisasmMoveAW();
+		} else {
+			DisasmIllegal();
+		}
+	} else if (! IsValidAddrMode()) {
+		DisasmIllegal();
+	} else if (! IsValidDstAddrMode()) {
+		DisasmIllegal();
+	} else {
+		DisasmMoveW();
+	}
+}
+
+LOCALPROCUSEDONCE DisasmCode4(void)
+{
+	if (Disasm_b8 != 0) {
+		switch (Disasm_b76) {
+			case 0:
+#if Use68020
+				/* Chk.L 0100ddd100mmmrrr */
+				if (IsValidDataAddrMode()) {
+					DisasmChkL();
+				} else {
+					DisasmIllegal();
+				}
+#else
+				DisasmIllegal();
+#endif
+				break;
+			case 1:
+				DisasmIllegal();
+				break;
+			case 2:
+				/* Chk.W 0100ddd110mmmrrr */
+				if (IsValidDataAddrMode()) {
+					DisasmChkW();
+				} else {
+					DisasmIllegal();
+				}
+				break;
+			case 3:
+			default: /* keep compiler happy */
+#if Use68020
+				if ((0 == Disasm_mode) && (4 == Disasm_rg9)) {
+					DisasmEXTBL();
+				} else
+#endif
+				{
+					/* Lea 0100aaa111mmmrrr */
+					if (IsValidControlAddrMode()) {
+						DisasmLea();
+					} else {
+						DisasmIllegal();
+					}
+				}
+				break;
+		}
+	} else {
+		switch (Disasm_rg9) {
+			case 0:
+				if (Disasm_b76 != 3) {
+					/* NegX 01000000ssmmmrrr */
+					if (IsValidDataAltAddrMode()) {
+						DisasmNegX();
+					} else {
+						DisasmIllegal();
+					}
+				} else {
+#if Use68020
+/* reference seems incorrect to say not for 68000 */
+#endif
+					/* Move from SR 0100000011mmmrrr */
+					if (IsValidDataAltAddrMode()) {
+						DisasmMoveSREa();
+					} else {
+						DisasmIllegal();
+					}
+				}
+				break;
+			case 1:
+				if (Disasm_b76 != 3) {
+					/* Clr 01000010ssmmmrrr */
+					if (IsValidDataAltAddrMode()) {
+						DisasmClr();
+					} else {
+						DisasmIllegal();
+					}
+				} else {
+#if Use68020
+					/* Move from CCR 0100001011mmmrrr */
+					if (IsValidDataAltAddrMode()) {
+						DisasmMoveCCREa();
+					} else {
+						DisasmIllegal();
+					}
+#else
+					DisasmIllegal();
+#endif
+				}
+				break;
+			case 2:
+				if (Disasm_b76 != 3) {
+					/* Neg 01000100ssmmmrrr */
+					if (IsValidDataAltAddrMode()) {
+						DisasmNeg();
+					} else {
+						DisasmIllegal();
+					}
+				} else {
+					/* Move to CCR 0100010011mmmrrr */
+					if (IsValidDataAddrMode()) {
+						DisasmMoveEaCR();
+					} else {
+						DisasmIllegal();
+					}
+				}
+				break;
+			case 3:
+				if (Disasm_b76 != 3) {
+					/* Not 01000110ssmmmrrr */
+					if (IsValidDataAltAddrMode()) {
+						DisasmNot();
+					} else {
+						DisasmIllegal();
+					}
+				} else {
+					/* Move from SR 0100011011mmmrrr */
+					if (IsValidDataAddrMode()) {
+						DisasmMoveEaSR();
+					} else {
+						DisasmIllegal();
+					}
+				}
+				break;
+			case 4:
+				switch (Disasm_b76) {
+					case 0:
+#if Use68020
+						if (Disasm_mode == 1) {
+							/* Link.L 0100100000001rrr */
+							DisasmLinkL();
+						} else
+#endif
+						{
+							/* Nbcd 0100100000mmmrrr */
+							if (IsValidDataAltAddrMode()) {
+								DisasmNbcd();
+							} else {
+								DisasmIllegal();
+							}
+						}
+						break;
+					case 1:
+						if (Disasm_mode == 0) {
+							/* Swap 0100100001000rrr */
+							DisasmSwap();
+						} else
+#if Use68020
+						if (Disasm_mode == 1) {
+							DisasmBkpt();
+						} else
+#endif
+						{
+							/* PEA 0100100001mmmrrr */
+							if (IsValidControlAddrMode()) {
+								DisasmPEA();
+							} else {
+								DisasmIllegal();
+							}
+						}
+						break;
+					case 2:
+						if (Disasm_mode == 0) {
+							/* EXT.W */
+							DisasmEXTW();
+						} else {
+							/*
+								MOVEM Disasm_reg
+									to mem 01001d001ssmmmrrr
+							*/
+							if (Disasm_mode == 4) {
+								DisasmMOVEMRmM();
+							} else {
+								if (IsValidControlAltAddrMode()) {
+									DisasmMOVEMrm();
+								} else {
+									DisasmIllegal();
+								}
+							}
+						}
+						break;
+					case 3:
+					default: /* keep compiler happy */
+						if (Disasm_mode == 0) {
+							/* EXT.L */
+							DisasmEXTL();
+						} else {
+							/*
+								MOVEM Disasm_reg
+									to mem 01001d001ssmmmrrr
+							*/
+							if (Disasm_mode == 4) {
+								DisasmMOVEMRmM();
+							} else {
+								if (IsValidControlAltAddrMode()) {
+									DisasmMOVEMrm();
+								} else {
+									DisasmIllegal();
+								}
+							}
+						}
+						break;
+				}
+				break;
+			case 5:
+				if (Disasm_b76 == 3) {
+					if ((Disasm_mode == 7) && (Disasm_reg == 4)) {
+						/* the ILLEGAL instruction */
+						DisasmIllegal();
+					} else {
+						/* Tas 0100101011mmmrrr */
+						if (IsValidDataAltAddrMode()) {
+							DisasmTas();
+						} else {
+							DisasmIllegal();
+						}
+					}
+				} else {
+					/* Tst 01001010ssmmmrrr */
+					if (Disasm_b76 == 0) {
+						if (IsValidDataAltAddrMode()) {
+							DisasmTst();
+						} else {
+							DisasmIllegal();
+						}
+					} else {
+						if (IsValidAddrMode()) {
+							DisasmTst();
+						} else {
+							DisasmIllegal();
+						}
+					}
+				}
+				break;
+			case 6:
+				if (((Disasm_opcode >> 7) & 1) == 1) {
+					/* MOVEM mem to Disasm_reg 0100110011smmmrrr */
+					if (Disasm_mode == 3) {
+						DisasmMOVEMApR();
+					} else {
+						if (IsValidControlAddrMode()) {
+							DisasmMOVEMmr();
+						} else {
+							DisasmIllegal();
+						}
+					}
+				} else {
+#if Use68020
+					if (((Disasm_opcode >> 6) & 1) == 1) {
+						/* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */
+						/* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */
+						DisasmDivL();
+					} else {
+						/* MULU 0100110000mmmrrr 0rrr0s0000000rrr */
+						/* MULS 0100110000mmmrrr 0rrr1s0000000rrr */
+						DisasmMulL();
+					}
+#else
+					DisasmIllegal();
+#endif
+				}
+				break;
+			case 7:
+			default: /* keep compiler happy */
+				switch (Disasm_b76) {
+					case 0:
+						DisasmIllegal();
+						break;
+					case 1:
+						switch (Disasm_mode) {
+							case 0:
+							case 1:
+								/* Trap 010011100100vvvv */
+								DisasmTrap();
+								break;
+							case 2:
+								/* Link */
+								if (Disasm_reg == 6) {
+									DisasmLinkA6();
+								} else {
+									DisasmLink();
+								}
+								break;
+							case 3:
+								/* Unlk */
+								if (Disasm_reg == 6) {
+									DisasmUnlkA6();
+								} else {
+									DisasmUnlk();
+								}
+								break;
+							case 4:
+								/* MOVE USP 0100111001100aaa */
+								DisasmMoveRUSP();
+								break;
+							case 5:
+								/* MOVE USP 0100111001101aaa */
+								DisasmMoveUSPR();
+								break;
+							case 6:
+								switch (Disasm_reg) {
+									case 0:
+										/* Reset 0100111001100000 */
+										DisasmReset();
+										break;
+									case 1:
+										/*
+											Nop Opcode
+												= 0100111001110001
+										*/
+										DisasmNop();
+										break;
+									case 2:
+										/* Stop 0100111001110010 */
+										DisasmStop();
+										break;
+									case 3:
+										/* Rte 0100111001110011 */
+										DisasmRte();
+										break;
+									case 4:
+										/* Rtd 0100111001110100 */
+#if Use68020
+										DisasmRtd();
+#else
+										DisasmIllegal();
+#endif
+										break;
+									case 5:
+										/* Rts 0100111001110101 */
+										DisasmRts();
+										break;
+									case 6:
+										/* TrapV 0100111001110110 */
+										DisasmTrapV();
+										break;
+									case 7:
+									default: /* keep compiler happy */
+										/* Rtr 0100111001110111 */
+										DisasmRtr();
+										break;
+								}
+								break;
+							case 7:
+							default: /* keep compiler happy */
+#if Use68020
+								/* MOVEC 010011100111101m */
+								DisasmMoveC();
+#else
+								DisasmIllegal();
+#endif
+								break;
+						}
+						break;
+					case 2:
+						/* Jsr 0100111010mmmrrr */
+						if (IsValidControlAddrMode()) {
+							DisasmJsr();
+						} else {
+							DisasmIllegal();
+						}
+						break;
+					case 3:
+					default: /* keep compiler happy */
+						/* JMP 0100111011mmmrrr */
+						if (IsValidControlAddrMode()) {
+							DisasmJmp();
+						} else {
+							DisasmIllegal();
+						}
+						break;
+				}
+				break;
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DisasmCode5(void)
+{
+	if (Disasm_b76 == 3) {
+		if (Disasm_mode == 1) {
+			/* DBcc 0101cccc11001ddd */
+			DisasmDBcc();
+		} else {
+#if Use68020
+			if ((Disasm_mode == 7) && (Disasm_reg >= 2)) {
+				/* TRAPcc 0101cccc11111sss */
+				DisasmTRAPcc();
+			} else
+#endif
+			{
+				/* Scc 0101cccc11mmmrrr */
+				if (IsValidDataAltAddrMode()) {
+					DisasmScc();
+				} else {
+					DisasmIllegal();
+				}
+			}
+		}
+	} else {
+		if (Disasm_mode == 1) {
+			if (Disasm_b8 == 0) {
+				DisasmAddQA(); /* AddQA 0101nnn0ss001rrr */
+			} else {
+				DisasmSubQA(); /* SubQA 0101nnn1ss001rrr */
+			}
+		} else {
+			if (Disasm_b8 == 0) {
+				/* AddQ 0101nnn0ssmmmrrr */
+				if (IsValidDataAltAddrMode()) {
+					DisasmAddQ();
+				} else {
+					DisasmIllegal();
+				}
+			} else {
+				/* SubQ 0101nnn1ssmmmrrr */
+				if (IsValidDataAltAddrMode()) {
+					DisasmSubQ();
+				} else {
+					DisasmIllegal();
+				}
+			}
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DisasmCode6(void)
+{
+	ui5b cond = (Disasm_opcode >> 8) & 15;
+
+	if (cond == 1) {
+		/* Bsr 01100001nnnnnnnn */
+		DisasmBsr();
+	} else if (cond == 0) {
+		/* Bra 01100000nnnnnnnn */
+		DisasmBcc();
+	} else {
+		/* Bcc 0110ccccnnnnnnnn */
+		DisasmBcc();
+	}
+}
+
+LOCALPROCUSEDONCE DisasmCode7(void)
+{
+	if (Disasm_b8 == 0) {
+		DisasmMoveQ();
+	} else {
+		DisasmIllegal();
+	}
+}
+
+LOCALPROCUSEDONCE DisasmCode8(void)
+{
+	if (Disasm_b76 == 3) {
+		if (Disasm_b8 == 0) {
+			/* DivU 1000ddd011mmmrrr */
+			if (IsValidDataAddrMode()) {
+				DisasmDivU();
+			} else {
+				DisasmIllegal();
+			}
+		} else {
+			/* DivS 1000ddd111mmmrrr */
+			if (IsValidDataAddrMode()) {
+				DisasmDivS();
+			} else {
+				DisasmIllegal();
+			}
+		}
+	} else {
+		if (Disasm_b8 == 0) {
+			/* OR 1000ddd0ssmmmrrr */
+			if (IsValidDataAddrMode()) {
+				DisasmOrEaD();
+			} else {
+				DisasmIllegal();
+			}
+		} else {
+			if (Disasm_mode < 2) {
+				switch (Disasm_b76) {
+					case 0:
+						/* SBCD 1000xxx10000mxxx */
+						if (Disasm_mode == 0) {
+							DisasmSbcdr();
+						} else {
+							DisasmSbcdm();
+						}
+						break;
+#if Use68020
+					case 1:
+						/* PACK 1000rrr10100mrrr */
+						DisasmPack();
+						break;
+					case 2:
+						/* UNPK 1000rrr11000mrrr */
+						DisasmUnpk();
+						break;
+#endif
+					default:
+						DisasmIllegal();
+						break;
+				}
+			} else {
+				/* OR 1000ddd1ssmmmrrr */
+				if (IsValidDataAltAddrMode()) {
+					DisasmOrDEa();
+				} else {
+					DisasmIllegal();
+				}
+			}
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DisasmCode9(void)
+{
+	if (Disasm_b76 == 3) {
+		/* SUBA 1001dddm11mmmrrr */
+		if (IsValidAddrMode()) {
+			DisasmSubA();
+		} else {
+			DisasmIllegal();
+		}
+	} else {
+		if (Disasm_b8 == 0) {
+			/* SUB 1001ddd0ssmmmrrr */
+			if (IsValidAddrMode()) {
+				DisasmSubEaR();
+			} else {
+				DisasmIllegal();
+			}
+		} else {
+			if (Disasm_mode == 0) {
+				/* SUBX 1001ddd1ss000rrr */
+				DisasmSubXd();
+			} else if (Disasm_mode == 1) {
+				/* SUBX 1001ddd1ss001rrr */
+				DisasmSubXm();
+			} else {
+				/* SUB 1001ddd1ssmmmrrr */
+				if (IsValidAltMemAddrMode()) {
+					DisasmSubREa();
+				} else {
+					DisasmIllegal();
+				}
+			}
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DisasmCodeA(void)
+{
+	DisasmALine();
+}
+
+LOCALPROCUSEDONCE DisasmCodeB(void)
+{
+	if (Disasm_b76 == 3) {
+		/* CMPA 1011ddds11mmmrrr */
+		if (IsValidAddrMode()) {
+			DisasmCmpA();
+		} else {
+			DisasmIllegal();
+		}
+	} else if (Disasm_b8 == 1) {
+		if (Disasm_mode == 1) {
+			/* CmpM 1011ddd1ss001rrr */
+			DisasmCmpM();
+		} else {
+			/* Eor 1011ddd1ssmmmrrr */
+			if (IsValidDataAltAddrMode()) {
+				DisasmEor();
+			} else {
+				DisasmIllegal();
+			}
+		}
+	} else {
+		/* Cmp 1011ddd0ssmmmrrr */
+		if (IsValidAddrMode()) {
+			DisasmCompare();
+		} else {
+			DisasmIllegal();
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DisasmCodeC(void)
+{
+	if (Disasm_b76 == 3) {
+		if (Disasm_b8 == 0) {
+			/* MulU 1100ddd011mmmrrr */
+			if (IsValidDataAddrMode()) {
+				DisasmMulU();
+			} else {
+				DisasmIllegal();
+			}
+		} else {
+			/* MulS 1100ddd111mmmrrr */
+			if (IsValidDataAddrMode()) {
+				DisasmMulS();
+			} else {
+				DisasmIllegal();
+			}
+		}
+	} else {
+		if (Disasm_b8 == 0) {
+			/* And 1100ddd0ssmmmrrr */
+			if (IsValidDataAddrMode()) {
+				DisasmAndEaD();
+			} else {
+				DisasmIllegal();
+			}
+		} else {
+			if (Disasm_mode < 2) {
+				switch (Disasm_b76) {
+					case 0:
+						/* ABCD 1100ddd10000mrrr */
+						if (Disasm_mode == 0) {
+							DisasmAbcdr();
+						} else {
+							DisasmAbcdm();
+						}
+						break;
+					case 1:
+						/* Exg 1100ddd10100trrr */
+						if (Disasm_mode == 0) {
+							DisasmExgdd();
+						} else {
+							DisasmExgaa();
+						}
+						break;
+					case 2:
+					default: /* keep compiler happy */
+						if (Disasm_mode == 0) {
+							DisasmIllegal();
+						} else {
+							/* Exg 1100ddd110001rrr */
+							DisasmExgda();
+						}
+						break;
+				}
+			} else {
+				/* And 1100ddd1ssmmmrrr */
+				if (IsValidAltMemAddrMode()) {
+					DisasmAndDEa();
+				} else {
+					DisasmIllegal();
+				}
+			}
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DisasmCodeD(void)
+{
+	if (Disasm_b76 == 3) {
+		/* ADDA 1101dddm11mmmrrr */
+		if (IsValidAddrMode()) {
+			DisasmAddA();
+		} else {
+			DisasmIllegal();
+		}
+	} else {
+		if (Disasm_b8 == 0) {
+			/* ADD 1101ddd0ssmmmrrr */
+			if (IsValidAddrMode()) {
+				DisasmAddEaR();
+			} else {
+				DisasmIllegal();
+			}
+		} else {
+			if (Disasm_mode == 0) {
+				DisasmAddXd();
+			} else if (Disasm_mode == 1) {
+				DisasmAddXm();
+			} else {
+				/* ADD 1101ddd1ssmmmrrr */
+				if (IsValidAltMemAddrMode()) {
+					DisasmAddREa();
+				} else {
+					DisasmIllegal();
+				}
+			}
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DisasmCodeE(void)
+{
+	if (Disasm_b76 == 3) {
+		if ((Disasm_opcode & 0x0800) != 0) {
+#if Use68020
+			/* 11101???11mmmrrr */
+			switch (Disasm_mode) {
+				case 1:
+				case 3:
+				case 4:
+				default: /* keep compiler happy */
+					DisasmIllegal();
+					break;
+				case 0:
+				case 2:
+				case 5:
+				case 6:
+					DisasmBitField();
+					break;
+				case 7:
+					switch (Disasm_reg) {
+						case 0:
+						case 1:
+							DisasmBitField();
+							break;
+						case 2:
+						case 3:
+							switch ((Disasm_opcode >> 8) & 7) {
+								case 0: /* BFTST */
+								case 1: /* BFEXTU */
+								case 3: /* BFEXTS */
+								case 5: /* BFFFO */
+									DisasmBitField();
+									break;
+								default:
+									DisasmIllegal();
+									break;
+							}
+							break;
+						default:
+							DisasmIllegal();
+							break;
+					}
+					break;
+			}
+#else
+			DisasmIllegal();
+#endif
+		} else {
+			/* 11100ttd11mmmddd */
+			if (IsValidAltMemAddrMode()) {
+				DisasmRolopNM();
+			} else {
+				DisasmIllegal();
+			}
+		}
+	} else {
+		if (Disasm_mode < 4) {
+			/* 1110cccdss0ttddd */
+			DisasmRolopND();
+		} else {
+			/* 1110rrrdss1ttddd */
+			DisasmRolopDD();
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DisasmCodeF(void)
+{
+	DisasmFLine();
+}
+
+LOCALPROC m68k_Disasm_one(void)
+{
+	Disasm_opcode = Disasm_nextiword();
+
+	switch (Disasm_opcode >> 12) {
+		case 0x0:
+			DisasmCode0();
+			break;
+		case 0x1:
+			DisasmCode1();
+			break;
+		case 0x2:
+			DisasmCode2();
+			break;
+		case 0x3:
+			DisasmCode3();
+			break;
+		case 0x4:
+			DisasmCode4();
+			break;
+		case 0x5:
+			DisasmCode5();
+			break;
+		case 0x6:
+			DisasmCode6();
+			break;
+		case 0x7:
+			DisasmCode7();
+			break;
+		case 0x8:
+			DisasmCode8();
+			break;
+		case 0x9:
+			DisasmCode9();
+			break;
+		case 0xA:
+			DisasmCodeA();
+			break;
+		case 0xB:
+			DisasmCodeB();
+			break;
+		case 0xC:
+			DisasmCodeC();
+			break;
+		case 0xD:
+			DisasmCodeD();
+			break;
+		case 0xE:
+			DisasmCodeE();
+			break;
+		case 0xF:
+		default: /* keep compiler happy */
+			DisasmCodeF();
+			break;
+	}
+}
+
+#define Ln2SavedPCs 4
+#define NumSavedPCs (1 << Ln2SavedPCs)
+#define SavedPCsMask (NumSavedPCs - 1)
+LOCALVAR ui5r SavedPCs[NumSavedPCs];
+LOCALVAR ui5r SavedPCsIn = 0;
+LOCALVAR ui5r SavedPCsOut = 0;
+
+#define DisasmIncludeCycles 0
+
+LOCALPROCUSEDONCE DisasmOneAndBack(ui5r pc)
+{
+#if DisasmIncludeCycles
+	dbglog_writeHex(GetCuriCount());
+	dbglog_writeCStr(" ");
+#endif
+	dbglog_writeHex(pc);
+	dbglog_writeCStr("  ");
+	Disasm_setpc(pc);
+	m68k_Disasm_one();
+}
+
+LOCALPROCUSEDONCE DisasmSavedPCs(void)
+{
+	ui5r n = SavedPCsIn - SavedPCsOut;
+
+	if (n != 0) {
+		ui5r pc;
+#if DisasmIncludeCycles
+		ui5r i;
+#endif
+#if 0
+		blnr Skipped = falseblnr;
+#endif
+		ui5r j = SavedPCsOut;
+
+		SavedPCsOut = SavedPCsIn;
+			/*
+				do first, prevent recursion
+				in case of error while disassembling.
+				(i.e. failure to read emulated memory.)
+			*/
+
+#if DisasmIncludeCycles
+		i = GetCuriCount();
+#endif
+
+		if (n > NumSavedPCs) {
+			n = NumSavedPCs;
+			j = SavedPCsIn - NumSavedPCs;
+			dbglog_writeReturn();
+#if 0
+			Skipped = trueblnr;
+#endif
+		}
+
+		do {
+			--n;
+			pc = SavedPCs[j & SavedPCsMask];
+#if DisasmIncludeCycles
+			dbglog_writeHex(i /* - n */);
+			dbglog_writeCStr("-? ");
+#endif
+			dbglog_writeHex(pc);
+			dbglog_writeCStr("  ");
+			Disasm_setpc(pc);
+			m68k_Disasm_one();
+			++j;
+		} while (n != 0);
+
+#if 0
+		if (Skipped) {
+			si4b z;
+
+			for (z = 0; z < 16; ++z) {
+				if (z >= 8) {
+					dbglog_writeCStr(" A");
+					dbglog_writeHex(z - 8);
+				} else {
+					dbglog_writeCStr(" D");
+					dbglog_writeHex(z);
+				}
+				dbglog_writeCStr(" = ");
+				dbglog_writeHex(regs.regs[z]);
+				dbglog_writeReturn();
+			}
+		}
+#endif
+	}
+}
+
+LOCALVAR ui5r DisasmCounter = 0;
+
+GLOBALPROC DisasmOneOrSave(ui5r pc)
+{
+	if (0 != DisasmCounter) {
+		DisasmOneAndBack(pc);
+		--DisasmCounter;
+	} else {
+		SavedPCs[SavedPCsIn & SavedPCsMask] = pc;
+		++SavedPCsIn;
+	}
+}
+
+GLOBALPROC m68k_WantDisasmContext(void)
+{
+	DisasmSavedPCs();
+	DisasmCounter = /* 256 */ 128;
+}
--- /dev/null
+++ b/src/DISAM68K.h
@@ -1,0 +1,29 @@
+/*
+	DISAM68K.h
+
+	Copyright (C) 2010 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	DISAssemble Motorola 68K instructions.
+*/
+
+#ifdef DIS1M68K_H
+#error "header already included"
+#else
+#define DIS1M68K_H
+#endif
+
+EXPORTPROC DisasmOneOrSave(ui5r pc);
+
+EXPORTPROC m68k_WantDisasmContext(void);
--- /dev/null
+++ b/src/ENDIANAC.h
@@ -1,0 +1,135 @@
+/*
+	ENDIANAC.h
+
+	Copyright (C) 2006 Bernd Schmidt, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	ENDIAN ACcess
+
+	Deals with endian issues in memory access.
+
+	This code is adapted from code in the Un*x Amiga Emulator by
+	Bernd Schmidt, as found in vMac by Philip Cummins.
+*/
+
+#ifdef ENDIANAC_H
+#ifndef AllFiles
+#error "header already included"
+#endif
+#else
+#define ENDIANAC_H
+#endif
+
+
+#define do_get_mem_byte(a) ((ui3r)*((ui3b *)(a)))
+
+#if BigEndianUnaligned
+#define do_get_mem_word(a) ((ui4r)*((ui4b *)(a)))
+#else
+LOCALINLINEFUNC ui4r do_get_mem_word(ui3p a)
+{
+#if LittleEndianUnaligned
+	ui4b b = (*((ui4b *)(a)));
+
+	return ((b & 0x00FF) << 8) | ((b >> 8) & 0x00FF);
+#else
+	return (((ui4r)*a) << 8) | ((ui4r)*(a + 1));
+#endif
+}
+#endif
+
+#if BigEndianUnaligned
+#define do_get_mem_long(a) ((ui5r)*((ui5b *)(a)))
+#elif HaveMySwapUi5r && LittleEndianUnaligned
+#define do_get_mem_long(a) (MySwapUi5r((ui5r)*((ui5b *)(a))))
+#else
+LOCALINLINEFUNC ui5r do_get_mem_long(ui3p a)
+{
+#if LittleEndianUnaligned
+#if 0
+	ui5b b = (*((ui5b *)(a)));
+	return ((b & 0x000000FF) << 24)
+		|  ((b & 0x0000FF00) <<  8)
+		|  ((b & 0x00FF0000) >>  8)
+		|  ((b & 0xFF000000) >> 24);
+#endif
+#if 0
+	ui5b b = (*((ui5b *)(a)));
+	return ((b << 24) & 0xFF000000)
+		|  ((b <<  8) & 0x00FF0000)
+		|  ((b >>  8) & 0x0000FF00)
+		|  ((b >> 24) & 0x000000FF);
+	/*
+		no, this doesn't do well with apple tools,
+		instead try combining two 16 bit swaps.
+	*/
+#endif
+	ui5b b = (*((ui5b *)(a)));
+	ui4b b1 = b;
+	ui4b b2 = b >> 16;
+	ui4b c1 = ((b1 & 0x00FF) << 8) | ((b1 >> 8) & 0x00FF);
+	ui4b c2 = ((b2 & 0x00FF) << 8) | ((b2 >> 8) & 0x00FF);
+
+	return (((ui5r)c1) << 16) | ((ui5r)c2);
+	/*
+		better, though still doesn't use BSWAP
+		instruction with apple tools for intel.
+	*/
+#else
+	return (((ui5r)*a) << 24) | (((ui5r)*(a + 1)) << 16)
+		| (((ui5r)*(a + 2)) << 8) | ((ui5r)*(a + 3));
+#endif
+}
+#endif
+
+#define do_put_mem_byte(a, v) ((*((ui3b *)(a))) = (v))
+
+#if BigEndianUnaligned
+#define do_put_mem_word(a, v) ((*((ui4b *)(a))) = (v))
+#else
+LOCALINLINEFUNC void do_put_mem_word(ui3p a, ui4r v)
+{
+#if LittleEndianUnaligned
+	ui4b b = ((v & 0x00FF) << 8) | ((v >> 8) & 0x00FF);
+
+	*(ui4b *)a = b;
+#else
+	*a = v >> 8;
+	*(a + 1) = v;
+#endif
+}
+#endif
+
+#if BigEndianUnaligned
+#define do_put_mem_long(a, v) ((*((ui5b *)(a))) = (v))
+#elif HaveMySwapUi5r && LittleEndianUnaligned
+#define do_put_mem_long(a, v) ((*((ui5b *)(a))) = MySwapUi5r(v))
+#else
+LOCALINLINEFUNC void do_put_mem_long(ui3p a, ui5r v)
+{
+#if LittleEndianUnaligned
+	ui4b b1 = v;
+	ui4b b2 = v >> 16;
+	ui4b c1 = ((b1 & 0x00FF) << 8) | ((b1 >> 8) & 0x00FF);
+	ui4b c2 = ((b2 & 0x00FF) << 8) | ((b2 >> 8) & 0x00FF);
+
+	*(ui5b *)a = (c1 << 16) | c2;
+#else
+	*a = v >> 24;
+	*(a + 1) = v >> 16;
+	*(a + 2) = v >> 8;
+	*(a + 3) = v;
+#endif
+}
+#endif
--- /dev/null
+++ b/src/FPCPEMDV.h
@@ -1,0 +1,1218 @@
+/*
+	FPCPEMDV.h
+
+	Copyright (C) 2007 Ross Martin, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Floating Point CoProcessor Emulated Device
+	(included by MINEM68K.c)
+*/
+
+/*
+	ReportAbnormalID unused 0x0306 - 0x03FF
+*/
+
+
+LOCALVAR struct fpustruct
+{
+	myfpr fp[8];
+	CPTR FPIAR; /* Floating point instruction address register */
+} fpu_dat;
+
+LOCALPROC myfp_SetFPIAR(ui5r v)
+{
+	fpu_dat.FPIAR = v;
+}
+
+LOCALFUNC ui5r myfp_GetFPIAR(void)
+{
+	return fpu_dat.FPIAR;
+}
+
+LOCALFUNC blnr DecodeAddrModeRegister(ui5b sz)
+{
+	ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat;
+	ui4r themode = (Dat >> 3) & 7;
+	ui4r thereg = Dat & 7;
+
+	switch (themode) {
+		case 2 :
+		case 3 :
+		case 4 :
+		case 5 :
+		case 6 :
+			return DecodeModeRegister(sz);
+			break;
+		case 7 :
+			switch (thereg) {
+				case 0 :
+				case 1 :
+				case 2 :
+				case 3 :
+				case 4 :
+					return DecodeModeRegister(sz);
+					break;
+				default :
+					return falseblnr;
+					break;
+			}
+			break;
+		default :
+			return falseblnr;
+			break;
+	}
+}
+
+LOCALPROC read_long_double(ui5r addr, myfpr *r)
+{
+	ui4r v2;
+	ui5r v1;
+	ui5r v0;
+
+	v2 = get_word(addr + 0);
+	/* ignore word at offset 2 */
+	v1 = get_long(addr + 4);
+	v0 = get_long(addr + 8);
+
+	myfp_FromExtendedFormat(r, v2, v1, v0);
+}
+
+LOCALPROC write_long_double(ui5r addr, myfpr *xx)
+{
+	ui4r v2;
+	ui5r v1;
+	ui5r v0;
+
+	myfp_ToExtendedFormat(xx, &v2, &v1, &v0);
+
+	put_word(addr + 0, v2);
+	put_word(addr + 2,  0);
+	put_long(addr + 4, v1);
+	put_long(addr + 8, v0);
+}
+
+LOCALPROC read_double(ui5r addr, myfpr *r)
+{
+	ui5r v1;
+	ui5r v0;
+
+	v1 = get_long(addr + 0);
+	v0 = get_long(addr + 4);
+
+	myfp_FromDoubleFormat(r, v1, v0);
+}
+
+LOCALPROC write_double(ui5r addr, myfpr *dd)
+{
+	ui5r v1;
+	ui5r v0;
+
+	myfp_ToDoubleFormat(dd, &v1, &v0);
+
+	put_long(addr + 0, v1);
+	put_long(addr + 4, v0);
+}
+
+#if 0
+LOCALPROC read_single(ui5r addr, myfpr *r)
+{
+	myfp_FromSingleFormat(r, get_long(addr));
+}
+
+LOCALPROC write_single(ui5r addr, myfpr *ff)
+{
+	put_long(addr, myfp_ToSingleFormat(ff));
+}
+#endif
+
+
+LOCALFUNC int CheckFPCondition(ui4b predicate)
+{
+	int condition_true = 0;
+
+	ui3r cc = myfp_GetConditionCodeByte();
+
+	int c_nan  = (cc) & 1;
+	/* int c_inf  = (cc >> 1) & 1; */
+	int c_zero = (cc >> 2) & 1;
+	int c_neg  = (cc >> 3) & 1;
+
+	/*
+		printf(
+			"FPSR Checked: c_nan=%d, c_zero=%d, c_neg=%d,"
+			" predicate=0x%04x\n",
+			c_nan, c_zero, c_neg, predicate);
+	*/
+
+	switch (predicate) {
+		case 0x11: /* SEQ */
+		case 0x01: /* EQ */
+			condition_true = c_zero;
+			break;
+		case 0x1E: /* SNE */
+		case 0x0E: /* NE */
+			condition_true = ! c_zero;
+			break;
+		case 0x02: /* OGT */
+		case 0x12: /* GT */
+			condition_true = (! c_neg) && (! c_zero) && (! c_nan);
+			break;
+		case 0x0D: /* ULE */
+		case 0x1D: /* NGT */
+			condition_true = c_neg || c_zero || c_nan;
+			break;
+		case 0x03: /* OGE */
+		case 0x13: /* GE */
+			condition_true = c_zero || ((! c_neg) && (! c_nan));
+			break;
+		case 0x0C: /* ULT */
+		case 0x1C: /* NGE */
+			condition_true = c_nan || ((! c_zero) && c_neg) ;
+			break;
+		case 0x04: /* OLT */
+		case 0x14: /* LT */
+			condition_true = c_neg && (! c_nan) && (! c_zero);
+			break;
+		case 0x0B: /* UGE */
+		case 0x1B: /* NLT */
+			condition_true = c_nan || c_zero || (! c_neg);
+			break;
+		case 0x05: /* OLE */
+		case 0x15: /* LE */
+			condition_true = ((! c_nan) && c_neg) || c_zero;
+			break;
+		case 0x0A: /* UGT */
+		case 0x1A: /* NLE */
+			condition_true = c_nan || ((! c_neg) && (! c_zero));
+			break;
+		case 0x06: /* OGL */
+		case 0x16: /* GL */
+			condition_true = (! c_nan) && (! c_zero);
+			break;
+		case 0x09: /* UEQ */
+		case 0x19: /* NGL */
+			condition_true = c_nan || c_zero;
+			break;
+		case 0x07: /* OR */
+		case 0x17: /* GLE */
+			condition_true = ! c_nan;
+			break;
+		case 0x08: /* NGLE */
+		case 0x18: /* NGLE */
+			condition_true = c_nan;
+			break;
+		case 0x00: /* SFALSE */
+		case 0x10: /* FALSE */
+			condition_true = 0;
+			break;
+		case 0x0F: /* STRUE */
+		case 0x1F: /* TRUE */
+			condition_true = 1;
+			break;
+	}
+
+	/* printf("condition_true=%d\n", condition_true); */
+
+	return condition_true;
+}
+
+LOCALIPROC DoCodeFPU_dflt(void)
+{
+	ReportAbnormalID(0x0301,
+		"unimplemented Floating Point Instruction");
+#if dbglog_HAVE
+	{
+		ui4r opcode = ((ui4r)(V_regs.CurDecOpY.v[0].AMd) << 8)
+			| V_regs.CurDecOpY.v[0].ArgDat;
+
+		dbglog_writelnNum("opcode", opcode);
+	}
+#endif
+	DoCodeFdefault();
+}
+
+LOCALIPROC DoCodeFPU_Save(void)
+{
+	ui4r opcode = ((ui4r)(V_regs.CurDecOpY.v[0].AMd) << 8)
+		| V_regs.CurDecOpY.v[0].ArgDat;
+	if ((opcode == 0xF327) || (opcode == 0xF32D)) {
+#if 0
+		DecodeModeRegister(4);
+		SetArgValueL(0); /* for now, try null state frame */
+#endif
+		/* 28 byte 68881 IDLE frame */
+
+		if (! DecodeAddrModeRegister(28)) {
+			DoCodeFPU_dflt();
+#if dbglog_HAVE
+			dbglog_writeln(
+				"DecodeAddrModeRegister fails in DoCodeFPU_Save");
+#endif
+		} else {
+			put_long(V_regs.ArgAddr.mem, 0x1f180000);
+			put_long(V_regs.ArgAddr.mem + 4, 0);
+			put_long(V_regs.ArgAddr.mem + 8, 0);
+			put_long(V_regs.ArgAddr.mem + 12, 0);
+			put_long(V_regs.ArgAddr.mem + 16, 0);
+			put_long(V_regs.ArgAddr.mem + 20, 0);
+			put_long(V_regs.ArgAddr.mem + 24, 0x70000000);
+		}
+
+	} else {
+		DoCodeFPU_dflt();
+#if dbglog_HAVE
+		dbglog_writeln("unimplemented FPU Save");
+#endif
+	}
+}
+
+LOCALIPROC DoCodeFPU_Restore(void)
+{
+	ui4r opcode = ((ui4r)(V_regs.CurDecOpY.v[0].AMd) << 8)
+		| V_regs.CurDecOpY.v[0].ArgDat;
+	ui4r themode = (opcode >> 3) & 7;
+	ui4r thereg = opcode & 7;
+	if ((opcode == 0xF35F) || (opcode == 0xF36D)) {
+		ui5r dstvalue;
+
+		if (! DecodeAddrModeRegister(4)) {
+			DoCodeFPU_dflt();
+#if dbglog_HAVE
+			dbglog_writeln(
+				"DecodeAddrModeRegister fails in DoCodeFPU_Restore");
+#endif
+		} else {
+			dstvalue = get_long(V_regs.ArgAddr.mem);
+			if (dstvalue != 0) {
+				if (0x1f180000 == dstvalue) {
+					if (3 == themode) {
+						m68k_areg(thereg) = V_regs.ArgAddr.mem + 28;
+					}
+				} else {
+					DoCodeFPU_dflt();
+#if dbglog_HAVE
+					dbglog_writeln("unknown restore");
+						/* not a null state we saved */
+#endif
+				}
+			}
+		}
+	} else {
+		DoCodeFPU_dflt();
+#if dbglog_HAVE
+		dbglog_writeln("unimplemented FPU Restore");
+#endif
+	}
+}
+
+LOCALIPROC DoCodeFPU_FBccW(void)
+{
+	/*
+		Also get here for a NOP instruction (opcode 0xF280),
+		which is simply a FBF.w with offset 0
+	*/
+	ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat;
+
+	if (CheckFPCondition(Dat & 0x3F)) {
+		DoCodeBraW();
+	} else {
+		SkipiWord();
+	}
+
+	/* printf("pc_p set to 0x%p in FBcc (32bit)\n", V_pc_p); */
+}
+
+LOCALIPROC DoCodeFPU_FBccL(void)
+{
+	ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat;
+
+	if (CheckFPCondition(Dat & 0x3F)) {
+		DoCodeBraL();
+	} else {
+		SkipiLong();
+	}
+}
+
+LOCALIPROC DoCodeFPU_DBcc(void)
+{
+	ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat;
+	ui4r thereg = Dat & 7;
+	ui4b word2 = (int)nextiword();
+
+	ui4b predicate = word2 & 0x3F;
+
+	int condition_true = CheckFPCondition(predicate);
+
+	if (! condition_true) {
+		ui5b fdb_count = ui5r_FromSWord(m68k_dreg(thereg)) - 1;
+
+		m68k_dreg(thereg) =
+			(m68k_dreg(thereg) & ~ 0xFFFF) | (fdb_count & 0xFFFF);
+		if ((si5b)fdb_count == -1) {
+			SkipiWord();
+		} else {
+			DoCodeBraW();
+		}
+	} else {
+		SkipiWord();
+	}
+}
+
+LOCALIPROC DoCodeFPU_Trapcc(void)
+{
+	ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat;
+	ui4r thereg = Dat & 7;
+
+	ui4b word2 = (int)nextiword();
+
+	ui4b predicate = word2 & 0x3F;
+
+	int condition_true = CheckFPCondition(predicate);
+
+	if (thereg == 2) {
+		(void) nextiword();
+	} else if (thereg == 3) {
+		(void) nextilong();
+	} else if (thereg == 4) {
+	} else {
+		ReportAbnormalID(0x0302, "Invalid FTRAPcc (?");
+	}
+
+	if (condition_true) {
+		ReportAbnormalID(0x0303, "FTRAPcc trapping");
+		Exception(7);
+	}
+}
+
+LOCALIPROC DoCodeFPU_Scc(void)
+{
+	ui4b word2 = (int)nextiword();
+
+	if (! DecodeModeRegister(1)) {
+		DoCodeFPU_dflt();
+#if dbglog_HAVE
+		dbglog_writeln("bad mode/reg in DoCodeFPU_Scc");
+#endif
+	} else {
+		if (CheckFPCondition(word2 & 0x3F)) {
+			SetArgValueB(0xFFFF);
+		} else {
+			SetArgValueB(0x0000);
+		}
+	}
+}
+
+LOCALPROC DoCodeF_InvalidPlusWord(void)
+{
+	BackupPC();
+	DoCodeFPU_dflt();
+}
+
+LOCALFUNC int CountCSIAlist(ui4b word2)
+{
+	ui4b regselect = (word2 >> 10) & 0x7;
+	int num = 0;
+
+	if (regselect & 1) {
+		num++;
+	}
+	if (regselect & 2) {
+		num++;
+	}
+	if (regselect & 4) {
+		num++;
+	}
+
+	return num;
+}
+
+LOCALPROC DoCodeFPU_Move_EA_CSIA(ui4b word2)
+{
+	int n;
+	ui5b ea_value[3];
+	ui4b regselect = (word2 >> 10) & 0x7;
+	int num = CountCSIAlist(word2);
+
+	if (regselect == 0) {
+		DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+		dbglog_writeln("Invalid FMOVE instruction");
+#endif
+		return;
+	}
+
+	/* FMOVEM.L <EA>, <FP CR,SR,IAR list> */
+
+	if (! DecodeModeRegister(4 * num)) {
+		DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+		dbglog_writeln("bad mode/reg in DoCodeFPU_Move_EA_CSIA");
+#endif
+	} else {
+		ea_value[0] = GetArgValueL();
+		if (num > 1) {
+			ea_value[1] = get_long(V_regs.ArgAddr.mem + 4);
+		}
+		if (num > 2) {
+			ea_value[2] = get_long(V_regs.ArgAddr.mem + 8);
+		}
+
+		n = 0;
+		if (regselect & (1 << 2)) {
+			myfp_SetFPCR(ea_value[n++]);
+		}
+		if (regselect & (1 << 1)) {
+			myfp_SetFPSR(ea_value[n++]);
+		}
+		if (regselect & (1 << 0)) {
+			myfp_SetFPIAR(ea_value[n++]);
+		}
+	}
+}
+
+LOCALPROC DoCodeFPU_MoveM_CSIA_EA(ui4b word2)
+{
+	int n;
+	ui5b ea_value[3];
+	int num = CountCSIAlist(word2);
+
+	ui4b regselect = (word2 >> 10) & 0x7;
+
+	/* FMOVEM.L <FP CR,SR,IAR list>, <EA> */
+
+	if (0 == regselect) {
+		DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+		dbglog_writeln("Invalid FMOVE instruction");
+#endif
+	} else
+	if (! DecodeModeRegister(4 * num)) {
+		DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+		dbglog_writeln("bad mode/reg in DoCodeFPU_MoveM_CSIA_EA");
+#endif
+	} else
+	{
+		n = 0;
+		if (regselect & (1 << 2)) {
+			ea_value[n++] = myfp_GetFPCR();
+		}
+		if (regselect & (1 << 1)) {
+			ea_value[n++] = myfp_GetFPSR();
+		}
+		if (regselect & (1 << 0)) {
+			ea_value[n++] = myfp_GetFPIAR();
+		}
+
+		SetArgValueL(ea_value[0]);
+		if (num > 1) {
+			put_long(V_regs.ArgAddr.mem + 4, ea_value[1]);
+		}
+		if (num > 2) {
+			put_long(V_regs.ArgAddr.mem + 8, ea_value[2]);
+		}
+	}
+}
+
+LOCALPROC DoCodeFPU_MoveM_EA_list(ui4b word2)
+{
+	int i;
+	ui5r myaddr;
+	ui5r count;
+	ui4b register_list = word2;
+
+	ui4b fmove_mode = (word2 >> 11) & 0x3;
+
+	/* FMOVEM.X <ea>, <list> */
+
+	if ((fmove_mode == 0) || (fmove_mode == 1)) {
+		DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+		dbglog_writeln("Invalid FMOVEM.X instruction");
+#endif
+		return;
+	}
+
+	if (fmove_mode == 3) {
+		/* Dynamic mode */
+		register_list = V_regs.regs[(word2 >> 4) & 7];
+	}
+
+	count = 0;
+	for (i = 0; i <= 7; i++) {
+		int j = 1 << (7 - i);
+		if (j & register_list) {
+			++count;
+		}
+	}
+
+	if (! DecodeModeRegister(12 * count)) {
+		DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+		dbglog_writeln(
+			"DecodeModeRegister fails DoCodeFPU_MoveM_EA_list");
+#endif
+	} else {
+		/* Postincrement mode or Control mode */
+
+		myaddr = V_regs.ArgAddr.mem;
+
+		for (i = 0; i <= 7; i++) {
+			int j = 1 << (7 - i);
+			if (j & register_list) {
+				read_long_double(myaddr, &fpu_dat.fp[i]);
+				myaddr += 12;
+			}
+		}
+	}
+}
+
+LOCALPROC DoCodeFPU_MoveM_list_EA(ui4b word2)
+{
+	/* FMOVEM.X <list>, <ea> */
+
+	int i;
+	ui5r myaddr;
+	ui5r count;
+	ui4b register_list = word2;
+	ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat;
+	ui4r themode = (Dat >> 3) & 7;
+
+	ui4b fmove_mode = (word2 >> 11) & 0x3;
+
+	if ((fmove_mode == 1) || (fmove_mode == 3)) {
+		/* Dynamic mode */
+		register_list = V_regs.regs[(word2 >> 4) & 7];
+	}
+
+	count = 0;
+	for (i = 7; i >= 0; i--) {
+		int j = 1 << i;
+		if (j & register_list) {
+			++count;
+		}
+	}
+
+	if (! DecodeModeRegister(12 * count)) {
+		DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+		dbglog_writeln(
+			"DecodeModeRegister fails DoCodeFPU_MoveM_list_EA");
+#endif
+	} else {
+		if (themode == 4) {
+			/* Predecrement mode */
+
+			myaddr = V_regs.ArgAddr.mem + 12 * count;
+
+			for (i = 7; i >= 0; i--) {
+				int j = 1 << i;
+				if (j & register_list) {
+					myaddr -= 12;
+					write_long_double(myaddr, &fpu_dat.fp[i]);
+				}
+			}
+		} else {
+			/* Control mode */
+
+			myaddr = V_regs.ArgAddr.mem;
+
+			for (i = 0; i <= 7; i++) {
+				int j = 1 << (7 - i);
+				if (j & register_list) {
+					write_long_double(myaddr, &fpu_dat.fp[i]);
+					myaddr += 12;
+				}
+			}
+		}
+	}
+}
+
+LOCALPROC DoCodeFPU_MoveCR(ui4b word2)
+{
+	/* FMOVECR */
+	ui4r opcode = ((ui4r)(V_regs.CurDecOpY.v[0].AMd) << 8)
+		| V_regs.CurDecOpY.v[0].ArgDat;
+
+	if (opcode != 0xF200) {
+		DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+		dbglog_writeln("bad opcode in FMOVECR");
+#endif
+	} else {
+		ui4b RomOffset = word2 & 0x7F;
+		ui4b DestReg = (word2 >> 7) & 0x7;
+
+		if (! myfp_getCR(&fpu_dat.fp[DestReg], RomOffset)) {
+			DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+			dbglog_writeln("Invalid constant number in FMOVECR");
+#endif
+		}
+	}
+}
+
+LOCALPROC SaveResultAndFPSR(myfpr *DestReg, myfpr *result)
+{
+	*DestReg = *result;
+	myfp_SetConditionCodeByteFromResult(result);
+}
+
+LOCALPROC DoCodeFPU_GenOp(ui4b word2, myfpr *source)
+{
+	myfpr result;
+	myfpr t0;
+	myfpr *DestReg = &fpu_dat.fp[(word2 >> 7) & 0x7];
+
+	switch (word2 & 0x7F) {
+
+		case 0x00: /* FMOVE */
+			SaveResultAndFPSR(DestReg, source);
+			break;
+
+		case 0x01: /* FINT */
+			myfp_Int(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x02: /* FSINH */
+			myfp_Sinh(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x03: /* FINTRZ */
+			myfp_IntRZ(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x04: /* FSQRT */
+			myfp_Sqrt(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x06: /* FLOGNP1 */
+			myfp_LogNP1(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x08: /* FETOXM1 */
+			myfp_EToXM1(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x09: /* FTANH */
+			myfp_Tanh(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x0A: /* FATAN */
+			myfp_ATan(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x0C: /* FASIN */
+			myfp_ASin(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x0D: /* FATANH */
+			myfp_ATanh(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x0E: /* FSIN */
+			myfp_Sin(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x0F: /* FTAN */
+			myfp_Tan(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x10: /* FETOX */
+			myfp_EToX(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x11: /* FTWOTOX */
+			myfp_TwoToX(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x12: /* FTENTOX */
+			myfp_TenToX(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x14: /* FLOGN */
+			myfp_LogN(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x15: /* FLOG10 */
+			myfp_Log10(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x16: /* FLOG2 */
+			myfp_Log2(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x18: /* FABS */
+			myfp_Abs(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x19: /* FCOSH */
+			myfp_Cosh(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x1A: /* FNEG */
+			myfp_Neg(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x1C: /* FACOS */
+			myfp_ACos(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x1D: /* FCOS */
+			myfp_Cos(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x1E: /* FGETEXP */
+			myfp_GetExp(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x1F: /* FGETMAN */
+			myfp_GetMan(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x20: /* FDIV */
+			myfp_Div(&result, DestReg, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x21: /* FMOD */  /* 0x2D in some docs, 0x21 in others ? */
+			myfp_Mod(&result, DestReg, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x22: /* FADD */
+			myfp_Add(&result, DestReg, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x23: /* FMUL */
+			myfp_Mul(&result, DestReg, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x24: /* FSGLDIV */
+			myfp_Div(&t0, DestReg, source);
+			myfp_RoundToSingle(&result, &t0);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x25: /* FREM */
+			myfp_Rem(&result, DestReg, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x26: /* FSCALE */
+			myfp_Scale(&result, DestReg, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x27: /* FSGLMUL */
+			myfp_Mul(&t0, DestReg, source);
+			myfp_RoundToSingle(&result, &t0);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x28: /* FSUB */
+			myfp_Sub(&result, DestReg, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x30:
+		case 0x31:
+		case 0x32:
+		case 0x33:
+		case 0x34:
+		case 0x35:
+		case 0x36:
+		case 0x37:
+			/* FSINCOS */
+			myfp_SinCos(&result, &fpu_dat.fp[word2 & 0x7], source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x38: /* FCMP */
+			myfp_Sub(&result, DestReg, source);
+			/* don't save result */
+			myfp_SetConditionCodeByteFromResult(&result);
+			break;
+
+		case 0x3A: /* FTST */
+			myfp_SetConditionCodeByteFromResult(source);
+			break;
+
+		/*
+			everything after here is not in 68881/68882,
+			appears first in 68040
+		*/
+
+		case 0x40: /* FSMOVE */
+			myfp_RoundToSingle(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x41: /* FSSQRT */
+			myfp_Sqrt(&t0, source);
+			myfp_RoundToSingle(&result, &t0);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x44: /* FDMOVE */
+			myfp_RoundToDouble(&result, source);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x45: /* FDSQRT */
+			myfp_Sqrt(&t0, source);
+			myfp_RoundToDouble(&result, &t0);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x58: /* FSABS */
+			myfp_Abs(&t0, source);
+			myfp_RoundToSingle(&result, &t0);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x5A: /* FSNEG */
+			myfp_Neg(&t0, source);
+			myfp_RoundToSingle(&result, &t0);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x5C: /* FDABS */
+			myfp_Abs(&t0, source);
+			myfp_RoundToDouble(&result, &t0);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x5E: /* FDNEG */
+			myfp_Neg(&t0, source);
+			myfp_RoundToDouble(&result, &t0);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x60: /* FSDIV */
+			myfp_Div(&t0, DestReg, source);
+			myfp_RoundToSingle(&result, &t0);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x62: /* FSADD */
+			myfp_Add(&t0, DestReg, source);
+			myfp_RoundToSingle(&result, &t0);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x63: /* FSMUL */
+			myfp_Mul(&t0, DestReg, source);
+			myfp_RoundToSingle(&result, &t0);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x64: /* FDDIV */
+			myfp_Div(&t0, DestReg, source);
+			myfp_RoundToDouble(&result, &t0);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x66: /* FDADD */
+			myfp_Add(&t0, DestReg, source);
+			myfp_RoundToDouble(&result, &t0);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x67: /* FDMUL */
+			myfp_Mul(&t0, DestReg, source);
+			myfp_RoundToDouble(&result, &t0);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x68: /* FSSUB */
+			myfp_Sub(&t0, DestReg, source);
+			myfp_RoundToSingle(&result, &t0);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		case 0x6C: /* FDSUB */
+			myfp_Sub(&t0, DestReg, source);
+			myfp_RoundToDouble(&result, &t0);
+			SaveResultAndFPSR(DestReg, &result);
+			break;
+
+		default:
+			DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+			dbglog_writeln("Invalid DoCodeFPU_GenOp");
+#endif
+			break;
+	}
+}
+
+LOCALPROC DoCodeFPU_GenOpReg(ui4b word2)
+{
+	ui4r regselect = (word2 >> 10) & 0x7;
+
+	DoCodeFPU_GenOp(word2, &fpu_dat.fp[regselect]);
+}
+
+LOCALPROC DoCodeFPU_GenOpEA(ui4b word2)
+{
+	myfpr source;
+
+	switch ((word2 >> 10) & 0x7) {
+		case 0: /* long-word integer */
+			if (! DecodeModeRegister(4)) {
+				DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+				dbglog_writeln(
+					"DecodeModeRegister fails GetFPSource L");
+#endif
+			} else {
+				myfp_FromLong(&source, GetArgValueL());
+				DoCodeFPU_GenOp(word2, &source);
+			}
+			break;
+		case 1: /* Single-Precision real */
+			if (! DecodeModeRegister(4)) {
+				DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+				dbglog_writeln(
+					"DecodeModeRegister fails GetFPSource S");
+#endif
+			} else {
+				myfp_FromSingleFormat(&source, GetArgValueL());
+				DoCodeFPU_GenOp(word2, &source);
+			}
+			break;
+		case 2: /* extended precision real */
+			if (! DecodeAddrModeRegister(12)) {
+				DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+				dbglog_writeln(
+					"DecodeAddrModeRegister fails GetFPSource X");
+#endif
+			} else {
+				read_long_double(V_regs.ArgAddr.mem, &source);
+				DoCodeFPU_GenOp(word2, &source);
+			}
+			break;
+		case 3: /* packed-decimal real */
+			if (! DecodeAddrModeRegister(16)) {
+				DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+				dbglog_writeln(
+					"DecodeAddrModeRegister fails GetFPSource P");
+#endif
+			} else {
+				ReportAbnormalID(0x0304,
+					"Packed Decimal in GetFPSource");
+					/* correct? just set to a constant for now */
+				/* *r = 9123456789.0; */
+				DoCodeFPU_GenOp(word2, &source);
+			}
+			break;
+		case 4: /* Word integer */
+			if (! DecodeModeRegister(2)) {
+				DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+				dbglog_writeln(
+					"DecodeModeRegister fails GetFPSource W");
+#endif
+			} else {
+				myfp_FromLong(&source, GetArgValueW());
+				DoCodeFPU_GenOp(word2, &source);
+			}
+			break;
+		case 5: /* Double-precision real */
+			if (! DecodeAddrModeRegister(8)) {
+				DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+				dbglog_writeln(
+					"DecodeAddrModeRegister fails GetFPSource D");
+#endif
+			} else {
+				read_double(V_regs.ArgAddr.mem, &source);
+				DoCodeFPU_GenOp(word2, &source);
+			}
+			break;
+		case 6: /* Byte Integer */
+			if (! DecodeModeRegister(1)) {
+				DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+				dbglog_writeln(
+					"DecodeModeRegister fails GetFPSource B");
+#endif
+			} else {
+				myfp_FromLong(&source, GetArgValueB());
+				DoCodeFPU_GenOp(word2, &source);
+			}
+			break;
+		case 7: /* Not a valid source specifier */
+			DoCodeFPU_MoveCR(word2);
+			break;
+		default:
+			/* should not be able to get here */
+			break;
+	}
+}
+
+LOCALPROC DoCodeFPU_Move_FP_EA(ui4b word2)
+{
+	/* FMOVE FP?, <EA> */
+
+	ui4r SourceReg = (word2 >> 7) & 0x7;
+	myfpr *source = &fpu_dat.fp[SourceReg];
+
+	switch ((word2 >> 10) & 0x7) {
+		case 0: /* long-word integer */
+			if (! DecodeModeRegister(4)) {
+				DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+				dbglog_writeln("DecodeModeRegister fails FMOVE L");
+#endif
+			} else {
+				SetArgValueL(myfp_ToLong(source));
+			}
+			break;
+		case 1: /* Single-Precision real */
+			if (! DecodeModeRegister(4)) {
+				DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+				dbglog_writeln("DecodeModeRegister fails FMOVE S");
+#endif
+			} else {
+				SetArgValueL(myfp_ToSingleFormat(source));
+			}
+			break;
+		case 2: /* extended precision real */
+			if (! DecodeAddrModeRegister(12)) {
+				DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+				dbglog_writeln("DecodeAddrModeRegister fails FMOVE X");
+#endif
+			} else {
+				write_long_double(V_regs.ArgAddr.mem, source);
+			}
+			break;
+		case 3: /* packed-decimal real */
+			if (! DecodeAddrModeRegister(16)) {
+				DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+				dbglog_writeln("DecodeAddrModeRegister fails FMOVE P");
+#endif
+			} else {
+				ReportAbnormalID(0x0305, "Packed Decimal in FMOVE");
+				/* ? */
+			}
+			break;
+		case 4: /* Word integer */
+			if (! DecodeModeRegister(2)) {
+				DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+				dbglog_writeln("DecodeModeRegister fails FMOVE W");
+#endif
+			} else {
+				SetArgValueW(myfp_ToLong(source));
+			}
+			break;
+		case 5: /* Double-precision real */
+			if (! DecodeAddrModeRegister(8)) {
+				DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+				dbglog_writeln("DecodeAddrModeRegister fails FMOVE D");
+#endif
+			} else {
+				write_double(V_regs.ArgAddr.mem, source);
+			}
+			break;
+		case 6: /* Byte Integer */
+			if (! DecodeModeRegister(1)) {
+				DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+				dbglog_writeln("DecodeModeRegister fails FMOVE B");
+#endif
+			} else {
+				SetArgValueB(myfp_ToLong(source));
+			}
+			break;
+		default:
+			DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+			dbglog_writelnNum("Bad Source Specifier in FMOVE",
+				(word2 >> 10) & 0x7);
+#endif
+			break;
+	}
+}
+
+LOCALIPROC DoCodeFPU_md60(void)
+{
+	ui4b word2 = (int)nextiword();
+
+	switch ((word2 >> 13) & 0x7) {
+		case 0:
+			DoCodeFPU_GenOpReg(word2);
+			break;
+		case 2:
+			DoCodeFPU_GenOpEA(word2);
+			break;
+		case 3:
+			DoCodeFPU_Move_FP_EA(word2);
+			break;
+		case 4:
+			DoCodeFPU_Move_EA_CSIA(word2);
+			break;
+		case 5:
+			DoCodeFPU_MoveM_CSIA_EA(word2);
+			break;
+		case 6:
+			DoCodeFPU_MoveM_EA_list(word2);
+			break;
+		case 7:
+			DoCodeFPU_MoveM_list_EA(word2);
+			break;
+		default:
+			DoCodeF_InvalidPlusWord();
+#if dbglog_HAVE
+			dbglog_writelnNum("Invalid DoCodeFPU_md60",
+				(word2 >> 13) & 0x7);
+#endif
+			break;
+	}
+}
--- /dev/null
+++ b/src/FPMATHEM.h
@@ -1,0 +1,6262 @@
+/*
+	FPMATHEM.h
+
+	Copyright (C) 2007 John R. Hauser, Stanislav Shwartsman,
+		Ross Martin, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Floating Point MATH implemented with software EMulation
+
+	Based on the SoftFloat IEC/IEEE Floating-point Arithmetic
+	Package, Release 2b, written by John R. Hauser.
+
+	Also uses extensions to SoftFloat, written for
+	Bochs (x86 achitecture simulator), by Stanislav Shwartsman.
+*/
+
+/*
+	original SoftFloat Copyright notice:
+
+	Written by John R. Hauser.  This work was made possible in part by the
+	International Computer Science Institute, located at Suite 600, 1947 Center
+	Street, Berkeley, California 94704.  Funding was partially provided by the
+	National Science Foundation under grant MIP-9311980.  The original version
+	of this code was written as part of a project to build a fixed-point vector
+	processor in collaboration with the University of California at Berkeley,
+	overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
+	is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
+	arithmetic/SoftFloat.html'.
+
+	THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort has
+	been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
+	RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
+	AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
+	COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
+	EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
+	INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
+	OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
+
+	Derivative works are acceptable, even for commercial purposes, so long as
+	(1) the source code for the derivative work includes prominent notice that
+	the work is derivative, and (2) the source code includes prominent notice with
+	these four paragraphs for those parts of this code that are retained.
+*/
+
+/*
+	original Stanislav Shwartsman Copyright notice:
+
+	This source file is an extension to the SoftFloat IEC/IEEE Floating-point
+	Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator)
+	floating point emulation.
+
+	THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort has
+	been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
+	RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
+	AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
+	COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
+	EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
+	INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
+	OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
+
+	Derivative works are acceptable, even for commercial purposes, so long as
+	(1) the source code for the derivative work includes prominent notice that
+	the work is derivative, and (2) the source code includes prominent notice with
+	these four paragraphs for those parts of this code that are retained.
+
+	.*============================================================================
+	* Written for Bochs (x86 achitecture simulator) by
+	*            Stanislav Shwartsman [sshwarts at sourceforge net]
+	* ==========================================================================*.
+*/
+
+
+/*
+	ReportAbnormalID unused 0x0204 - 0x02FF
+*/
+
+
+/* soft float stuff */
+
+/*
+	should avoid 64 bit literals.
+*/
+
+typedef ui3r flag; /* 0/1 */
+
+/*
+	To fix: softfloat representation of
+	denormalized extended precision numbers
+	is different than on 68881.
+*/
+
+#define cIncludeFPUUnused cIncludeUnused
+
+/* ----- from original file "softfloat.h" ----- */
+
+/*======================================================================
+
+This C header file is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2b.
+
+["original SoftFloat Copyright notice" went here, included near top of
+this file.]
+
+======================================================================*/
+
+/*----------------------------------------------------------------------------
+| The macro `FLOATX80' must be defined to enable the extended double-precision
+| floating-point format `floatx80'.  If this macro is not defined, the
+| `floatx80' type will not be defined, and none of the functions that either
+| input or output the `floatx80' type will be defined.  The same applies to
+| the `FLOAT128' macro and the quadruple-precision format `float128'.
+*----------------------------------------------------------------------------*/
+#define FLOATX80
+#define FLOAT128
+
+/*----------------------------------------------------------------------------
+| Software IEC/IEEE floating-point types.
+*----------------------------------------------------------------------------*/
+
+typedef struct {
+	ui6b low;
+	unsigned short high;
+} floatx80;
+
+#ifdef FLOAT128
+typedef struct {
+	ui6b low, high;
+} float128;
+#endif
+
+
+/* ----- end from original file "softfloat.h" ----- */
+
+
+/*----------------------------------------------------------------------------
+| Software IEC/IEEE floating-point rounding mode.
+*----------------------------------------------------------------------------*/
+enum {
+	float_round_nearest_even = 0,
+	float_round_down         = 1,
+	float_round_up           = 2,
+	float_round_to_zero      = 3
+};
+
+/*----------------------------------------------------------------------------
+| Floating-point rounding mode, extended double-precision rounding precision,
+| and exception flags.
+*----------------------------------------------------------------------------*/
+
+LOCALVAR si3r float_rounding_mode = float_round_nearest_even;
+
+
+/*----------------------------------------------------------------------------
+| Software IEC/IEEE floating-point exception flags.
+*----------------------------------------------------------------------------*/
+
+enum {
+	float_flag_invalid   =  1,
+	float_flag_divbyzero =  4,
+	float_flag_overflow  =  8,
+	float_flag_underflow = 16,
+	float_flag_inexact   = 32
+};
+LOCALVAR si3r float_exception_flags = 0;
+
+/*----------------------------------------------------------------------------
+| Software IEC/IEEE extended double-precision rounding precision.  Valid
+| values are 32, 64, and 80.
+*----------------------------------------------------------------------------*/
+
+LOCALVAR si3r floatx80_rounding_precision = 80;
+
+/*----------------------------------------------------------------------------
+| Primitive arithmetic functions, including multi-word arithmetic, and
+| division and square root approximations.  (Can be specialized to target if
+| desired.)
+*----------------------------------------------------------------------------*/
+
+/* ----- from original file "softfloat-macros" ----- */
+
+/*============================================================================
+
+This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2b.
+
+["original SoftFloat Copyright notice" went here, included near top of this file.]
+
+=============================================================================*/
+
+/*----------------------------------------------------------------------------
+| Shifts `a' right by the number of bits given in `count'.  If any nonzero
+| bits are shifted off, they are ``jammed'' into the least significant bit of
+| the result by setting the least significant bit to 1.  The value of `count'
+| can be arbitrarily large; in particular, if `count' is greater than 32, the
+| result will be either 0 or 1, depending on whether `a' is zero or nonzero.
+| The result is stored in the location pointed to by `zPtr'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEPROC shift32RightJamming( ui5b a, si4r count, ui5b *zPtr )
+{
+	ui5b z;
+
+	if ( count == 0 ) {
+		z = a;
+	}
+	else if ( count < 32 ) {
+		z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 );
+	}
+	else {
+		z = ( a != 0 );
+	}
+	*zPtr = z;
+
+}
+
+/*----------------------------------------------------------------------------
+| Shifts `a' right by the number of bits given in `count'.  If any nonzero
+| bits are shifted off, they are ``jammed'' into the least significant bit of
+| the result by setting the least significant bit to 1.  The value of `count'
+| can be arbitrarily large; in particular, if `count' is greater than 64, the
+| result will be either 0 or 1, depending on whether `a' is zero or nonzero.
+| The result is stored in the location pointed to by `zPtr'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEPROC shift64RightJamming( ui6b a, si4r count, ui6b *zPtr )
+{
+	ui6b z;
+
+	if ( count == 0 ) {
+		z = a;
+	}
+	else if ( count < 64 ) {
+		z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 );
+	}
+	else {
+		z = ( a != 0 );
+	}
+	*zPtr = z;
+
+}
+
+/*----------------------------------------------------------------------------
+| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64
+| _plus_ the number of bits given in `count'.  The shifted result is at most
+| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'.  The
+| bits shifted off form a second 64-bit result as follows:  The _last_ bit
+| shifted off is the most-significant bit of the extra result, and the other
+| 63 bits of the extra result are all zero if and only if _all_but_the_last_
+| bits shifted off were all zero.  This extra result is stored in the location
+| pointed to by `z1Ptr'.  The value of `count' can be arbitrarily large.
+|     (This routine makes more sense if `a0' and `a1' are considered to form
+| a fixed-point value with binary point between `a0' and `a1'.  This fixed-
+| point value is shifted right by the number of bits given in `count', and
+| the integer part of the result is returned at the location pointed to by
+| `z0Ptr'.  The fractional part of the result may be slightly corrupted as
+| described above, and is returned at the location pointed to by `z1Ptr'.)
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEPROC shift64ExtraRightJamming(
+	ui6b a0, ui6b a1, si4r count, ui6b *z0Ptr, ui6b *z1Ptr )
+{
+	ui6b z0, z1;
+	si3r negCount = ( - count ) & 63;
+
+	if ( count == 0 ) {
+		z1 = a1;
+		z0 = a0;
+	}
+	else if ( count < 64 ) {
+		z1 = ( a0<<negCount ) | ( a1 != 0 );
+		z0 = a0>>count;
+	}
+	else {
+		if ( count == 64 ) {
+			z1 = a0 | ( a1 != 0 );
+		}
+		else {
+			z1 = ( ( a0 | a1 ) != 0 );
+		}
+		z0 = 0;
+	}
+	*z1Ptr = z1;
+	*z0Ptr = z0;
+
+}
+
+/*----------------------------------------------------------------------------
+| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
+| number of bits given in `count'.  Any bits shifted off are lost.  The value
+| of `count' can be arbitrarily large; in particular, if `count' is greater
+| than 128, the result will be 0.  The result is broken into two 64-bit pieces
+| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEPROC shift128Right(
+	ui6b a0, ui6b a1, si4r count, ui6b *z0Ptr, ui6b *z1Ptr )
+{
+	ui6b z0, z1;
+	si3r negCount = ( - count ) & 63;
+
+	if ( count == 0 ) {
+		z1 = a1;
+		z0 = a0;
+	}
+	else if ( count < 64 ) {
+		z1 = ( a0<<negCount ) | ( a1>>count );
+		z0 = a0>>count;
+	}
+	else {
+		z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0;
+		z0 = 0;
+	}
+	*z1Ptr = z1;
+	*z0Ptr = z0;
+
+}
+
+/*----------------------------------------------------------------------------
+| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
+| number of bits given in `count'.  If any nonzero bits are shifted off, they
+| are ``jammed'' into the least significant bit of the result by setting the
+| least significant bit to 1.  The value of `count' can be arbitrarily large;
+| in particular, if `count' is greater than 128, the result will be either
+| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or
+| nonzero.  The result is broken into two 64-bit pieces which are stored at
+| the locations pointed to by `z0Ptr' and `z1Ptr'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEPROC shift128RightJamming(
+	ui6b a0, ui6b a1, si4r count, ui6b *z0Ptr, ui6b *z1Ptr )
+{
+	ui6b z0, z1;
+	si3r negCount = ( - count ) & 63;
+
+	if ( count == 0 ) {
+		z1 = a1;
+		z0 = a0;
+	}
+	else if ( count < 64 ) {
+		z1 = ( a0<<negCount ) | ( a1>>count ) | ( ( a1<<negCount ) != 0 );
+		z0 = a0>>count;
+	}
+	else {
+		if ( count == 64 ) {
+			z1 = a0 | ( a1 != 0 );
+		}
+		else if ( count < 128 ) {
+			z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<<negCount ) | a1 ) != 0 );
+		}
+		else {
+			z1 = ( ( a0 | a1 ) != 0 );
+		}
+		z0 = 0;
+	}
+	*z1Ptr = z1;
+	*z0Ptr = z0;
+
+}
+
+/*----------------------------------------------------------------------------
+| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right
+| by 64 _plus_ the number of bits given in `count'.  The shifted result is
+| at most 128 nonzero bits; these are broken into two 64-bit pieces which are
+| stored at the locations pointed to by `z0Ptr' and `z1Ptr'.  The bits shifted
+| off form a third 64-bit result as follows:  The _last_ bit shifted off is
+| the most-significant bit of the extra result, and the other 63 bits of the
+| extra result are all zero if and only if _all_but_the_last_ bits shifted off
+| were all zero.  This extra result is stored in the location pointed to by
+| `z2Ptr'.  The value of `count' can be arbitrarily large.
+|     (This routine makes more sense if `a0', `a1', and `a2' are considered
+| to form a fixed-point value with binary point between `a1' and `a2'.  This
+| fixed-point value is shifted right by the number of bits given in `count',
+| and the integer part of the result is returned at the locations pointed to
+| by `z0Ptr' and `z1Ptr'.  The fractional part of the result may be slightly
+| corrupted as described above, and is returned at the location pointed to by
+| `z2Ptr'.)
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEPROC shift128ExtraRightJamming(
+	ui6b a0,
+	ui6b a1,
+	ui6b a2,
+	si4r count,
+	ui6b *z0Ptr,
+	ui6b *z1Ptr,
+	ui6b *z2Ptr)
+{
+	ui6b z0, z1, z2;
+	si3r negCount = ( - count ) & 63;
+
+	if ( count == 0 ) {
+		z2 = a2;
+		z1 = a1;
+		z0 = a0;
+	}
+	else {
+		if ( count < 64 ) {
+			z2 = a1<<negCount;
+			z1 = ( a0<<negCount ) | ( a1>>count );
+			z0 = a0>>count;
+		}
+		else {
+			if ( count == 64 ) {
+				z2 = a1;
+				z1 = a0;
+			}
+			else {
+				a2 |= a1;
+				if ( count < 128 ) {
+					z2 = a0<<negCount;
+					z1 = a0>>( count & 63 );
+				}
+				else {
+					z2 = ( count == 128 ) ? a0 : ( a0 != 0 );
+					z1 = 0;
+				}
+			}
+			z0 = 0;
+		}
+		z2 |= ( a2 != 0 );
+	}
+	*z2Ptr = z2;
+	*z1Ptr = z1;
+	*z0Ptr = z0;
+
+}
+
+/*----------------------------------------------------------------------------
+| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the
+| number of bits given in `count'.  Any bits shifted off are lost.  The value
+| of `count' must be less than 64.  The result is broken into two 64-bit
+| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEPROC shortShift128Left(
+	ui6b a0, ui6b a1, si4r count, ui6b *z0Ptr, ui6b *z1Ptr )
+{
+
+	*z1Ptr = a1<<count;
+	*z0Ptr =
+		( count == 0 ) ? a0 : ( a0<<count ) | ( a1>>( ( - count ) & 63 ) );
+
+}
+
+/*----------------------------------------------------------------------------
+| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit
+| value formed by concatenating `b0' and `b1'.  Addition is modulo 2^128, so
+| any carry out is lost.  The result is broken into two 64-bit pieces which
+| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEPROC add128(
+	ui6b a0, ui6b a1, ui6b b0, ui6b b1, ui6b *z0Ptr, ui6b *z1Ptr )
+{
+	ui6b z1;
+
+	z1 = a1 + b1;
+	*z1Ptr = z1;
+	*z0Ptr = a0 + b0 + ( z1 < a1 );
+}
+
+/*----------------------------------------------------------------------------
+| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the
+| 192-bit value formed by concatenating `b0', `b1', and `b2'.  Addition is
+| modulo 2^192, so any carry out is lost.  The result is broken into three
+| 64-bit pieces which are stored at the locations pointed to by `z0Ptr',
+| `z1Ptr', and `z2Ptr'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEPROC add192(
+	ui6b a0,
+	ui6b a1,
+	ui6b a2,
+	ui6b b0,
+	ui6b b1,
+	ui6b b2,
+	ui6b *z0Ptr,
+	ui6b *z1Ptr,
+	ui6b *z2Ptr)
+{
+	ui6b z0, z1, z2;
+	si3r carry0, carry1;
+
+	z2 = a2 + b2;
+	carry1 = ( z2 < a2 );
+	z1 = a1 + b1;
+	carry0 = ( z1 < a1 );
+	z0 = a0 + b0;
+	z1 += carry1;
+	z0 += ( z1 < carry1 );
+	z0 += carry0;
+	*z2Ptr = z2;
+	*z1Ptr = z1;
+	*z0Ptr = z0;
+
+}
+
+/*----------------------------------------------------------------------------
+| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the
+| 128-bit value formed by concatenating `a0' and `a1'.  Subtraction is modulo
+| 2^128, so any borrow out (carry out) is lost.  The result is broken into two
+| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and
+| `z1Ptr'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEPROC
+ sub128(
+	 ui6b a0, ui6b a1, ui6b b0, ui6b b1, ui6b *z0Ptr, ui6b *z1Ptr )
+{
+
+	*z1Ptr = a1 - b1;
+	*z0Ptr = a0 - b0 - ( a1 < b1 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2'
+| from the 192-bit value formed by concatenating `a0', `a1', and `a2'.
+| Subtraction is modulo 2^192, so any borrow out (carry out) is lost.  The
+| result is broken into three 64-bit pieces which are stored at the locations
+| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEPROC
+ sub192(
+	 ui6b a0,
+	 ui6b a1,
+	 ui6b a2,
+	 ui6b b0,
+	 ui6b b1,
+	 ui6b b2,
+	 ui6b *z0Ptr,
+	 ui6b *z1Ptr,
+	 ui6b *z2Ptr
+ )
+{
+	ui6b z0, z1, z2;
+	si3r borrow0, borrow1;
+
+	z2 = a2 - b2;
+	borrow1 = ( a2 < b2 );
+	z1 = a1 - b1;
+	borrow0 = ( a1 < b1 );
+	z0 = a0 - b0;
+	z0 -= ( z1 < borrow1 );
+	z1 -= borrow1;
+	z0 -= borrow0;
+	*z2Ptr = z2;
+	*z1Ptr = z1;
+	*z0Ptr = z0;
+
+}
+
+/*----------------------------------------------------------------------------
+| Multiplies `a' by `b' to obtain a 128-bit product.  The product is broken
+| into two 64-bit pieces which are stored at the locations pointed to by
+| `z0Ptr' and `z1Ptr'.
+*----------------------------------------------------------------------------*/
+
+
+#ifndef HaveUi5to6Mul
+#define HaveUi5to6Mul 1
+#endif
+
+#if HaveUi5to6Mul
+LOCALINLINEPROC Ui5to6Mul( ui5b src1, ui5b src2, ui6b *z)
+{
+	*z = ((ui6b) src1) * src2;
+}
+#else
+
+LOCALINLINEPROC Ui6fromHiLo(ui5b hi, ui5b lo, ui6b *z)
+{
+	*z = (((ui6b)(hi)) << 32) + lo;
+#if 0
+	z->lo = hi;
+	z->hi = lo;
+#endif
+}
+
+LOCALPROC Ui5to6Mul( ui5b src1, ui5b src2, ui6b *z)
+{
+	ui4b src1_lo = ui5b_lo(src1);
+	ui4b src2_lo = ui5b_lo(src2);
+	ui4b src1_hi = ui5b_hi(src1);
+	ui4b src2_hi = ui5b_hi(src2);
+
+	ui5b r0 = ( (ui6b) src1_lo ) * src2_lo;
+	ui5b r1 = ( (ui6b) src1_hi ) * src2_lo;
+	ui5b r2 = ( (ui6b) src1_lo ) * src2_hi;
+	ui5b r3 = ( (ui6b) src1_hi ) * src2_hi;
+
+	ui5b ra1 = ui5b_hi(r0) + ui5b_lo(r1) + ui5b_lo(r2);
+
+	ui5b lo = (ui5b_lo(ra1) << 16) | ui5b_lo(r0);
+	ui5b hi = ui5b_hi(ra1) + ui5b_hi(r1) + ui5b_hi(r2) + r3;
+
+	Ui6fromHiLo(hi, lo, z);
+}
+
+#endif
+
+
+LOCALINLINEPROC mul64To128( ui6b a, ui6b b, ui6b *z0Ptr, ui6b *z1Ptr )
+{
+	ui5b aHigh, aLow, bHigh, bLow;
+	ui6b z0, zMiddleA, zMiddleB, z1;
+
+	aLow = a;
+	aHigh = a>>32;
+	bLow = b;
+	bHigh = b>>32;
+
+	Ui5to6Mul(aLow, bLow, &z1);
+	Ui5to6Mul(aLow, bHigh, &zMiddleA);
+	Ui5to6Mul(aHigh, bLow, &zMiddleB);
+	Ui5to6Mul(aHigh, bHigh, &z0);
+
+	zMiddleA += zMiddleB;
+	z0 += ( ( (ui6b) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 );
+	zMiddleA <<= 32;
+	z1 += zMiddleA;
+	z0 += ( z1 < zMiddleA );
+	*z1Ptr = z1;
+	*z0Ptr = z0;
+
+}
+
+/*----------------------------------------------------------------------------
+| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by
+| `b' to obtain a 192-bit product.  The product is broken into three 64-bit
+| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
+| `z2Ptr'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEPROC
+ mul128By64To192(
+	 ui6b a0,
+	 ui6b a1,
+	 ui6b b,
+	 ui6b *z0Ptr,
+	 ui6b *z1Ptr,
+	 ui6b *z2Ptr
+ )
+{
+	ui6b z0, z1, z2, more1;
+
+	mul64To128( a1, b, &z1, &z2 );
+	mul64To128( a0, b, &z0, &more1 );
+	add128( z0, more1, 0, z1, &z0, &z1 );
+	*z2Ptr = z2;
+	*z1Ptr = z1;
+	*z0Ptr = z0;
+
+}
+
+/*----------------------------------------------------------------------------
+| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the
+| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit
+| product.  The product is broken into four 64-bit pieces which are stored at
+| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEPROC
+ mul128To256(
+	 ui6b a0,
+	 ui6b a1,
+	 ui6b b0,
+	 ui6b b1,
+	 ui6b *z0Ptr,
+	 ui6b *z1Ptr,
+	 ui6b *z2Ptr,
+	 ui6b *z3Ptr
+ )
+{
+	ui6b z0, z1, z2, z3;
+	ui6b more1, more2;
+
+	mul64To128( a1, b1, &z2, &z3 );
+	mul64To128( a1, b0, &z1, &more2 );
+	add128( z1, more2, 0, z2, &z1, &z2 );
+	mul64To128( a0, b0, &z0, &more1 );
+	add128( z0, more1, 0, z1, &z0, &z1 );
+	mul64To128( a0, b1, &more1, &more2 );
+	add128( more1, more2, 0, z2, &more1, &z2 );
+	add128( z0, z1, 0, more1, &z0, &z1 );
+	*z3Ptr = z3;
+	*z2Ptr = z2;
+	*z1Ptr = z1;
+	*z0Ptr = z0;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns an approximation to the 64-bit integer quotient obtained by dividing
+| `b' into the 128-bit value formed by concatenating `a0' and `a1'.  The
+| divisor `b' must be at least 2^63.  If q is the exact quotient truncated
+| toward zero, the approximation returned lies between q and q + 2 inclusive.
+| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit
+| unsigned integer is returned.
+*----------------------------------------------------------------------------*/
+
+#ifndef HaveUi6Div
+#define HaveUi6Div 0
+#endif
+
+#if HaveUi6Div
+#define Ui6Div(x, y) ((x) / (y))
+#else
+/*
+	Assuming other 64 bit operations available,
+	like compare, subtract, shift.
+*/
+LOCALFUNC ui6b Ui6Div(ui6b num, ui6b den)
+{
+	ui6b bit = 1;
+	ui6b res = 0;
+
+	while ((den < num) && bit && ! (den & (LIT64(1) << 63))) {
+		den <<= 1;
+		bit <<= 1;
+	}
+
+	while (bit) {
+		if (num >= den) {
+			num -= den;
+			res |= bit;
+		}
+		bit >>= 1;
+		den >>= 1;
+	}
+
+	return res;
+}
+#endif
+
+LOCALFUNC ui6b estimateDiv128To64( ui6b a0, ui6b a1, ui6b b )
+{
+	ui6b b0, b1;
+	ui6b rem0, rem1, term0, term1;
+	ui6b z;
+
+	if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF );
+	b0 = b>>32;
+	z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : Ui6Div(a0, b0) << 32;
+	mul64To128( b, z, &term0, &term1 );
+	sub128( a0, a1, term0, term1, &rem0, &rem1 );
+	while ( ( (si6b) rem0 ) < 0 ) {
+		z -= LIT64( 0x100000000 );
+		b1 = b<<32;
+		add128( rem0, rem1, b0, b1, &rem0, &rem1 );
+	}
+	rem0 = ( rem0<<32 ) | ( rem1>>32 );
+	z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : Ui6Div(rem0, b0);
+	return z;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns an approximation to the square root of the 32-bit significand given
+| by `a'.  Considered as an integer, `a' must be at least 2^31.  If bit 0 of
+| `aExp' (the least significant bit) is 1, the integer returned approximates
+| 2^31*sqrt(`a'/2^31), where `a' is considered an integer.  If bit 0 of `aExp'
+| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30).  In either
+| case, the approximation returned lies strictly within +/-2 of the exact
+| value.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC ui5b estimateSqrt32( si4r aExp, ui5b a )
+{
+	static const ui4b sqrtOddAdjustments[] = {
+		0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
+		0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67
+	};
+	static const ui4b sqrtEvenAdjustments[] = {
+		0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E,
+		0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002
+	};
+	si3r index;
+	ui5b z;
+
+	index = ( a>>27 ) & 15;
+	if ( aExp & 1 ) {
+		z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ];
+		z = ( ( a / z )<<14 ) + ( z<<15 );
+		a >>= 1;
+	}
+	else {
+		z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ];
+		z = a / z + z;
+		z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 );
+		if ( z <= a ) return (ui5b) ( ( (si5b) a )>>1 );
+	}
+	return ( (ui5b) Ui6Div( ( ( (ui6b) a )<<31 ), z ) ) + ( z>>1 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the number of leading 0 bits before the most-significant 1 bit of
+| `a'.  If `a' is zero, 32 is returned.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC si3r countLeadingZeros32( ui5b a )
+{
+	static const si3r countLeadingZerosHigh[] = {
+		8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+		3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+		2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+		2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+		1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+	};
+	si3r shiftCount;
+
+	shiftCount = 0;
+	if ( a < 0x10000 ) {
+		shiftCount += 16;
+		a <<= 16;
+	}
+	if ( a < 0x1000000 ) {
+		shiftCount += 8;
+		a <<= 8;
+	}
+	shiftCount += countLeadingZerosHigh[ a>>24 ];
+	return shiftCount;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the number of leading 0 bits before the most-significant 1 bit of
+| `a'.  If `a' is zero, 64 is returned.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC si3r countLeadingZeros64( ui6b a )
+{
+	si3r shiftCount;
+
+	shiftCount = 0;
+	if ( a < ( (ui6b) 1 )<<32 ) {
+		shiftCount += 32;
+	}
+	else {
+		a >>= 32;
+	}
+	shiftCount += countLeadingZeros32( a );
+	return shiftCount;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1'
+| is equal to the 128-bit value formed by concatenating `b0' and `b1'.
+| Otherwise, returns 0.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC flag eq128( ui6b a0, ui6b a1, ui6b b0, ui6b b1 )
+{
+
+	return ( a0 == b0 ) && ( a1 == b1 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
+| than or equal to the 128-bit value formed by concatenating `b0' and `b1'.
+| Otherwise, returns 0.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC flag le128( ui6b a0, ui6b a1, ui6b b0, ui6b b1 )
+{
+
+	return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
+| than the 128-bit value formed by concatenating `b0' and `b1'.  Otherwise,
+| returns 0.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC flag lt128( ui6b a0, ui6b a1, ui6b b0, ui6b b1 )
+{
+
+	return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is
+| not equal to the 128-bit value formed by concatenating `b0' and `b1'.
+| Otherwise, returns 0.
+*----------------------------------------------------------------------------*/
+
+#if cIncludeFPUUnused
+LOCALINLINEFUNC flag ne128( ui6b a0, ui6b a1, ui6b b0, ui6b b1 )
+{
+
+	return ( a0 != b0 ) || ( a1 != b1 );
+
+}
+#endif
+
+/* ----- end from original file "softfloat-macros" ----- */
+
+/*----------------------------------------------------------------------------
+| Functions and definitions to determine:  (1) whether tininess for underflow
+| is detected before or after rounding by default, (2) what (if anything)
+| happens when exceptions are raised, (3) how signaling NaNs are distinguished
+| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
+| are propagated from function inputs to output.  These details are target-
+| specific.
+*----------------------------------------------------------------------------*/
+
+/* ----- from original file "softfloat-specialize" ----- */
+
+/*============================================================================
+
+This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2b.
+
+["original SoftFloat Copyright notice" went here, included near top of this file.]
+
+=============================================================================*/
+
+/*----------------------------------------------------------------------------
+| Software IEC/IEEE floating-point underflow tininess-detection mode.
+*----------------------------------------------------------------------------*/
+enum {
+	float_tininess_after_rounding  = 0,
+	float_tininess_before_rounding = 1
+};
+
+/*----------------------------------------------------------------------------
+| Underflow tininess-detection mode, statically initialized to default value.
+| (The declaration in `softfloat.h' must match the `si3r' type here.)
+*----------------------------------------------------------------------------*/
+LOCALVAR si3r float_detect_tininess = float_tininess_after_rounding;
+
+/*----------------------------------------------------------------------------
+| Routine to raise any or all of the software IEC/IEEE floating-point
+| exception flags.
+*----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------
+| Raises the exceptions specified by `flags'.  Floating-point traps can be
+| defined here if desired.  It is currently not possible for such a trap
+| to substitute a result value.  If traps are not implemented, this routine
+| should be simply `float_exception_flags |= flags;'.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC void float_raise( si3r flags )
+{
+
+	float_exception_flags |= flags;
+
+}
+
+/*----------------------------------------------------------------------------
+| Internal canonical NaN format.
+*----------------------------------------------------------------------------*/
+typedef struct {
+	flag sign;
+	ui6b high, low;
+} commonNaNT;
+
+/*----------------------------------------------------------------------------
+| The pattern for a default generated extended double-precision NaN.  The
+| `high' and `low' values hold the most- and least-significant bits,
+| respectively.
+*----------------------------------------------------------------------------*/
+#define floatx80_default_nan_high 0xFFFF
+#define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the extended double-precision floating-point value `a' is a
+| NaN; otherwise returns 0.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC flag floatx80_is_nan( floatx80 a )
+{
+
+	return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (ui6b) ( a.low<<1 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the extended double-precision floating-point value `a' is a
+| signaling NaN; otherwise returns 0.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC flag floatx80_is_signaling_nan( floatx80 a )
+{
+	ui6b aLow;
+
+	aLow = a.low & ~ LIT64( 0x4000000000000000 );
+	return
+		   ( ( a.high & 0x7FFF ) == 0x7FFF )
+		&& (ui6b) ( aLow<<1 )
+		&& ( a.low == aLow );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the extended double-precision floating-
+| point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
+| invalid exception is raised.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC commonNaNT floatx80ToCommonNaN( floatx80 a )
+{
+	commonNaNT z;
+
+	if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
+	z.sign = a.high>>15;
+	z.low = 0;
+	z.high = a.low<<1;
+	return z;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the canonical NaN `a' to the extended
+| double-precision floating-point format.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 commonNaNToFloatx80( commonNaNT a )
+{
+	floatx80 z;
+
+	z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
+	z.high = ( ( (ui4b) a.sign )<<15 ) | 0x7FFF;
+	return z;
+
+}
+
+/*----------------------------------------------------------------------------
+| Takes two extended double-precision floating-point values `a' and `b', one
+| of which is a NaN, and returns the appropriate NaN result.  If either `a' or
+| `b' is a signaling NaN, the invalid exception is raised.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
+{
+	flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+
+	aIsNaN = floatx80_is_nan( a );
+	aIsSignalingNaN = floatx80_is_signaling_nan( a );
+	bIsNaN = floatx80_is_nan( b );
+	bIsSignalingNaN = floatx80_is_signaling_nan( b );
+	a.low |= LIT64( 0xC000000000000000 );
+	b.low |= LIT64( 0xC000000000000000 );
+	if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
+	if ( aIsSignalingNaN ) {
+		if ( bIsSignalingNaN ) goto returnLargerSignificand;
+		return bIsNaN ? b : a;
+	}
+	else if ( aIsNaN ) {
+		if ( bIsSignalingNaN | ! bIsNaN ) return a;
+ returnLargerSignificand:
+		if ( a.low < b.low ) return b;
+		if ( b.low < a.low ) return a;
+		return ( a.high < b.high ) ? a : b;
+	}
+	else {
+		return b;
+	}
+
+}
+
+#ifdef FLOAT128
+
+/*----------------------------------------------------------------------------
+| The pattern for a default generated quadruple-precision NaN.  The `high' and
+| `low' values hold the most- and least-significant bits, respectively.
+*----------------------------------------------------------------------------*/
+#define float128_default_nan_high LIT64( 0xFFFF800000000000 )
+#define float128_default_nan_low  LIT64( 0x0000000000000000 )
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
+| otherwise returns 0.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC flag float128_is_nan( float128 a )
+{
+
+	return
+		   ( LIT64( 0xFFFE000000000000 ) <= (ui6b) ( a.high<<1 ) )
+		&& ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the quadruple-precision floating-point value `a' is a
+| signaling NaN; otherwise returns 0.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC flag float128_is_signaling_nan( float128 a )
+{
+
+	return
+		   ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
+		&& ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the quadruple-precision floating-point NaN
+| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
+| exception is raised.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC commonNaNT float128ToCommonNaN( float128 a )
+{
+	commonNaNT z;
+
+	if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
+	z.sign = a.high>>63;
+	shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
+	return z;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the canonical NaN `a' to the quadruple-
+| precision floating-point format.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC float128 commonNaNToFloat128( commonNaNT a )
+{
+	float128 z;
+
+	shift128Right( a.high, a.low, 16, &z.high, &z.low );
+	z.high |= ( ( (ui6b) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
+	return z;
+
+}
+
+/*----------------------------------------------------------------------------
+| Takes two quadruple-precision floating-point values `a' and `b', one of
+| which is a NaN, and returns the appropriate NaN result.  If either `a' or
+| `b' is a signaling NaN, the invalid exception is raised.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC float128 propagateFloat128NaN( float128 a, float128 b )
+{
+	flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+
+	aIsNaN = float128_is_nan( a );
+	aIsSignalingNaN = float128_is_signaling_nan( a );
+	bIsNaN = float128_is_nan( b );
+	bIsSignalingNaN = float128_is_signaling_nan( b );
+	a.high |= LIT64( 0x0000800000000000 );
+	b.high |= LIT64( 0x0000800000000000 );
+	if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
+	if ( aIsSignalingNaN ) {
+		if ( bIsSignalingNaN ) goto returnLargerSignificand;
+		return bIsNaN ? b : a;
+	}
+	else if ( aIsNaN ) {
+		if ( bIsSignalingNaN | ! bIsNaN ) return a;
+ returnLargerSignificand:
+		if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
+		if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
+		return ( a.high < b.high ) ? a : b;
+	}
+	else {
+		return b;
+	}
+
+}
+
+#endif
+
+/* ----- end from original file "softfloat-specialize" ----- */
+
+/* ----- from original file "softfloat.c" ----- */
+
+
+/*============================================================================
+
+This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
+Package, Release 2b.
+
+["original SoftFloat Copyright notice" went here, included near top of this file.]
+
+=============================================================================*/
+
+/*----------------------------------------------------------------------------
+| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
+| and 7, and returns the properly rounded 32-bit integer corresponding to the
+| input.  If `zSign' is 1, the input is negated before being converted to an
+| integer.  Bit 63 of `absZ' must be zero.  Ordinarily, the fixed-point input
+| is simply rounded to an integer, with the inexact exception raised if the
+| input cannot be represented exactly as an integer.  However, if the fixed-
+| point input is too large, the invalid exception is raised and the largest
+| positive or negative integer is returned.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC si5r roundAndPackInt32( flag zSign, ui6b absZ )
+{
+	si3r roundingMode;
+	flag roundNearestEven;
+	si3r roundIncrement, roundBits;
+	si5r z;
+
+	roundingMode = float_rounding_mode;
+	roundNearestEven = ( roundingMode == float_round_nearest_even );
+	roundIncrement = 0x40;
+	if ( ! roundNearestEven ) {
+		if ( roundingMode == float_round_to_zero ) {
+			roundIncrement = 0;
+		}
+		else {
+			roundIncrement = 0x7F;
+			if ( zSign ) {
+				if ( roundingMode == float_round_up ) roundIncrement = 0;
+			}
+			else {
+				if ( roundingMode == float_round_down ) roundIncrement = 0;
+			}
+		}
+	}
+	roundBits = absZ & 0x7F;
+	absZ = ( absZ + roundIncrement )>>7;
+	absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
+	z = absZ;
+	if ( zSign ) z = - z;
+	if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) {
+		float_raise( float_flag_invalid );
+		return zSign ? (si5b) 0x80000000 : 0x7FFFFFFF;
+	}
+	if ( roundBits ) float_exception_flags |= float_flag_inexact;
+	return z;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the fraction bits of the extended double-precision floating-point
+| value `a'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC ui6b extractFloatx80Frac( floatx80 a )
+{
+
+	return a.low;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the exponent bits of the extended double-precision floating-point
+| value `a'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC si5r extractFloatx80Exp( floatx80 a )
+{
+
+	return a.high & 0x7FFF;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the sign bit of the extended double-precision floating-point value
+| `a'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC flag extractFloatx80Sign( floatx80 a )
+{
+
+	return a.high>>15;
+
+}
+
+/*----------------------------------------------------------------------------
+| Normalizes the subnormal extended double-precision floating-point value
+| represented by the denormalized significand `aSig'.  The normalized exponent
+| and significand are stored at the locations pointed to by `zExpPtr' and
+| `zSigPtr', respectively.
+*----------------------------------------------------------------------------*/
+
+LOCALPROC
+ normalizeFloatx80Subnormal( ui6b aSig, si5r *zExpPtr, ui6b *zSigPtr )
+{
+	si3r shiftCount;
+
+	shiftCount = countLeadingZeros64( aSig );
+	*zSigPtr = aSig<<shiftCount;
+	*zExpPtr = 1 - shiftCount;
+
+}
+
+/*----------------------------------------------------------------------------
+| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an
+| extended double-precision floating-point value, returning the result.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC floatx80 packFloatx80( flag zSign, si5r zExp, ui6b zSig )
+{
+	floatx80 z;
+
+	z.low = zSig;
+	z.high = ( ( (ui4b) zSign )<<15 ) + zExp;
+	return z;
+
+}
+
+/*----------------------------------------------------------------------------
+| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+| and extended significand formed by the concatenation of `zSig0' and `zSig1',
+| and returns the proper extended double-precision floating-point value
+| corresponding to the abstract input.  Ordinarily, the abstract value is
+| rounded and packed into the extended double-precision format, with the
+| inexact exception raised if the abstract input cannot be represented
+| exactly.  However, if the abstract value is too large, the overflow and
+| inexact exceptions are raised and an infinity or maximal finite value is
+| returned.  If the abstract value is too small, the input value is rounded to
+| a subnormal number, and the underflow and inexact exceptions are raised if
+| the abstract input cannot be represented exactly as a subnormal extended
+| double-precision floating-point number.
+|     If `roundingPrecision' is 32 or 64, the result is rounded to the same
+| number of bits as single or double precision, respectively.  Otherwise, the
+| result is rounded to the full precision of the extended double-precision
+| format.
+|     The input significand must be normalized or smaller.  If the input
+| significand is not normalized, `zExp' must be 0; in that case, the result
+| returned is a subnormal number, and it must not require rounding.  The
+| handling of underflow and overflow follows the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80
+ roundAndPackFloatx80(
+	 si3r roundingPrecision, flag zSign, si5r zExp, ui6b zSig0, ui6b zSig1
+ )
+{
+	si3r roundingMode;
+	flag roundNearestEven, increment, isTiny;
+	si6r roundIncrement, roundMask, roundBits;
+
+	roundingMode = float_rounding_mode;
+	roundNearestEven = ( roundingMode == float_round_nearest_even );
+	if ( roundingPrecision == 80 ) goto precision80;
+	if ( roundingPrecision == 64 ) {
+		roundIncrement = LIT64( 0x0000000000000400 );
+		roundMask = LIT64( 0x00000000000007FF );
+	}
+	else if ( roundingPrecision == 32 ) {
+		roundIncrement = LIT64( 0x0000008000000000 );
+		roundMask = LIT64( 0x000000FFFFFFFFFF );
+	}
+	else {
+		goto precision80;
+	}
+	zSig0 |= ( zSig1 != 0 );
+	if ( ! roundNearestEven ) {
+		if ( roundingMode == float_round_to_zero ) {
+			roundIncrement = 0;
+		}
+		else {
+			roundIncrement = roundMask;
+			if ( zSign ) {
+				if ( roundingMode == float_round_up ) roundIncrement = 0;
+			}
+			else {
+				if ( roundingMode == float_round_down ) roundIncrement = 0;
+			}
+		}
+	}
+	roundBits = zSig0 & roundMask;
+	if ( 0x7FFD <= (ui5b) ( zExp - 1 ) ) {
+		if (    ( 0x7FFE < zExp )
+			 || ( ( zExp == 0x7FFE ) && ( zSig0 + roundIncrement < zSig0 ) )
+		   ) {
+			goto overflow;
+		}
+		if ( zExp <= 0 ) {
+			isTiny =
+				   ( float_detect_tininess == float_tininess_before_rounding )
+				|| ( zExp < 0 )
+				|| ( zSig0 <= zSig0 + roundIncrement );
+			shift64RightJamming( zSig0, 1 - zExp, &zSig0 );
+			zExp = 0;
+			roundBits = zSig0 & roundMask;
+			if ( isTiny && roundBits ) float_raise( float_flag_underflow );
+			if ( roundBits ) float_exception_flags |= float_flag_inexact;
+			zSig0 += roundIncrement;
+			if ( (si6b) zSig0 < 0 ) zExp = 1;
+			roundIncrement = roundMask + 1;
+			if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
+				roundMask |= roundIncrement;
+			}
+			zSig0 &= ~ roundMask;
+			return packFloatx80( zSign, zExp, zSig0 );
+		}
+	}
+	if ( roundBits ) float_exception_flags |= float_flag_inexact;
+	zSig0 += roundIncrement;
+	if ( zSig0 < roundIncrement ) {
+		++zExp;
+		zSig0 = LIT64( 0x8000000000000000 );
+	}
+	roundIncrement = roundMask + 1;
+	if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
+		roundMask |= roundIncrement;
+	}
+	zSig0 &= ~ roundMask;
+	if ( zSig0 == 0 ) zExp = 0;
+	return packFloatx80( zSign, zExp, zSig0 );
+ precision80:
+	increment = ( (si6b) zSig1 < 0 );
+	if ( ! roundNearestEven ) {
+		if ( roundingMode == float_round_to_zero ) {
+			increment = 0;
+		}
+		else {
+			if ( zSign ) {
+				increment = ( roundingMode == float_round_down ) && zSig1;
+			}
+			else {
+				increment = ( roundingMode == float_round_up ) && zSig1;
+			}
+		}
+	}
+	if ( 0x7FFD <= (ui5b) ( zExp - 1 ) ) {
+		if (    ( 0x7FFE < zExp )
+			 || (    ( zExp == 0x7FFE )
+				  && ( zSig0 == LIT64( 0xFFFFFFFFFFFFFFFF ) )
+				  && increment
+				)
+		   ) {
+			roundMask = 0;
+ overflow:
+			float_raise( float_flag_overflow | float_flag_inexact );
+			if (    ( roundingMode == float_round_to_zero )
+				 || ( zSign && ( roundingMode == float_round_up ) )
+				 || ( ! zSign && ( roundingMode == float_round_down ) )
+			   ) {
+				return packFloatx80( zSign, 0x7FFE, ~ roundMask );
+			}
+			return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+		}
+		if ( zExp <= 0 ) {
+			isTiny =
+				   ( float_detect_tininess == float_tininess_before_rounding )
+				|| ( zExp < 0 )
+				|| ! increment
+				|| ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) );
+			shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 );
+			zExp = 0;
+			if ( isTiny && zSig1 ) float_raise( float_flag_underflow );
+			if ( zSig1 ) float_exception_flags |= float_flag_inexact;
+			if ( roundNearestEven ) {
+				increment = ( (si6b) zSig1 < 0 );
+			}
+			else {
+				if ( zSign ) {
+					increment = ( roundingMode == float_round_down ) && zSig1;
+				}
+				else {
+					increment = ( roundingMode == float_round_up ) && zSig1;
+				}
+			}
+			if ( increment ) {
+				++zSig0;
+				zSig0 &=
+					~ ( ( (ui6b) ( zSig1<<1 ) == 0 ) & roundNearestEven );
+				if ( (si6b) zSig0 < 0 ) zExp = 1;
+			}
+			return packFloatx80( zSign, zExp, zSig0 );
+		}
+	}
+	if ( zSig1 ) float_exception_flags |= float_flag_inexact;
+	if ( increment ) {
+		++zSig0;
+		if ( zSig0 == 0 ) {
+			++zExp;
+			zSig0 = LIT64( 0x8000000000000000 );
+		}
+		else {
+			zSig0 &= ~ ( ( (ui6b) ( zSig1<<1 ) == 0 ) & roundNearestEven );
+		}
+	}
+	else {
+		if ( zSig0 == 0 ) zExp = 0;
+	}
+	return packFloatx80( zSign, zExp, zSig0 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Takes an abstract floating-point value having sign `zSign', exponent
+| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
+| and returns the proper extended double-precision floating-point value
+| corresponding to the abstract input.  This routine is just like
+| `roundAndPackFloatx80' except that the input significand does not have to be
+| normalized.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80
+ normalizeRoundAndPackFloatx80(
+	 si3r roundingPrecision, flag zSign, si5r zExp, ui6b zSig0, ui6b zSig1
+ )
+{
+	si3r shiftCount;
+
+	if ( zSig0 == 0 ) {
+		zSig0 = zSig1;
+		zSig1 = 0;
+		zExp -= 64;
+	}
+	shiftCount = countLeadingZeros64( zSig0 );
+	shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
+	zExp -= shiftCount;
+	return
+		roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 );
+
+}
+
+#ifdef FLOAT128
+
+/*----------------------------------------------------------------------------
+| Returns the least-significant 64 fraction bits of the quadruple-precision
+| floating-point value `a'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC ui6b extractFloat128Frac1( float128 a )
+{
+
+	return a.low;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the most-significant 48 fraction bits of the quadruple-precision
+| floating-point value `a'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC ui6b extractFloat128Frac0( float128 a )
+{
+
+	return a.high & LIT64( 0x0000FFFFFFFFFFFF );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the exponent bits of the quadruple-precision floating-point value
+| `a'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC si5r extractFloat128Exp( float128 a )
+{
+
+	return ( a.high>>48 ) & 0x7FFF;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the sign bit of the quadruple-precision floating-point value `a'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC flag extractFloat128Sign( float128 a )
+{
+
+	return a.high>>63;
+
+}
+
+/*----------------------------------------------------------------------------
+| Normalizes the subnormal quadruple-precision floating-point value
+| represented by the denormalized significand formed by the concatenation of
+| `aSig0' and `aSig1'.  The normalized exponent is stored at the location
+| pointed to by `zExpPtr'.  The most significant 49 bits of the normalized
+| significand are stored at the location pointed to by `zSig0Ptr', and the
+| least significant 64 bits of the normalized significand are stored at the
+| location pointed to by `zSig1Ptr'.
+*----------------------------------------------------------------------------*/
+
+LOCALPROC
+ normalizeFloat128Subnormal(
+	 ui6b aSig0,
+	 ui6b aSig1,
+	 si5r *zExpPtr,
+	 ui6b *zSig0Ptr,
+	 ui6b *zSig1Ptr
+ )
+{
+	si3r shiftCount;
+
+	if ( aSig0 == 0 ) {
+		shiftCount = countLeadingZeros64( aSig1 ) - 15;
+		if ( shiftCount < 0 ) {
+			*zSig0Ptr = aSig1>>( - shiftCount );
+			*zSig1Ptr = aSig1<<( shiftCount & 63 );
+		}
+		else {
+			*zSig0Ptr = aSig1<<shiftCount;
+			*zSig1Ptr = 0;
+		}
+		*zExpPtr = - shiftCount - 63;
+	}
+	else {
+		shiftCount = countLeadingZeros64( aSig0 ) - 15;
+		shortShift128Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );
+		*zExpPtr = 1 - shiftCount;
+	}
+
+}
+
+/*----------------------------------------------------------------------------
+| Packs the sign `zSign', the exponent `zExp', and the significand formed
+| by the concatenation of `zSig0' and `zSig1' into a quadruple-precision
+| floating-point value, returning the result.  After being shifted into the
+| proper positions, the three fields `zSign', `zExp', and `zSig0' are simply
+| added together to form the most significant 32 bits of the result.  This
+| means that any integer portion of `zSig0' will be added into the exponent.
+| Since a properly normalized significand will have an integer portion equal
+| to 1, the `zExp' input should be 1 less than the desired result exponent
+| whenever `zSig0' and `zSig1' concatenated form a complete, normalized
+| significand.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC float128
+ packFloat128( flag zSign, si5r zExp, ui6b zSig0, ui6b zSig1 )
+{
+	float128 z;
+
+	z.low = zSig1;
+	z.high = ( ( (ui6b) zSign )<<63 ) + ( ( (ui6b) zExp )<<48 ) + zSig0;
+	return z;
+
+}
+
+/*----------------------------------------------------------------------------
+| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+| and extended significand formed by the concatenation of `zSig0', `zSig1',
+| and `zSig2', and returns the proper quadruple-precision floating-point value
+| corresponding to the abstract input.  Ordinarily, the abstract value is
+| simply rounded and packed into the quadruple-precision format, with the
+| inexact exception raised if the abstract input cannot be represented
+| exactly.  However, if the abstract value is too large, the overflow and
+| inexact exceptions are raised and an infinity or maximal finite value is
+| returned.  If the abstract value is too small, the input value is rounded to
+| a subnormal number, and the underflow and inexact exceptions are raised if
+| the abstract input cannot be represented exactly as a subnormal quadruple-
+| precision floating-point number.
+|     The input significand must be normalized or smaller.  If the input
+| significand is not normalized, `zExp' must be 0; in that case, the result
+| returned is a subnormal number, and it must not require rounding.  In the
+| usual case that the input significand is normalized, `zExp' must be 1 less
+| than the ``true'' floating-point exponent.  The handling of underflow and
+| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC float128
+ roundAndPackFloat128(
+	 flag zSign, si5r zExp, ui6b zSig0, ui6b zSig1, ui6b zSig2 )
+{
+	si3r roundingMode;
+	flag roundNearestEven, increment, isTiny;
+
+	roundingMode = float_rounding_mode;
+	roundNearestEven = ( roundingMode == float_round_nearest_even );
+	increment = ( (si6b) zSig2 < 0 );
+	if ( ! roundNearestEven ) {
+		if ( roundingMode == float_round_to_zero ) {
+			increment = 0;
+		}
+		else {
+			if ( zSign ) {
+				increment = ( roundingMode == float_round_down ) && zSig2;
+			}
+			else {
+				increment = ( roundingMode == float_round_up ) && zSig2;
+			}
+		}
+	}
+	if ( 0x7FFD <= (ui5b) zExp ) {
+		if (    ( 0x7FFD < zExp )
+			 || (    ( zExp == 0x7FFD )
+				  && eq128(
+						 LIT64( 0x0001FFFFFFFFFFFF ),
+						 LIT64( 0xFFFFFFFFFFFFFFFF ),
+						 zSig0,
+						 zSig1
+					 )
+				  && increment
+				)
+		   ) {
+			float_raise( float_flag_overflow | float_flag_inexact );
+			if (    ( roundingMode == float_round_to_zero )
+				 || ( zSign && ( roundingMode == float_round_up ) )
+				 || ( ! zSign && ( roundingMode == float_round_down ) )
+			   ) {
+				return
+					packFloat128(
+						zSign,
+						0x7FFE,
+						LIT64( 0x0000FFFFFFFFFFFF ),
+						LIT64( 0xFFFFFFFFFFFFFFFF )
+					);
+			}
+			return packFloat128( zSign, 0x7FFF, 0, 0 );
+		}
+		if ( zExp < 0 ) {
+			isTiny =
+				   ( float_detect_tininess == float_tininess_before_rounding )
+				|| ( zExp < -1 )
+				|| ! increment
+				|| lt128(
+					   zSig0,
+					   zSig1,
+					   LIT64( 0x0001FFFFFFFFFFFF ),
+					   LIT64( 0xFFFFFFFFFFFFFFFF )
+				   );
+			shift128ExtraRightJamming(
+				zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 );
+			zExp = 0;
+			if ( isTiny && zSig2 ) float_raise( float_flag_underflow );
+			if ( roundNearestEven ) {
+				increment = ( (si6b) zSig2 < 0 );
+			}
+			else {
+				if ( zSign ) {
+					increment = ( roundingMode == float_round_down ) && zSig2;
+				}
+				else {
+					increment = ( roundingMode == float_round_up ) && zSig2;
+				}
+			}
+		}
+	}
+	if ( zSig2 ) float_exception_flags |= float_flag_inexact;
+	if ( increment ) {
+		add128( zSig0, zSig1, 0, 1, &zSig0, &zSig1 );
+		zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven );
+	}
+	else {
+		if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0;
+	}
+	return packFloat128( zSign, zExp, zSig0, zSig1 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+| and significand formed by the concatenation of `zSig0' and `zSig1', and
+| returns the proper quadruple-precision floating-point value corresponding
+| to the abstract input.  This routine is just like `roundAndPackFloat128'
+| except that the input significand has fewer bits and does not have to be
+| normalized.  In all cases, `zExp' must be 1 less than the ``true'' floating-
+| point exponent.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC float128
+ normalizeRoundAndPackFloat128(
+	 flag zSign, si5r zExp, ui6b zSig0, ui6b zSig1 )
+{
+	si3r shiftCount;
+	ui6b zSig2;
+
+	if ( zSig0 == 0 ) {
+		zSig0 = zSig1;
+		zSig1 = 0;
+		zExp -= 64;
+	}
+	shiftCount = countLeadingZeros64( zSig0 ) - 15;
+	if ( 0 <= shiftCount ) {
+		zSig2 = 0;
+		shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
+	}
+	else {
+		shift128ExtraRightJamming(
+			zSig0, zSig1, 0, - shiftCount, &zSig0, &zSig1, &zSig2 );
+	}
+	zExp -= shiftCount;
+	return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+#endif
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the 32-bit two's complement integer `a'
+| to the extended double-precision floating-point format.  The conversion
+| is performed according to the IEC/IEEE Standard for Binary Floating-Point
+| Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 int32_to_floatx80( si5r a )
+{
+	flag zSign;
+	ui5r absA;
+	si3r shiftCount;
+	ui6b zSig;
+
+	if ( a == 0 ) return packFloatx80( 0, 0, 0 );
+	zSign = ( a < 0 );
+	absA = zSign ? - a : a;
+	shiftCount = countLeadingZeros32( absA ) + 32;
+	zSig = absA;
+	return packFloatx80( zSign, 0x403E - shiftCount, zSig<<shiftCount );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the extended double-precision floating-
+| point value `a' to the 32-bit two's complement integer format.  The
+| conversion is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic---which means in particular that the conversion
+| is rounded according to the current rounding mode.  If `a' is a NaN, the
+| largest positive integer is returned.  Otherwise, if the conversion
+| overflows, the largest integer with the same sign as `a' is returned.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC si5r floatx80_to_int32( floatx80 a )
+{
+	flag aSign;
+	si5r aExp, shiftCount;
+	ui6b aSig;
+
+	aSig = extractFloatx80Frac( a );
+	aExp = extractFloatx80Exp( a );
+	aSign = extractFloatx80Sign( a );
+	if ( ( aExp == 0x7FFF ) && (ui6b) ( aSig<<1 ) ) aSign = 0;
+	shiftCount = 0x4037 - aExp;
+	if ( shiftCount <= 0 ) shiftCount = 1;
+	shift64RightJamming( aSig, shiftCount, &aSig );
+	return roundAndPackInt32( aSign, aSig );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the extended double-precision floating-
+| point value `a' to the 32-bit two's complement integer format.  The
+| conversion is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic, except that the conversion is always rounded
+| toward zero.  If `a' is a NaN, the largest positive integer is returned.
+| Otherwise, if the conversion overflows, the largest integer with the same
+| sign as `a' is returned.
+*----------------------------------------------------------------------------*/
+
+#if cIncludeFPUUnused
+LOCALFUNC si5r floatx80_to_int32_round_to_zero( floatx80 a )
+{
+	flag aSign;
+	si5r aExp, shiftCount;
+	ui6b aSig, savedASig;
+	si5r z;
+
+	aSig = extractFloatx80Frac( a );
+	aExp = extractFloatx80Exp( a );
+	aSign = extractFloatx80Sign( a );
+	if ( 0x401E < aExp ) {
+		if ( ( aExp == 0x7FFF ) && (ui6b) ( aSig<<1 ) ) aSign = 0;
+		goto invalid;
+	}
+	else if ( aExp < 0x3FFF ) {
+		if ( aExp || aSig ) float_exception_flags |= float_flag_inexact;
+		return 0;
+	}
+	shiftCount = 0x403E - aExp;
+	savedASig = aSig;
+	aSig >>= shiftCount;
+	z = aSig;
+	if ( aSign ) z = - z;
+	if ( ( z < 0 ) ^ aSign ) {
+ invalid:
+		float_raise( float_flag_invalid );
+		return aSign ? (si5b) 0x80000000 : 0x7FFFFFFF;
+	}
+	if ( ( aSig<<shiftCount ) != savedASig ) {
+		float_exception_flags |= float_flag_inexact;
+	}
+	return z;
+
+}
+#endif
+
+#ifdef FLOAT128
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the extended double-precision floating-
+| point value `a' to the quadruple-precision floating-point format.  The
+| conversion is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC float128 floatx80_to_float128( floatx80 a )
+{
+	flag aSign;
+	si4r aExp;
+	ui6b aSig, zSig0, zSig1;
+
+	aSig = extractFloatx80Frac( a );
+	aExp = extractFloatx80Exp( a );
+	aSign = extractFloatx80Sign( a );
+	if ( ( aExp == 0x7FFF ) && (ui6b) ( aSig<<1 ) ) {
+		return commonNaNToFloat128( floatx80ToCommonNaN( a ) );
+	}
+	shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 );
+	return packFloat128( aSign, aExp, zSig0, zSig1 );
+
+}
+
+#endif
+
+/*----------------------------------------------------------------------------
+| Rounds the extended double-precision floating-point value `a' to an integer,
+| and returns the result as an extended quadruple-precision floating-point
+| value.  The operation is performed according to the IEC/IEEE Standard for
+| Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 floatx80_round_to_int( floatx80 a )
+{
+	flag aSign;
+	si5r aExp;
+	ui6b lastBitMask, roundBitsMask;
+	si3r roundingMode;
+	floatx80 z;
+
+	aExp = extractFloatx80Exp( a );
+	if ( 0x403E <= aExp ) {
+		if ( ( aExp == 0x7FFF ) && (ui6b) ( extractFloatx80Frac( a )<<1 ) ) {
+			return propagateFloatx80NaN( a, a );
+		}
+		return a;
+	}
+	if ( aExp < 0x3FFF ) {
+		if (    ( aExp == 0 )
+			 && ( (ui6b) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) {
+			return a;
+		}
+		float_exception_flags |= float_flag_inexact;
+		aSign = extractFloatx80Sign( a );
+		switch ( float_rounding_mode ) {
+		 case float_round_nearest_even:
+			if ( ( aExp == 0x3FFE ) && (ui6b) ( extractFloatx80Frac( a )<<1 )
+			   ) {
+				return
+					packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) );
+			}
+			break;
+		 case float_round_down:
+			return
+				  aSign ?
+					  packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) )
+				: packFloatx80( 0, 0, 0 );
+		 case float_round_up:
+			return
+				  aSign ? packFloatx80( 1, 0, 0 )
+				: packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) );
+		}
+		return packFloatx80( aSign, 0, 0 );
+	}
+	lastBitMask = 1;
+	lastBitMask <<= 0x403E - aExp;
+	roundBitsMask = lastBitMask - 1;
+	z = a;
+	roundingMode = float_rounding_mode;
+	if ( roundingMode == float_round_nearest_even ) {
+		z.low += lastBitMask>>1;
+		if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
+	}
+	else if ( roundingMode != float_round_to_zero ) {
+		if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) {
+			z.low += roundBitsMask;
+		}
+	}
+	z.low &= ~ roundBitsMask;
+	if ( z.low == 0 ) {
+		++z.high;
+		z.low = LIT64( 0x8000000000000000 );
+	}
+	if ( z.low != a.low ) float_exception_flags |= float_flag_inexact;
+	return z;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of adding the absolute values of the extended double-
+| precision floating-point values `a' and `b'.  If `zSign' is 1, the sum is
+| negated before being returned.  `zSign' is ignored if the result is a NaN.
+| The addition is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
+{
+	si5r aExp, bExp, zExp;
+	ui6b aSig, bSig, zSig0, zSig1;
+	si5r expDiff;
+
+	aSig = extractFloatx80Frac( a );
+	aExp = extractFloatx80Exp( a );
+	bSig = extractFloatx80Frac( b );
+	bExp = extractFloatx80Exp( b );
+	expDiff = aExp - bExp;
+	if ( 0 < expDiff ) {
+		if ( aExp == 0x7FFF ) {
+			if ( (ui6b) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b );
+			return a;
+		}
+		if ( bExp == 0 ) --expDiff;
+		shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
+		zExp = aExp;
+	}
+	else if ( expDiff < 0 ) {
+		if ( bExp == 0x7FFF ) {
+			if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+			return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+		}
+		if ( aExp == 0 ) ++expDiff;
+		shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
+		zExp = bExp;
+	}
+	else {
+		if ( aExp == 0x7FFF ) {
+			if ( (ui6b) ( ( aSig | bSig )<<1 ) ) {
+				return propagateFloatx80NaN( a, b );
+			}
+			return a;
+		}
+		zSig1 = 0;
+		zSig0 = aSig + bSig;
+		if ( aExp == 0 ) {
+			normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 );
+			goto roundAndPack;
+		}
+		zExp = aExp;
+		goto shiftRight1;
+	}
+	zSig0 = aSig + bSig;
+	if ( (si6b) zSig0 < 0 ) goto roundAndPack;
+ shiftRight1:
+	shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 );
+	zSig0 |= LIT64( 0x8000000000000000 );
+	++zExp;
+ roundAndPack:
+	return
+		roundAndPackFloatx80(
+			floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of subtracting the absolute values of the extended
+| double-precision floating-point values `a' and `b'.  If `zSign' is 1, the
+| difference is negated before being returned.  `zSign' is ignored if the
+| result is a NaN.  The subtraction is performed according to the IEC/IEEE
+| Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
+{
+	si5r aExp, bExp, zExp;
+	ui6b aSig, bSig, zSig0, zSig1;
+	si5r expDiff;
+	floatx80 z;
+
+	aSig = extractFloatx80Frac( a );
+	aExp = extractFloatx80Exp( a );
+	bSig = extractFloatx80Frac( b );
+	bExp = extractFloatx80Exp( b );
+	expDiff = aExp - bExp;
+	if ( 0 < expDiff ) goto aExpBigger;
+	if ( expDiff < 0 ) goto bExpBigger;
+	if ( aExp == 0x7FFF ) {
+		if ( (ui6b) ( ( aSig | bSig )<<1 ) ) {
+			return propagateFloatx80NaN( a, b );
+		}
+		float_raise( float_flag_invalid );
+		z.low = floatx80_default_nan_low;
+		z.high = floatx80_default_nan_high;
+		return z;
+	}
+	if ( aExp == 0 ) {
+		aExp = 1;
+		bExp = 1;
+	}
+	zSig1 = 0;
+	if ( bSig < aSig ) goto aBigger;
+	if ( aSig < bSig ) goto bBigger;
+	return packFloatx80( float_rounding_mode == float_round_down, 0, 0 );
+ bExpBigger:
+	if ( bExp == 0x7FFF ) {
+		if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+		return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) );
+	}
+	if ( aExp == 0 ) ++expDiff;
+	shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
+ bBigger:
+	sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 );
+	zExp = bExp;
+	zSign ^= 1;
+	goto normalizeRoundAndPack;
+ aExpBigger:
+	if ( aExp == 0x7FFF ) {
+		if ( (ui6b) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b );
+		return a;
+	}
+	if ( bExp == 0 ) --expDiff;
+	shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
+ aBigger:
+	sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 );
+	zExp = aExp;
+ normalizeRoundAndPack:
+	return
+		normalizeRoundAndPackFloatx80(
+			floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of adding the extended double-precision floating-point
+| values `a' and `b'.  The operation is performed according to the IEC/IEEE
+| Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 floatx80_add( floatx80 a, floatx80 b )
+{
+	flag aSign, bSign;
+
+	aSign = extractFloatx80Sign( a );
+	bSign = extractFloatx80Sign( b );
+	if ( aSign == bSign ) {
+		return addFloatx80Sigs( a, b, aSign );
+	}
+	else {
+		return subFloatx80Sigs( a, b, aSign );
+	}
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of subtracting the extended double-precision floating-
+| point values `a' and `b'.  The operation is performed according to the
+| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 floatx80_sub( floatx80 a, floatx80 b )
+{
+	flag aSign, bSign;
+
+	aSign = extractFloatx80Sign( a );
+	bSign = extractFloatx80Sign( b );
+	if ( aSign == bSign ) {
+		return subFloatx80Sigs( a, b, aSign );
+	}
+	else {
+		return addFloatx80Sigs( a, b, aSign );
+	}
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of multiplying the extended double-precision floating-
+| point values `a' and `b'.  The operation is performed according to the
+| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 floatx80_mul( floatx80 a, floatx80 b )
+{
+	flag aSign, bSign, zSign;
+	si5r aExp, bExp, zExp;
+	ui6b aSig, bSig, zSig0, zSig1;
+	floatx80 z;
+
+	aSig = extractFloatx80Frac( a );
+	aExp = extractFloatx80Exp( a );
+	aSign = extractFloatx80Sign( a );
+	bSig = extractFloatx80Frac( b );
+	bExp = extractFloatx80Exp( b );
+	bSign = extractFloatx80Sign( b );
+	zSign = aSign ^ bSign;
+	if ( aExp == 0x7FFF ) {
+		if (    (ui6b) ( aSig<<1 )
+			 || ( ( bExp == 0x7FFF ) && (ui6b) ( bSig<<1 ) ) ) {
+			return propagateFloatx80NaN( a, b );
+		}
+		if ( ( bExp | bSig ) == 0 ) goto invalid;
+		return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+	}
+	if ( bExp == 0x7FFF ) {
+		if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+		if ( ( aExp | aSig ) == 0 ) {
+ invalid:
+			float_raise( float_flag_invalid );
+			z.low = floatx80_default_nan_low;
+			z.high = floatx80_default_nan_high;
+			return z;
+		}
+		return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+	}
+	if ( aExp == 0 ) {
+		if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
+		normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
+	}
+	if ( bExp == 0 ) {
+		if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 );
+		normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
+	}
+	zExp = aExp + bExp - 0x3FFE;
+	mul64To128( aSig, bSig, &zSig0, &zSig1 );
+	if ( 0 < (si6b) zSig0 ) {
+		shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 );
+		--zExp;
+	}
+	return
+		roundAndPackFloatx80(
+			floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of dividing the extended double-precision floating-point
+| value `a' by the corresponding value `b'.  The operation is performed
+| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 floatx80_div( floatx80 a, floatx80 b )
+{
+	flag aSign, bSign, zSign;
+	si5r aExp, bExp, zExp;
+	ui6b aSig, bSig, zSig0, zSig1;
+	ui6b rem0, rem1, rem2, term0, term1, term2;
+	floatx80 z;
+
+	aSig = extractFloatx80Frac( a );
+	aExp = extractFloatx80Exp( a );
+	aSign = extractFloatx80Sign( a );
+	bSig = extractFloatx80Frac( b );
+	bExp = extractFloatx80Exp( b );
+	bSign = extractFloatx80Sign( b );
+	zSign = aSign ^ bSign;
+	if ( aExp == 0x7FFF ) {
+		if ( (ui6b) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b );
+		if ( bExp == 0x7FFF ) {
+			if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+			goto invalid;
+		}
+		return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+	}
+	if ( bExp == 0x7FFF ) {
+		if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+		return packFloatx80( zSign, 0, 0 );
+	}
+	if ( bExp == 0 ) {
+		if ( bSig == 0 ) {
+			if ( ( aExp | aSig ) == 0 ) {
+ invalid:
+				float_raise( float_flag_invalid );
+				z.low = floatx80_default_nan_low;
+				z.high = floatx80_default_nan_high;
+				return z;
+			}
+			float_raise( float_flag_divbyzero );
+			return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+		}
+		normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
+	}
+	if ( aExp == 0 ) {
+		if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
+		normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
+	}
+	if ( aSig == 0 ) {
+		/*
+			added by pcp. this invalid input seems to
+			cause hang in estimateDiv128To64. should
+			validate inputs generally.
+		*/
+		return packFloatx80( zSign, 0, 0 );
+	}
+	if ( (si6b) bSig >= 0 ) {
+		/*
+			added by pcp. another check.
+			invalid input, most significant bit should be set?
+		*/
+		return packFloatx80( zSign, 0, 0 );
+	}
+	zExp = aExp - bExp + 0x3FFE;
+	rem1 = 0;
+	if ( bSig <= aSig ) {
+		shift128Right( aSig, 0, 1, &aSig, &rem1 );
+		++zExp;
+	}
+	zSig0 = estimateDiv128To64( aSig, rem1, bSig );
+	mul64To128( bSig, zSig0, &term0, &term1 );
+	sub128( aSig, rem1, term0, term1, &rem0, &rem1 );
+	while ( (si6b) rem0 < 0 ) {
+		--zSig0;
+		add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
+	}
+	zSig1 = estimateDiv128To64( rem1, 0, bSig );
+	if ( (ui6b) ( zSig1<<1 ) <= 8 ) {
+		mul64To128( bSig, zSig1, &term1, &term2 );
+		sub128( rem1, 0, term1, term2, &rem1, &rem2 );
+		while ( (si6b) rem1 < 0 ) {
+			--zSig1;
+			add128( rem1, rem2, 0, bSig, &rem1, &rem2 );
+		}
+		zSig1 |= ( ( rem1 | rem2 ) != 0 );
+	}
+	return
+		roundAndPackFloatx80(
+			floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the remainder of the extended double-precision floating-point value
+| `a' with respect to the corresponding value `b'.  The operation is performed
+| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 floatx80_rem( floatx80 a, floatx80 b )
+{
+	flag aSign, /* bSign, */ zSign;
+	si5r aExp, bExp, expDiff;
+	ui6b aSig0, aSig1, bSig;
+	ui6b q, term0, term1, alternateASig0, alternateASig1;
+	floatx80 z;
+
+	aSig0 = extractFloatx80Frac( a );
+	aExp = extractFloatx80Exp( a );
+	aSign = extractFloatx80Sign( a );
+	bSig = extractFloatx80Frac( b );
+	bExp = extractFloatx80Exp( b );
+	/*
+		not used. should it be?
+		bSign = extractFloatx80Sign( b );
+	*/
+	if ( aExp == 0x7FFF ) {
+		if (    (ui6b) ( aSig0<<1 )
+			 || ( ( bExp == 0x7FFF ) && (ui6b) ( bSig<<1 ) ) ) {
+			return propagateFloatx80NaN( a, b );
+		}
+		goto invalid;
+	}
+	if ( bExp == 0x7FFF ) {
+		if ( (ui6b) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+		return a;
+	}
+	if ( bExp == 0 ) {
+		if ( bSig == 0 ) {
+ invalid:
+			float_raise( float_flag_invalid );
+			z.low = floatx80_default_nan_low;
+			z.high = floatx80_default_nan_high;
+			return z;
+		}
+		normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
+	}
+	if ( aExp == 0 ) {
+		if ( (ui6b) ( aSig0<<1 ) == 0 ) return a;
+		normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
+	}
+	bSig |= LIT64( 0x8000000000000000 );
+	zSign = aSign;
+	expDiff = aExp - bExp;
+	aSig1 = 0;
+	if ( expDiff < 0 ) {
+		if ( expDiff < -1 ) return a;
+		shift128Right( aSig0, 0, 1, &aSig0, &aSig1 );
+		expDiff = 0;
+	}
+	q = ( bSig <= aSig0 );
+	if ( q ) aSig0 -= bSig;
+	expDiff -= 64;
+	while ( 0 < expDiff ) {
+		q = estimateDiv128To64( aSig0, aSig1, bSig );
+		q = ( 2 < q ) ? q - 2 : 0;
+		mul64To128( bSig, q, &term0, &term1 );
+		sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
+		shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 );
+		expDiff -= 62;
+	}
+	expDiff += 64;
+	if ( 0 < expDiff ) {
+		q = estimateDiv128To64( aSig0, aSig1, bSig );
+		q = ( 2 < q ) ? q - 2 : 0;
+		q >>= 64 - expDiff;
+		mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 );
+		sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
+		shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 );
+		while ( le128( term0, term1, aSig0, aSig1 ) ) {
+			++q;
+			sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
+		}
+	}
+	else {
+		term1 = 0;
+		term0 = bSig;
+	}
+	sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 );
+	if (    lt128( alternateASig0, alternateASig1, aSig0, aSig1 )
+		 || (    eq128( alternateASig0, alternateASig1, aSig0, aSig1 )
+			  && ( q & 1 ) )
+	   ) {
+		aSig0 = alternateASig0;
+		aSig1 = alternateASig1;
+		zSign = ! zSign;
+	}
+	return
+		normalizeRoundAndPackFloatx80(
+			80, zSign, bExp + expDiff, aSig0, aSig1 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the square root of the extended double-precision floating-point
+| value `a'.  The operation is performed according to the IEC/IEEE Standard
+| for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 floatx80_sqrt( floatx80 a )
+{
+	flag aSign;
+	si5r aExp, zExp;
+	ui6b aSig0, aSig1, zSig0, zSig1, doubleZSig0;
+	ui6b rem0, rem1, rem2, rem3, term0, term1, term2, term3;
+	floatx80 z;
+
+	aSig0 = extractFloatx80Frac( a );
+	aExp = extractFloatx80Exp( a );
+	aSign = extractFloatx80Sign( a );
+	if ( aExp == 0x7FFF ) {
+		if ( (ui6b) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a );
+		if ( ! aSign ) return a;
+		goto invalid;
+	}
+	if ( aSign ) {
+		if ( ( aExp | aSig0 ) == 0 ) return a;
+ invalid:
+		float_raise( float_flag_invalid );
+		z.low = floatx80_default_nan_low;
+		z.high = floatx80_default_nan_high;
+		return z;
+	}
+	if ( aExp == 0 ) {
+		if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 );
+		normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
+	}
+	zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF;
+	zSig0 = estimateSqrt32( aExp, aSig0>>32 );
+	shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 );
+	zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 );
+	doubleZSig0 = zSig0<<1;
+	mul64To128( zSig0, zSig0, &term0, &term1 );
+	sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 );
+	while ( (si6b) rem0 < 0 ) {
+		--zSig0;
+		doubleZSig0 -= 2;
+		add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 );
+	}
+	zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 );
+	if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) {
+		if ( zSig1 == 0 ) zSig1 = 1;
+		mul64To128( doubleZSig0, zSig1, &term1, &term2 );
+		sub128( rem1, 0, term1, term2, &rem1, &rem2 );
+		mul64To128( zSig1, zSig1, &term2, &term3 );
+		sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
+		while ( (si6b) rem1 < 0 ) {
+			--zSig1;
+			shortShift128Left( 0, zSig1, 1, &term2, &term3 );
+			term3 |= 1;
+			term2 |= doubleZSig0;
+			add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 );
+		}
+		zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
+	}
+	shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 );
+	zSig0 |= doubleZSig0;
+	return
+		roundAndPackFloatx80(
+			floatx80_rounding_precision, 0, zExp, zSig0, zSig1 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the extended double-precision floating-point value `a' is
+| equal to the corresponding value `b', and 0 otherwise.  The comparison is
+| performed according to the IEC/IEEE Standard for Binary Floating-Point
+| Arithmetic.
+*----------------------------------------------------------------------------*/
+
+#if cIncludeFPUUnused
+LOCALFUNC flag floatx80_eq( floatx80 a, floatx80 b )
+{
+
+	if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
+			  && (ui6b) ( extractFloatx80Frac( a )<<1 ) )
+		 || (    ( extractFloatx80Exp( b ) == 0x7FFF )
+			  && (ui6b) ( extractFloatx80Frac( b )<<1 ) )
+	   ) {
+		if (    floatx80_is_signaling_nan( a )
+			 || floatx80_is_signaling_nan( b ) ) {
+			float_raise( float_flag_invalid );
+		}
+		return 0;
+	}
+	return
+		   ( a.low == b.low )
+		&& (    ( a.high == b.high )
+			 || (    ( a.low == 0 )
+				  && ( (ui4b) ( ( a.high | b.high )<<1 ) == 0 ) )
+		   );
+
+}
+#endif
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the extended double-precision floating-point value `a' is
+| less than or equal to the corresponding value `b', and 0 otherwise.  The
+| comparison is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+#if cIncludeFPUUnused
+LOCALFUNC flag floatx80_le( floatx80 a, floatx80 b )
+{
+	flag aSign, bSign;
+
+	if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
+			  && (ui6b) ( extractFloatx80Frac( a )<<1 ) )
+		 || (    ( extractFloatx80Exp( b ) == 0x7FFF )
+			  && (ui6b) ( extractFloatx80Frac( b )<<1 ) )
+	   ) {
+		float_raise( float_flag_invalid );
+		return 0;
+	}
+	aSign = extractFloatx80Sign( a );
+	bSign = extractFloatx80Sign( b );
+	if ( aSign != bSign ) {
+		return
+			   aSign
+			|| (    ( ( (ui4b) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+				 == 0 );
+	}
+	return
+		  aSign ? le128( b.high, b.low, a.high, a.low )
+		: le128( a.high, a.low, b.high, b.low );
+
+}
+#endif
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the extended double-precision floating-point value `a' is
+| less than the corresponding value `b', and 0 otherwise.  The comparison
+| is performed according to the IEC/IEEE Standard for Binary Floating-Point
+| Arithmetic.
+*----------------------------------------------------------------------------*/
+
+#if cIncludeFPUUnused
+LOCALFUNC flag floatx80_lt( floatx80 a, floatx80 b )
+{
+	flag aSign, bSign;
+
+	if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
+			  && (ui6b) ( extractFloatx80Frac( a )<<1 ) )
+		 || (    ( extractFloatx80Exp( b ) == 0x7FFF )
+			  && (ui6b) ( extractFloatx80Frac( b )<<1 ) )
+	   ) {
+		float_raise( float_flag_invalid );
+		return 0;
+	}
+	aSign = extractFloatx80Sign( a );
+	bSign = extractFloatx80Sign( b );
+	if ( aSign != bSign ) {
+		return
+			   aSign
+			&& (    ( ( (ui4b) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+				 != 0 );
+	}
+	return
+		  aSign ? lt128( b.high, b.low, a.high, a.low )
+		: lt128( a.high, a.low, b.high, b.low );
+
+}
+#endif
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the extended double-precision floating-point value `a' is equal
+| to the corresponding value `b', and 0 otherwise.  The invalid exception is
+| raised if either operand is a NaN.  Otherwise, the comparison is performed
+| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+#if cIncludeFPUUnused
+LOCALFUNC flag floatx80_eq_signaling( floatx80 a, floatx80 b )
+{
+
+	if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
+			  && (ui6b) ( extractFloatx80Frac( a )<<1 ) )
+		 || (    ( extractFloatx80Exp( b ) == 0x7FFF )
+			  && (ui6b) ( extractFloatx80Frac( b )<<1 ) )
+	   ) {
+		float_raise( float_flag_invalid );
+		return 0;
+	}
+	return
+		   ( a.low == b.low )
+		&& (    ( a.high == b.high )
+			 || (    ( a.low == 0 )
+				  && ( (ui4b) ( ( a.high | b.high )<<1 ) == 0 ) )
+		   );
+
+}
+#endif
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the extended double-precision floating-point value `a' is less
+| than or equal to the corresponding value `b', and 0 otherwise.  Quiet NaNs
+| do not cause an exception.  Otherwise, the comparison is performed according
+| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+#if cIncludeFPUUnused
+LOCALFUNC flag floatx80_le_quiet( floatx80 a, floatx80 b )
+{
+	flag aSign, bSign;
+
+	if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
+			  && (ui6b) ( extractFloatx80Frac( a )<<1 ) )
+		 || (    ( extractFloatx80Exp( b ) == 0x7FFF )
+			  && (ui6b) ( extractFloatx80Frac( b )<<1 ) )
+	   ) {
+		if (    floatx80_is_signaling_nan( a )
+			 || floatx80_is_signaling_nan( b ) ) {
+			float_raise( float_flag_invalid );
+		}
+		return 0;
+	}
+	aSign = extractFloatx80Sign( a );
+	bSign = extractFloatx80Sign( b );
+	if ( aSign != bSign ) {
+		return
+			   aSign
+			|| (    ( ( (ui4b) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+				 == 0 );
+	}
+	return
+		  aSign ? le128( b.high, b.low, a.high, a.low )
+		: le128( a.high, a.low, b.high, b.low );
+
+}
+#endif
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the extended double-precision floating-point value `a' is less
+| than the corresponding value `b', and 0 otherwise.  Quiet NaNs do not cause
+| an exception.  Otherwise, the comparison is performed according to the
+| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+#if cIncludeFPUUnused
+LOCALFUNC flag floatx80_lt_quiet( floatx80 a, floatx80 b )
+{
+	flag aSign, bSign;
+
+	if (    (    ( extractFloatx80Exp( a ) == 0x7FFF )
+			  && (ui6b) ( extractFloatx80Frac( a )<<1 ) )
+		 || (    ( extractFloatx80Exp( b ) == 0x7FFF )
+			  && (ui6b) ( extractFloatx80Frac( b )<<1 ) )
+	   ) {
+		if (    floatx80_is_signaling_nan( a )
+			 || floatx80_is_signaling_nan( b ) ) {
+			float_raise( float_flag_invalid );
+		}
+		return 0;
+	}
+	aSign = extractFloatx80Sign( a );
+	bSign = extractFloatx80Sign( b );
+	if ( aSign != bSign ) {
+		return
+			   aSign
+			&& (    ( ( (ui4b) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+				 != 0 );
+	}
+	return
+		  aSign ? lt128( b.high, b.low, a.high, a.low )
+		: lt128( a.high, a.low, b.high, b.low );
+
+}
+#endif
+
+#ifdef FLOAT128
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the quadruple-precision floating-point
+| value `a' to the extended double-precision floating-point format.  The
+| conversion is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 float128_to_floatx80( float128 a )
+{
+	flag aSign;
+	si5r aExp;
+	ui6b aSig0, aSig1;
+
+	aSig1 = extractFloat128Frac1( a );
+	aSig0 = extractFloat128Frac0( a );
+	aExp = extractFloat128Exp( a );
+	aSign = extractFloat128Sign( a );
+	if ( aExp == 0x7FFF ) {
+		if ( aSig0 | aSig1 ) {
+			return commonNaNToFloatx80( float128ToCommonNaN( a ) );
+		}
+		return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+	}
+	if ( aExp == 0 ) {
+		if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 );
+		normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
+	}
+	else {
+		aSig0 |= LIT64( 0x0001000000000000 );
+	}
+	shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 );
+	return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of adding the absolute values of the quadruple-precision
+| floating-point values `a' and `b'.  If `zSign' is 1, the sum is negated
+| before being returned.  `zSign' is ignored if the result is a NaN.
+| The addition is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC float128 addFloat128Sigs( float128 a, float128 b, flag zSign )
+{
+	si5r aExp, bExp, zExp;
+	ui6b aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
+	si5r expDiff;
+
+	aSig1 = extractFloat128Frac1( a );
+	aSig0 = extractFloat128Frac0( a );
+	aExp = extractFloat128Exp( a );
+	bSig1 = extractFloat128Frac1( b );
+	bSig0 = extractFloat128Frac0( b );
+	bExp = extractFloat128Exp( b );
+	expDiff = aExp - bExp;
+	if ( 0 < expDiff ) {
+		if ( aExp == 0x7FFF ) {
+			if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b );
+			return a;
+		}
+		if ( bExp == 0 ) {
+			--expDiff;
+		}
+		else {
+			bSig0 |= LIT64( 0x0001000000000000 );
+		}
+		shift128ExtraRightJamming(
+			bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 );
+		zExp = aExp;
+	}
+	else if ( expDiff < 0 ) {
+		if ( bExp == 0x7FFF ) {
+			if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b );
+			return packFloat128( zSign, 0x7FFF, 0, 0 );
+		}
+		if ( aExp == 0 ) {
+			++expDiff;
+		}
+		else {
+			aSig0 |= LIT64( 0x0001000000000000 );
+		}
+		shift128ExtraRightJamming(
+			aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 );
+		zExp = bExp;
+	}
+	else {
+		if ( aExp == 0x7FFF ) {
+			if ( aSig0 | aSig1 | bSig0 | bSig1 ) {
+				return propagateFloat128NaN( a, b );
+			}
+			return a;
+		}
+		add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
+		if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 );
+		zSig2 = 0;
+		zSig0 |= LIT64( 0x0002000000000000 );
+		zExp = aExp;
+		goto shiftRight1;
+	}
+	aSig0 |= LIT64( 0x0001000000000000 );
+	add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
+	--zExp;
+	if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack;
+	++zExp;
+ shiftRight1:
+	shift128ExtraRightJamming(
+		zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
+ roundAndPack:
+	return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of subtracting the absolute values of the quadruple-
+| precision floating-point values `a' and `b'.  If `zSign' is 1, the
+| difference is negated before being returned.  `zSign' is ignored if the
+| result is a NaN.  The subtraction is performed according to the IEC/IEEE
+| Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC float128 subFloat128Sigs( float128 a, float128 b, flag zSign )
+{
+	si5r aExp, bExp, zExp;
+	ui6b aSig0, aSig1, bSig0, bSig1, zSig0, zSig1;
+	si5r expDiff;
+	float128 z;
+
+	aSig1 = extractFloat128Frac1( a );
+	aSig0 = extractFloat128Frac0( a );
+	aExp = extractFloat128Exp( a );
+	bSig1 = extractFloat128Frac1( b );
+	bSig0 = extractFloat128Frac0( b );
+	bExp = extractFloat128Exp( b );
+	expDiff = aExp - bExp;
+	shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 );
+	shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 );
+	if ( 0 < expDiff ) goto aExpBigger;
+	if ( expDiff < 0 ) goto bExpBigger;
+	if ( aExp == 0x7FFF ) {
+		if ( aSig0 | aSig1 | bSig0 | bSig1 ) {
+			return propagateFloat128NaN( a, b );
+		}
+		float_raise( float_flag_invalid );
+		z.low = float128_default_nan_low;
+		z.high = float128_default_nan_high;
+		return z;
+	}
+	if ( aExp == 0 ) {
+		aExp = 1;
+		bExp = 1;
+	}
+	if ( bSig0 < aSig0 ) goto aBigger;
+	if ( aSig0 < bSig0 ) goto bBigger;
+	if ( bSig1 < aSig1 ) goto aBigger;
+	if ( aSig1 < bSig1 ) goto bBigger;
+	return packFloat128( float_rounding_mode == float_round_down, 0, 0, 0 );
+ bExpBigger:
+	if ( bExp == 0x7FFF ) {
+		if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b );
+		return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 );
+	}
+	if ( aExp == 0 ) {
+		++expDiff;
+	}
+	else {
+		aSig0 |= LIT64( 0x4000000000000000 );
+	}
+	shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 );
+	bSig0 |= LIT64( 0x4000000000000000 );
+ bBigger:
+	sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 );
+	zExp = bExp;
+	zSign ^= 1;
+	goto normalizeRoundAndPack;
+ aExpBigger:
+	if ( aExp == 0x7FFF ) {
+		if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b );
+		return a;
+	}
+	if ( bExp == 0 ) {
+		--expDiff;
+	}
+	else {
+		bSig0 |= LIT64( 0x4000000000000000 );
+	}
+	shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 );
+	aSig0 |= LIT64( 0x4000000000000000 );
+ aBigger:
+	sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
+	zExp = aExp;
+ normalizeRoundAndPack:
+	--zExp;
+	return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of adding the quadruple-precision floating-point values
+| `a' and `b'.  The operation is performed according to the IEC/IEEE Standard
+| for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC float128 float128_add( float128 a, float128 b )
+{
+	flag aSign, bSign;
+
+	aSign = extractFloat128Sign( a );
+	bSign = extractFloat128Sign( b );
+	if ( aSign == bSign ) {
+		return addFloat128Sigs( a, b, aSign );
+	}
+	else {
+		return subFloat128Sigs( a, b, aSign );
+	}
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of subtracting the quadruple-precision floating-point
+| values `a' and `b'.  The operation is performed according to the IEC/IEEE
+| Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC float128 float128_sub( float128 a, float128 b )
+{
+	flag aSign, bSign;
+
+	aSign = extractFloat128Sign( a );
+	bSign = extractFloat128Sign( b );
+	if ( aSign == bSign ) {
+		return subFloat128Sigs( a, b, aSign );
+	}
+	else {
+		return addFloat128Sigs( a, b, aSign );
+	}
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of multiplying the quadruple-precision floating-point
+| values `a' and `b'.  The operation is performed according to the IEC/IEEE
+| Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC float128 float128_mul( float128 a, float128 b )
+{
+	flag aSign, bSign, zSign;
+	si5r aExp, bExp, zExp;
+	ui6b aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3;
+	float128 z;
+
+	aSig1 = extractFloat128Frac1( a );
+	aSig0 = extractFloat128Frac0( a );
+	aExp = extractFloat128Exp( a );
+	aSign = extractFloat128Sign( a );
+	bSig1 = extractFloat128Frac1( b );
+	bSig0 = extractFloat128Frac0( b );
+	bExp = extractFloat128Exp( b );
+	bSign = extractFloat128Sign( b );
+	zSign = aSign ^ bSign;
+	if ( aExp == 0x7FFF ) {
+		if (    ( aSig0 | aSig1 )
+			 || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) {
+			return propagateFloat128NaN( a, b );
+		}
+		if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid;
+		return packFloat128( zSign, 0x7FFF, 0, 0 );
+	}
+	if ( bExp == 0x7FFF ) {
+		if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b );
+		if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
+ invalid:
+			float_raise( float_flag_invalid );
+			z.low = float128_default_nan_low;
+			z.high = float128_default_nan_high;
+			return z;
+		}
+		return packFloat128( zSign, 0x7FFF, 0, 0 );
+	}
+	if ( aExp == 0 ) {
+		if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
+		normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
+	}
+	if ( bExp == 0 ) {
+		if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
+		normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
+	}
+	zExp = aExp + bExp - 0x4000;
+	aSig0 |= LIT64( 0x0001000000000000 );
+	shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 );
+	mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 );
+	add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 );
+	zSig2 |= ( zSig3 != 0 );
+	if ( LIT64( 0x0002000000000000 ) <= zSig0 ) {
+		shift128ExtraRightJamming(
+			zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
+		++zExp;
+	}
+	return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of dividing the quadruple-precision floating-point value
+| `a' by the corresponding value `b'.  The operation is performed according to
+| the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC float128 float128_div( float128 a, float128 b )
+{
+	flag aSign, bSign, zSign;
+	si5r aExp, bExp, zExp;
+	ui6b aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
+	ui6b rem0, rem1, rem2, rem3, term0, term1, term2, term3;
+	float128 z;
+
+	aSig1 = extractFloat128Frac1( a );
+	aSig0 = extractFloat128Frac0( a );
+	aExp = extractFloat128Exp( a );
+	aSign = extractFloat128Sign( a );
+	bSig1 = extractFloat128Frac1( b );
+	bSig0 = extractFloat128Frac0( b );
+	bExp = extractFloat128Exp( b );
+	bSign = extractFloat128Sign( b );
+	zSign = aSign ^ bSign;
+	if ( aExp == 0x7FFF ) {
+		if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b );
+		if ( bExp == 0x7FFF ) {
+			if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b );
+			goto invalid;
+		}
+		return packFloat128( zSign, 0x7FFF, 0, 0 );
+	}
+	if ( bExp == 0x7FFF ) {
+		if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b );
+		return packFloat128( zSign, 0, 0, 0 );
+	}
+	if ( bExp == 0 ) {
+		if ( ( bSig0 | bSig1 ) == 0 ) {
+			if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
+ invalid:
+				float_raise( float_flag_invalid );
+				z.low = float128_default_nan_low;
+				z.high = float128_default_nan_high;
+				return z;
+			}
+			float_raise( float_flag_divbyzero );
+			return packFloat128( zSign, 0x7FFF, 0, 0 );
+		}
+		normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
+	}
+	if ( aExp == 0 ) {
+		if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
+		normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
+	}
+	zExp = aExp - bExp + 0x3FFD;
+	shortShift128Left(
+		aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 );
+	shortShift128Left(
+		bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 );
+	if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) {
+		shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 );
+		++zExp;
+	}
+	zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 );
+	mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 );
+	sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 );
+	while ( (si6b) rem0 < 0 ) {
+		--zSig0;
+		add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 );
+	}
+	zSig1 = estimateDiv128To64( rem1, rem2, bSig0 );
+	if ( ( zSig1 & 0x3FFF ) <= 4 ) {
+		mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 );
+		sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 );
+		while ( (si6b) rem1 < 0 ) {
+			--zSig1;
+			add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 );
+		}
+		zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
+	}
+	shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 );
+	return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+#endif
+
+typedef unsigned int float32;
+
+/*----------------------------------------------------------------------------
+| Normalizes the subnormal single-precision floating-point value represented
+| by the denormalized significand `aSig'.  The normalized exponent and
+| significand are stored at the locations pointed to by `zExpPtr' and
+| `zSigPtr', respectively.
+*----------------------------------------------------------------------------*/
+
+LOCALPROC
+ normalizeFloat32Subnormal( ui5b aSig, si4r *zExpPtr, ui5b *zSigPtr )
+{
+	si3r shiftCount;
+
+	shiftCount = countLeadingZeros32( aSig ) - 8;
+	*zSigPtr = aSig<<shiftCount;
+	*zExpPtr = 1 - shiftCount;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the fraction bits of the single-precision floating-point value `a'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC ui5b extractFloat32Frac( float32 a )
+{
+
+	return a & 0x007FFFFF;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the exponent bits of the single-precision floating-point value `a'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC si4r extractFloat32Exp( float32 a )
+{
+
+	return ( a>>23 ) & 0xFF;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the sign bit of the single-precision floating-point value `a'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC flag extractFloat32Sign( float32 a )
+{
+
+	return a>>31;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the single-precision floating-point value `a' is a signaling
+| NaN; otherwise returns 0.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC flag float32_is_signaling_nan( float32 a )
+{
+
+	return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the single-precision floating-point NaN
+| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
+| exception is raised.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC commonNaNT float32ToCommonNaN( float32 a )
+{
+	commonNaNT z;
+
+	if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
+	z.sign = a>>31;
+	z.low = 0;
+	z.high = ( (ui6b) a )<<41;
+	return z;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the single-precision floating-point value
+| `a' to the extended double-precision floating-point format.  The conversion
+| is performed according to the IEC/IEEE Standard for Binary Floating-Point
+| Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 float32_to_floatx80( float32 a )
+{
+	flag aSign;
+	si4r aExp;
+	ui5b aSig;
+
+	aSig = extractFloat32Frac( a );
+	aExp = extractFloat32Exp( a );
+	aSign = extractFloat32Sign( a );
+	if ( aExp == 0xFF ) {
+		if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a ) );
+		return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+	}
+	if ( aExp == 0 ) {
+		if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
+		normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+	}
+	aSig |= 0x00800000;
+	return packFloatx80( aSign, aExp + 0x3F80, ( (ui6b) aSig )<<40 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
+| single-precision floating-point value, returning the result.  After being
+| shifted into the proper positions, the three fields are simply added
+| together to form the result.  This means that any integer portion of `zSig'
+| will be added into the exponent.  Since a properly normalized significand
+| will have an integer portion equal to 1, the `zExp' input should be 1 less
+| than the desired result exponent whenever `zSig' is a complete, normalized
+| significand.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC float32 packFloat32( flag zSign, si4r zExp, ui5b zSig )
+{
+
+	return ( ( (ui5b) zSign )<<31 ) + ( ( (ui5b) zExp )<<23 ) + zSig;
+
+}
+
+/*----------------------------------------------------------------------------
+| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+| and significand `zSig', and returns the proper single-precision floating-
+| point value corresponding to the abstract input.  Ordinarily, the abstract
+| value is simply rounded and packed into the single-precision format, with
+| the inexact exception raised if the abstract input cannot be represented
+| exactly.  However, if the abstract value is too large, the overflow and
+| inexact exceptions are raised and an infinity or maximal finite value is
+| returned.  If the abstract value is too small, the input value is rounded to
+| a subnormal number, and the underflow and inexact exceptions are raised if
+| the abstract input cannot be represented exactly as a subnormal single-
+| precision floating-point number.
+|     The input significand `zSig' has its binary point between bits 30
+| and 29, which is 7 bits to the left of the usual location.  This shifted
+| significand must be normalized or smaller.  If `zSig' is not normalized,
+| `zExp' must be 0; in that case, the result returned is a subnormal number,
+| and it must not require rounding.  In the usual case that `zSig' is
+| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
+| The handling of underflow and overflow follows the IEC/IEEE Standard for
+| Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC float32 roundAndPackFloat32( flag zSign, si4r zExp, ui5b zSig )
+{
+	si3r roundingMode;
+	flag roundNearestEven;
+	si3r roundIncrement, roundBits;
+	flag isTiny;
+
+	roundingMode = float_rounding_mode;
+	roundNearestEven = ( roundingMode == float_round_nearest_even );
+	roundIncrement = 0x40;
+	if ( ! roundNearestEven ) {
+		if ( roundingMode == float_round_to_zero ) {
+			roundIncrement = 0;
+		}
+		else {
+			roundIncrement = 0x7F;
+			if ( zSign ) {
+				if ( roundingMode == float_round_up ) roundIncrement = 0;
+			}
+			else {
+				if ( roundingMode == float_round_down ) roundIncrement = 0;
+			}
+		}
+	}
+	roundBits = zSig & 0x7F;
+	if ( 0xFD <= (ui4b) zExp ) {
+		if (    ( 0xFD < zExp )
+			 || (    ( zExp == 0xFD )
+				  && ( (si5b) ( zSig + roundIncrement ) < 0 ) )
+		   ) {
+			float_raise( float_flag_overflow | float_flag_inexact );
+			return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 );
+		}
+		if ( zExp < 0 ) {
+			isTiny =
+				   ( float_detect_tininess == float_tininess_before_rounding )
+				|| ( zExp < -1 )
+				|| ( zSig + roundIncrement < 0x80000000 );
+			shift32RightJamming( zSig, - zExp, &zSig );
+			zExp = 0;
+			roundBits = zSig & 0x7F;
+			if ( isTiny && roundBits ) float_raise( float_flag_underflow );
+		}
+	}
+	if ( roundBits ) float_exception_flags |= float_flag_inexact;
+	zSig = ( zSig + roundIncrement )>>7;
+	zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
+	if ( zSig == 0 ) zExp = 0;
+	return packFloat32( zSign, zExp, zSig );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the canonical NaN `a' to the single-
+| precision floating-point format.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC float32 commonNaNToFloat32( commonNaNT a )
+{
+
+	return ( ( (ui5b) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the extended double-precision floating-
+| point value `a' to the single-precision floating-point format.  The
+| conversion is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC float32 floatx80_to_float32( floatx80 a )
+{
+	flag aSign;
+	si5r aExp;
+	ui6b aSig;
+
+	aSig = extractFloatx80Frac( a );
+	aExp = extractFloatx80Exp( a );
+	aSign = extractFloatx80Sign( a );
+	if ( aExp == 0x7FFF ) {
+		if ( (ui6b) ( aSig<<1 ) ) {
+			return commonNaNToFloat32( floatx80ToCommonNaN( a ) );
+		}
+		return packFloat32( aSign, 0xFF, 0 );
+	}
+	shift64RightJamming( aSig, 33, &aSig );
+	if ( aExp || aSig ) aExp -= 0x3F81;
+	return roundAndPackFloat32( aSign, aExp, aSig );
+
+}
+
+
+typedef ui6b float64;
+
+/*----------------------------------------------------------------------------
+| Returns the fraction bits of the double-precision floating-point value `a'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC ui6b extractFloat64Frac( float64 a )
+{
+
+	return a & LIT64( 0x000FFFFFFFFFFFFF );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the exponent bits of the double-precision floating-point value `a'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC si4r extractFloat64Exp( float64 a )
+{
+
+	return ( a>>52 ) & 0x7FF;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the sign bit of the double-precision floating-point value `a'.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC flag extractFloat64Sign( float64 a )
+{
+
+	return a>>63;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the double-precision floating-point value `a' is a signaling
+| NaN; otherwise returns 0.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC flag float64_is_signaling_nan( float64 a )
+{
+
+	return
+		   ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
+		&& ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the double-precision floating-point NaN
+| `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
+| exception is raised.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC commonNaNT float64ToCommonNaN( float64 a )
+{
+	commonNaNT z;
+
+	if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
+	z.sign = a>>63;
+	z.low = 0;
+	z.high = a<<12;
+	return z;
+
+}
+
+/*----------------------------------------------------------------------------
+| Normalizes the subnormal double-precision floating-point value represented
+| by the denormalized significand `aSig'.  The normalized exponent and
+| significand are stored at the locations pointed to by `zExpPtr' and
+| `zSigPtr', respectively.
+*----------------------------------------------------------------------------*/
+
+LOCALPROC
+ normalizeFloat64Subnormal( ui6b aSig, si4r *zExpPtr, ui6b *zSigPtr )
+{
+	si3r shiftCount;
+
+	shiftCount = countLeadingZeros64( aSig ) - 11;
+	*zSigPtr = aSig<<shiftCount;
+	*zExpPtr = 1 - shiftCount;
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the double-precision floating-point value
+| `a' to the extended double-precision floating-point format.  The conversion
+| is performed according to the IEC/IEEE Standard for Binary Floating-Point
+| Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 float64_to_floatx80( float64 a )
+{
+	flag aSign;
+	si4r aExp;
+	ui6b aSig;
+
+	aSig = extractFloat64Frac( a );
+	aExp = extractFloat64Exp( a );
+	aSign = extractFloat64Sign( a );
+	if ( aExp == 0x7FF ) {
+		if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a ) );
+		return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+	}
+	if ( aExp == 0 ) {
+		if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
+		normalizeFloat64Subnormal( aSig, &aExp, &aSig );
+	}
+	return
+		packFloatx80(
+			aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
+| double-precision floating-point value, returning the result.  After being
+| shifted into the proper positions, the three fields are simply added
+| together to form the result.  This means that any integer portion of `zSig'
+| will be added into the exponent.  Since a properly normalized significand
+| will have an integer portion equal to 1, the `zExp' input should be 1 less
+| than the desired result exponent whenever `zSig' is a complete, normalized
+| significand.
+*----------------------------------------------------------------------------*/
+
+LOCALINLINEFUNC float64 packFloat64( flag zSign, si4r zExp, ui6b zSig )
+{
+
+	return ( ( (ui6b) zSign )<<63 ) + ( ( (ui6b) zExp )<<52 ) + zSig;
+
+}
+
+/*----------------------------------------------------------------------------
+| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+| and significand `zSig', and returns the proper double-precision floating-
+| point value corresponding to the abstract input.  Ordinarily, the abstract
+| value is simply rounded and packed into the double-precision format, with
+| the inexact exception raised if the abstract input cannot be represented
+| exactly.  However, if the abstract value is too large, the overflow and
+| inexact exceptions are raised and an infinity or maximal finite value is
+| returned.  If the abstract value is too small, the input value is rounded
+| to a subnormal number, and the underflow and inexact exceptions are raised
+| if the abstract input cannot be represented exactly as a subnormal double-
+| precision floating-point number.
+|     The input significand `zSig' has its binary point between bits 62
+| and 61, which is 10 bits to the left of the usual location.  This shifted
+| significand must be normalized or smaller.  If `zSig' is not normalized,
+| `zExp' must be 0; in that case, the result returned is a subnormal number,
+| and it must not require rounding.  In the usual case that `zSig' is
+| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
+| The handling of underflow and overflow follows the IEC/IEEE Standard for
+| Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC float64 roundAndPackFloat64( flag zSign, si4r zExp, ui6b zSig )
+{
+	si3r roundingMode;
+	flag roundNearestEven;
+	si4r roundIncrement, roundBits;
+	flag isTiny;
+
+	roundingMode = float_rounding_mode;
+	roundNearestEven = ( roundingMode == float_round_nearest_even );
+	roundIncrement = 0x200;
+	if ( ! roundNearestEven ) {
+		if ( roundingMode == float_round_to_zero ) {
+			roundIncrement = 0;
+		}
+		else {
+			roundIncrement = 0x3FF;
+			if ( zSign ) {
+				if ( roundingMode == float_round_up ) roundIncrement = 0;
+			}
+			else {
+				if ( roundingMode == float_round_down ) roundIncrement = 0;
+			}
+		}
+	}
+	roundBits = zSig & 0x3FF;
+	if ( 0x7FD <= (ui4b) zExp ) {
+		if (    ( 0x7FD < zExp )
+			 || (    ( zExp == 0x7FD )
+				  && ( (si6b) ( zSig + roundIncrement ) < 0 ) )
+		   ) {
+			float_raise( float_flag_overflow | float_flag_inexact );
+			return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 );
+		}
+		if ( zExp < 0 ) {
+			isTiny =
+				   ( float_detect_tininess == float_tininess_before_rounding )
+				|| ( zExp < -1 )
+				|| ( zSig + roundIncrement < LIT64( 0x8000000000000000 ) );
+			shift64RightJamming( zSig, - zExp, &zSig );
+			zExp = 0;
+			roundBits = zSig & 0x3FF;
+			if ( isTiny && roundBits ) float_raise( float_flag_underflow );
+		}
+	}
+	if ( roundBits ) float_exception_flags |= float_flag_inexact;
+	zSig = ( zSig + roundIncrement )>>10;
+	zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven );
+	if ( zSig == 0 ) zExp = 0;
+	return packFloat64( zSign, zExp, zSig );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the canonical NaN `a' to the double-
+| precision floating-point format.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC float64 commonNaNToFloat64( commonNaNT a )
+{
+
+	return
+		  ( ( (ui6b) a.sign )<<63 )
+		| LIT64( 0x7FF8000000000000 )
+		| ( a.high>>12 );
+
+}
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the extended double-precision floating-
+| point value `a' to the double-precision floating-point format.  The
+| conversion is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC float64 floatx80_to_float64( floatx80 a )
+{
+	flag aSign;
+	si5r aExp;
+	ui6b aSig, zSig;
+
+	aSig = extractFloatx80Frac( a );
+	aExp = extractFloatx80Exp( a );
+	aSign = extractFloatx80Sign( a );
+	if ( aExp == 0x7FFF ) {
+		if ( (ui6b) ( aSig<<1 ) ) {
+			return commonNaNToFloat64( floatx80ToCommonNaN( a ) );
+		}
+		return packFloat64( aSign, 0x7FF, 0 );
+	}
+	shift64RightJamming( aSig, 1, &zSig );
+	if ( aExp || aSig ) aExp -= 0x3C01;
+	return roundAndPackFloat64( aSign, aExp, zSig );
+
+}
+
+/* ----- end from original file "softfloat.c" ----- */
+
+typedef si4r Bit16s;
+typedef si5r Bit32s;
+typedef si6r Bit64s;
+
+typedef ui5r Bit32u;
+typedef ui6r Bit64u;
+
+#define int16_indefinite 0x8000
+
+/*----------------------------------------------------------------------------
+| Takes extended double-precision floating-point  NaN  `a' and returns the
+| appropriate NaN result. If `a' is a signaling NaN, the invalid exception
+| is raised.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 propagateOneFloatx80NaN(floatx80 *a)
+{
+	if (floatx80_is_signaling_nan(*a))
+		float_raise(float_flag_invalid);
+
+	a->low |= LIT64(0xC000000000000000);
+
+	return *a;
+}
+
+#define float_flag_denormal 0x02
+
+#define floatx80_default_nan_exp 0xFFFF
+#define floatx80_default_nan_fraction LIT64(0xC000000000000000)
+
+#define packFloatx80m(zSign, zExp, zSig) {(zSig), ((zSign) << 15) + (zExp) }
+
+/*----------------------------------------------------------------------------
+| Packs two 64-bit precision integers into into the quadruple-precision
+| floating-point value, returning the result.
+*----------------------------------------------------------------------------*/
+
+#define packFloat2x128m(zHi, zLo) {(zLo), (zHi)}
+#define PACK_FLOAT_128(hi,lo) packFloat2x128m(LIT64(hi),LIT64(lo))
+
+static const floatx80 floatx80_default_nan =
+	packFloatx80m(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
+
+/*----------------------------------------------------------------------------
+| Software IEC/IEEE floating-point ordering relations
+*----------------------------------------------------------------------------*/
+enum {
+	float_relation_less      = -1,
+	float_relation_equal     =  0,
+	float_relation_greater   =  1,
+	float_relation_unordered =  2
+};
+
+#define EXP_BIAS 0x3FFF
+
+
+/*----------------------------------------------------------------------------
+| Returns the result of multiplying the extended double-precision floating-
+| point value `a' and quadruple-precision floating point value `b'. The
+| operation is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 floatx80_mul128(floatx80 a, float128 b)
+{
+	Bit32s aExp, bExp, zExp;
+	Bit64u aSig, bSig0, bSig1, zSig0, zSig1, zSig2;
+	int aSign, bSign, zSign;
+
+	// handle unsupported extended double-precision floating encodings
+	if (0 /* floatx80_is_unsupported(a) */)
+	{
+ invalid:
+		float_raise(float_flag_invalid);
+		return floatx80_default_nan;
+	}
+
+	aSig = extractFloatx80Frac(a);
+	aExp = extractFloatx80Exp(a);
+	aSign = extractFloatx80Sign(a);
+	bSig0 = extractFloat128Frac0(b);
+	bSig1 = extractFloat128Frac1(b);
+	bExp = extractFloat128Exp(b);
+	bSign = extractFloat128Sign(b);
+
+	zSign = aSign ^ bSign;
+
+	if (aExp == 0x7FFF) {
+		if ((Bit64u) (aSig<<1)
+			 || ((bExp == 0x7FFF) && (bSig0 | bSig1)))
+		{
+			floatx80 r = commonNaNToFloatx80(float128ToCommonNaN(b));
+			return propagateFloatx80NaN(a, r);
+		}
+		if (bExp == 0) {
+			if ((bSig0 | bSig1) == 0) goto invalid;
+			float_raise(float_flag_denormal);
+		}
+		return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000));
+	}
+	if (bExp == 0x7FFF) {
+		if (bSig0 | bSig1) {
+			floatx80 r = commonNaNToFloatx80(float128ToCommonNaN(b));
+			return propagateFloatx80NaN(a, r);
+		}
+		if (aExp == 0) {
+			if (aSig == 0) goto invalid;
+			float_raise(float_flag_denormal);
+		}
+		return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000));
+	}
+	if (aExp == 0) {
+		if (aSig == 0) {
+			if ((bExp == 0) && (bSig0 | bSig1)) float_raise(float_flag_denormal);
+			return packFloatx80(zSign, 0, 0);
+		}
+		float_raise(float_flag_denormal);
+		normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+	}
+	if (bExp == 0) {
+		if ((bSig0 | bSig1) == 0) return packFloatx80(zSign, 0, 0);
+		float_raise(float_flag_denormal);
+		normalizeFloat128Subnormal(bSig0, bSig1, &bExp, &bSig0, &bSig1);
+	}
+	else bSig0 |= LIT64(0x0001000000000000);
+
+	zExp = aExp + bExp - 0x3FFE;
+	shortShift128Left(bSig0, bSig1, 15, &bSig0, &bSig1);
+	mul128By64To192(bSig0, bSig1, aSig, &zSig0, &zSig1, &zSig2);
+	if (0 < (Bit64s) zSig0) {
+		shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
+		--zExp;
+	}
+	return
+		roundAndPackFloatx80(floatx80_rounding_precision,
+			 zSign, zExp, zSig0, zSig1);
+}
+
+/* ----- from original file "softfloatx80.h" ----- */
+
+/*
+	["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.]
+*/
+
+
+/*----------------------------------------------------------------------------
+| Software IEC/IEEE floating-point class.
+*----------------------------------------------------------------------------*/
+typedef enum {
+	float_zero,
+	float_NaN,
+	float_negative_inf,
+	float_positive_inf,
+	float_denormal,
+	float_normalized
+} float_class_t;
+
+
+/*-----------------------------------------------------------------------------
+| Calculates the absolute value of the extended double-precision floating-point
+| value `a'.  The operation is performed according to the IEC/IEEE Standard
+| for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+#if 0
+inline floatx80 floatx80_abs(floatx80 *reg)
+{
+	reg->high &= 0x7FFF;
+	return *reg;
+}
+#endif
+
+/*-----------------------------------------------------------------------------
+| Changes the sign of the extended double-precision floating-point value 'a'.
+| The operation is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 floatx80_chs(floatx80 *x)
+{
+	x->high ^= 0x8000;
+	return *x;
+}
+
+/* ----- end from original file "softfloatx80.h" ----- */
+
+/* ----- from original file "softfloatx80.cc" ----- */
+
+/*
+	["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.]
+*/
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the extended double-precision floating-
+| point value `a' to the 16-bit two's complement integer format.  The
+| conversion is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic - which means in particular that the conversion
+| is rounded according to the current rounding mode. If `a' is a NaN or the
+| conversion overflows, the integer indefinite value is returned.
+*----------------------------------------------------------------------------*/
+
+#if cIncludeFPUUnused
+LOCALFUNC Bit16s floatx80_to_int16(floatx80 a)
+{
+#if 0
+   if (floatx80_is_unsupported(a))
+   {
+		float_raise(float_flag_invalid);
+		return int16_indefinite;
+   }
+#endif
+
+   Bit32s v32 = floatx80_to_int32(a);
+
+   if ((v32 > 32767) || (v32 < -32768)) {
+		float_exception_flags = float_flag_invalid; // throw way other flags
+		return int16_indefinite;
+   }
+
+   return (Bit16s) v32;
+}
+#endif
+
+/*----------------------------------------------------------------------------
+| Returns the result of converting the extended double-precision floating-
+| point value `a' to the 16-bit two's complement integer format.  The
+| conversion is performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic, except that the conversion is always rounded
+| toward zero.  If `a' is a NaN or the conversion overflows, the integer
+| indefinite value is returned.
+*----------------------------------------------------------------------------*/
+
+#if cIncludeFPUUnused
+LOCALFUNC Bit16s floatx80_to_int16_round_to_zero(floatx80 a)
+{
+#if 0
+   if (floatx80_is_unsupported(a))
+   {
+		float_raise(float_flag_invalid);
+		return int16_indefinite;
+   }
+#endif
+
+   Bit32s v32 = floatx80_to_int32_round_to_zero(a);
+
+   if ((v32 > 32767) || (v32 < -32768)) {
+		float_exception_flags = float_flag_invalid; // throw way other flags
+		return int16_indefinite;
+   }
+
+   return (Bit16s) v32;
+}
+#endif
+
+/*----------------------------------------------------------------------------
+| Separate the source extended double-precision floating point value `a'
+| into its exponent and significand, store the significant back to the
+| 'a' and return the exponent. The operation performed is a superset of
+| the IEC/IEEE recommended logb(x) function.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 floatx80_extract(floatx80 *a)
+{
+	Bit64u aSig = extractFloatx80Frac(*a);
+	Bit32s aExp = extractFloatx80Exp(*a);
+	int   aSign = extractFloatx80Sign(*a);
+
+#if 0
+	if (floatx80_is_unsupported(*a))
+	{
+		float_raise(float_flag_invalid);
+		*a = floatx80_default_nan;
+		return *a;
+	}
+#endif
+
+	if (aExp == 0x7FFF) {
+		if ((Bit64u) (aSig<<1))
+		{
+			*a = propagateOneFloatx80NaN(a);
+			return *a;
+		}
+		return packFloatx80(0, 0x7FFF, LIT64(0x8000000000000000));
+	}
+	if (aExp == 0)
+	{
+		if (aSig == 0) {
+			float_raise(float_flag_divbyzero);
+			*a = packFloatx80(aSign, 0, 0);
+			return packFloatx80(1, 0x7FFF, LIT64(0x8000000000000000));
+		}
+		float_raise(float_flag_denormal);
+		normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+	}
+
+	a->high = (aSign << 15) + 0x3FFF;
+	a->low = aSig;
+	return int32_to_floatx80(aExp - 0x3FFF);
+}
+
+/*----------------------------------------------------------------------------
+| Scales extended double-precision floating-point value in operand `a' by
+| value `b'. The function truncates the value in the second operand 'b' to
+| an integral value and adds that value to the exponent of the operand 'a'.
+| The operation performed according to the IEC/IEEE Standard for Binary
+| Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 floatx80_scale(floatx80 a, floatx80 b)
+{
+	int shiftCount;
+	Bit32s scale;
+
+	// handle unsupported extended double-precision floating encodings
+#if 0
+	if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b))
+	{
+		float_raise(float_flag_invalid);
+		return floatx80_default_nan;
+	}
+#endif
+
+	Bit64u aSig = extractFloatx80Frac(a);
+	Bit32s aExp = extractFloatx80Exp(a);
+	int aSign = extractFloatx80Sign(a);
+	Bit64u bSig = extractFloatx80Frac(b);
+	Bit32s bExp = extractFloatx80Exp(b);
+	int bSign = extractFloatx80Sign(b);
+
+	if (aExp == 0x7FFF) {
+		if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1)))
+		{
+			return propagateFloatx80NaN(a, b);
+		}
+		if ((bExp == 0x7FFF) && bSign) {
+			float_raise(float_flag_invalid);
+			return floatx80_default_nan;
+		}
+		if (bSig && (bExp == 0)) float_raise(float_flag_denormal);
+		return a;
+	}
+	if (bExp == 0x7FFF) {
+		if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b);
+		if ((aExp | aSig) == 0) {
+			if (! bSign) {
+				float_raise(float_flag_invalid);
+				return floatx80_default_nan;
+			}
+			return a;
+		}
+		if (aSig && (aExp == 0)) float_raise(float_flag_denormal);
+		if (bSign) return packFloatx80(aSign, 0, 0);
+		return packFloatx80(aSign, 0x7FFF, LIT64(0x8000000000000000));
+	}
+	if (aExp == 0) {
+		if (bSig && (bExp == 0)) float_raise(float_flag_denormal);
+		if (aSig == 0) return a;
+		float_raise(float_flag_denormal);
+		normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+		if (bExp < 0x3FFF)
+			return normalizeRoundAndPackFloatx80(80, aSign, aExp, aSig, 0);
+	}
+	if (bExp == 0) {
+		if (bSig == 0) return a;
+		float_raise(float_flag_denormal);
+		normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
+	}
+
+	if (bExp > 0x400E) {
+		/* generate appropriate overflow/underflow */
+		return roundAndPackFloatx80(80, aSign,
+						  bSign ? -0x3FFF : 0x7FFF, aSig, 0);
+	}
+
+	if (bExp < 0x3FFF) return a;
+
+	shiftCount = 0x403E - bExp;
+	bSig >>= shiftCount;
+	scale = (Bit32s) bSig;
+	if (bSign) scale = -scale; /* -32768..32767 */
+	return
+		roundAndPackFloatx80(80, aSign, aExp+scale, aSig, 0);
+}
+
+/*----------------------------------------------------------------------------
+| Determine extended-precision floating-point number class.
+*----------------------------------------------------------------------------*/
+
+#if cIncludeFPUUnused
+LOCALFUNC float_class_t floatx80_class(floatx80 a)
+{
+   Bit32s aExp = extractFloatx80Exp(a);
+   Bit64u aSig = extractFloatx80Frac(a);
+
+   if(aExp == 0) {
+	   if (aSig == 0)
+		   return float_zero;
+
+	   /* denormal or pseudo-denormal */
+	   return float_denormal;
+   }
+
+   /* valid numbers have the MS bit set */
+   if (!(aSig & LIT64(0x8000000000000000)))
+	   return float_NaN; /* report unsupported as NaNs */
+
+   if(aExp == 0x7fff) {
+	   int aSign = extractFloatx80Sign(a);
+
+	   if (((Bit64u) (aSig<< 1)) == 0)
+		   return (aSign) ? float_negative_inf : float_positive_inf;
+
+	   return float_NaN;
+   }
+
+   return float_normalized;
+}
+#endif
+
+/*----------------------------------------------------------------------------
+| Compare  between  two extended precision  floating  point  numbers. Returns
+| 'float_relation_equal'  if the operands are equal, 'float_relation_less' if
+| the    value    'a'   is   less   than   the   corresponding   value   `b',
+| 'float_relation_greater' if the value 'a' is greater than the corresponding
+| value `b', or 'float_relation_unordered' otherwise.
+*----------------------------------------------------------------------------*/
+
+#if cIncludeFPUUnused
+LOCALFUNC int floatx80_compare(floatx80 a, floatx80 b)
+{
+	int aSign;
+	int bSign;
+	Bit64u aSig;
+	Bit32s aExp;
+	Bit64u bSig;
+	Bit32s bExp;
+	int less_than;
+	float_class_t aClass = floatx80_class(a);
+	float_class_t bClass = floatx80_class(b);
+
+	if (aClass == float_NaN || bClass == float_NaN)
+	{
+		float_raise(float_flag_invalid);
+		return float_relation_unordered;
+	}
+
+	if (aClass == float_denormal || bClass == float_denormal)
+	{
+		float_raise(float_flag_denormal);
+	}
+
+	aSign = extractFloatx80Sign(a);
+	bSign = extractFloatx80Sign(b);
+
+	if (aClass == float_zero) {
+		if (bClass == float_zero) return float_relation_equal;
+		return bSign ? float_relation_greater : float_relation_less;
+	}
+
+	if (bClass == float_zero || aSign != bSign) {
+		return aSign ? float_relation_less : float_relation_greater;
+	}
+
+	aSig = extractFloatx80Frac(a);
+	aExp = extractFloatx80Exp(a);
+	bSig = extractFloatx80Frac(b);
+	bExp = extractFloatx80Exp(b);
+
+	if (aClass == float_denormal)
+		normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+
+	if (bClass == float_denormal)
+		normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
+
+	if (aExp == bExp && aSig == bSig)
+		return float_relation_equal;
+
+	less_than =
+		aSign ? ((bExp < aExp) || ((bExp == aExp) && (bSig < aSig)))
+			  : ((aExp < bExp) || ((aExp == bExp) && (aSig < bSig)));
+
+	if (less_than) return float_relation_less;
+
+	return float_relation_greater;
+}
+#endif
+
+/*----------------------------------------------------------------------------
+| Compare  between  two extended precision  floating  point  numbers. Returns
+| 'float_relation_equal'  if the operands are equal, 'float_relation_less' if
+| the    value    'a'   is   less   than   the   corresponding   value   `b',
+| 'float_relation_greater' if the value 'a' is greater than the corresponding
+| value `b', or 'float_relation_unordered' otherwise. Quiet NaNs do not cause
+| an exception.
+*----------------------------------------------------------------------------*/
+
+#if cIncludeFPUUnused
+LOCALFUNC int floatx80_compare_quiet(floatx80 a, floatx80 b)
+{
+	int aSign;
+	int bSign;
+	Bit64u aSig;
+	Bit32s aExp;
+	Bit64u bSig;
+	Bit32s bExp;
+	int less_than;
+	float_class_t aClass = floatx80_class(a);
+	float_class_t bClass = floatx80_class(b);
+
+	if (aClass == float_NaN || bClass == float_NaN)
+	{
+#if 0
+		if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b))
+			float_raise(float_flag_invalid);
+#endif
+
+		if (floatx80_is_signaling_nan(a) || floatx80_is_signaling_nan(b))
+			float_raise(float_flag_invalid);
+
+		return float_relation_unordered;
+	}
+
+	if (aClass == float_denormal || bClass == float_denormal)
+	{
+		float_raise(float_flag_denormal);
+	}
+
+	aSign = extractFloatx80Sign(a);
+	bSign = extractFloatx80Sign(b);
+
+	if (aClass == float_zero) {
+		if (bClass == float_zero) return float_relation_equal;
+		return bSign ? float_relation_greater : float_relation_less;
+	}
+
+	if (bClass == float_zero || aSign != bSign) {
+		return aSign ? float_relation_less : float_relation_greater;
+	}
+
+	aSig = extractFloatx80Frac(a);
+	aExp = extractFloatx80Exp(a);
+	bSig = extractFloatx80Frac(b);
+	bExp = extractFloatx80Exp(b);
+
+	if (aClass == float_denormal)
+		normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+
+	if (bClass == float_denormal)
+		normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
+
+	if (aExp == bExp && aSig == bSig)
+		return float_relation_equal;
+
+	less_than =
+		aSign ? ((bExp < aExp) || ((bExp == aExp) && (bSig < aSig)))
+			  : ((aExp < bExp) || ((aExp == bExp) && (aSig < bSig)));
+
+	if (less_than) return float_relation_less;
+	return float_relation_greater;
+}
+#endif
+
+/* ----- end from original file "softfloatx80.cc" ----- */
+
+/* ----- from original file "fprem.cc" ----- */
+
+/*
+	["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.]
+*/
+
+#define USE_estimateDiv128To64
+
+/* executes single exponent reduction cycle */
+LOCALFUNC Bit64u remainder_kernel(Bit64u aSig0, Bit64u bSig, int expDiff, Bit64u *zSig0, Bit64u *zSig1)
+{
+	Bit64u term0, term1;
+	Bit64u aSig1 = 0;
+	Bit64u q;
+
+	shortShift128Left(aSig1, aSig0, expDiff, &aSig1, &aSig0);
+	q = estimateDiv128To64(aSig1, aSig0, bSig);
+	mul64To128(bSig, q, &term0, &term1);
+	sub128(aSig1, aSig0, term0, term1, zSig1, zSig0);
+	while ((Bit64s)(*zSig1) < 0) {
+		--q;
+		add128(*zSig1, *zSig0, 0, bSig, zSig1, zSig0);
+	}
+	return q;
+}
+
+LOCALFUNC floatx80 do_fprem(floatx80 a, floatx80 b, Bit64u *q, int rounding_mode)
+{
+	Bit32s aExp, bExp, zExp, expDiff;
+	Bit64u aSig0, aSig1, bSig;
+	int aSign;
+	*q = 0;
+
+#if 0
+	// handle unsupported extended double-precision floating encodings
+	if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b))
+	{
+		float_raise(float_flag_invalid);
+		return floatx80_default_nan;
+	}
+#endif
+
+	aSig0 = extractFloatx80Frac(a);
+	aExp = extractFloatx80Exp(a);
+	aSign = extractFloatx80Sign(a);
+	bSig = extractFloatx80Frac(b);
+	bExp = extractFloatx80Exp(b);
+
+	if (aExp == 0x7FFF) {
+		if ((Bit64u) (aSig0<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) {
+			return propagateFloatx80NaN(a, b);
+		}
+		float_raise(float_flag_invalid);
+		return floatx80_default_nan;
+	}
+	if (bExp == 0x7FFF) {
+		if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b);
+		if (aExp == 0 && aSig0) {
+			float_raise(float_flag_denormal);
+			normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
+			return (a.low & LIT64(0x8000000000000000)) ?
+					packFloatx80(aSign, aExp, aSig0) : a;
+		}
+		return a;
+	}
+	if (bExp == 0) {
+		if (bSig == 0) {
+			float_raise(float_flag_invalid);
+			return floatx80_default_nan;
+		}
+		float_raise(float_flag_denormal);
+		normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
+	}
+	if (aExp == 0) {
+		if (aSig0 == 0) return a;
+		float_raise(float_flag_denormal);
+		normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
+	}
+	expDiff = aExp - bExp;
+	aSig1 = 0;
+
+	if (expDiff >= 64) {
+		int n = (expDiff & 0x1f) | 0x20;
+		remainder_kernel(aSig0, bSig, n, &aSig0, &aSig1);
+		zExp = aExp - n;
+		*q = (Bit64u) -1;
+	}
+	else {
+		zExp = bExp;
+
+		if (expDiff < 0) {
+			if (expDiff < -1)
+			   return (a.low & LIT64(0x8000000000000000)) ?
+					packFloatx80(aSign, aExp, aSig0) : a;
+			shift128Right(aSig0, 0, 1, &aSig0, &aSig1);
+			expDiff = 0;
+		}
+
+		if (expDiff > 0) {
+			*q = remainder_kernel(aSig0, bSig, expDiff, &aSig0, &aSig1);
+		}
+		else {
+			if (bSig <= aSig0) {
+			   aSig0 -= bSig;
+			   *q = 1;
+			}
+		}
+
+		if (rounding_mode == float_round_nearest_even)
+		{
+			Bit64u term0, term1;
+			shift128Right(bSig, 0, 1, &term0, &term1);
+
+			if (! lt128(aSig0, aSig1, term0, term1))
+			{
+			   int lt = lt128(term0, term1, aSig0, aSig1);
+			   int eq = eq128(aSig0, aSig1, term0, term1);
+
+			   if ((eq && (*q & 1)) || lt) {
+				  aSign = !aSign;
+				  ++*q;
+			   }
+			   if (lt) sub128(bSig, 0, aSig0, aSig1, &aSig0, &aSig1);
+			}
+		}
+	}
+
+	return normalizeRoundAndPackFloatx80(80, aSign, zExp, aSig0, aSig1);
+}
+
+/*----------------------------------------------------------------------------
+| Returns the remainder of the extended double-precision floating-point value
+| `a' with respect to the corresponding value `b'.  The operation is performed
+| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+*----------------------------------------------------------------------------*/
+
+#if cIncludeFPUUnused
+LOCALFUNC floatx80 floatx80_ieee754_remainder(floatx80 a, floatx80 b, Bit64u *q)
+{
+	return do_fprem(a, b, q, float_round_nearest_even);
+}
+#endif
+
+/*----------------------------------------------------------------------------
+| Returns the remainder of the extended double-precision floating-point value
+| `a' with  respect to  the corresponding value `b'. Unlike previous function
+| the  function  does not compute  the remainder  specified  in  the IEC/IEEE
+| Standard  for Binary  Floating-Point  Arithmetic.  This  function  operates
+| differently  from the  previous  function in  the way  that it  rounds  the
+| quotient of 'a' divided by 'b' to an integer.
+*----------------------------------------------------------------------------*/
+
+LOCALFUNC floatx80 floatx80_remainder(floatx80 a, floatx80 b, Bit64u *q)
+{
+	return do_fprem(a, b, q, float_round_to_zero);
+}
+
+/* ----- end from original file "fprem.cc" ----- */
+
+/* ----- from original file "fpu_constant.h" ----- */
+
+/*
+	["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.]
+*/
+
+// Pentium CPU uses only 68-bit precision M_PI approximation
+// #define BETTER_THAN_PENTIUM
+
+//////////////////////////////
+// PI, PI/2, PI/4 constants
+//////////////////////////////
+
+#define FLOATX80_PI_EXP  (0x4000)
+
+// 128-bit PI fraction
+#ifdef BETTER_THAN_PENTIUM
+#define FLOAT_PI_HI (LIT64(0xc90fdaa22168c234))
+#define FLOAT_PI_LO (LIT64(0xc4c6628b80dc1cd1))
+#else
+#define FLOAT_PI_HI (LIT64(0xc90fdaa22168c234))
+#define FLOAT_PI_LO (LIT64(0xC000000000000000))
+#endif
+
+#define FLOATX80_PI2_EXP  (0x3FFF)
+#define FLOATX80_PI4_EXP  (0x3FFE)
+
+//////////////////////////////
+// 3PI/4 constant
+//////////////////////////////
+
+#define FLOATX80_3PI4_EXP (0x4000)
+
+// 128-bit 3PI/4 fraction
+#ifdef BETTER_THAN_PENTIUM
+#define FLOAT_3PI4_HI (LIT64(0x96cbe3f9990e91a7))
+#define FLOAT_3PI4_LO (LIT64(0x9394c9e8a0a5159c))
+#else
+#define FLOAT_3PI4_HI (LIT64(0x96cbe3f9990e91a7))
+#define FLOAT_3PI4_LO (LIT64(0x9000000000000000))
+#endif
+
+//////////////////////////////
+// 1/LN2 constant
+//////////////////////////////
+
+#define FLOAT_LN2INV_EXP  (0x3FFF)
+
+// 128-bit 1/LN2 fraction
+#ifdef BETTER_THAN_PENTIUM
+#define FLOAT_LN2INV_HI (LIT64(0xb8aa3b295c17f0bb))
+#define FLOAT_LN2INV_LO (LIT64(0xbe87fed0691d3e89))
+#else
+#define FLOAT_LN2INV_HI (LIT64(0xb8aa3b295c17f0bb))
+#define FLOAT_LN2INV_LO (LIT64(0xC000000000000000))
+#endif
+
+/* ----- end from original file "fpu_constant.h" ----- */
+
+/* ----- from original file "poly.cc" ----- */
+
+/*
+	["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.]
+*/
+
+//                            2         3         4               n
+// f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x)
+//         0    1         2         3         4               n
+//
+//          --       2k                --        2k+1
+//   p(x) = >  C  * x           q(x) = >  C   * x
+//          --  2k                     --  2k+1
+//
+//   f(x) ~ [ p(x) + x * q(x) ]
+//
+
+LOCALFUNC float128 EvalPoly(float128 x, float128 *arr, unsigned n)
+{
+	float128 r2;
+	float128 x2 = float128_mul(x, x);
+	unsigned i;
+
+#if 0
+	assert(n > 1);
+#endif
+
+	float128 r1 = arr[--n];
+	i = n;
+	while(i >= 2) {
+		r1 = float128_mul(r1, x2);
+		i -= 2;
+		r1 = float128_add(r1, arr[i]);
+	}
+	if (i) r1 = float128_mul(r1, x);
+
+	r2 = arr[--n];
+	i = n;
+	while(i >= 2) {
+		r2 = float128_mul(r2, x2);
+		i -= 2;
+		r2 = float128_add(r2, arr[i]);
+	}
+	if (i) r2 = float128_mul(r2, x);
+
+	return float128_add(r1, r2);
+}
+
+//                  2         4         6         8               2n
+// f(x) ~ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x)
+//         0    1         2         3         4               n
+//
+//          --       4k                --        4k+2
+//   p(x) = >  C  * x           q(x) = >  C   * x
+//          --  2k                     --  2k+1
+//
+//                    2
+//   f(x) ~ [ p(x) + x * q(x) ]
+//
+
+LOCALFUNC float128 EvenPoly(float128 x, float128 *arr, unsigned n)
+{
+	 return EvalPoly(float128_mul(x, x), arr, n);
+}
+
+//                        3         5         7         9               2n+1
+// f(x) ~ (C * x) + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x)
+//          0         1         2         3         4               n
+//                        2         4         6         8               2n
+//      = x * [ C + (C * x) + (C * x) + (C * x) + (C * x) + ... + (C * x)
+//               0    1         2         3         4               n
+//
+//          --       4k                --        4k+2
+//   p(x) = >  C  * x           q(x) = >  C   * x
+//          --  2k                     --  2k+1
+//
+//                        2
+//   f(x) ~ x * [ p(x) + x * q(x) ]
+//
+
+LOCALFUNC float128 OddPoly(float128 x, float128 *arr, unsigned n)
+{
+	 return float128_mul(x, EvenPoly(x, arr, n));
+}
+
+/* ----- end from original file "poly.cc" ----- */
+
+/* ----- from original file "fyl2x.cc" ----- */
+
+/*
+	["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.]
+*/
+
+static const floatx80 floatx80_one =
+	packFloatx80m(0, 0x3fff, LIT64(0x8000000000000000));
+
+static const float128 float128_one =
+	packFloat2x128m(LIT64(0x3fff000000000000), LIT64(0x0000000000000000));
+static const float128 float128_two =
+	packFloat2x128m(LIT64(0x4000000000000000), LIT64(0x0000000000000000));
+
+static const float128 float128_ln2inv2 =
+	packFloat2x128m(LIT64(0x400071547652b82f), LIT64(0xe1777d0ffda0d23a));
+
+#define SQRT2_HALF_SIG 	LIT64(0xb504f333f9de6484)
+
+#define L2_ARR_SIZE 9
+
+static float128 ln_arr[L2_ARR_SIZE] =
+{
+	PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /*  1 */
+	PACK_FLOAT_128(0x3ffd555555555555, 0x5555555555555555), /*  3 */
+	PACK_FLOAT_128(0x3ffc999999999999, 0x999999999999999a), /*  5 */
+	PACK_FLOAT_128(0x3ffc249249249249, 0x2492492492492492), /*  7 */
+	PACK_FLOAT_128(0x3ffbc71c71c71c71, 0xc71c71c71c71c71c), /*  9 */
+	PACK_FLOAT_128(0x3ffb745d1745d174, 0x5d1745d1745d1746), /* 11 */
+	PACK_FLOAT_128(0x3ffb3b13b13b13b1, 0x3b13b13b13b13b14), /* 13 */
+	PACK_FLOAT_128(0x3ffb111111111111, 0x1111111111111111), /* 15 */
+	PACK_FLOAT_128(0x3ffae1e1e1e1e1e1, 0xe1e1e1e1e1e1e1e2)  /* 17 */
+};
+
+LOCALFUNC float128 poly_ln(float128 x1)
+{
+/*
+	//
+	//                     3     5     7     9     11     13     15
+	//        1+u         u     u     u     u     u      u      u
+	// 1/2 ln ---  ~ u + --- + --- + --- + --- + ---- + ---- + ---- =
+	//        1-u         3     5     7     9     11     13     15
+	//
+	//                     2     4     6     8     10     12     14
+	//                    u     u     u     u     u      u      u
+	//       = u * [ 1 + --- + --- + --- + --- + ---- + ---- + ---- ] =
+	//                    3     5     7     9     11     13     15
+	//
+	//           3                          3
+	//          --       4k                --        4k+2
+	//   p(u) = >  C  * u           q(u) = >  C   * u
+	//          --  2k                     --  2k+1
+	//          k=0                        k=0
+	//
+	//          1+u                 2
+	//   1/2 ln --- ~ u * [ p(u) + u * q(u) ]
+	//          1-u
+	//
+*/
+	return OddPoly(x1, ln_arr, L2_ARR_SIZE);
+}
+
+/* required sqrt(2)/2 < x < sqrt(2) */
+LOCALFUNC float128 poly_l2(float128 x)
+{
+	/* using float128 for approximation */
+	float128 x_p1 = float128_add(x, float128_one);
+	float128 x_m1 = float128_sub(x, float128_one);
+	x = float128_div(x_m1, x_p1);
+	x = poly_ln(x);
+	x = float128_mul(x, float128_ln2inv2);
+	return x;
+}
+
+LOCALFUNC float128 poly_l2p1(float128 x)
+{
+	/* using float128 for approximation */
+	float128 x_p2 = float128_add(x, float128_two);
+	x = float128_div(x, x_p2);
+	x = poly_ln(x);
+	x = float128_mul(x, float128_ln2inv2);
+	return x;
+}
+
+// =================================================
+// FYL2X                   Compute y * log (x)
+//                                        2
+// =================================================
+
+//
+// Uses the following identities:
+//
+// 1. ----------------------------------------------------------
+//              ln(x)
+//   log (x) = -------,  ln (x*y) = ln(x) + ln(y)
+//      2       ln(2)
+//
+// 2. ----------------------------------------------------------
+//                1+u             x-1
+//   ln (x) = ln -----, when u = -----
+//                1-u             x+1
+//
+// 3. ----------------------------------------------------------
+//                        3     5     7           2n+1
+//       1+u             u     u     u           u
+//   ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ]
+//       1-u             3     5     7           2n+1
+//
+
+LOCALFUNC floatx80 fyl2x(floatx80 a, floatx80 b)
+{
+	int aSign;
+	int bSign;
+	Bit64u aSig;
+	Bit32s aExp;
+	Bit64u bSig;
+	Bit32s bExp;
+	int zSign;
+	int ExpDiff;
+	Bit64u zSig0, zSig1;
+	float128 x;
+
+	// handle unsupported extended double-precision floating encodings
+	if (0 /* floatx80_is_unsupported(a) */) {
+invalid:
+		float_raise(float_flag_invalid);
+		return floatx80_default_nan;
+	}
+
+	aSig = extractFloatx80Frac(a);
+	aExp = extractFloatx80Exp(a);
+	aSign = extractFloatx80Sign(a);
+	bSig = extractFloatx80Frac(b);
+	bExp = extractFloatx80Exp(b);
+	bSign = extractFloatx80Sign(b);
+
+	zSign = bSign ^ 1;
+
+	if (aExp == 0x7FFF) {
+		if ((Bit64u) (aSig<<1)
+			 || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1)))
+		{
+			return propagateFloatx80NaN(a, b);
+		}
+		if (aSign) goto invalid;
+		else {
+			if (bExp == 0) {
+				if (bSig == 0) goto invalid;
+				float_raise(float_flag_denormal);
+			}
+			return packFloatx80(bSign, 0x7FFF, LIT64(0x8000000000000000));
+		}
+	}
+	if (bExp == 0x7FFF)
+	{
+		if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b);
+		if (aSign && (Bit64u)(aExp | aSig)) goto invalid;
+		if (aSig && (aExp == 0))
+			float_raise(float_flag_denormal);
+		if (aExp < 0x3FFF) {
+			return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000));
+		}
+		if (aExp == 0x3FFF && ((Bit64u) (aSig<<1) == 0)) goto invalid;
+		return packFloatx80(bSign, 0x7FFF, LIT64(0x8000000000000000));
+	}
+	if (aExp == 0) {
+		if (aSig == 0) {
+			if ((bExp | bSig) == 0) goto invalid;
+			float_raise(float_flag_divbyzero);
+			return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000));
+		}
+		if (aSign) goto invalid;
+		float_raise(float_flag_denormal);
+		normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+	}
+	if (aSign) goto invalid;
+	if (bExp == 0) {
+		if (bSig == 0) {
+			if (aExp < 0x3FFF) return packFloatx80(zSign, 0, 0);
+			return packFloatx80(bSign, 0, 0);
+		}
+		float_raise(float_flag_denormal);
+		normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
+	}
+	if (aExp == 0x3FFF && ((Bit64u) (aSig<<1) == 0))
+		return packFloatx80(bSign, 0, 0);
+
+	float_raise(float_flag_inexact);
+
+	ExpDiff = aExp - 0x3FFF;
+	aExp = 0;
+	if (aSig >= SQRT2_HALF_SIG) {
+		ExpDiff++;
+		aExp--;
+	}
+
+	/* ******************************** */
+	/* using float128 for approximation */
+	/* ******************************** */
+
+	shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1);
+	x = packFloat128(0, aExp+0x3FFF, zSig0, zSig1);
+	x = poly_l2(x);
+	x = float128_add(x, floatx80_to_float128(int32_to_floatx80(ExpDiff)));
+	return floatx80_mul128(b, x);
+}
+
+// =================================================
+// FYL2XP1                 Compute y * log (x + 1)
+//                                        2
+// =================================================
+
+//
+// Uses the following identities:
+//
+// 1. ----------------------------------------------------------
+//              ln(x)
+//   log (x) = -------
+//      2       ln(2)
+//
+// 2. ----------------------------------------------------------
+//                  1+u              x
+//   ln (x+1) = ln -----, when u = -----
+//                  1-u             x+2
+//
+// 3. ----------------------------------------------------------
+//                        3     5     7           2n+1
+//       1+u             u     u     u           u
+//   ln ----- = 2 [ u + --- + --- + --- + ... + ------ + ... ]
+//       1-u             3     5     7           2n+1
+//
+
+LOCALFUNC floatx80 fyl2xp1(floatx80 a, floatx80 b)
+{
+	Bit32s aExp, bExp;
+	Bit64u aSig, bSig, zSig0, zSig1, zSig2;
+	int aSign, bSign;
+	int zSign;
+	float128 x;
+
+	// handle unsupported extended double-precision floating encodings
+	if (0 /* floatx80_is_unsupported(a) */) {
+invalid:
+		float_raise(float_flag_invalid);
+		return floatx80_default_nan;
+	}
+
+	aSig = extractFloatx80Frac(a);
+	aExp = extractFloatx80Exp(a);
+	aSign = extractFloatx80Sign(a);
+	bSig = extractFloatx80Frac(b);
+	bExp = extractFloatx80Exp(b);
+	bSign = extractFloatx80Sign(b);
+	zSign = aSign ^ bSign;
+
+	if (aExp == 0x7FFF) {
+		if ((Bit64u) (aSig<<1)
+			 || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1)))
+		{
+			return propagateFloatx80NaN(a, b);
+		}
+		if (aSign) goto invalid;
+		else {
+			if (bExp == 0) {
+				if (bSig == 0) goto invalid;
+				float_raise(float_flag_denormal);
+			}
+			return packFloatx80(bSign, 0x7FFF, LIT64(0x8000000000000000));
+		}
+	}
+	if (bExp == 0x7FFF)
+	{
+		if ((Bit64u) (bSig<<1))
+			return propagateFloatx80NaN(a, b);
+
+		if (aExp == 0) {
+			if (aSig == 0) goto invalid;
+			float_raise(float_flag_denormal);
+		}
+
+		return packFloatx80(zSign, 0x7FFF, LIT64(0x8000000000000000));
+	}
+	if (aExp == 0) {
+		if (aSig == 0) {
+			if (bSig && (bExp == 0)) float_raise(float_flag_denormal);
+			return packFloatx80(zSign, 0, 0);
+		}
+		float_raise(float_flag_denormal);
+		normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+	}
+	if (bExp == 0) {
+		if (bSig == 0) return packFloatx80(zSign, 0, 0);
+		float_raise(float_flag_denormal);
+		normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
+	}
+
+	float_raise(float_flag_inexact);
+
+	if (aSign && aExp >= 0x3FFF)
+		return a;
+
+	if (aExp >= 0x3FFC) // big argument
+	{
+		return fyl2x(floatx80_add(a, floatx80_one), b);
+	}
+
+	// handle tiny argument
+	if (aExp < EXP_BIAS-70)
+	{
+		// first order approximation, return (a*b)/ln(2)
+		Bit32s zExp = aExp + FLOAT_LN2INV_EXP - 0x3FFE;
+
+	mul128By64To192(FLOAT_LN2INV_HI, FLOAT_LN2INV_LO, aSig, &zSig0, &zSig1, &zSig2);
+		if (0 < (Bit64s) zSig0) {
+			shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
+			--zExp;
+		}
+
+		zExp = zExp + bExp - 0x3FFE;
+	mul128By64To192(zSig0, zSig1, bSig, &zSig0, &zSig1, &zSig2);
+		if (0 < (Bit64s) zSig0) {
+			shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
+			--zExp;
+		}
+
+		return
+			roundAndPackFloatx80(80, aSign ^ bSign, zExp, zSig0, zSig1);
+	}
+
+	/* ******************************** */
+	/* using float128 for approximation */
+	/* ******************************** */
+
+	shift128Right(aSig<<1, 0, 16, &zSig0, &zSig1);
+	x = packFloat128(aSign, aExp, zSig0, zSig1);
+	x = poly_l2p1(x);
+	return floatx80_mul128(b, x);
+}
+
+/* ----- end from original file "fyl2x.cc" ----- */
+
+/* ----- from original file "f2xm1.cc" ----- */
+
+/*
+	["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.]
+*/
+
+static const floatx80 floatx80_negone  = packFloatx80m(1, 0x3fff, LIT64(0x8000000000000000));
+static const floatx80 floatx80_neghalf = packFloatx80m(1, 0x3ffe, LIT64(0x8000000000000000));
+static const float128 float128_ln2     =
+	packFloat2x128m(LIT64(0x3ffe62e42fefa39e), LIT64(0xf35793c7673007e6));
+
+#define LN2_SIG        LIT64(0xb17217f7d1cf79ac)
+
+#define EXP_ARR_SIZE 15
+
+static float128 exp_arr[EXP_ARR_SIZE] =
+{
+	PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /*  1 */
+	PACK_FLOAT_128(0x3ffe000000000000, 0x0000000000000000), /*  2 */
+	PACK_FLOAT_128(0x3ffc555555555555, 0x5555555555555555), /*  3 */
+	PACK_FLOAT_128(0x3ffa555555555555, 0x5555555555555555), /*  4 */
+	PACK_FLOAT_128(0x3ff8111111111111, 0x1111111111111111), /*  5 */
+	PACK_FLOAT_128(0x3ff56c16c16c16c1, 0x6c16c16c16c16c17), /*  6 */
+	PACK_FLOAT_128(0x3ff2a01a01a01a01, 0xa01a01a01a01a01a), /*  7 */
+	PACK_FLOAT_128(0x3fefa01a01a01a01, 0xa01a01a01a01a01a), /*  8 */
+	PACK_FLOAT_128(0x3fec71de3a556c73, 0x38faac1c88e50017), /*  9 */
+	PACK_FLOAT_128(0x3fe927e4fb7789f5, 0xc72ef016d3ea6679), /* 10 */
+	PACK_FLOAT_128(0x3fe5ae64567f544e, 0x38fe747e4b837dc7), /* 11 */
+	PACK_FLOAT_128(0x3fe21eed8eff8d89, 0x7b544da987acfe85), /* 12 */
+	PACK_FLOAT_128(0x3fde6124613a86d0, 0x97ca38331d23af68), /* 13 */
+	PACK_FLOAT_128(0x3fda93974a8c07c9, 0xd20badf145dfa3e5), /* 14 */
+	PACK_FLOAT_128(0x3fd6ae7f3e733b81, 0xf11d8656b0ee8cb0)  /* 15 */
+};
+
+/* required -1 < x < 1 */
+LOCALFUNC float128 poly_exp(float128 x)
+{
+/*
+	//               2     3     4     5     6     7     8     9
+	//  x           x     x     x     x     x     x     x     x
+	// e - 1 ~ x + --- + --- + --- + --- + --- + --- + --- + --- + ...
+	//              2!    3!    4!    5!    6!    7!    8!    9!
+	//
+	//                     2     3     4     5     6     7     8
+	//              x     x     x     x     x     x     x     x
+	//   = x [ 1 + --- + --- + --- + --- + --- + --- + --- + --- + ... ]
+	//              2!    3!    4!    5!    6!    7!    8!    9!
+	//
+	//           8                          8
+	//          --       2k                --        2k+1
+	//   p(x) = >  C  * x           q(x) = >  C   * x
+	//          --  2k                     --  2k+1
+	//          k=0                        k=0
+	//
+	//    x
+	//   e  - 1 ~ x * [ p(x) + x * q(x) ]
+	//
+*/
+	float128 t = EvalPoly(x, exp_arr, EXP_ARR_SIZE);
+	return float128_mul(t, x);
+}
+
+// =================================================
+//                                  x
+// FX2P1                   Compute 2  - 1
+// =================================================
+
+//
+// Uses the following identities:
+//
+// 1. ----------------------------------------------------------
+//      x    x*ln(2)
+//     2  = e
+//
+// 2. ----------------------------------------------------------
+//                      2     3     4     5           n
+//      x        x     x     x     x     x           x
+//     e  = 1 + --- + --- + --- + --- + --- + ... + --- + ...
+//               1!    2!    3!    4!    5!          n!
+//
+
+LOCALFUNC floatx80 f2xm1(floatx80 a)
+{
+	Bit64u zSig0, zSig1;
+	float128 x;
+
+#if 0
+	// handle unsupported extended double-precision floating encodings
+	if (floatx80_is_unsupported(a))
+	{
+		float_raise(float_flag_invalid);
+		return floatx80_default_nan;
+	}
+#endif
+
+	Bit64u aSig = extractFloatx80Frac(a);
+	Bit32s aExp = extractFloatx80Exp(a);
+	int aSign = extractFloatx80Sign(a);
+
+	if (aExp == 0x7FFF) {
+		if ((Bit64u) (aSig<<1))
+			return propagateOneFloatx80NaN(&a);
+
+		return (aSign) ? floatx80_negone : a;
+	}
+
+	if (aExp == 0) {
+		if (aSig == 0) return a;
+		float_raise(float_flag_denormal | float_flag_inexact);
+		normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+
+	tiny_argument:
+		mul64To128(aSig, LN2_SIG, &zSig0, &zSig1);
+		if (0 < (Bit64s) zSig0) {
+			shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
+			--aExp;
+		}
+		return
+			roundAndPackFloatx80(80, aSign, aExp, zSig0, zSig1);
+	}
+
+	float_raise(float_flag_inexact);
+
+	if (aExp < 0x3FFF)
+	{
+		if (aExp < EXP_BIAS-68)
+			goto tiny_argument;
+
+		/* ******************************** */
+		/* using float128 for approximation */
+		/* ******************************** */
+
+		x = floatx80_to_float128(a);
+		x = float128_mul(x, float128_ln2);
+		x = poly_exp(x);
+		return float128_to_floatx80(x);
+	}
+	else
+	{
+		if ((a.high == 0xBFFF) && (! (aSig<<1)))
+		   return floatx80_neghalf;
+
+		return a;
+	}
+}
+
+/* ----- end from original file "f2xm1.cc" ----- */
+
+/* ----- from original file "fsincos.cc" ----- */
+
+/*
+	["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.]
+*/
+
+#define USE_estimateDiv128To64
+
+#if 0
+static const floatx80 floatx80_one = packFloatx80m(0, 0x3fff, LIT64(0x8000000000000000));
+#endif
+
+/* reduce trigonometric function argument using 128-bit precision
+   M_PI approximation */
+LOCALFUNC Bit64u argument_reduction_kernel(Bit64u aSig0, int Exp, Bit64u *zSig0, Bit64u *zSig1)
+{
+	Bit64u term0, term1, term2;
+	Bit64u aSig1 = 0;
+	Bit64u q;
+
+	shortShift128Left(aSig1, aSig0, Exp, &aSig1, &aSig0);
+	q = estimateDiv128To64(aSig1, aSig0, FLOAT_PI_HI);
+	mul128By64To192(FLOAT_PI_HI, FLOAT_PI_LO, q, &term0, &term1, &term2);
+	sub128(aSig1, aSig0, term0, term1, zSig1, zSig0);
+	while ((Bit64s)(*zSig1) < 0) {
+		--q;
+		add192(*zSig1, *zSig0, term2, 0, FLOAT_PI_HI, FLOAT_PI_LO, zSig1, zSig0, &term2);
+	}
+	*zSig1 = term2;
+	return q;
+}
+
+LOCALFUNC int reduce_trig_arg(int expDiff, int *zSign, Bit64u *aSig0, Bit64u *aSig1)
+{
+	Bit64u term0, term1, q = 0;
+
+	if (expDiff < 0) {
+		shift128Right(*aSig0, 0, 1, aSig0, aSig1);
+		expDiff = 0;
+	}
+	if (expDiff > 0) {
+		q = argument_reduction_kernel(*aSig0, expDiff, aSig0, aSig1);
+	}
+	else {
+		if (FLOAT_PI_HI <= *aSig0) {
+			*aSig0 -= FLOAT_PI_HI;
+			q = 1;
+		}
+	}
+
+	shift128Right(FLOAT_PI_HI, FLOAT_PI_LO, 1, &term0, &term1);
+	if (! lt128(*aSig0, *aSig1, term0, term1))
+	{
+		int lt = lt128(term0, term1, *aSig0, *aSig1);
+		int eq = eq128(*aSig0, *aSig1, term0, term1);
+
+		if ((eq && (q & 1)) || lt) {
+			*zSign = !*zSign;
+			++q;
+		}
+		if (lt) sub128(FLOAT_PI_HI, FLOAT_PI_LO, *aSig0, *aSig1, aSig0, aSig1);
+	}
+
+	return (int)(q & 3);
+}
+
+#define SIN_ARR_SIZE 9
+#define COS_ARR_SIZE 9
+
+static float128 sin_arr[SIN_ARR_SIZE] =
+{
+	PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /*  1 */
+	PACK_FLOAT_128(0xbffc555555555555, 0x5555555555555555), /*  3 */
+	PACK_FLOAT_128(0x3ff8111111111111, 0x1111111111111111), /*  5 */
+	PACK_FLOAT_128(0xbff2a01a01a01a01, 0xa01a01a01a01a01a), /*  7 */
+	PACK_FLOAT_128(0x3fec71de3a556c73, 0x38faac1c88e50017), /*  9 */
+	PACK_FLOAT_128(0xbfe5ae64567f544e, 0x38fe747e4b837dc7), /* 11 */
+	PACK_FLOAT_128(0x3fde6124613a86d0, 0x97ca38331d23af68), /* 13 */
+	PACK_FLOAT_128(0xbfd6ae7f3e733b81, 0xf11d8656b0ee8cb0), /* 15 */
+	PACK_FLOAT_128(0x3fce952c77030ad4, 0xa6b2605197771b00)  /* 17 */
+};
+
+static float128 cos_arr[COS_ARR_SIZE] =
+{
+	PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /*  0 */
+	PACK_FLOAT_128(0xbffe000000000000, 0x0000000000000000), /*  2 */
+	PACK_FLOAT_128(0x3ffa555555555555, 0x5555555555555555), /*  4 */
+	PACK_FLOAT_128(0xbff56c16c16c16c1, 0x6c16c16c16c16c17), /*  6 */
+	PACK_FLOAT_128(0x3fefa01a01a01a01, 0xa01a01a01a01a01a), /*  8 */
+	PACK_FLOAT_128(0xbfe927e4fb7789f5, 0xc72ef016d3ea6679), /* 10 */
+	PACK_FLOAT_128(0x3fe21eed8eff8d89, 0x7b544da987acfe85), /* 12 */
+	PACK_FLOAT_128(0xbfda93974a8c07c9, 0xd20badf145dfa3e5), /* 14 */
+	PACK_FLOAT_128(0x3fd2ae7f3e733b81, 0xf11d8656b0ee8cb0)  /* 16 */
+};
+
+/* 0 <= x <= pi/4 */
+LOCALINLINEFUNC float128 poly_sin(float128 x)
+{
+	//                 3     5     7     9     11     13     15
+	//                x     x     x     x     x      x      x
+	// sin (x) ~ x - --- + --- - --- + --- - ---- + ---- - ---- =
+	//                3!    5!    7!    9!    11!    13!    15!
+	//
+	//                 2     4     6     8     10     12     14
+	//                x     x     x     x     x      x      x
+	//   = x * [ 1 - --- + --- - --- + --- - ---- + ---- - ---- ] =
+	//                3!    5!    7!    9!    11!    13!    15!
+	//
+	//           3                          3
+	//          --       4k                --        4k+2
+	//   p(x) = >  C  * x   > 0     q(x) = >  C   * x     < 0
+	//          --  2k                     --  2k+1
+	//          k=0                        k=0
+	//
+	//                          2
+	//   sin(x) ~ x * [ p(x) + x * q(x) ]
+	//
+
+	return OddPoly(x, sin_arr, SIN_ARR_SIZE);
+}
+
+/* 0 <= x <= pi/4 */
+LOCALINLINEFUNC float128 poly_cos(float128 x)
+{
+	//                 2     4     6     8     10     12     14
+	//                x     x     x     x     x      x      x
+	// cos (x) ~ 1 - --- + --- - --- + --- - ---- + ---- - ----
+	//                2!    4!    6!    8!    10!    12!    14!
+	//
+	//           3                          3
+	//          --       4k                --        4k+2
+	//   p(x) = >  C  * x   > 0     q(x) = >  C   * x     < 0
+	//          --  2k                     --  2k+1
+	//          k=0                        k=0
+	//
+	//                      2
+	//   cos(x) ~ [ p(x) + x * q(x) ]
+	//
+
+	return EvenPoly(x, cos_arr, COS_ARR_SIZE);
+}
+
+LOCALINLINEPROC sincos_invalid(floatx80 *sin_a, floatx80 *cos_a, floatx80 a)
+{
+	if (sin_a) *sin_a = a;
+	if (cos_a) *cos_a = a;
+}
+
+LOCALINLINEPROC sincos_tiny_argument(floatx80 *sin_a, floatx80 *cos_a, floatx80 a)
+{
+	if (sin_a) *sin_a = a;
+	if (cos_a) *cos_a = floatx80_one;
+}
+
+LOCALFUNC floatx80 sincos_approximation(int neg, float128 r, Bit64u quotient)
+{
+	floatx80 result;
+
+	if (quotient & 0x1) {
+		r = poly_cos(r);
+		neg = 0;
+	} else  {
+		r = poly_sin(r);
+	}
+
+	result = float128_to_floatx80(r);
+	if (quotient & 0x2)
+		neg = ! neg;
+
+	if (neg)
+		floatx80_chs(&result);
+
+	return result;
+}
+
+// =================================================
+// FSINCOS               Compute sin(x) and cos(x)
+// =================================================
+
+//
+// Uses the following identities:
+// ----------------------------------------------------------
+//
+//  sin(-x) = -sin(x)
+//  cos(-x) =  cos(x)
+//
+//  sin(x+y) = sin(x)*cos(y)+cos(x)*sin(y)
+//  cos(x+y) = sin(x)*sin(y)+cos(x)*cos(y)
+//
+//  sin(x+ pi/2)  =  cos(x)
+//  sin(x+ pi)    = -sin(x)
+//  sin(x+3pi/2)  = -cos(x)
+//  sin(x+2pi)    =  sin(x)
+//
+
+LOCALFUNC int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a)
+{
+	float128 r;
+	Bit64u aSig0, aSig1 = 0;
+	Bit32s aExp, zExp, expDiff;
+	int aSign, zSign;
+	int q = 0;
+
+#if 0
+	// handle unsupported extended double-precision floating encodings
+	if (floatx80_is_unsupported(a))
+	{
+		goto invalid;
+	}
+#endif
+
+	aSig0 = extractFloatx80Frac(a);
+	aExp = extractFloatx80Exp(a);
+	aSign = extractFloatx80Sign(a);
+
+	/* invalid argument */
+	if (aExp == 0x7FFF) {
+		if ((Bit64u) (aSig0<<1)) {
+			sincos_invalid(sin_a, cos_a, propagateOneFloatx80NaN(&a));
+			return 0;
+		}
+
+#if 0
+	invalid:
+#endif
+		float_raise(float_flag_invalid);
+		sincos_invalid(sin_a, cos_a, floatx80_default_nan);
+		return 0;
+	}
+
+	if (aExp == 0) {
+		if (aSig0 == 0) {
+			sincos_tiny_argument(sin_a, cos_a, a);
+			return 0;
+		}
+
+		float_raise(float_flag_denormal);
+
+		/* handle pseudo denormals */
+		if (! (aSig0 & LIT64(0x8000000000000000)))
+		{
+			float_raise(float_flag_inexact);
+			if (sin_a)
+				float_raise(float_flag_underflow);
+			sincos_tiny_argument(sin_a, cos_a, a);
+			return 0;
+		}
+
+		normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
+	}
+
+	zSign = aSign;
+	zExp = EXP_BIAS;
+	expDiff = aExp - zExp;
+
+	/* argument is out-of-range */
+	if (expDiff >= 63)
+		return -1;
+
+	float_raise(float_flag_inexact);
+
+	if (expDiff < -1) {    // doesn't require reduction
+		if (expDiff <= -68) {
+			a = packFloatx80(aSign, aExp, aSig0);
+			sincos_tiny_argument(sin_a, cos_a, a);
+			return 0;
+		}
+		zExp = aExp;
+	}
+	else {
+		q = reduce_trig_arg(expDiff, &zSign, &aSig0, &aSig1);
+	}
+
+	/* **************************** */
+	/* argument reduction completed */
+	/* **************************** */
+
+	/* using float128 for approximation */
+	r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1);
+
+	if (aSign) q = -q;
+	if (sin_a) *sin_a = sincos_approximation(zSign, r,   q);
+	if (cos_a) *cos_a = sincos_approximation(zSign, r, q+1);
+
+	return 0;
+}
+
+// =================================================
+// FPTAN                 Compute tan(x)
+// =================================================
+
+//
+// Uses the following identities:
+//
+// 1. ----------------------------------------------------------
+//
+//  sin(-x) = -sin(x)
+//  cos(-x) =  cos(x)
+//
+//  sin(x+y) = sin(x)*cos(y)+cos(x)*sin(y)
+//  cos(x+y) = sin(x)*sin(y)+cos(x)*cos(y)
+//
+//  sin(x+ pi/2)  =  cos(x)
+//  sin(x+ pi)    = -sin(x)
+//  sin(x+3pi/2)  = -cos(x)
+//  sin(x+2pi)    =  sin(x)
+//
+// 2. ----------------------------------------------------------
+//
+//           sin(x)
+//  tan(x) = ------
+//           cos(x)
+//
+
+LOCALFUNC int ftan(floatx80 *a)
+{
+	float128 r;
+	float128 sin_r;
+	float128 cos_r;
+	Bit64u aSig0, aSig1 = 0;
+	Bit32s aExp, zExp, expDiff;
+	int aSign, zSign;
+	int q = 0;
+
+#if 0
+	// handle unsupported extended double-precision floating encodings
+	if (floatx80_is_unsupported(*a))
+	{
+		goto invalid;
+	}
+#endif
+
+	aSig0 = extractFloatx80Frac(*a);
+	aExp = extractFloatx80Exp(*a);
+	aSign = extractFloatx80Sign(*a);
+
+	/* invalid argument */
+	if (aExp == 0x7FFF) {
+		if ((Bit64u) (aSig0<<1))
+		{
+			*a = propagateOneFloatx80NaN(a);
+			return 0;
+		}
+
+#if 0
+	invalid:
+#endif
+		float_raise(float_flag_invalid);
+		*a = floatx80_default_nan;
+		return 0;
+	}
+
+	if (aExp == 0) {
+		if (aSig0 == 0) return 0;
+		float_raise(float_flag_denormal);
+		/* handle pseudo denormals */
+		if (! (aSig0 & LIT64(0x8000000000000000)))
+		{
+			float_raise(float_flag_inexact | float_flag_underflow);
+			return 0;
+		}
+		normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
+	}
+
+	zSign = aSign;
+	zExp = EXP_BIAS;
+	expDiff = aExp - zExp;
+
+	/* argument is out-of-range */
+	if (expDiff >= 63)
+		return -1;
+
+	float_raise(float_flag_inexact);
+
+	if (expDiff < -1) {    // doesn't require reduction
+		if (expDiff <= -68) {
+			*a = packFloatx80(aSign, aExp, aSig0);
+			return 0;
+		}
+		zExp = aExp;
+	}
+	else {
+		q = reduce_trig_arg(expDiff, &zSign, &aSig0, &aSig1);
+	}
+
+	/* **************************** */
+	/* argument reduction completed */
+	/* **************************** */
+
+	/* using float128 for approximation */
+	r = normalizeRoundAndPackFloat128(0, zExp-0x10, aSig0, aSig1);
+
+	sin_r = poly_sin(r);
+	cos_r = poly_cos(r);
+
+	if (q & 0x1) {
+		r = float128_div(cos_r, sin_r);
+		zSign = ! zSign;
+	} else {
+		r = float128_div(sin_r, cos_r);
+	}
+
+	*a = float128_to_floatx80(r);
+	if (zSign)
+		floatx80_chs(a);
+
+	return 0;
+}
+
+/* ----- end from original file "fsincos.cc" ----- */
+
+/* ----- from original file "fpatan.cc" ----- */
+
+/*
+	["original Stanislav Shwartsman Copyright notice" went here, included near top of this file.]
+*/
+
+#define FPATAN_ARR_SIZE 11
+
+#if 0
+static const float128 float128_one =
+		packFloat2x128m(LIT64(0x3fff000000000000), LIT64(0x0000000000000000));
+#endif
+static const float128 float128_sqrt3 =
+		packFloat2x128m(LIT64(0x3fffbb67ae8584ca), LIT64(0xa73b25742d7078b8));
+static const floatx80 floatx80_pi  =
+		packFloatx80m(0, 0x4000, LIT64(0xc90fdaa22168c235));
+
+static const float128 float128_pi2 =
+		packFloat2x128m(LIT64(0x3fff921fb54442d1), LIT64(0x8469898CC5170416));
+static const float128 float128_pi4 =
+		packFloat2x128m(LIT64(0x3ffe921fb54442d1), LIT64(0x8469898CC5170416));
+static const float128 float128_pi6 =
+		packFloat2x128m(LIT64(0x3ffe0c152382d736), LIT64(0x58465BB32E0F580F));
+
+static float128 atan_arr[FPATAN_ARR_SIZE] =
+{
+	PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /*  1 */
+	PACK_FLOAT_128(0xbffd555555555555, 0x5555555555555555), /*  3 */
+	PACK_FLOAT_128(0x3ffc999999999999, 0x999999999999999a), /*  5 */
+	PACK_FLOAT_128(0xbffc249249249249, 0x2492492492492492), /*  7 */
+	PACK_FLOAT_128(0x3ffbc71c71c71c71, 0xc71c71c71c71c71c), /*  9 */
+	PACK_FLOAT_128(0xbffb745d1745d174, 0x5d1745d1745d1746), /* 11 */
+	PACK_FLOAT_128(0x3ffb3b13b13b13b1, 0x3b13b13b13b13b14), /* 13 */
+	PACK_FLOAT_128(0xbffb111111111111, 0x1111111111111111), /* 15 */
+	PACK_FLOAT_128(0x3ffae1e1e1e1e1e1, 0xe1e1e1e1e1e1e1e2), /* 17 */
+	PACK_FLOAT_128(0xbffaaf286bca1af2, 0x86bca1af286bca1b), /* 19 */
+	PACK_FLOAT_128(0x3ffa861861861861, 0x8618618618618618)  /* 21 */
+};
+
+/* |x| < 1/4 */
+LOCALFUNC float128 poly_atan(float128 x1)
+{
+/*
+	//                 3     5     7     9     11     13     15     17
+	//                x     x     x     x     x      x      x      x
+	// atan(x) ~ x - --- + --- - --- + --- - ---- + ---- - ---- + ----
+	//                3     5     7     9     11     13     15     17
+	//
+	//                 2     4     6     8     10     12     14     16
+	//                x     x     x     x     x      x      x      x
+	//   = x * [ 1 - --- + --- - --- + --- - ---- + ---- - ---- + ---- ]
+	//                3     5     7     9     11     13     15     17
+	//
+	//           5                          5
+	//          --       4k                --        4k+2
+	//   p(x) = >  C  * x           q(x) = >  C   * x
+	//          --  2k                     --  2k+1
+	//          k=0                        k=0
+	//
+	//                            2
+	//    atan(x) ~ x * [ p(x) + x * q(x) ]
+	//
+*/
+	return OddPoly(x1, atan_arr, FPATAN_ARR_SIZE);
+}
+
+// =================================================
+// FPATAN                  Compute y * log (x)
+//                                        2
+// =================================================
+
+//
+// Uses the following identities:
+//
+// 1. ----------------------------------------------------------
+//
+//   atan(-x) = -atan(x)
+//
+// 2. ----------------------------------------------------------
+//
+//                             x + y
+//   atan(x) + atan(y) = atan -------, xy < 1
+//                             1-xy
+//
+//                             x + y
+//   atan(x) + atan(y) = atan ------- + PI, x > 0, xy > 1
+//                             1-xy
+//
+//                             x + y
+//   atan(x) + atan(y) = atan ------- - PI, x < 0, xy > 1
+//                             1-xy
+//
+// 3. ----------------------------------------------------------
+//
+//   atan(x) = atan(INF) + atan(- 1/x)
+//
+//                           x-1
+//   atan(x) = PI/4 + atan( ----- )
+//                           x+1
+//
+//                           x * sqrt(3) - 1
+//   atan(x) = PI/6 + atan( ----------------- )
+//                             x + sqrt(3)
+//
+// 4. ----------------------------------------------------------
+//                   3     5     7     9                 2n+1
+//                  x     x     x     x              n  x
+//   atan(x) = x - --- + --- - --- + --- - ... + (-1)  ------ + ...
+//                  3     5     7     9                 2n+1
+//
+
+LOCALFUNC floatx80 fpatan(floatx80 a, floatx80 b)
+{
+	float128 a128;
+	float128 b128;
+	float128 x;
+	int swap, add_pi6, add_pi4;
+	Bit32s xExp;
+	floatx80 result;
+	int rSign;
+
+	// handle unsupported extended double-precision floating encodings
+#if 0
+	if (floatx80_is_unsupported(a)) {
+		float_raise(float_flag_invalid);
+		return floatx80_default_nan;
+	}
+#endif
+
+	Bit64u aSig = extractFloatx80Frac(a);
+	Bit32s aExp = extractFloatx80Exp(a);
+	int aSign = extractFloatx80Sign(a);
+	Bit64u bSig = extractFloatx80Frac(b);
+	Bit32s bExp = extractFloatx80Exp(b);
+	int bSign = extractFloatx80Sign(b);
+
+	int zSign = aSign ^ bSign;
+
+	if (bExp == 0x7FFF)
+	{
+		if ((Bit64u) (bSig<<1))
+			return propagateFloatx80NaN(a, b);
+
+		if (aExp == 0x7FFF) {
+			if ((Bit64u) (aSig<<1))
+				return propagateFloatx80NaN(a, b);
+
+			if (aSign) {   /* return 3PI/4 */
+				return roundAndPackFloatx80(80, bSign,
+						FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO);
+			}
+			else {         /* return  PI/4 */
+				return roundAndPackFloatx80(80, bSign,
+						FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO);
+			}
+		}
+
+		if (aSig && (aExp == 0))
+			float_raise(float_flag_denormal);
+
+		/* return PI/2 */
+		return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO);
+	}
+	if (aExp == 0x7FFF)
+	{
+		if ((Bit64u) (aSig<<1))
+			return propagateFloatx80NaN(a, b);
+
+		if (bSig && (bExp == 0))
+			float_raise(float_flag_denormal);
+
+return_PI_or_ZERO:
+
+		if (aSign) {   /* return PI */
+			return roundAndPackFloatx80(80, bSign, FLOATX80_PI_EXP, FLOAT_PI_HI, FLOAT_PI_LO);
+		} else {       /* return  0 */
+			return packFloatx80(bSign, 0, 0);
+		}
+	}
+	if (bExp == 0)
+	{
+		if (bSig == 0) {
+			 if (aSig && (aExp == 0)) float_raise(float_flag_denormal);
+			 goto return_PI_or_ZERO;
+		}
+
+		float_raise(float_flag_denormal);
+		normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
+	}
+	if (aExp == 0)
+	{
+		if (aSig == 0)   /* return PI/2 */
+			return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO);
+
+		float_raise(float_flag_denormal);
+		normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
+	}
+
+	float_raise(float_flag_inexact);
+
+	/* |a| = |b| ==> return PI/4 */
+	if (aSig == bSig && aExp == bExp)
+		return roundAndPackFloatx80(80, bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO);
+
+	/* ******************************** */
+	/* using float128 for approximation */
+	/* ******************************** */
+
+	a128 = normalizeRoundAndPackFloat128(0, aExp-0x10, aSig, 0);
+	b128 = normalizeRoundAndPackFloat128(0, bExp-0x10, bSig, 0);
+	swap = 0;
+	add_pi6 = 0;
+	add_pi4 = 0;
+
+	if (aExp > bExp || (aExp == bExp && aSig > bSig))
+	{
+		x = float128_div(b128, a128);
+	}
+	else {
+		x = float128_div(a128, b128);
+		swap = 1;
+	}
+
+	xExp = extractFloat128Exp(x);
+
+	if (xExp <= EXP_BIAS-40)
+		goto approximation_completed;
+
+	if (x.high >= LIT64(0x3ffe800000000000))        // 3/4 < x < 1
+	{
+		/*
+		arctan(x) = arctan((x-1)/(x+1)) + pi/4
+		*/
+		float128 t1 = float128_sub(x, float128_one);
+		float128 t2 = float128_add(x, float128_one);
+		x = float128_div(t1, t2);
+		add_pi4 = 1;
+	}
+	else
+	{
+		/* argument correction */
+		if (xExp >= 0x3FFD)                     // 1/4 < x < 3/4
+		{
+			/*
+			arctan(x) = arctan((x*sqrt(3)-1)/(x+sqrt(3))) + pi/6
+			*/
+			float128 t1 = float128_mul(x, float128_sqrt3);
+			float128 t2 = float128_add(x, float128_sqrt3);
+			x = float128_sub(t1, float128_one);
+			x = float128_div(x, t2);
+			add_pi6 = 1;
+		}
+	}
+
+	x = poly_atan(x);
+	if (add_pi6) x = float128_add(x, float128_pi6);
+	if (add_pi4) x = float128_add(x, float128_pi4);
+
+approximation_completed:
+	if (swap) x = float128_sub(float128_pi2, x);
+	result = float128_to_floatx80(x);
+	if (zSign) floatx80_chs(&result);
+	rSign = extractFloatx80Sign(result);
+	if (!bSign && rSign)
+		return floatx80_add(result, floatx80_pi);
+	if (bSign && !rSign)
+		return floatx80_sub(result, floatx80_pi);
+	return result;
+}
+
+/* ----- end from original file "fpatan.cc" ----- */
+
+/* end soft float stuff */
+
+typedef floatx80 myfpr;
+
+LOCALPROC myfp_FromExtendedFormat(myfpr *r, ui4r v2, ui5r v1, ui5r v0)
+{
+	r->high = v2;
+	r->low = (((ui6b)v1) << 32) | (v0 & 0xFFFFFFFF);
+}
+
+LOCALPROC myfp_ToExtendedFormat(myfpr *dd, ui4r *v2, ui5r *v1, ui5r *v0)
+{
+	*v0 = ((ui6b) dd->low) & 0xFFFFFFFF;
+	*v1 = (((ui6b) dd->low) >> 32) & 0xFFFFFFFF;
+	*v2 = dd->high;
+}
+
+LOCALPROC myfp_FromDoubleFormat(myfpr *r, ui5r v1, ui5r v0)
+{
+	float64 t = (float64)((((ui6b)v1) << 32) | (v0 & 0xFFFFFFFF));
+
+	*r = float64_to_floatx80(t);
+}
+
+LOCALPROC myfp_ToDoubleFormat(myfpr *dd, ui5r *v1, ui5r *v0)
+{
+	float64 t = floatx80_to_float64(*dd);
+
+	*v0 = ((ui6b) t) & 0xFFFFFFFF;
+	*v1 = (((ui6b) t) >> 32) & 0xFFFFFFFF;
+}
+
+LOCALPROC myfp_FromSingleFormat(myfpr *r, ui5r x)
+{
+	*r = float32_to_floatx80(x);
+}
+
+LOCALFUNC ui5r myfp_ToSingleFormat(myfpr *ff)
+{
+	return floatx80_to_float32(*ff);
+}
+
+LOCALPROC myfp_FromLong(myfpr *r, ui5r x)
+{
+	*r = int32_to_floatx80( x );
+}
+
+LOCALFUNC ui5r myfp_ToLong(myfpr *x)
+{
+	return floatx80_to_int32( *x );
+}
+
+LOCALFUNC blnr myfp_IsNan(myfpr *x)
+{
+	return floatx80_is_nan(*x);
+}
+
+LOCALFUNC blnr myfp_IsInf(myfpr *x)
+{
+	return ( ( x->high & 0x7FFF ) == 0x7FFF ) && (0 == ((ui6b) ( x->low<<1 )));
+}
+
+LOCALFUNC blnr myfp_IsZero(myfpr *x)
+{
+	return ( ( x->high & 0x7FFF ) == 0x0000 ) && (0 == ((ui6b) ( x->low<<1 )));
+}
+
+LOCALFUNC blnr myfp_IsNeg(myfpr *x)
+{
+	return ( ( x->high & 0x8000 ) != 0x0000 );
+}
+
+LOCALPROC myfp_Add(myfpr *r, const myfpr *a, const myfpr *b)
+{
+	*r = floatx80_add(*a, *b);
+}
+
+LOCALPROC myfp_Sub(myfpr *r, const myfpr *a, const myfpr *b)
+{
+	*r = floatx80_sub(*a, *b);
+}
+
+LOCALPROC myfp_Mul(myfpr *r, const myfpr *a, const myfpr *b)
+{
+	*r = floatx80_mul(*a, *b);
+}
+
+LOCALPROC myfp_Div(myfpr *r, const myfpr *a, const myfpr *b)
+{
+	*r = floatx80_div(*a, *b);
+}
+
+LOCALPROC myfp_Rem(myfpr *r, const myfpr *a, const myfpr *b)
+{
+	*r = floatx80_rem(*a, *b);
+}
+
+LOCALPROC myfp_Sqrt(myfpr *r, myfpr *x)
+{
+	*r = floatx80_sqrt(*x);
+}
+
+LOCALPROC myfp_Mod(myfpr *r, myfpr *a, myfpr *b)
+{
+	Bit64u q;
+	*r = floatx80_remainder(*a, *b, &q);
+		/* should save low byte of q */
+}
+
+LOCALPROC myfp_Scale(myfpr *r, myfpr *a, myfpr *b)
+{
+	*r = floatx80_scale(*a, *b);
+}
+
+LOCALPROC myfp_GetMan(myfpr *r, myfpr *x)
+{
+	*r = *x;
+	(void) floatx80_extract(r);
+}
+
+LOCALPROC myfp_GetExp(myfpr *r, myfpr *x)
+{
+	floatx80 t0 = *x;
+	*r = floatx80_extract(&t0);
+}
+
+LOCALPROC myfp_floor(myfpr *r, myfpr *x)
+{
+	si3r SaveRoundingMode = float_rounding_mode;
+
+	float_rounding_mode = float_round_down;
+	*r = floatx80_round_to_int(*x);
+	float_rounding_mode = SaveRoundingMode;
+}
+
+LOCALPROC myfp_IntRZ(myfpr *r, myfpr *x)
+{
+	si3r SaveRoundingMode = float_rounding_mode;
+
+	float_rounding_mode = float_round_to_zero;
+	*r = floatx80_round_to_int(*x);
+	float_rounding_mode = SaveRoundingMode;
+}
+
+LOCALPROC myfp_Int(myfpr *r, myfpr *x)
+{
+	*r = floatx80_round_to_int(*x);
+}
+
+LOCALPROC myfp_RoundToSingle(myfpr *r, myfpr *x)
+{
+	float32 t0 = floatx80_to_float32(*x);
+
+	*r = float32_to_floatx80(t0);
+}
+
+LOCALPROC myfp_RoundToDouble(myfpr *r, myfpr *x)
+{
+	float64 t0 = floatx80_to_float64(*x);
+
+	*r = float64_to_floatx80(t0);
+}
+
+LOCALPROC myfp_Abs(myfpr *r, myfpr *x)
+{
+	*r = *x;
+	r->high &= 0x7FFF;
+}
+
+LOCALPROC myfp_Neg(myfpr *r, myfpr *x)
+{
+	*r = *x;
+	r->high ^= 0x8000;
+}
+
+LOCALPROC myfp_TwoToX(myfpr *r, myfpr *x)
+{
+	floatx80 t2;
+	floatx80 t3;
+	floatx80 t4;
+	floatx80 t5;
+	myfp_floor(&t2, x);
+	t3 = floatx80_sub(*x, t2);
+	t4 = f2xm1(t3);
+	t5 = floatx80_add(t4, floatx80_one);
+	*r = floatx80_scale(t5, t2);
+}
+
+LOCALPROC myfp_TenToX(myfpr *r, myfpr *x)
+{
+	floatx80 t1;
+	const floatx80 t = /* 1.0 / log(2.0) */
+		packFloatx80m(0, 0x3fff, LIT64(0xb8aa3b295c17f0bc));
+	const floatx80 t2 = /* log(10.0) */
+		packFloatx80m(0, 0x4000, LIT64(0x935d8dddaaa8ac17));
+	t1 = floatx80_mul(floatx80_mul(*x, t), t2);
+	myfp_TwoToX(r, &t1);
+}
+
+LOCALPROC myfp_EToX(myfpr *r, myfpr *x)
+{
+	floatx80 t1;
+	const floatx80 t = /* 1.0 / log(2.0) */
+		packFloatx80m(0, 0x3fff, LIT64(0xb8aa3b295c17f0bc));
+	t1 = floatx80_mul(*x, t);
+	myfp_TwoToX(r, &t1);
+}
+
+LOCALPROC myfp_EToXM1(myfpr *r, myfpr *x)
+{
+	floatx80 t1;
+	floatx80 t2;
+	floatx80 t3;
+	floatx80 t4;
+	floatx80 t5;
+	floatx80 t6;
+	const floatx80 t = /* 1.0 / log(2.0) */
+		packFloatx80m(0, 0x3fff, LIT64(0xb8aa3b295c17f0bc));
+	t1 = floatx80_mul(*x, t);
+	myfp_floor(&t2, &t1);
+	t3 = floatx80_sub(t1, t2);
+	t4 = f2xm1(t3);
+	if (myfp_IsZero(&t2)) {
+		*r = t4;
+	} else {
+		t5 = floatx80_add(t4, floatx80_one);
+		t6 = floatx80_scale(t5, t2);
+		*r = floatx80_sub(t6, floatx80_one);
+	}
+}
+
+LOCALPROC myfp_Log2(myfpr *r, myfpr *x)
+{
+	*r = fyl2x(*x, floatx80_one);
+}
+
+LOCALPROC myfp_LogN(myfpr *r, myfpr *x)
+{
+	const floatx80 t = /* log(2.0) */
+		packFloatx80m(0, 0x3ffe, LIT64(0xb17217f7d1cf79ac));
+	*r = fyl2x(*x, t);
+}
+
+LOCALPROC myfp_Log10(myfpr *r, myfpr *x)
+{
+	const floatx80 t = /* log10(2.0) = ln(2) / ln(10), unknown accuracy */
+		packFloatx80m(0, 0x3ffd, LIT64(0x9a209a84fbcff798));
+	*r = fyl2x(*x, t);
+}
+
+LOCALPROC myfp_LogNP1(myfpr *r, myfpr *x)
+{
+	const floatx80 t = /* log(2.0) */
+		packFloatx80m(0, 0x3ffe, LIT64(0xb17217f7d1cf79ac));
+	*r = fyl2xp1(*x, t);
+}
+
+LOCALPROC myfp_Sin(myfpr *r, myfpr *x)
+{
+	(void) fsincos(*x, r, 0);
+}
+
+LOCALPROC myfp_Cos(myfpr *r, myfpr *x)
+{
+	(void) fsincos(*x, 0, r);
+}
+
+LOCALPROC myfp_Tan(myfpr *r, myfpr *x)
+{
+	*r = *x;
+	(void) ftan(r);
+}
+
+LOCALPROC myfp_ATan(myfpr *r, myfpr *x)
+{
+	*r = fpatan(floatx80_one, *x);
+}
+
+LOCALPROC myfp_ASin(myfpr *r, myfpr *x)
+{
+	floatx80 x2 = floatx80_mul(*x, *x);
+	floatx80 mx2 = floatx80_sub(floatx80_one, x2);
+	floatx80 cx = floatx80_sqrt(mx2);
+
+	*r = fpatan(cx, *x);
+}
+
+LOCALPROC myfp_ACos(myfpr *r, myfpr *x)
+{
+	floatx80 x2 = floatx80_mul(*x, *x);
+	floatx80 mx2 = floatx80_sub(floatx80_one, x2);
+	floatx80 cx = floatx80_sqrt(mx2);
+
+	*r = fpatan(*x, cx);
+}
+
+static const floatx80 floatx80_zero =
+	packFloatx80m(0, 0x0000, LIT64(0x0000000000000000));
+
+static const floatx80 floatx80_Two =
+	packFloatx80m(0, 0x4000, LIT64(0x8000000000000000));
+
+static const floatx80 floatx80_Ten =
+	packFloatx80m(0, 0x4002, LIT64(0xa000000000000000));
+
+LOCALPROC myfp_Sinh(myfpr *r, myfpr *x)
+{
+	myfpr ex;
+	myfpr nx;
+	myfpr enx;
+	myfpr t1;
+
+	myfp_EToX(&ex, x);
+	myfp_Neg(&nx, x);
+	myfp_EToX(&enx, &nx);
+	myfp_Sub(&t1, &ex, &enx);
+	myfp_Div(r, &t1, &floatx80_Two);
+}
+
+LOCALPROC myfp_Cosh(myfpr *r, myfpr *x)
+{
+	myfpr ex;
+	myfpr nx;
+	myfpr enx;
+	myfpr t1;
+
+	myfp_EToX(&ex, x);
+	myfp_Neg(&nx, x);
+	myfp_EToX(&enx, &nx);
+	myfp_Add(&t1, &ex, &enx);
+	myfp_Div(r, &t1, &floatx80_Two);
+}
+
+LOCALPROC myfp_Tanh(myfpr *r, myfpr *x)
+{
+	myfpr x2;
+	myfpr ex2;
+	myfpr ex2m1;
+	myfpr ex2p1;
+
+	myfp_Mul(&x2, x, &floatx80_Two);
+	myfp_EToX(&ex2, &x2);
+	myfp_Sub(&ex2m1, &ex2, &floatx80_one);
+	myfp_Add(&ex2p1, &ex2, &floatx80_one);
+	myfp_Div(r, &ex2m1, &ex2p1);
+}
+
+LOCALPROC myfp_ATanh(myfpr *r, myfpr *x)
+{
+	myfpr onepx;
+	myfpr onemx;
+	myfpr dv;
+	myfpr ldv;
+
+	myfp_Add(&onepx, x, &floatx80_one);
+	myfp_Sub(&onemx, x, &floatx80_one);
+	myfp_Div(&dv, &onepx, &onemx);
+	myfp_LogN(&ldv, &dv);
+	myfp_Div(r, &ldv, &floatx80_Two);
+}
+
+LOCALPROC myfp_SinCos(myfpr *r_sin, myfpr *r_cos, myfpr *source)
+{
+	(void) fsincos(*source, r_sin, r_cos);
+}
+
+LOCALFUNC blnr myfp_getCR(myfpr *r, ui4b opmode)
+{
+	switch (opmode) {
+		case 0x00:
+			*r = floatx80_pi; /* M_PI */
+			break;
+		case 0x0B:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x3ffd, LIT64(0x9a209a84fbcff798));
+				*r = t; /* log10(2.0) = ln(2) / ln(10), unknown accuracy */
+			}
+			break;
+		case 0x0C:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x4000, LIT64(0xadf85458a2bb4a9b));
+				*r = t; /* exp(1.0), unknown accuracy */
+			}
+			break;
+		case 0x0D:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x3fff, LIT64(0xb8aa3b295c17f0bc));
+				*r = t; /* 1.0 / log(2.0) */
+			}
+			break;
+		case 0x0E:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x3ffd, LIT64(0xde5bd8a937287195));
+				*r = t; /* 1.0 / log(10.0), unknown accuracy */
+			}
+			break;
+		case 0x0F:
+			*r = floatx80_zero; /* 0.0 */
+			break;
+		case 0x30:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x3ffe, LIT64(0xb17217f7d1cf79ac));
+				*r = t; /* log(2.0) */
+			}
+			break;
+		case 0x31:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x4000, LIT64(0x935d8dddaaa8ac17));
+				*r = t; /* log(10.0) */
+			}
+			break;
+		case 0x32:
+			*r = floatx80_one; /* 1.0 */
+			break;
+		case 0x33:
+			*r = floatx80_Ten; /* 10.0 */
+			break;
+		case 0x34:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x4005, LIT64(0xc800000000000000));
+				*r = t; /* 100.0 */
+			}
+			break;
+		case 0x35:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x400c, LIT64(0x9c40000000000000));
+				*r = t; /* 10000.0 */
+			}
+			break;
+		case 0x36:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x4019, LIT64(0xbebc200000000000));
+				*r = t; /* 1.0e8 */
+			}
+			break;
+		case 0x37:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x4034, LIT64(0x8e1bc9bf04000000));
+				*r = t; /* 1.0e16 */
+			}
+			break;
+		case 0x38:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x4069, LIT64(0x9dc5ada82b70b59e));
+				*r = t; /* 1.0e32 */
+			}
+			break;
+		case 0x39:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x40d3, LIT64(0xc2781f49ffcfa6d5));
+				*r = t; /* 1.0e64 */
+			}
+			break;
+		case 0x3A:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x41a8, LIT64(0x93ba47c980e98ce0));
+				*r = t; /* 1.0e128 */
+			}
+			break;
+		case 0x3B:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x4351, LIT64(0xaa7eebfb9df9de8e));
+				*r = t; /* 1.0e256 */
+			}
+			break;
+		case 0x3C:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x46a3, LIT64(0xe319a0aea60e91c7));
+				*r = t; /* 1.0e512 */
+			}
+			break;
+		case 0x3D:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x4d48, LIT64(0xc976758681750c17));
+				*r = t; /* 1.0e1024 */
+			}
+			break;
+		case 0x3E:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x5a92, LIT64(0x9e8b3b5dc53d5de5));
+				*r = t; /* 1.0e2048 */
+			}
+			break;
+		case 0x3F:
+			{
+				const floatx80 t =
+					packFloatx80m(0, 0x7525, LIT64(0xc46052028a20979b));
+				*r = t; /* 1.0e4096 */
+			}
+			break;
+		default:
+			return falseblnr;
+	}
+	return trueblnr;
+}
+
+/* Floating point control register */
+
+LOCALPROC myfp_SetFPCR(ui5r v)
+{
+	switch ((v >> 4) & 0x03) {
+		case 0:
+			float_rounding_mode = float_round_nearest_even;
+			break;
+		case 1:
+			float_rounding_mode = float_round_to_zero;
+			break;
+		case 2:
+			float_rounding_mode = float_round_down;
+			break;
+		case 3:
+			float_rounding_mode = float_round_up;
+			break;
+	}
+	switch ((v >> 6) & 0x03) {
+		case 0:
+			floatx80_rounding_precision = 80;
+			break;
+		case 1:
+			floatx80_rounding_precision = 32;
+			break;
+		case 2:
+			floatx80_rounding_precision = 64;
+			break;
+		case 3:
+			ReportAbnormalID(0x0201,
+				"Bad rounding precision in myfp_SetFPCR");
+			floatx80_rounding_precision = 80;
+			break;
+	}
+	if (0 != (v & 0xF)) {
+		ReportAbnormalID(0x0202,
+			"Reserved bits not zero in myfp_SetFPCR");
+	}
+}
+
+LOCALFUNC ui5r myfp_GetFPCR(void)
+{
+	ui5r v = 0;
+
+	switch (float_rounding_mode) {
+		case float_round_nearest_even:
+			/* v |= (0 << 4); */
+			break;
+		case float_round_to_zero:
+			v |= (1 << 4);
+			break;
+		case float_round_down:
+			v |= (2 << 4);
+			break;
+		case float_round_up:
+			v |= (3 << 4);
+			break;
+	}
+
+	if (80 == floatx80_rounding_precision) {
+		/* v |= (0 << 6); */
+	} else if (32 == floatx80_rounding_precision) {
+		v |= (1 << 6);
+	} else if (64 == floatx80_rounding_precision) {
+		v |= (2 << 6);
+	} else {
+		ReportAbnormalID(0x0203,
+			"Bad rounding precision in myfp_GetFPCR");
+	}
+
+	return v;
+}
+
+LOCALVAR struct myfp_envStruct
+{
+	ui5r FPSR;  /* Floating point status register */
+} myfp_env;
+
+LOCALPROC myfp_SetFPSR(ui5r v)
+{
+	myfp_env.FPSR = v;
+}
+
+LOCALFUNC ui5r myfp_GetFPSR(void)
+{
+	return myfp_env.FPSR;
+}
+
+LOCALFUNC ui3r myfp_GetConditionCodeByte(void)
+{
+	return (myfp_env.FPSR >> 24) & 0x0F;
+}
+
+LOCALPROC myfp_SetConditionCodeByte(ui3r v)
+{
+	myfp_env.FPSR = ((myfp_env.FPSR & 0x00FFFFFF)
+		| (v << 24));
+}
+
+LOCALPROC myfp_SetConditionCodeByteFromResult(myfpr *result)
+{
+	/* Set condition codes here based on result */
+
+	int c_nan  = myfp_IsNan(result) ? 1 : 0;
+	int c_inf  = myfp_IsInf(result) ? 1 : 0;
+	int c_zero = myfp_IsZero(result) ? 1 : 0;
+	int c_neg  = myfp_IsNeg(result) ? 1 : 0;
+
+	myfp_SetConditionCodeByte(c_nan
+		| (c_inf  << 1)
+		| (c_zero << 2)
+		| (c_neg  << 3));
+}
--- /dev/null
+++ b/src/GLOBGLUE.c
@@ -1,0 +1,1762 @@
+/*
+	GLOBGLUE.c
+
+	Copyright (C) 2003 Bernd Schmidt, Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	GLOBal GLUE (or GLOB of GLUE)
+
+	Holds the program together.
+
+	Some code here adapted from "custom.c" in vMac by Philip Cummins,
+	in turn descended from code in the Un*x Amiga Emulator by
+	Bernd Schmidt.
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+
+#include "MYOSGLUE.h"
+#include "ENDIANAC.h"
+#include "EMCONFIG.h"
+#endif
+
+#include "GLOBGLUE.h"
+
+/*
+	ReportAbnormalID unused 0x111D - 0x11FF
+*/
+
+/*
+	ReportAbnormalID ranges unused 0x12xx - 0xFFxx
+*/
+
+IMPORTPROC m68k_reset(void);
+IMPORTPROC IWM_Reset(void);
+IMPORTPROC SCC_Reset(void);
+IMPORTPROC SCSI_Reset(void);
+IMPORTPROC VIA1_Reset(void);
+#if EmVIA2
+IMPORTPROC VIA2_Reset(void);
+#endif
+IMPORTPROC Sony_Reset(void);
+
+IMPORTPROC ExtnDisk_Access(CPTR p);
+IMPORTPROC ExtnSony_Access(CPTR p);
+#if EmVidCard
+IMPORTPROC ExtnVideo_Access(CPTR p);
+#endif
+
+IMPORTPROC Sony_SetQuitOnEject(void);
+
+IMPORTPROC m68k_IPLchangeNtfy(void);
+IMPORTPROC MINEM68K_Init(
+	ui3b *fIPL);
+
+IMPORTFUNC si5r GetCyclesRemaining(void);
+IMPORTPROC SetCyclesRemaining(si5r n);
+
+IMPORTPROC SetHeadATTel(ATTep p);
+IMPORTFUNC ATTep FindATTel(CPTR addr);
+
+IMPORTFUNC ui5b SCSI_Access(ui5b Data, blnr WriteMem, CPTR addr);
+IMPORTFUNC ui5b SCC_Access(ui5b Data, blnr WriteMem, CPTR addr);
+IMPORTFUNC ui5b IWM_Access(ui5b Data, blnr WriteMem, CPTR addr);
+IMPORTFUNC ui5b VIA1_Access(ui5b Data, blnr WriteMem, CPTR addr);
+#if EmVIA2
+IMPORTFUNC ui5b VIA2_Access(ui5b Data, blnr WriteMem, CPTR addr);
+#endif
+#if EmASC
+IMPORTFUNC ui5b ASC_Access(ui5b Data, blnr WriteMem, CPTR addr);
+#endif
+
+IMPORTFUNC ui3r get_vm_byte(CPTR addr);
+IMPORTFUNC ui4r get_vm_word(CPTR addr);
+IMPORTFUNC ui5r get_vm_long(CPTR addr);
+
+IMPORTPROC put_vm_byte(CPTR addr, ui3r b);
+IMPORTPROC put_vm_word(CPTR addr, ui4r w);
+IMPORTPROC put_vm_long(CPTR addr, ui5r l);
+
+GLOBALVAR ui5r my_disk_icon_addr;
+
+GLOBALPROC customreset(void)
+{
+	IWM_Reset();
+	SCC_Reset();
+	SCSI_Reset();
+	VIA1_Reset();
+#if EmVIA2
+	VIA2_Reset();
+#endif
+	Sony_Reset();
+	Extn_Reset();
+#if CurEmMd <= kEmMd_Plus
+	WantMacReset = trueblnr;
+	/*
+		kludge, code in Finder appears
+		to do RESET and not expect
+		to come back. Maybe asserting
+		the RESET somehow causes
+		other hardware compenents to
+		later reset the 68000.
+	*/
+#endif
+}
+
+GLOBALVAR ui3p RAM = nullpr;
+
+#if EmVidCard
+GLOBALVAR ui3p VidROM = nullpr;
+#endif
+
+#if IncludeVidMem
+GLOBALVAR ui3p VidMem = nullpr;
+#endif
+
+GLOBALVAR ui3b Wires[kNumWires];
+
+
+#if WantDisasm
+IMPORTPROC m68k_WantDisasmContext(void);
+#endif
+
+#if WantDisasm
+GLOBALPROC dbglog_StartLine(void)
+{
+	m68k_WantDisasmContext();
+	dbglog_writeCStr(" ");
+}
+#endif
+
+#if dbglog_HAVE
+GLOBALPROC dbglog_WriteMemArrow(blnr WriteMem)
+{
+	if (WriteMem) {
+		dbglog_writeCStr(" <- ");
+	} else {
+		dbglog_writeCStr(" -> ");
+	}
+}
+#endif
+
+#if dbglog_HAVE
+GLOBALPROC dbglog_AddrAccess(char *s, ui5r Data,
+	blnr WriteMem, ui5r addr)
+{
+	dbglog_StartLine();
+	dbglog_writeCStr(s);
+	dbglog_writeCStr("[");
+	dbglog_writeHex(addr);
+	dbglog_writeCStr("]");
+	dbglog_WriteMemArrow(WriteMem);
+	dbglog_writeHex(Data);
+	dbglog_writeReturn();
+}
+#endif
+
+#if dbglog_HAVE
+GLOBALPROC dbglog_Access(char *s, ui5r Data, blnr WriteMem)
+{
+	dbglog_StartLine();
+	dbglog_writeCStr(s);
+	dbglog_WriteMemArrow(WriteMem);
+	dbglog_writeHex(Data);
+	dbglog_writeReturn();
+}
+#endif
+
+#if dbglog_HAVE
+GLOBALPROC dbglog_WriteNote(char *s)
+{
+	dbglog_StartLine();
+	dbglog_writeCStr(s);
+	dbglog_writeReturn();
+}
+#endif
+
+#if dbglog_HAVE
+GLOBALPROC dbglog_WriteSetBool(char *s, blnr v)
+{
+	dbglog_StartLine();
+	dbglog_writeCStr(s);
+	dbglog_writeCStr(" <- ");
+	if (v) {
+		dbglog_writeCStr("1");
+	} else {
+		dbglog_writeCStr("0");
+	}
+	dbglog_writeReturn();
+}
+#endif
+
+#if WantAbnormalReports
+LOCALVAR blnr GotOneAbnormal = falseblnr;
+#endif
+
+#ifndef ReportAbnormalInterrupt
+#define ReportAbnormalInterrupt 0
+#endif
+
+#if WantAbnormalReports
+GLOBALPROC DoReportAbnormalID(ui4r id
+#if dbglog_HAVE
+	, char *s
+#endif
+	)
+{
+#if dbglog_HAVE
+	dbglog_StartLine();
+	dbglog_writeCStr("*** abnormal : ");
+	dbglog_writeCStr(s);
+	dbglog_writeReturn();
+#endif
+
+	if (! GotOneAbnormal) {
+		WarnMsgAbnormalID(id);
+#if ReportAbnormalInterrupt
+		SetInterruptButton(trueblnr);
+#endif
+		GotOneAbnormal = trueblnr;
+	}
+}
+#endif
+
+/* map of address space */
+
+#define kRAM_Base 0x00000000 /* when overlay off */
+#if (CurEmMd == kEmMd_PB100)
+#define kRAM_ln2Spc 23
+#elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+#define kRAM_ln2Spc 23
+#else
+#define kRAM_ln2Spc 22
+#endif
+
+#if IncludeVidMem
+#if CurEmMd == kEmMd_PB100
+#define kVidMem_Base 0x00FA0000
+#define kVidMem_ln2Spc 16
+#else
+#define kVidMem_Base 0x00540000
+#define kVidMem_ln2Spc 18
+#endif
+#endif
+
+#if CurEmMd == kEmMd_PB100
+#define kSCSI_Block_Base 0x00F90000
+#define kSCSI_ln2Spc 16
+#else
+#define kSCSI_Block_Base 0x00580000
+#define kSCSI_ln2Spc 19
+#endif
+
+#define kRAM_Overlay_Base 0x00600000 /* when overlay on */
+#define kRAM_Overlay_Top  0x00800000
+
+#if CurEmMd == kEmMd_PB100
+#define kSCCRd_Block_Base 0x00FD0000
+#define kSCC_ln2Spc 16
+#else
+#define kSCCRd_Block_Base 0x00800000
+#define kSCC_ln2Spc 22
+#endif
+
+#if CurEmMd != kEmMd_PB100
+#define kSCCWr_Block_Base 0x00A00000
+#define kSCCWr_Block_Top  0x00C00000
+#endif
+
+#if CurEmMd == kEmMd_PB100
+#define kIWM_Block_Base 0x00F60000
+#define kIWM_ln2Spc 16
+#else
+#define kIWM_Block_Base 0x00C00000
+#define kIWM_ln2Spc 21
+#endif
+
+#if CurEmMd == kEmMd_PB100
+#define kVIA1_Block_Base 0x00F70000
+#define kVIA1_ln2Spc 16
+#else
+#define kVIA1_Block_Base 0x00E80000
+#define kVIA1_ln2Spc 19
+#endif
+
+#if CurEmMd == kEmMd_PB100
+#define kASC_Block_Base 0x00FB0000
+#define kASC_ln2Spc 16
+#endif
+#define kASC_Mask 0x00000FFF
+
+
+#if IncludeExtnPbufs
+LOCALFUNC tMacErr PbufTransferVM(CPTR Buffera,
+	tPbuf i, ui5r offset, ui5r count, blnr IsWrite)
+{
+	tMacErr result;
+	ui5b contig;
+	ui3p Buffer;
+
+label_1:
+	if (0 == count) {
+		result = mnvm_noErr;
+	} else {
+		Buffer = get_real_address0(count, ! IsWrite, Buffera, &contig);
+		if (0 == contig) {
+			result = mnvm_miscErr;
+		} else {
+			PbufTransfer(Buffer, i, offset, contig, IsWrite);
+			offset += contig;
+			Buffera += contig;
+			count -= contig;
+			goto label_1;
+		}
+	}
+
+	return result;
+}
+#endif
+
+/* extension mechanism */
+
+#if IncludeExtnPbufs
+#define kCmndPbufFeatures 1
+#define kCmndPbufNew 2
+#define kCmndPbufDispose 3
+#define kCmndPbufGetSize 4
+#define kCmndPbufTransfer 5
+#endif
+
+#if IncludeExtnPbufs
+LOCALPROC ExtnParamBuffers_Access(CPTR p)
+{
+	tMacErr result = mnvm_controlErr;
+
+	switch (get_vm_word(p + ExtnDat_commnd)) {
+		case kCmndVersion:
+			put_vm_word(p + ExtnDat_version, 1);
+			result = mnvm_noErr;
+			break;
+		case kCmndPbufFeatures:
+			put_vm_long(p + ExtnDat_params + 0, 0);
+			result = mnvm_noErr;
+			break;
+		case kCmndPbufNew:
+			{
+				tPbuf Pbuf_No;
+				ui5b count = get_vm_long(p + ExtnDat_params + 4);
+				/* reserved word at offset 2, should be zero */
+				result = PbufNew(count, &Pbuf_No);
+				put_vm_word(p + ExtnDat_params + 0, Pbuf_No);
+			}
+			break;
+		case kCmndPbufDispose:
+			{
+				tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 0);
+				/* reserved word at offset 2, should be zero */
+				result = CheckPbuf(Pbuf_No);
+				if (mnvm_noErr == result) {
+					PbufDispose(Pbuf_No);
+				}
+			}
+			break;
+		case kCmndPbufGetSize:
+			{
+				ui5r Count;
+				tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 0);
+				/* reserved word at offset 2, should be zero */
+
+				result = PbufGetSize(Pbuf_No, &Count);
+				if (mnvm_noErr == result) {
+					put_vm_long(p + ExtnDat_params + 4, Count);
+				}
+			}
+			break;
+		case kCmndPbufTransfer:
+			{
+				ui5r PbufCount;
+				tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 0);
+				/* reserved word at offset 2, should be zero */
+				ui5r offset = get_vm_long(p + ExtnDat_params + 4);
+				ui5r count = get_vm_long(p + ExtnDat_params + 8);
+				CPTR Buffera = get_vm_long(p + ExtnDat_params + 12);
+				blnr IsWrite =
+					(get_vm_word(p + ExtnDat_params + 16) != 0);
+				result = PbufGetSize(Pbuf_No, &PbufCount);
+				if (mnvm_noErr == result) {
+					ui5r endoff = offset + count;
+					if ((endoff < offset) /* overflow */
+						|| (endoff > PbufCount))
+					{
+						result = mnvm_eofErr;
+					} else {
+						result = PbufTransferVM(Buffera,
+							Pbuf_No, offset, count, IsWrite);
+					}
+				}
+			}
+			break;
+	}
+
+	put_vm_word(p + ExtnDat_result, result);
+}
+#endif
+
+#if IncludeExtnHostTextClipExchange
+#define kCmndHTCEFeatures 1
+#define kCmndHTCEExport 2
+#define kCmndHTCEImport 3
+#endif
+
+#if IncludeExtnHostTextClipExchange
+LOCALPROC ExtnHostTextClipExchange_Access(CPTR p)
+{
+	tMacErr result = mnvm_controlErr;
+
+	switch (get_vm_word(p + ExtnDat_commnd)) {
+		case kCmndVersion:
+			put_vm_word(p + ExtnDat_version, 1);
+			result = mnvm_noErr;
+			break;
+		case kCmndHTCEFeatures:
+			put_vm_long(p + ExtnDat_params + 0, 0);
+			result = mnvm_noErr;
+			break;
+		case kCmndHTCEExport:
+			{
+				tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 0);
+
+				result = CheckPbuf(Pbuf_No);
+				if (mnvm_noErr == result) {
+					result = HTCEexport(Pbuf_No);
+				}
+			}
+			break;
+		case kCmndHTCEImport:
+			{
+				tPbuf Pbuf_No;
+				result = HTCEimport(&Pbuf_No);
+				put_vm_word(p + ExtnDat_params + 0, Pbuf_No);
+			}
+			break;
+	}
+
+	put_vm_word(p + ExtnDat_result, result);
+}
+#endif
+
+#define kFindExtnExtension 0x64E1F58A
+#define kDiskDriverExtension 0x4C9219E6
+#if IncludeExtnPbufs
+#define kHostParamBuffersExtension 0x314C87BF
+#endif
+#if IncludeExtnHostTextClipExchange
+#define kHostClipExchangeExtension 0x27B130CA
+#endif
+
+#define kCmndFindExtnFind 1
+#define kCmndFindExtnId2Code 2
+#define kCmndFindExtnCount 3
+
+#define kParamFindExtnTheExtn 8
+#define kParamFindExtnTheId 12
+
+LOCALPROC ExtnFind_Access(CPTR p)
+{
+	tMacErr result = mnvm_controlErr;
+
+	switch (get_vm_word(p + ExtnDat_commnd)) {
+		case kCmndVersion:
+			put_vm_word(p + ExtnDat_version, 1);
+			result = mnvm_noErr;
+			break;
+		case kCmndFindExtnFind:
+			{
+				ui5b extn = get_vm_long(p + kParamFindExtnTheExtn);
+
+				if (extn == kDiskDriverExtension) {
+					put_vm_word(p + kParamFindExtnTheId, kExtnDisk);
+					result = mnvm_noErr;
+				} else
+#if IncludeExtnPbufs
+				if (extn == kHostParamBuffersExtension) {
+					put_vm_word(p + kParamFindExtnTheId,
+						kExtnParamBuffers);
+					result = mnvm_noErr;
+				} else
+#endif
+#if IncludeExtnHostTextClipExchange
+				if (extn == kHostClipExchangeExtension) {
+					put_vm_word(p + kParamFindExtnTheId,
+						kExtnHostTextClipExchange);
+					result = mnvm_noErr;
+				} else
+#endif
+				if (extn == kFindExtnExtension) {
+					put_vm_word(p + kParamFindExtnTheId,
+						kExtnFindExtn);
+					result = mnvm_noErr;
+				} else
+				{
+					/* not found */
+				}
+			}
+			break;
+		case kCmndFindExtnId2Code:
+			{
+				ui4r extn = get_vm_word(p + kParamFindExtnTheId);
+
+				if (extn == kExtnDisk) {
+					put_vm_long(p + kParamFindExtnTheExtn,
+						kDiskDriverExtension);
+					result = mnvm_noErr;
+				} else
+#if IncludeExtnPbufs
+				if (extn == kExtnParamBuffers) {
+					put_vm_long(p + kParamFindExtnTheExtn,
+						kHostParamBuffersExtension);
+					result = mnvm_noErr;
+				} else
+#endif
+#if IncludeExtnHostTextClipExchange
+				if (extn == kExtnHostTextClipExchange) {
+					put_vm_long(p + kParamFindExtnTheExtn,
+						kHostClipExchangeExtension);
+					result = mnvm_noErr;
+				} else
+#endif
+				if (extn == kExtnFindExtn) {
+					put_vm_long(p + kParamFindExtnTheExtn,
+						kFindExtnExtension);
+					result = mnvm_noErr;
+				} else
+				{
+					/* not found */
+				}
+			}
+			break;
+		case kCmndFindExtnCount:
+			put_vm_word(p + kParamFindExtnTheId, kNumExtns);
+			result = mnvm_noErr;
+			break;
+	}
+
+	put_vm_word(p + ExtnDat_result, result);
+}
+
+#define kDSK_Params_Hi 0
+#define kDSK_Params_Lo 1
+#define kDSK_QuitOnEject 3 /* obsolete */
+
+LOCALVAR ui4b ParamAddrHi;
+
+LOCALPROC Extn_Access(ui5b Data, CPTR addr)
+{
+	switch (addr) {
+		case kDSK_Params_Hi:
+			ParamAddrHi = Data;
+			break;
+		case kDSK_Params_Lo:
+			{
+				CPTR p = ParamAddrHi << 16 | Data;
+
+				ParamAddrHi = (ui4b) - 1;
+				if (kcom_callcheck == get_vm_word(p + ExtnDat_checkval))
+				{
+					put_vm_word(p + ExtnDat_checkval, 0);
+
+					switch (get_vm_word(p + ExtnDat_extension)) {
+						case kExtnFindExtn:
+							ExtnFind_Access(p);
+							break;
+#if EmVidCard
+						case kExtnVideo:
+							ExtnVideo_Access(p);
+							break;
+#endif
+#if IncludeExtnPbufs
+						case kExtnParamBuffers:
+							ExtnParamBuffers_Access(p);
+							break;
+#endif
+#if IncludeExtnHostTextClipExchange
+						case kExtnHostTextClipExchange:
+							ExtnHostTextClipExchange_Access(p);
+							break;
+#endif
+						case kExtnDisk:
+							ExtnDisk_Access(p);
+							break;
+						case kExtnSony:
+							ExtnSony_Access(p);
+							break;
+						default:
+							put_vm_word(p + ExtnDat_result,
+								mnvm_controlErr);
+							break;
+					}
+				}
+			}
+			break;
+		case kDSK_QuitOnEject:
+			/* obsolete, kept for compatibility */
+			Sony_SetQuitOnEject();
+			break;
+	}
+}
+
+GLOBALPROC Extn_Reset(void)
+{
+	ParamAddrHi = (ui4b) - 1;
+}
+
+/* implementation of read/write for everything but RAM and ROM */
+
+#define kSCC_Mask 0x03
+
+#define kVIA1_Mask 0x00000F
+#if EmVIA2
+#define kVIA2_Mask 0x00000F
+#endif
+
+#define kIWM_Mask 0x00000F /* Allocated Memory Bandwidth for IWM */
+
+#if CurEmMd <= kEmMd_512Ke
+#define ROM_CmpZeroMask 0
+#elif CurEmMd <= kEmMd_Plus
+#if kROM_Size > 0x00020000
+#define ROM_CmpZeroMask 0 /* For hacks like Mac ROM-inator */
+#else
+#define ROM_CmpZeroMask 0x00020000
+#endif
+#elif CurEmMd <= kEmMd_PB100
+#define ROM_CmpZeroMask 0
+#elif CurEmMd <= kEmMd_IIx
+#define ROM_CmpZeroMask 0
+#else
+#error "ROM_CmpZeroMask not defined"
+#endif
+
+#define kROM_cmpmask (0x00F00000 | ROM_CmpZeroMask)
+
+#if CurEmMd <= kEmMd_512Ke
+#define Overlay_ROM_CmpZeroMask 0x00100000
+#elif CurEmMd <= kEmMd_Plus
+#define Overlay_ROM_CmpZeroMask 0x00020000
+#elif CurEmMd <= kEmMd_Classic
+#define Overlay_ROM_CmpZeroMask 0x00300000
+#elif CurEmMd <= kEmMd_PB100
+#define Overlay_ROM_CmpZeroMask 0
+#elif CurEmMd <= kEmMd_IIx
+#define Overlay_ROM_CmpZeroMask 0
+#else
+#error "Overlay_ROM_CmpZeroMask not defined"
+#endif
+
+enum {
+	kMMDV_VIA1,
+#if EmVIA2
+	kMMDV_VIA2,
+#endif
+	kMMDV_SCC,
+	kMMDV_Extn,
+#if EmASC
+	kMMDV_ASC,
+#endif
+	kMMDV_SCSI,
+	kMMDV_IWM,
+
+	kNumMMDVs
+};
+
+enum {
+#if CurEmMd >= kEmMd_SE
+	kMAN_OverlayOff,
+#endif
+
+	kNumMANs
+};
+
+
+LOCALVAR ATTer ATTListA[MaxATTListN];
+LOCALVAR ui4r LastATTel;
+
+
+LOCALPROC AddToATTList(ATTep p)
+{
+	ui4r NewLast = LastATTel + 1;
+	if (NewLast >= MaxATTListN) {
+		ReportAbnormalID(0x1101, "MaxATTListN not big enough");
+	} else {
+		ATTListA[LastATTel] = *p;
+		LastATTel = NewLast;
+	}
+}
+
+LOCALPROC InitATTList(void)
+{
+	LastATTel = 0;
+}
+
+LOCALPROC FinishATTList(void)
+{
+	{
+		/* add guard */
+		ATTer r;
+
+		r.cmpmask = 0;
+		r.cmpvalu = 0;
+		r.usemask = 0;
+		r.usebase = nullpr;
+		r.Access = 0;
+		AddToATTList(&r);
+	}
+
+	{
+		ui4r i = LastATTel;
+		ATTep p = &ATTListA[LastATTel];
+		ATTep h = nullpr;
+
+		while (0 != i) {
+			--i;
+			--p;
+			p->Next = h;
+			h = p;
+		}
+
+#if 0 /* verify list. not for final version */
+		{
+			ATTep q1;
+			ATTep q2;
+			for (q1 = h; nullpr != q1->Next; q1 = q1->Next) {
+				if ((q1->cmpvalu & ~ q1->cmpmask) != 0) {
+					ReportAbnormalID(0x1102, "ATTListA bad entry");
+				}
+				for (q2 = q1->Next; nullpr != q2->Next; q2 = q2->Next) {
+					ui5r common_mask = (q1->cmpmask) & (q2->cmpmask);
+					if ((q1->cmpvalu & common_mask) ==
+						(q2->cmpvalu & common_mask))
+					{
+						ReportAbnormalID(0x1103, "ATTListA Conflict");
+					}
+				}
+			}
+		}
+#endif
+
+		SetHeadATTel(h);
+	}
+}
+
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+LOCALPROC SetUp_RAM24(void)
+{
+	ATTer r;
+	ui5r bankbit = 0x00100000 << (((VIA2_iA7 << 1) | VIA2_iA6) << 1);
+
+#if kRAMa_Size == kRAMb_Size
+	if (kRAMa_Size == bankbit) {
+		/* properly set up balanced RAM */
+		r.cmpmask = 0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1);
+		r.cmpvalu = 0;
+		r.usemask = ((1 << kRAM_ln2Spc) - 1) & (kRAM_Size - 1);
+		r.usebase = RAM;
+		r.Access = kATTA_readwritereadymask;
+		AddToATTList(&r);
+	} else
+#endif
+	{
+		bankbit &= 0x00FFFFFF; /* if too large, always use RAMa */
+
+		if (0 != bankbit) {
+#if kRAMb_Size != 0
+			r.cmpmask = bankbit
+				| (0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1));
+			r.cmpvalu = bankbit;
+			r.usemask = ((1 << kRAM_ln2Spc) - 1) & (kRAMb_Size - 1);
+			r.usebase = kRAMa_Size + RAM;
+			r.Access = kATTA_readwritereadymask;
+			AddToATTList(&r);
+#endif
+		}
+
+		{
+			r.cmpmask = bankbit
+				| (0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1));
+			r.cmpvalu = 0;
+			r.usemask = ((1 << kRAM_ln2Spc) - 1) & (kRAMa_Size - 1);
+			r.usebase = RAM;
+			r.Access = kATTA_readwritereadymask;
+			AddToATTList(&r);
+		}
+	}
+}
+#endif
+
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+LOCALPROC SetUp_io(void)
+{
+	ATTer r;
+
+	if (Addr32) {
+		r.cmpmask = 0xFF01E000;
+		r.cmpvalu = 0x50000000;
+	} else {
+		r.cmpmask = 0x00F1E000;
+		r.cmpvalu = 0x00F00000;
+	}
+	r.usebase = nullpr;
+	r.Access = kATTA_mmdvmask;
+	r.MMDV = kMMDV_VIA1;
+	AddToATTList(&r);
+
+	if (Addr32) {
+		r.cmpmask = 0xFF01E000;
+		r.cmpvalu = 0x50000000 | 0x2000;
+	} else {
+		r.cmpmask = 0x00F1E000;
+		r.cmpvalu = 0x00F00000 | 0x2000;
+	}
+	r.usebase = nullpr;
+	r.Access = kATTA_mmdvmask;
+	r.MMDV = kMMDV_VIA2;
+	AddToATTList(&r);
+
+	if (Addr32) {
+		r.cmpmask = 0xFF01E000;
+		r.cmpvalu = 0x50000000 | 0x4000;
+	} else {
+		r.cmpmask = 0x00F1E000;
+		r.cmpvalu = 0x00F00000 | 0x4000;
+	}
+	r.usebase = nullpr;
+	r.Access = kATTA_mmdvmask;
+	r.MMDV = kMMDV_SCC;
+	AddToATTList(&r);
+
+	if (Addr32) {
+		r.cmpmask = 0xFF01E000;
+		r.cmpvalu = 0x50000000 | 0x0C000;
+	} else {
+		r.cmpmask = 0x00F1E000;
+		r.cmpvalu = 0x00F00000 | 0x0C000;
+	}
+	r.usebase = nullpr;
+	r.Access = kATTA_mmdvmask;
+	r.MMDV = kMMDV_Extn;
+	AddToATTList(&r);
+
+	if (Addr32) {
+		r.cmpmask = 0xFF01E000;
+		r.cmpvalu = 0x50000000 | 0x10000;
+	} else {
+		r.cmpmask = 0x00F1E000;
+		r.cmpvalu = 0x00F00000 | 0x10000;
+	}
+	r.usebase = nullpr;
+	r.Access = kATTA_mmdvmask;
+	r.MMDV = kMMDV_SCSI;
+	AddToATTList(&r);
+
+	if (Addr32) {
+		r.cmpmask = 0xFF01E000;
+		r.cmpvalu = 0x50000000 | 0x14000;
+	} else {
+		r.cmpmask = 0x00F1E000;
+		r.cmpvalu = 0x00F00000 | 0x14000;
+	}
+	r.usebase = nullpr;
+	r.Access = kATTA_mmdvmask;
+	r.MMDV = kMMDV_ASC;
+	AddToATTList(&r);
+
+	if (Addr32) {
+		r.cmpmask = 0xFF01E000;
+		r.cmpvalu = 0x50000000 | 0x16000;
+	} else {
+		r.cmpmask = 0x00F1E000;
+		r.cmpvalu = 0x00F00000 | 0x16000;
+	}
+	r.usebase = nullpr;
+	r.Access = kATTA_mmdvmask;
+	r.MMDV = kMMDV_IWM;
+	AddToATTList(&r);
+
+#if 0
+		case 14:
+			/*
+				fail, nothing supposed to be here,
+				but rom accesses it anyway
+			*/
+			{
+				ui5r addr2 = addr & 0x1FFFF;
+
+				if ((addr2 != 0x1DA00) && (addr2 != 0x1DC00)) {
+					ReportAbnormalID(0x1104, "another unknown access");
+				}
+			}
+			get_fail_realblock(p);
+			break;
+#endif
+}
+#endif
+
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+LOCALPROC SetUp_address24(void)
+{
+	ATTer r;
+
+#if 0
+	if (MemOverlay) {
+		ReportAbnormalID(0x1105, "Overlay with 24 bit addressing");
+	}
+#endif
+
+	if (MemOverlay) {
+		r.cmpmask = Overlay_ROM_CmpZeroMask |
+			(0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1));
+		r.cmpvalu = kRAM_Base;
+		r.usemask = kROM_Size - 1;
+		r.usebase = ROM;
+		r.Access = kATTA_readreadymask;
+		AddToATTList(&r);
+	} else {
+		SetUp_RAM24();
+	}
+
+	r.cmpmask = kROM_cmpmask;
+	r.cmpvalu = kROM_Base;
+	r.usemask = kROM_Size - 1;
+	r.usebase = ROM;
+	r.Access = kATTA_readreadymask;
+	AddToATTList(&r);
+
+	r.cmpmask = 0x00FFFFFF & ~ (0x100000 - 1);
+	r.cmpvalu = 0x900000;
+	r.usemask = (kVidMemRAM_Size - 1) & (0x100000 - 1);
+	r.usebase = VidMem;
+	r.Access = kATTA_readwritereadymask;
+	AddToATTList(&r);
+#if kVidMemRAM_Size >= 0x00200000
+	r.cmpmask = 0x00FFFFFF & ~ (0x100000 - 1);
+	r.cmpvalu = 0xA00000;
+	r.usemask = (0x100000 - 1);
+	r.usebase = VidMem + (1 << 20);
+	r.Access = kATTA_readwritereadymask;
+	AddToATTList(&r);
+#endif
+#if kVidMemRAM_Size >= 0x00400000
+	r.cmpmask = 0x00FFFFFF & ~ (0x100000 - 1);
+	r.cmpvalu = 0xB00000;
+	r.usemask = (0x100000 - 1);
+	r.usebase = VidMem + (2 << 20);
+	r.Access = kATTA_readwritereadymask;
+	AddToATTList(&r);
+	r.cmpmask = 0x00FFFFFF & ~ (0x100000 - 1);
+	r.cmpvalu = 0xC00000;
+	r.usemask = (0x100000 - 1);
+	r.usebase = VidMem + (3 << 20);
+	r.Access = kATTA_readwritereadymask;
+	AddToATTList(&r);
+#endif
+
+	SetUp_io();
+}
+#endif
+
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+LOCALPROC SetUp_address32(void)
+{
+	ATTer r;
+
+	if (MemOverlay) {
+		r.cmpmask = ~ ((1 << 30) - 1);
+		r.cmpvalu = 0;
+		r.usemask = kROM_Size - 1;
+		r.usebase = ROM;
+		r.Access = kATTA_readreadymask;
+		AddToATTList(&r);
+	} else {
+		ui5r bankbit =
+			0x00100000 << (((VIA2_iA7 << 1) | VIA2_iA6) << 1);
+#if kRAMa_Size == kRAMb_Size
+		if (kRAMa_Size == bankbit) {
+			/* properly set up balanced RAM */
+			r.cmpmask = ~ ((1 << 30) - 1);
+			r.cmpvalu = 0;
+			r.usemask = kRAM_Size - 1;
+			r.usebase = RAM;
+			r.Access = kATTA_readwritereadymask;
+			AddToATTList(&r);
+		} else
+#endif
+		{
+#if kRAMb_Size != 0
+			r.cmpmask = bankbit | ~ ((1 << 30) - 1);
+			r.cmpvalu = bankbit;
+			r.usemask = kRAMb_Size - 1;
+			r.usebase = kRAMa_Size + RAM;
+			r.Access = kATTA_readwritereadymask;
+			AddToATTList(&r);
+#endif
+
+			r.cmpmask = bankbit | ~ ((1 << 30) - 1);
+			r.cmpvalu = 0;
+			r.usemask = kRAMa_Size - 1;
+			r.usebase = RAM;
+			r.Access = kATTA_readwritereadymask;
+			AddToATTList(&r);
+		}
+	}
+
+	r.cmpmask = ~ ((1 << 28) - 1);
+	r.cmpvalu = 0x40000000;
+	r.usemask = kROM_Size - 1;
+	r.usebase = ROM;
+	r.Access = kATTA_readreadymask;
+	AddToATTList(&r);
+
+#if 0
+	/* haven't persuaded emulated computer to look here yet. */
+	/* NuBus super space */
+	r.cmpmask = ~ ((1 << 28) - 1);
+	r.cmpvalu = 0x90000000;
+	r.usemask = kVidMemRAM_Size - 1;
+	r.usebase = VidMem;
+	r.Access = kATTA_readwritereadymask;
+	AddToATTList(&r);
+#endif
+
+	/* Standard NuBus space */
+	r.cmpmask = ~ ((1 << 20) - 1);
+	r.cmpvalu = 0xF9F00000;
+	r.usemask = kVidROM_Size - 1;
+	r.usebase = VidROM;
+	r.Access = kATTA_readreadymask;
+	AddToATTList(&r);
+#if 0
+	r.cmpmask = ~ 0x007FFFFF;
+	r.cmpvalu = 0xF9000000;
+	r.usemask = 0x007FFFFF & (kVidMemRAM_Size - 1);
+	r.usebase = VidMem;
+	r.Access = kATTA_readwritereadymask;
+	AddToATTList(&r);
+#endif
+
+	r.cmpmask = ~ 0x000FFFFF;
+	r.cmpvalu = 0xF9900000;
+	r.usemask = 0x000FFFFF & (kVidMemRAM_Size - 1);
+	r.usebase = VidMem;
+	r.Access = kATTA_readwritereadymask;
+	AddToATTList(&r);
+/* kludge to allow more than 1M of Video Memory */
+#if kVidMemRAM_Size >= 0x00200000
+	r.cmpmask = ~ 0x000FFFFF;
+	r.cmpvalu = 0xF9A00000;
+	r.usemask = 0x000FFFFF & (kVidMemRAM_Size - 1);
+	r.usebase = VidMem + (1 << 20);
+	r.Access = kATTA_readwritereadymask;
+	AddToATTList(&r);
+#endif
+#if kVidMemRAM_Size >= 0x00400000
+	r.cmpmask = ~ 0x000FFFFF;
+	r.cmpvalu = 0xF9B00000;
+	r.usemask = 0x000FFFFF & (kVidMemRAM_Size - 1);
+	r.usebase = VidMem + (2 << 20);
+	r.Access = kATTA_readwritereadymask;
+	AddToATTList(&r);
+	r.cmpmask = ~ 0x000FFFFF;
+	r.cmpvalu = 0xF9C00000;
+	r.usemask = 0x000FFFFF & (kVidMemRAM_Size - 1);
+	r.usebase = VidMem + (3 << 20);
+	r.Access = kATTA_readwritereadymask;
+	AddToATTList(&r);
+#endif
+
+	SetUp_io();
+
+#if 0
+	if ((addr >= 0x58000000) && (addr < 0x58000004)) {
+		/* test hardware. fail */
+	}
+#endif
+}
+#endif
+
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+LOCALPROC SetUp_address(void)
+{
+	if (Addr32) {
+		SetUp_address32();
+	} else {
+		SetUp_address24();
+	}
+}
+#endif
+
+/*
+	unlike in the real Mac Plus, Mini vMac
+	will allow misaligned memory access,
+	since it is easier to allow it than
+	it is to correctly simulate a bus error
+	and back out of the current instruction.
+*/
+
+#ifndef ln2mtb
+#define AddToATTListWithMTB AddToATTList
+#else
+LOCALPROC AddToATTListWithMTB(ATTep p)
+{
+	/*
+		Test of memory mapping system.
+	*/
+	ATTer r;
+
+	r.Access = p->Access;
+	r.cmpmask = p->cmpmask | (1 << ln2mtb);
+	r.usemask = p->usemask & ~ (1 << ln2mtb);
+
+	r.cmpvalu = p->cmpvalu + (1 << ln2mtb);
+	r.usebase = p->usebase;
+	AddToATTList(&r);
+
+	r.cmpvalu = p->cmpvalu;
+	r.usebase = p->usebase + (1 << ln2mtb);
+	AddToATTList(&r);
+}
+#endif
+
+#if (CurEmMd != kEmMd_II) && (CurEmMd != kEmMd_IIx)
+LOCALPROC SetUp_RAM24(void)
+{
+	ATTer r;
+
+#if (0 == kRAMb_Size) || (kRAMa_Size == kRAMb_Size)
+	r.cmpmask = 0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1);
+	r.cmpvalu = kRAM_Base;
+	r.usemask = kRAM_Size - 1;
+	r.usebase = RAM;
+	r.Access = kATTA_readwritereadymask;
+	AddToATTListWithMTB(&r);
+#else
+	/* unbalanced memory */
+
+#if 0 != (0x00FFFFFF & kRAMa_Size)
+	/* condition should always be true if configuration file right */
+	r.cmpmask = 0x00FFFFFF & (kRAMa_Size | ~ ((1 << kRAM_ln2Spc) - 1));
+	r.cmpvalu = kRAM_Base + kRAMa_Size;
+	r.usemask = kRAMb_Size - 1;
+	r.usebase = kRAMa_Size + RAM;
+	r.Access = kATTA_readwritereadymask;
+	AddToATTListWithMTB(&r);
+#endif
+
+	r.cmpmask = 0x00FFFFFF & (kRAMa_Size | ~ ((1 << kRAM_ln2Spc) - 1));
+	r.cmpvalu = kRAM_Base;
+	r.usemask = kRAMa_Size - 1;
+	r.usebase = RAM;
+	r.Access = kATTA_readwritereadymask;
+	AddToATTListWithMTB(&r);
+#endif
+}
+#endif
+
+#if (CurEmMd != kEmMd_II) && (CurEmMd != kEmMd_IIx)
+LOCALPROC SetUp_address(void)
+{
+	ATTer r;
+
+	if (MemOverlay) {
+		r.cmpmask = Overlay_ROM_CmpZeroMask |
+			(0x00FFFFFF & ~ ((1 << kRAM_ln2Spc) - 1));
+		r.cmpvalu = kRAM_Base;
+		r.usemask = kROM_Size - 1;
+		r.usebase = ROM;
+		r.Access = kATTA_readreadymask;
+		AddToATTListWithMTB(&r);
+	} else {
+		SetUp_RAM24();
+	}
+
+	r.cmpmask = kROM_cmpmask;
+	r.cmpvalu = kROM_Base;
+#if (CurEmMd >= kEmMd_SE)
+	if (MemOverlay) {
+		r.usebase = nullpr;
+		r.Access = kATTA_ntfymask;
+		r.Ntfy = kMAN_OverlayOff;
+		AddToATTList(&r);
+	} else
+#endif
+	{
+		r.usemask = kROM_Size - 1;
+		r.usebase = ROM;
+		r.Access = kATTA_readreadymask;
+		AddToATTListWithMTB(&r);
+	}
+
+	if (MemOverlay) {
+		r.cmpmask = 0x00E00000;
+		r.cmpvalu = kRAM_Overlay_Base;
+#if (0 == kRAMb_Size) || (kRAMa_Size == kRAMb_Size)
+		r.usemask = kRAM_Size - 1;
+			/* note that cmpmask and usemask overlap for 4M */
+		r.usebase = RAM;
+		r.Access = kATTA_readwritereadymask;
+#else
+		/* unbalanced memory */
+		r.usemask = kRAMb_Size - 1;
+		r.usebase = kRAMa_Size + RAM;
+		r.Access = kATTA_readwritereadymask;
+#endif
+		AddToATTListWithMTB(&r);
+	}
+
+#if IncludeVidMem
+	r.cmpmask = 0x00FFFFFF & ~ ((1 << kVidMem_ln2Spc) - 1);
+	r.cmpvalu = kVidMem_Base;
+	r.usemask = kVidMemRAM_Size - 1;
+	r.usebase = VidMem;
+	r.Access = kATTA_readwritereadymask;
+	AddToATTList(&r);
+#endif
+
+	r.cmpmask = 0x00FFFFFF & ~ ((1 << kVIA1_ln2Spc) - 1);
+	r.cmpvalu = kVIA1_Block_Base;
+	r.usebase = nullpr;
+	r.Access = kATTA_mmdvmask;
+	r.MMDV = kMMDV_VIA1;
+	AddToATTList(&r);
+
+	r.cmpmask = 0x00FFFFFF & ~ ((1 << kSCC_ln2Spc) - 1);
+	r.cmpvalu = kSCCRd_Block_Base;
+	r.usebase = nullpr;
+	r.Access = kATTA_mmdvmask;
+	r.MMDV = kMMDV_SCC;
+	AddToATTList(&r);
+
+	r.cmpmask = 0x00FFFFFF & ~ ((1 << kExtn_ln2Spc) - 1);
+	r.cmpvalu = kExtn_Block_Base;
+	r.usebase = nullpr;
+	r.Access = kATTA_mmdvmask;
+	r.MMDV = kMMDV_Extn;
+	AddToATTList(&r);
+
+#if CurEmMd == kEmMd_PB100
+	r.cmpmask = 0x00FFFFFF & ~ ((1 << kASC_ln2Spc) - 1);
+	r.cmpvalu = kASC_Block_Base;
+	r.usebase = nullpr;
+	r.Access = kATTA_mmdvmask;
+	r.MMDV = kMMDV_ASC;
+	AddToATTList(&r);
+#endif
+
+	r.cmpmask = 0x00FFFFFF & ~ ((1 << kSCSI_ln2Spc) - 1);
+	r.cmpvalu = kSCSI_Block_Base;
+	r.usebase = nullpr;
+	r.Access = kATTA_mmdvmask;
+	r.MMDV = kMMDV_SCSI;
+	AddToATTList(&r);
+
+	r.cmpmask = 0x00FFFFFF & ~ ((1 << kIWM_ln2Spc) - 1);
+	r.cmpvalu = kIWM_Block_Base;
+	r.usebase = nullpr;
+	r.Access = kATTA_mmdvmask;
+	r.MMDV = kMMDV_IWM;
+	AddToATTList(&r);
+}
+#endif
+
+LOCALPROC SetUpMemBanks(void)
+{
+	InitATTList();
+
+	SetUp_address();
+
+	FinishATTList();
+}
+
+#if 0
+LOCALPROC get_fail_realblock(ATTep p)
+{
+	p->cmpmask = 0;
+	p->cmpvalu = 0xFFFFFFFF;
+	p->usemask = 0;
+	p->usebase = nullpr;
+	p->Access = 0;
+}
+#endif
+
+GLOBALFUNC ui5b MMDV_Access(ATTep p, ui5b Data,
+	blnr WriteMem, blnr ByteSize, CPTR addr)
+{
+	switch (p->MMDV) {
+		case kMMDV_VIA1:
+			if (! ByteSize) {
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+				if (WriteMem && (addr == 0xF40006)) {
+					/* for weirdness on shutdown in System 6 */
+#if 0
+					VIA1_Access((Data >> 8) & 0x00FF, WriteMem,
+							(addr >> 9) & kVIA1_Mask);
+					VIA1_Access((Data) & 0x00FF, WriteMem,
+							(addr >> 9) & kVIA1_Mask);
+#endif
+				} else
+#endif
+				{
+					ReportAbnormalID(0x1106, "access VIA1 word");
+				}
+			} else if ((addr & 1) != 0) {
+				ReportAbnormalID(0x1107, "access VIA1 odd");
+			} else {
+#if CurEmMd != kEmMd_PB100
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+				if ((addr & 0x000001FE) != 0x00000000)
+#else
+				if ((addr & 0x000FE1FE) != 0x000FE1FE)
+#endif
+				{
+					ReportAbnormalID(0x1108,
+						"access VIA1 nonstandard address");
+				}
+#endif
+				Data = VIA1_Access(Data, WriteMem,
+					(addr >> 9) & kVIA1_Mask);
+			}
+
+			break;
+#if EmVIA2
+		case kMMDV_VIA2:
+			if (! ByteSize) {
+				if ((! WriteMem)
+					&& ((0x3e00 == (addr & 0x1FFFF))
+						|| (0x3e02 == (addr & 0x1FFFF))))
+				{
+					/* for weirdness at offset 0x71E in ROM */
+					Data =
+						(VIA2_Access(Data, WriteMem,
+							(addr >> 9) & kVIA2_Mask) << 8)
+						| VIA2_Access(Data, WriteMem,
+							(addr >> 9) & kVIA2_Mask);
+
+				} else {
+					ReportAbnormalID(0x1109, "access VIA2 word");
+				}
+			} else if ((addr & 1) != 0) {
+				if (0x3FFF == (addr & 0x1FFFF)) {
+					/*
+						for weirdness at offset 0x7C4 in ROM.
+						looks like bug.
+					*/
+					Data = VIA2_Access(Data, WriteMem,
+						(addr >> 9) & kVIA2_Mask);
+				} else {
+					ReportAbnormalID(0x110A, "access VIA2 odd");
+				}
+			} else {
+				if ((addr & 0x000001FE) != 0x00000000) {
+					ReportAbnormalID(0x110B,
+						"access VIA2 nonstandard address");
+				}
+				Data = VIA2_Access(Data, WriteMem,
+					(addr >> 9) & kVIA2_Mask);
+			}
+			break;
+#endif
+		case kMMDV_SCC:
+
+#if (CurEmMd >= kEmMd_SE) \
+	&& ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx))
+
+			if ((addr & 0x00100000) == 0) {
+				ReportAbnormalID(0x110C,
+					"access SCC unassigned address");
+			} else
+#endif
+			if (! ByteSize) {
+				ReportAbnormalID(0x110D, "Attemped Phase Adjust");
+			} else
+#if ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx))
+			if (WriteMem != ((addr & 1) != 0)) {
+				if (WriteMem) {
+#if CurEmMd >= kEmMd_512Ke
+#if CurEmMd != kEmMd_PB100
+					ReportAbnormalID(0x110E, "access SCC even/odd");
+					/*
+						This happens on boot with 64k ROM.
+					*/
+#endif
+#endif
+				} else {
+					SCC_Reset();
+				}
+			} else
+#endif
+#if (CurEmMd != kEmMd_PB100) \
+	&& ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx))
+
+			if (WriteMem != (addr >= kSCCWr_Block_Base)) {
+				ReportAbnormalID(0x110F, "access SCC wr/rd base wrong");
+			} else
+#endif
+			{
+#if CurEmMd != kEmMd_PB100
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+				if ((addr & 0x1FF9) != 0x00000000)
+#else
+				if ((addr & 0x001FFFF8) != 0x001FFFF8)
+#endif
+				{
+					ReportAbnormalID(0x1110,
+						"access SCC nonstandard address");
+				}
+#endif
+				Data = SCC_Access(Data, WriteMem,
+					(addr >> 1) & kSCC_Mask);
+			}
+			break;
+		case kMMDV_Extn:
+			if (ByteSize) {
+				ReportAbnormalID(0x1111, "access Sony byte");
+			} else if ((addr & 1) != 0) {
+				ReportAbnormalID(0x1112, "access Sony odd");
+			} else if (! WriteMem) {
+				ReportAbnormalID(0x1113, "access Sony read");
+			} else {
+				Extn_Access(Data, (addr >> 1) & 0x0F);
+			}
+			break;
+#if EmASC
+		case kMMDV_ASC:
+			if (! ByteSize) {
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+				if (WriteMem) {
+					(void) ASC_Access((Data >> 8) & 0x00FF,
+						WriteMem, addr & kASC_Mask);
+					Data = ASC_Access((Data) & 0x00FF,
+						WriteMem, (addr + 1) & kASC_Mask);
+				} else {
+					Data =
+						(ASC_Access((Data >> 8) & 0x00FF,
+							WriteMem, addr & kASC_Mask) << 8)
+						| ASC_Access((Data) & 0x00FF,
+							WriteMem, (addr + 1) & kASC_Mask);
+				}
+#else
+				ReportAbnormalID(0x1114, "access ASC word");
+#endif
+			} else {
+				Data = ASC_Access(Data, WriteMem, addr & kASC_Mask);
+			}
+			break;
+#endif
+		case kMMDV_SCSI:
+			if (! ByteSize) {
+				ReportAbnormalID(0x1115, "access SCSI word");
+			} else
+#if ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx))
+			if (WriteMem != ((addr & 1) != 0)) {
+				ReportAbnormalID(0x1116, "access SCSI even/odd");
+			} else
+#endif
+			{
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+				if ((addr & 0x1F8F) != 0x00000000) {
+					ReportAbnormalID(0x1117,
+						"access SCSI nonstandard address");
+				}
+#endif
+				Data = SCSI_Access(Data, WriteMem, (addr >> 4) & 0x07);
+			}
+
+			break;
+		case kMMDV_IWM:
+#if (CurEmMd >= kEmMd_SE) \
+	&& ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx))
+
+			if ((addr & 0x00100000) == 0) {
+				ReportAbnormalID(0x1118,
+					"access IWM unassigned address");
+			} else
+#endif
+			if (! ByteSize) {
+#if ExtraAbnormalReports
+				ReportAbnormalID(0x1119, "access IWM word");
+				/*
+					This happens when quitting 'Glider 3.1.2'.
+					perhaps a bad handle is being disposed of.
+				*/
+#endif
+			} else
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+			if ((addr & 1) != 0) {
+				ReportAbnormalID(0x111A, "access IWM odd");
+			} else
+#else
+			if ((addr & 1) == 0) {
+				ReportAbnormalID(0x111B, "access IWM even");
+			} else
+#endif
+			{
+#if (CurEmMd != kEmMd_PB100) \
+	&& ! ((CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx))
+
+				if ((addr & 0x001FE1FF) != 0x001FE1FF) {
+					ReportAbnormalID(0x111C,
+						"access IWM nonstandard address");
+				}
+#endif
+				Data = IWM_Access(Data, WriteMem,
+					(addr >> 9) & kIWM_Mask);
+			}
+
+			break;
+	}
+
+	return Data;
+}
+
+GLOBALFUNC blnr MemAccessNtfy(ATTep pT)
+{
+	blnr v = falseblnr;
+
+	switch (pT->Ntfy) {
+#if CurEmMd >= kEmMd_SE
+		case kMAN_OverlayOff:
+			pT->Access = kATTA_readreadymask;
+
+			MemOverlay = 0;
+			SetUpMemBanks();
+
+			v = trueblnr;
+
+			break;
+#endif
+	}
+
+	return v;
+}
+
+GLOBALPROC MemOverlay_ChangeNtfy(void)
+{
+#if CurEmMd <= kEmMd_Plus
+	SetUpMemBanks();
+#elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+	SetUpMemBanks();
+#endif
+}
+
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+GLOBALPROC Addr32_ChangeNtfy(void)
+{
+	SetUpMemBanks();
+}
+#endif
+
+LOCALFUNC ATTep get_address_realblock1(blnr WriteMem, CPTR addr)
+{
+	ATTep p;
+
+Label_Retry:
+	p = FindATTel(addr);
+	if (0 != (p->Access &
+		(WriteMem ? kATTA_writereadymask : kATTA_readreadymask)))
+	{
+		/* ok */
+	} else {
+		if (0 != (p->Access & kATTA_ntfymask)) {
+			if (MemAccessNtfy(p)) {
+				goto Label_Retry;
+			}
+		}
+		p = nullpr; /* fail */
+	}
+
+	return p;
+}
+
+GLOBALFUNC ui3p get_real_address0(ui5b L, blnr WritableMem, CPTR addr,
+	ui5b *actL)
+{
+	ui5b bankleft;
+	ui3p p;
+	ATTep q;
+
+	q = get_address_realblock1(WritableMem, addr);
+	if (nullpr == q) {
+		*actL = 0;
+		p = nullpr;
+	} else {
+		ui5r m2 = q->usemask & ~ q->cmpmask;
+		ui5r m3 = m2 & ~ (m2 + 1);
+		p = q->usebase + (addr & q->usemask);
+		bankleft = (m3 + 1) - (addr & m3);
+		if (bankleft >= L) {
+			/* this block is big enough (by far the most common case) */
+			*actL = L;
+		} else {
+			*actL = bankleft;
+		}
+	}
+
+	return p;
+}
+
+GLOBALVAR blnr InterruptButton = falseblnr;
+
+GLOBALPROC SetInterruptButton(blnr v)
+{
+	if (InterruptButton != v) {
+		InterruptButton = v;
+		VIAorSCCinterruptChngNtfy();
+	}
+}
+
+LOCALVAR ui3b CurIPL = 0;
+
+GLOBALPROC VIAorSCCinterruptChngNtfy(void)
+{
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+	ui3b NewIPL;
+
+	if (InterruptButton) {
+		NewIPL = 7;
+	} else if (SCCInterruptRequest) {
+		NewIPL = 4;
+	} else if (VIA2_InterruptRequest) {
+		NewIPL = 2;
+	} else if (VIA1_InterruptRequest) {
+		NewIPL = 1;
+	} else {
+		NewIPL = 0;
+	}
+#else
+	ui3b VIAandNotSCC = VIA1_InterruptRequest
+		& ~ SCCInterruptRequest;
+	ui3b NewIPL = VIAandNotSCC
+		| (SCCInterruptRequest << 1)
+		| (InterruptButton << 2);
+#endif
+	if (NewIPL != CurIPL) {
+		CurIPL = NewIPL;
+		m68k_IPLchangeNtfy();
+	}
+}
+
+GLOBALFUNC blnr AddrSpac_Init(void)
+{
+	int i;
+
+	for (i = 0; i < kNumWires; i++) {
+		Wires[i] = 1;
+	}
+
+	MINEM68K_Init(
+		&CurIPL);
+	return trueblnr;
+}
+
+GLOBALPROC Memory_Reset(void)
+{
+	MemOverlay = 1;
+	SetUpMemBanks();
+}
+
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+EXPORTPROC PowerOff_ChangeNtfy(void);
+GLOBALPROC PowerOff_ChangeNtfy(void)
+{
+	if (! VIA2_iB2) {
+		ForceMacOff = trueblnr;
+	}
+}
+#endif
+
+/* user event queue utilities */
+
+#if HaveMasterMyEvtQLock
+GLOBALVAR ui4r MasterMyEvtQLock = 0;
+	/*
+		Takes a few ticks to process button event because
+		of debounce code of Mac. So have this mechanism
+		to prevent processing further events meanwhile.
+	*/
+#endif
+
+GLOBALFUNC blnr FindKeyEvent(int *VirtualKey, blnr *KeyDown)
+{
+	MyEvtQEl *p;
+
+	if (
+#if HaveMasterMyEvtQLock
+		(0 == MasterMyEvtQLock) &&
+#endif
+		(nullpr != (p = MyEvtQOutP())))
+	{
+		if (MyEvtQElKindKey == p->kind) {
+			*VirtualKey = p->u.press.key;
+			*KeyDown = p->u.press.down;
+			MyEvtQOutDone();
+			return trueblnr;
+		}
+	}
+
+	return falseblnr;
+}
+
+/* task management */
+
+#ifdef _VIA_Debug
+#include <stdio.h>
+#endif
+
+GLOBALVAR uimr ICTactive;
+GLOBALVAR iCountt ICTwhen[kNumICTs];
+
+GLOBALPROC ICT_Zap(void)
+{
+	ICTactive = 0;
+}
+
+LOCALPROC InsertICT(int taskid, iCountt when)
+{
+	ICTwhen[taskid] = when;
+	ICTactive |= (1 << taskid);
+}
+
+GLOBALVAR iCountt NextiCount = 0;
+
+GLOBALFUNC iCountt GetCuriCount(void)
+{
+	return NextiCount - GetCyclesRemaining();
+}
+
+GLOBALPROC ICT_add(int taskid, ui5b n)
+{
+	/* n must be > 0 */
+	si5r x = GetCyclesRemaining();
+	ui5b when = NextiCount - x + n;
+
+#ifdef _VIA_Debug
+	fprintf(stderr, "ICT_add: %d, %d, %d\n", when, taskid, n);
+#endif
+	InsertICT(taskid, when);
+
+	if (x > (si5r)n) {
+		SetCyclesRemaining(n);
+		NextiCount = when;
+	}
+}
--- /dev/null
+++ b/src/GLOBGLUE.h
@@ -1,0 +1,276 @@
+/*
+	GLOBGLUE.h
+
+	Copyright (C) 2003 Bernd Schmidt, Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef GLOBGLUE_H
+#error "header already included"
+#else
+#define GLOBGLUE_H
+#endif
+
+
+#define kEmMd_Twig43      0
+#define kEmMd_Twiggy      1
+#define kEmMd_128K        2
+#define kEmMd_512Ke       3
+#define kEmMd_Plus        4
+#define kEmMd_SE          5
+#define kEmMd_SEFDHD      6
+#define kEmMd_Classic     7
+#define kEmMd_PB100       8
+#define kEmMd_II          9
+#define kEmMd_IIx        10
+
+#define RAMSafetyMarginFudge 4
+
+#define kRAM_Size (kRAMa_Size + kRAMb_Size)
+EXPORTVAR(ui3p, RAM)
+	/*
+		allocated by MYOSGLUE to be at least
+			kRAM_Size + RAMSafetyMarginFudge
+		bytes. Because of shortcuts taken in GLOBGLUE.c, it is in theory
+		possible for the emulator to write up to 3 bytes past kRAM_Size.
+	*/
+
+#if EmVidCard
+EXPORTVAR(ui3p, VidROM)
+#endif
+
+#if IncludeVidMem
+EXPORTVAR(ui3p, VidMem)
+#endif
+
+EXPORTPROC MemOverlay_ChangeNtfy(void);
+
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+EXPORTPROC Addr32_ChangeNtfy(void);
+#endif
+
+/*
+	representation of pointer into memory of emulated computer.
+*/
+typedef ui5b CPTR;
+
+/*
+	mapping of address space to real memory
+*/
+
+EXPORTFUNC ui3p get_real_address0(ui5b L, blnr WritableMem, CPTR addr,
+	ui5b *actL);
+
+/*
+	memory access routines that can use when have address
+	that is known to be in RAM (and that is in the first
+	copy of the ram, not the duplicates, i.e. < kRAM_Size).
+*/
+
+#ifndef ln2mtb
+
+#define get_ram_byte(addr) do_get_mem_byte((addr) + RAM)
+#define get_ram_word(addr) do_get_mem_word((addr) + RAM)
+#define get_ram_long(addr) do_get_mem_long((addr) + RAM)
+
+#define put_ram_byte(addr, b) do_put_mem_byte((addr) + RAM, (b))
+#define put_ram_word(addr, w) do_put_mem_word((addr) + RAM, (w))
+#define put_ram_long(addr, l) do_put_mem_long((addr) + RAM, (l))
+
+#else
+
+#define get_ram_byte get_vm_byte
+#define get_ram_word get_vm_word
+#define get_ram_long get_vm_long
+
+#define put_ram_byte put_vm_byte
+#define put_ram_word put_vm_word
+#define put_ram_long put_vm_long
+
+#endif
+
+#define get_ram_address(addr) ((addr) + RAM)
+
+/*
+	accessing addresses that don't map to
+	real memory, i.e. memory mapped devices
+*/
+
+EXPORTFUNC blnr AddrSpac_Init(void);
+
+
+#define ui5r_FromSByte(x) ((ui5r)(si5r)(si3b)(ui3b)(x))
+#define ui5r_FromSWord(x) ((ui5r)(si5r)(si4b)(ui4b)(x))
+#define ui5r_FromSLong(x) ((ui5r)(si5r)(si5b)(ui5b)(x))
+
+#define ui5r_FromUByte(x) ((ui5r)(ui3b)(x))
+#define ui5r_FromUWord(x) ((ui5r)(ui4b)(x))
+#define ui5r_FromULong(x) ((ui5r)(ui5b)(x))
+
+
+#if WantDisasm
+EXPORTPROC dbglog_StartLine(void);
+#else
+#define dbglog_StartLine()
+#endif
+
+#if dbglog_HAVE
+EXPORTPROC dbglog_WriteMemArrow(blnr WriteMem);
+
+EXPORTPROC dbglog_WriteNote(char *s);
+EXPORTPROC dbglog_WriteSetBool(char *s, blnr v);
+EXPORTPROC dbglog_AddrAccess(char *s,
+	ui5r Data, blnr WriteMem, ui5r addr);
+EXPORTPROC dbglog_Access(char *s, ui5r Data, blnr WriteMem);
+#endif
+
+#if ! WantAbnormalReports
+#define ReportAbnormalID(id, s)
+#else
+#if dbglog_HAVE
+#define ReportAbnormalID DoReportAbnormalID
+#else
+#define ReportAbnormalID(id, s) DoReportAbnormalID(id)
+#endif
+EXPORTPROC DoReportAbnormalID(ui4r id
+#if dbglog_HAVE
+	, char *s
+#endif
+	);
+#endif /* WantAbnormalReports */
+
+EXPORTPROC VIAorSCCinterruptChngNtfy(void);
+
+EXPORTVAR(blnr, InterruptButton)
+EXPORTPROC SetInterruptButton(blnr v);
+
+enum {
+	kICT_SubTick,
+#if EmClassicKbrd
+	kICT_Kybd_ReceiveCommand,
+	kICT_Kybd_ReceiveEndCommand,
+#endif
+#if EmADB
+	kICT_ADB_NewState,
+#endif
+#if EmPMU
+	kICT_PMU_Task,
+#endif
+	kICT_VIA1_Timer1Check,
+	kICT_VIA1_Timer2Check,
+#if EmVIA2
+	kICT_VIA2_Timer1Check,
+	kICT_VIA2_Timer2Check,
+#endif
+
+	kNumICTs
+};
+
+EXPORTPROC ICT_add(int taskid, ui5b n);
+
+#define iCountt ui5b
+EXPORTFUNC iCountt GetCuriCount(void);
+EXPORTPROC ICT_Zap(void);
+
+EXPORTVAR(uimr, ICTactive)
+EXPORTVAR(iCountt, ICTwhen[kNumICTs])
+EXPORTVAR(iCountt, NextiCount)
+
+EXPORTVAR(ui3b, Wires[kNumWires])
+
+#define kLn2CycleScale 6
+#define kCycleScale (1 << kLn2CycleScale)
+
+#if WantCycByPriOp
+#define RdAvgXtraCyc /* 0 */ (kCycleScale + kCycleScale / 4)
+#define WrAvgXtraCyc /* 0 */ (kCycleScale + kCycleScale / 4)
+#endif
+
+#define kNumSubTicks 16
+
+
+#define HaveMasterMyEvtQLock EmClassicKbrd
+#if HaveMasterMyEvtQLock
+EXPORTVAR(ui4r, MasterMyEvtQLock)
+#endif
+EXPORTFUNC blnr FindKeyEvent(int *VirtualKey, blnr *KeyDown);
+
+
+/* minivmac extensions */
+
+#define ExtnDat_checkval 0
+#define ExtnDat_extension 2
+#define ExtnDat_commnd 4
+#define ExtnDat_result 6
+#define ExtnDat_params 8
+
+#define kCmndVersion 0
+#define ExtnDat_version 8
+
+enum {
+	kExtnFindExtn, /* must be first */
+
+	kExtnDisk,
+	kExtnSony,
+#if EmVidCard
+	kExtnVideo,
+#endif
+#if IncludeExtnPbufs
+	kExtnParamBuffers,
+#endif
+#if IncludeExtnHostTextClipExchange
+	kExtnHostTextClipExchange,
+#endif
+
+	kNumExtns
+};
+
+#define kcom_callcheck 0x5B17
+
+EXPORTVAR(ui5r, my_disk_icon_addr)
+
+EXPORTPROC Memory_Reset(void);
+
+EXPORTPROC Extn_Reset(void);
+
+EXPORTPROC customreset(void);
+
+struct ATTer {
+	struct ATTer *Next;
+	ui5r cmpmask;
+	ui5r cmpvalu;
+	ui5r Access;
+	ui5r usemask; /* Should be one less than a power of two. */
+	ui3p usebase;
+	ui3r MMDV;
+	ui3r Ntfy;
+	ui4r Pad0;
+	ui5r Pad1; /* make 32 byte structure, on 32 bit systems */
+};
+typedef struct ATTer ATTer;
+typedef ATTer *ATTep;
+
+#define kATTA_readreadybit 0
+#define kATTA_writereadybit 1
+#define kATTA_mmdvbit 2
+#define kATTA_ntfybit 3
+
+#define kATTA_readwritereadymask \
+	((1 << kATTA_readreadybit) | (1 << kATTA_writereadybit))
+#define kATTA_readreadymask (1 << kATTA_readreadybit)
+#define kATTA_writereadymask (1 << kATTA_writereadybit)
+#define kATTA_mmdvmask (1 << kATTA_mmdvbit)
+#define kATTA_ntfymask (1 << kATTA_ntfybit)
+
+EXPORTFUNC ui5b MMDV_Access(ATTep p, ui5b Data,
+	blnr WriteMem, blnr ByteSize, CPTR addr);
+EXPORTFUNC blnr MemAccessNtfy(ATTep pT);
--- /dev/null
+++ b/src/HPMCHACK.h
@@ -1,0 +1,261 @@
+/*
+	HPMCHACK.c
+
+	Copyright (C) 2016 Steve Chamberlin, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	HaPpy MaCintosh Hack
+
+	Patch the ROM for alternatives to the
+	Happy Macintosh icon displayed on boot
+	when a disk is inserted.
+*/
+
+#define kAHM_aside 0
+#define kAHM_cheese 1
+#define kAHM_evil 2
+#define kAHM_horror 3
+#define kAHM_lady_mac 4
+#define kAHM_moustache 5
+#define kAHM_nerdy 6
+#define kAHM_pirate 7
+#define kAHM_sleepy 8
+#define kAHM_sly 9
+#define kAHM_sunglasses 10
+#define kAHM_surprise 11
+#define kAHM_tongue 12
+#define kAHM_yuck 13
+#define kAHM_zombie 14
+
+LOCALVAR const ui3b my_HappyMac_icon[] = {
+#if CurAltHappyMac == kAHM_aside
+	0x00, 0x00,
+	0x39, 0x38,
+	0x21, 0x20,
+	0x01, 0x00,
+	0x01, 0x00,
+	0x03, 0x00,
+	0x00, 0x00,
+	0x00, 0x00,
+	0x07, 0x80,
+	0x00, 0x00
+#endif
+#if CurAltHappyMac == kAHM_cheese
+	0x10, 0x10,
+	0x28, 0x28,
+	0x00, 0x00,
+	0x00, 0x00,
+	0x3F, 0xF8,
+	0x20, 0x08,
+	0x20, 0x08,
+	0x20, 0x08,
+	0x10, 0x10,
+	0x0F, 0xE0,
+#endif
+#if CurAltHappyMac == kAHM_evil
+	0x00, 0x00,
+	0x10, 0x10,
+	0x08, 0x20,
+	0x0C, 0x60,
+	0x00, 0x00,
+	0x20, 0x08,
+	0x20, 0x08,
+	0x1F, 0xF0,
+	0x00, 0x00,
+	0x00, 0x00
+#endif
+#if CurAltHappyMac == kAHM_horror
+	0x38, 0x38,
+	0x44, 0x44,
+	0x44, 0x44,
+	0x44, 0x44,
+	0x38, 0x38,
+	0x03, 0x80,
+	0x03, 0x80,
+	0x03, 0x80,
+	0x03, 0x80,
+	0x03, 0x80
+#endif
+#if CurAltHappyMac == kAHM_lady_mac
+	0x38, 0x38,
+	0x45, 0x44,
+	0x55, 0x54,
+	0x45, 0x44,
+	0x39, 0x38,
+	0x03, 0x00,
+	0x00, 0x00,
+	0x00, 0x00,
+	0x07, 0x80,
+	0x03, 0x00
+#endif
+#if CurAltHappyMac == kAHM_moustache
+	0x00, 0x00,
+	0x11, 0x10,
+	0x11, 0x10,
+	0x01, 0x00,
+	0x01, 0x00,
+	0x03, 0x00,
+	0x1F, 0xE0,
+	0x00, 0x00,
+	0x08, 0x40,
+	0x07, 0x80
+#endif
+#if CurAltHappyMac == kAHM_nerdy
+	0x38, 0x38,
+	0x45, 0x45,
+	0xD7, 0xD6,
+	0x45, 0x44,
+	0x39, 0x38,
+	0x03, 0x00,
+	0x00, 0x00,
+	0x00, 0x00,
+	0x0F, 0xC0,
+	0x00, 0x00
+#endif
+#if CurAltHappyMac == kAHM_pirate
+	0x00, 0x81,
+	0x00, 0x7E,
+	0x11, 0x7E,
+	0x11, 0x3C,
+	0x01, 0x3C,
+	0x01, 0x18,
+	0x03, 0x00,
+	0x00, 0x00,
+	0x08, 0x40,
+	0x07, 0x80
+#endif
+#if CurAltHappyMac == kAHM_sleepy
+	0x00, 0x00,
+	0x1C, 0x70,
+	0x22, 0x88,
+	0x00, 0x00,
+	0x1C, 0x70,
+	0x08, 0x20,
+	0x00, 0x00,
+	0x00, 0x00,
+	0x03, 0x80,
+	0x00, 0x00
+#endif
+#if CurAltHappyMac == kAHM_sly
+	0x00, 0x00,
+	0x08, 0x20,
+	0x14, 0x50,
+	0x00, 0x00,
+	0x00, 0x00,
+	0x20, 0x08,
+	0x3F, 0xF8,
+	0x00, 0x00,
+	0x00, 0x00,
+	0x00, 0x00
+#endif
+#if CurAltHappyMac == kAHM_sunglasses
+	0x00, 0x00,
+	0xFF, 0xFE,
+	0x7D, 0x7C,
+	0x7D, 0x7C,
+	0x39, 0x38,
+	0x03, 0x00,
+	0x00, 0x00,
+	0x1F, 0xF0,
+	0x00, 0x00,
+	0x00, 0x00
+#endif
+#if CurAltHappyMac == kAHM_surprise
+	0x1C, 0x70,
+	0x22, 0x88,
+	0x41, 0x04,
+	0x49, 0x24,
+	0x41, 0x04,
+	0x22, 0x88,
+	0x1C, 0x70,
+	0x01, 0x00,
+	0x03, 0x80,
+	0x03, 0x80
+#endif
+#if CurAltHappyMac == kAHM_tongue
+	0x00, 0x00,
+	0x1E, 0x78,
+	0x00, 0x00,
+	0x00, 0x00,
+	0x20, 0x04,
+	0x3F, 0xFC,
+	0x05, 0x40,
+	0x05, 0x40,
+	0x04, 0x40,
+	0x03, 0x80
+#endif
+#if CurAltHappyMac == kAHM_yuck
+	0x00, 0x00,
+	0x18, 0x30,
+	0x04, 0x40,
+	0x02, 0x80,
+	0x00, 0x00,
+	0x00, 0x00,
+	0x1F, 0xF0,
+	0x15, 0x50,
+	0x04, 0x40,
+	0x03, 0x80
+#endif
+#if CurAltHappyMac == kAHM_zombie
+	0x70, 0x7C,
+	0x88, 0x82,
+	0x88, 0x8A,
+	0xA8, 0x8A,
+	0x70, 0x82,
+	0x00, 0x42,
+	0x00, 0x3C,
+	0x1E, 0x00,
+	0x3F, 0x00,
+	0x3F, 0x00
+#endif
+};
+
+#if CurEmMd <= kEmMd_Twig43
+#define HappyMacBase 0xA34
+#elif CurEmMd <= kEmMd_Twiggy
+#define HappyMacBase 0x8F4
+#elif CurEmMd <= kEmMd_128K
+#define HappyMacBase 0x8A0
+#elif CurEmMd <= kEmMd_Plus
+#define HappyMacBase 0xFD2
+#elif CurEmMd <= kEmMd_Classic
+#define HappyMacBase 0x125C
+#elif CurEmMd <= kEmMd_PB100
+#define HappyMacBase 0x2BB0
+#elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+#define HappyMacBase 0x1948
+#endif
+
+LOCALPROC PatchHappyMac(void)
+{
+#if (CurEmMd == kEmMd_PB100) \
+	|| (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+
+	int i;
+	ui3b *dst = HappyMacBase + ROM + 0x18;
+	ui3b *src = (ui3b *)my_HappyMac_icon;
+
+	for (i = 10; --i >= 0; ) {
+		++dst;
+		*dst++ = *src++;
+		*dst++ = *src++;
+		++dst;
+	}
+
+#else
+	MyMoveBytes((anyp)my_HappyMac_icon,
+		(anyp)(HappyMacBase + ROM),
+		sizeof(my_HappyMac_icon));
+#endif
+}
--- /dev/null
+++ b/src/ICONAPPM.r
@@ -1,0 +1,192 @@
+/*
+	AppIcon.r
+
+	Copyright (C) 2003 Philip Cummins, Richard F. Bannister,
+		Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#if SmallIconAPIAvail
+resource 'ics#' (AppIconId, purgeable) {
+	{ /* array: 2 elements */
+		/* [1] */
+		$"0000 1FF8 2004 2FF4 2814 2A94 2B14 2A14"
+		$"2814 2FF4 2004 2004 20F4 2004 1FF8 1FF8",
+		/* [2] */
+		$"0000 1FF8 3FFC 3FFC 3FFC 3FFC 3FFC 3FFC"
+		$"3FFC 3FFC 3FFC 3FFC 3FFC 3FFC 1FF8 1FF8"
+	}
+};
+#endif
+
+#if ColorIconAPIAvail
+resource 'ics8' (AppIconId, purgeable) {
+	$"0000 0000 0000 0000 0000 0000 0000 0000"
+	$"0000 00FF FFFF FFFF FFFF FFFF FF00 0000"
+	$"0000 FF2B 2B2B 2B2B 2B2B 2B2B 2BFF 0000"
+	$"0000 FF2B FCFC FCFC FCFC FCFC 2BFF 0000"
+	$"0000 FF2B FC2A 2A2A 2A2A 2A00 2BFF 0000"
+	$"0000 FF2B FC2A EC2A EC2A 2A00 2BFF 0000"
+	$"0000 FF2B FC2A ECEC 2A2A 2A00 2BFF 0000"
+	$"0000 FF2B FC2A EC2A 2A2A 2A00 2BFF 0000"
+	$"0000 FF2B FC2A 2A2A 2A2A 2A00 2BFF 0000"
+	$"0000 FF2B FA00 0000 0000 0000 2BFF 0000"
+	$"0000 FF2B 2B2B 2B2B 2B2B 2B2B 2BFF 0000"
+	$"0000 FF2B E32B 2B2B 2B2B 2B2B 2BFF 0000"
+	$"0000 FF2B D82B 2B2B FFFF FFFF 2BFF 0000"
+	$"0000 FF2B 2B2B 2B2B 2B2B 2B2B 2BFF 0000"
+	$"0000 00FD FDFD FDFD FDFF FFFF FF00 0000"
+	$"0000 00FF FFFF FFFF FFFF FFFF FF"
+};
+#endif
+
+#if ColorIconAPIAvail
+resource 'ics4' (AppIconId, purgeable) {
+	$"0000 0000 0000 0000 000F FFFF FFFF F000"
+	$"00FC CCCC CCCC CF00 00FC EEEE EEEE CF00"
+	$"00FC ED0D 0D0C CF00 00FC E060 60D0 CF00"
+	$"00FC ED66 0D0C CF00 00FC E060 D0D0 CF00"
+	$"00FC ED0D 0D0C CF00 00FC D0C0 C0C0 CF00"
+	$"00FC CCCC CCCC CF00 00FC 8CCC CCCC CF00"
+	$"00FC 3CCC FFFF CF00 00FC CCCC CCCC CF00"
+	$"000F FFFF FFFF F000 000F FFFF FFFF F0"
+};
+#endif
+
+resource 'ICN#' (AppIconId, purgeable) {
+	{ /* array: 2 elements */
+		/* [1] */
+		$"0000 0000 07FF FFE0 0800 0010 0800 0010"
+		$"08FF FF10 0900 0090 0918 1890 0918 3090"
+		$"0918 6090 0918 C090 0919 8090 091B 0090"
+		$"091E 0090 091C 0090 0918 0090 0910 0090"
+		$"0900 0090 08FF FF10 0800 0010 0800 0010"
+		$"0800 0010 0800 0010 0800 FF10 0800 0010"
+		$"0800 0010 0800 0010 0800 0010 07FF FFE0"
+		$"0400 0020 0400 0020 0400 0020 07FF FFE0",
+		/* [2] */
+		$"0000 0000 07FF FFE0 0FFF FFF0 0FFF FFF0"
+		$"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0"
+		$"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0"
+		$"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0"
+		$"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0"
+		$"0FFF FFF0 0FFF FFF0 0FFF FFF0 0FFF FFF0"
+		$"0FFF FFF0 0FFF FFF0 0FFF FFF0 07FF FFE0"
+		$"07FF FFE0 07FF FFE0 07FF FFE0 07FF FFE0"
+	}
+};
+
+#if ColorIconAPIAvail
+resource 'icl8' (AppIconId, purgeable) {
+	$"0000 0000 0000 0000 0000 0000 0000 0000"
+	$"0000 0000 0000 0000 0000 0000 0000 0000"
+	$"0000 0000 00FF FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFFF FFFF FFFF FF00 0000 0000"
+	$"0000 0000 FF2B 2B2B 2B2B 2B2B 2B2B 2B2B"
+	$"2B2B 2B2B 2B2B 2B2B 2B2B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2B2B 2B2B 2B2B 2B2B 2B2B"
+	$"2B2B 2B2B 2B2B 2B2B 2B2B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2B2B FCFC FCFC FCFC FCFC"
+	$"FCFC FCFC FCFC FCFC 2B2B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2BFC 2A2A 2A2A 2A2A 2A2A"
+	$"2A2A 2A2A 2A2A 2A2A 002B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2BFC 2A2A 2AEC EC2A 2A2A"
+	$"2A2A 2AEC EC2A 2A2A 002B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2BFC 2A2A 2AEC EC2A 2A2A"
+	$"2A2A ECEC 2A2A 2A2A 002B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2BFC 2A2A 2AEC EC2A 2A2A"
+	$"2AEC EC2A 2A2A 2A2A 002B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2BFC 2A2A 2AEC EC2A 2A2A"
+	$"ECEC 2A2A 2A2A 2A2A 002B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2BFC 2A2A 2AEC EC2A 2AEC"
+	$"EC2A 2A2A 2A2A 2A2A 002B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2BFC 2A2A 2AEC EC2A ECEC"
+	$"2A2A 2A2A 2A2A 2A2A 002B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2BFC 2A2A 2AEC ECEC EC2A"
+	$"2A2A 2A2A 2A2A 2A2A 002B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2BFC 2A2A 2AEC ECEC 2A2A"
+	$"2A2A 2A2A 2A2A 2A2A 002B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2BFC 2A2A 2AEC EC2A 2A2A"
+	$"2A2A 2A2A 2A2A 2A2A 002B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2BFC 2A2A 2AEC 2A2A 2A2A"
+	$"2A2A 2A2A 2A2A 2A2A 002B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2BFC 2A2A 2A2A 2A2A 2A2A"
+	$"2A2A 2A2A 2A2A 2A2A 002B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2B2B 0000 0000 0000 0000"
+	$"0000 0000 0000 0000 2B2B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2B2B 2B2B 2B2B 2B2B 2B2B"
+	$"2B2B 2B2B 2B2B 2B2B 2B2B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2B2B 2B2B 2B2B 2B2B 2B2B"
+	$"2B2B 2B2B 2B2B 2B2B 2B2B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2B2B 2B2B 2B2B 2B2B 2B2B"
+	$"2B2B 2B2B 2B2B 2B2B 2B2B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2B2B 2B2B 2B2B 2B2B 2B2B"
+	$"2B2B 2B2B 2B2B 2B2B 2B2B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2B2B 2B2B 2B2B 2B2B 2B2B"
+	$"FFFF FFFF FFFF FFFF 2B2B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2B2B 2B2B 2B2B 2B2B 2B2B"
+	$"0000 0000 0000 0000 2B2B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2BE3 E32B 2B2B 2B2B 2B2B"
+	$"2B2B 2B2B 2B2B 2B2B 2B2B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2BD8 D82B 2B2B 2B2B 2B2B"
+	$"2B2B 2B2B 2B2B 2B2B 2B2B 2BFF 0000 0000"
+	$"0000 0000 FF2B 2B2B 2B2B 2B2B 2B2B 2B2B"
+	$"2B2B 2B2B 2B2B 2B2B 2B2B 2BFF 0000 0000"
+	$"0000 0000 00FF FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFFF FFFF FFFF FF00 0000 0000"
+	$"0000 0000 00FF FBFB FBFB FBFB FCFC FCFC"
+	$"FCFD FDFD FDFD FDFD FDFD FF00 0000 0000"
+	$"0000 0000 00FF FAFA FAFA FAFA FAFA FBFB"
+	$"FCFC FCFC FDFD FDFD FDFD FF00 0000 0000"
+	$"0000 0000 00FF F9F9 F9F9 F9F9 F9F9 FAFA"
+	$"FAFB FBFC FCFC FCFD FDFD FF00 0000 0000"
+	$"0000 0000 00FF FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFFF FFFF FFFF FF"
+};
+#endif
+
+#if ColorIconAPIAvail
+resource 'icl4' (AppIconId, purgeable) {
+	$"0000 0000 0000 0000 0000 0000 0000 0000"
+	$"0000 0FFF FFFF FFFF FFFF FFFF FFF0 0000"
+	$"0000 FCCC CCCC CCCC CCCC CCCC CCCF 0000"
+	$"0000 FCCC CCCC CCCC CCCC CCCC CCCF 0000"
+	$"0000 FCCC EEEE EEEE EEEE EEEE CCCF 0000"
+	$"0000 FCCE 0D0D 0D0D 0D0D 0D0D 0CCF 0000"
+	$"0000 FCCE D0D6 60D0 D0D6 60D0 CCCF 0000"
+	$"0000 FCCE 0D06 6D0D 0D66 0D0D 0CCF 0000"
+	$"0000 FCCE D0D6 60D0 D660 D0D0 CCCF 0000"
+	$"0000 FCCE 0D06 6D0D 660D 0D0D 0CCF 0000"
+	$"0000 FCCE D0D6 60D6 60D0 D0D0 CCCF 0000"
+	$"0000 FCCE 0D06 6D66 0D0D 0D0D 0CCF 0000"
+	$"0000 FCCE D0D6 6660 D0D0 D0D0 CCCF 0000"
+	$"0000 FCCE 0D06 660D 0D0D 0D0D 0CCF 0000"
+	$"0000 FCCE D0D6 60D0 D0D0 D0D0 CCCF 0000"
+	$"0000 FCCE 0D06 0D0D 0D0D 0D0D 0CCF 0000"
+	$"0000 FCCE D0D0 D0D0 D0D0 D0D0 CCCF 0000"
+	$"0000 FCCC 0C0C 0C0C 0C0C 0C0C 0CCF 0000"
+	$"0000 FCCC CCCC CCCC CCCC CCCC CCCF 0000"
+	$"0000 FCCC CCCC CCCC CCCC CCCC CCCF 0000"
+	$"0000 FCCC CCCC CCCC CCCC CCCC CCCF 0000"
+	$"0000 FCCC CCCC CCCC CCCC CCCC CCCF 0000"
+	$"0000 FCCC CCCC CCCC FFFF FFFF CCCF 0000"
+	$"0000 FCCC CCCC CCCC 0C0C 0C0C CCCF 0000"
+	$"0000 FCC8 8CCC CCCC CCCC CCCC CCCF 0000"
+	$"0000 FCC3 3CCC CCCC CCCC CCCC CCCF 0000"
+	$"0000 FCCC CCCC CCCC CCCC CCCC CCCF 0000"
+	$"0000 0FFF FFFF FFFF FFFF FFFF FFF0 0000"
+	$"0000 0FEE EEEE EEEE EEFF FFFF FFF0 0000"
+	$"0000 0FDD DDDD DDEE EEEE EEFF FFF0 0000"
+	$"0000 0FDD DDDD DDDD DEEE EEEE EEF0 0000"
+	$"0000 0FFF FFFF FFFF FFFF FFFF FFF0"
+};
+#endif
binary files /dev/null b/src/ICONAPPO.icns differ
binary files /dev/null b/src/ICONAPPW.ico differ
--- /dev/null
+++ b/src/ICONDSKM.r
@@ -1,0 +1,192 @@
+/*
+	DskIcon.r
+
+	Copyright (C) 2003 Philip Cummins, Richard F. Bannister,
+		Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#if SmallIconAPIAvail
+resource 'ics#' (DskIconId, purgeable) {
+	{ /* array: 2 elements */
+		/* [1] */
+		$"7FE0 4030 4028 403C 4004 4004 4004 4FC4"
+		$"4AA4 4BA4 4824 4BA4 4AA4 4FE4 4004 7FFC",
+		/* [2] */
+		$"7FE0 7FF0 7FF8 7FFC 7FFC 7FFC 7FFC 7FFC"
+		$"7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC"
+	}
+};
+#endif
+
+#if ColorIconAPIAvail
+resource 'ics8' (DskIconId, purgeable) {
+	$"00FF FFFF FFFF FFFF FFFF FF00 0000 0000"
+	$"00FF 0000 0000 0000 0000 FFFF 0000 0000"
+	$"00FF 0000 0000 0000 0000 FF2A FF00 0000"
+	$"00FF 0000 0000 0000 0000 FFFF FFFF 0000"
+	$"00FF 0000 0000 0000 0000 00FA FAFF 0000"
+	$"00FF 0000 0000 0000 0000 0000 00FF 0000"
+	$"00FF 0000 0000 0000 0000 0000 00FF 0000"
+	$"00FF 0000 E0E0 E0E0 E0E0 0000 00FF 0000"
+	$"00FF 0000 E054 AB2A AB54 E000 00FF 0000"
+	$"00FF 0000 E054 ABAB AB54 E000 00FF 0000"
+	$"00FF 0000 E054 5454 5454 E000 00FF 0000"
+	$"00FF 0000 E054 ABAB AB54 E000 00FF 0000"
+	$"00FF 0000 E054 AB2A AB54 E000 00FF 0000"
+	$"00FF 0000 E0FF E0E0 E0E0 E000 00FF 0000"
+	$"00FF 0000 0000 0000 0000 0000 00FF 0000"
+	$"00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+};
+#endif
+
+#if ColorIconAPIAvail
+resource 'ics4' (DskIconId, purgeable) {
+	$"0FFF FFFF FFF0 0000 0F00 0000 00FF 0000"
+	$"0F00 0000 00FC F000 0F00 0000 00FF FF00"
+	$"0F00 0000 000D DF00 0F00 0000 0000 0F00"
+	$"0F00 0000 0000 0F00 0F00 FFFF FF00 0F00"
+	$"0F00 FCE0 ECF0 0F00 0F00 FCEE ECF0 0F00"
+	$"0F00 FCCC CCF0 0F00 0F00 FCEE ECF0 0F00"
+	$"0F00 FCE0 ECF0 0F00 0F00 FFFF FFF0 0F00"
+	$"0F00 0000 0000 0F00 0FFF FFFF FFFF FF"
+};
+#endif
+
+resource 'ICN#' (DskIconId, purgeable) {
+	{ /* array: 2 elements */
+		/* [1] */
+		$"1FFF F800 1000 0C00 1000 0A00 1000 0900"
+		$"1000 0880 1000 0840 1000 0820 1000 0FF0"
+		$"1000 0010 1000 0010 1000 0010 1000 0010"
+		$"1000 0010 10FF FC10 1120 9210 1121 5110"
+		$"1121 5110 1121 5110 1120 9110 111F E110"
+		$"1100 0110 1100 0110 111F F110 1120 0910"
+		$"1120 0910 1122 8910 1123 0910 1122 0910"
+		$"1120 0910 10FF FE10 1000 0010 1FFF FFF0",
+		/* [2] */
+		$"1FFF F800 1FFF FC00 1FFF FE00 1FFF FF00"
+		$"1FFF FF80 1FFF FFC0 1FFF FFE0 1FFF FFF0"
+		$"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+		$"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+		$"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+		$"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+		$"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+		$"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+	}
+};
+
+#if ColorIconAPIAvail
+resource 'icl8' (DskIconId, purgeable) {
+	$"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FF00 0000 0000 0000 0000 0000"
+	$"0000 00FF 0000 0000 0000 0000 0000 0000"
+	$"0000 0000 FFFF 0000 0000 0000 0000 0000"
+	$"0000 00FF 0000 0000 0000 0000 0000 0000"
+	$"0000 0000 FF2A FF00 0000 0000 0000 0000"
+	$"0000 00FF 0000 0000 0000 0000 0000 0000"
+	$"0000 0000 FF2A 2AFF 0000 0000 0000 0000"
+	$"0000 00FF 0000 0000 0000 0000 0000 0000"
+	$"0000 0000 FF2A 2A2A FF00 0000 0000 0000"
+	$"0000 00FF 0000 0000 0000 0000 0000 0000"
+	$"0000 0000 FF2A 2A2A 2AFF 0000 0000 0000"
+	$"0000 00FF 0000 0000 0000 0000 0000 0000"
+	$"0000 0000 FF2A 2A2A 2A2A FF00 0000 0000"
+	$"0000 00FF 0000 0000 0000 0000 0000 0000"
+	$"0000 0000 FFFF FFFF FFFF FFFF 0000 0000"
+	$"0000 00FF 0000 0000 0000 0000 0000 0000"
+	$"0000 0000 00FA FAFA FAFA FAFF 0000 0000"
+	$"0000 00FF 0000 0000 0000 0000 0000 0000"
+	$"0000 0000 0000 0000 0000 00FF 0000 0000"
+	$"0000 00FF 0000 0000 0000 0000 0000 0000"
+	$"0000 0000 0000 0000 0000 00FF 0000 0000"
+	$"0000 00FF 0000 0000 0000 0000 0000 0000"
+	$"0000 0000 0000 0000 0000 00FF 0000 0000"
+	$"0000 00FF 0000 0000 0000 0000 0000 0000"
+	$"0000 0000 0000 0000 0000 00FF 0000 0000"
+	$"0000 00FF 0000 00F5 E0FF E0E0 E0E0 E0E0"
+	$"E0E0 E0E0 E0E0 0000 0000 00FF 0000 0000"
+	$"0000 00FF 0000 00E0 5454 AB2A 2A2A 2AFA"
+	$"FFFA 2AAB 5454 E000 0000 00FF 0000 0000"
+	$"0000 00FF 0000 00E0 5454 AB2A 2A2A 2AFF"
+	$"00FF 2AAB 5454 54E0 0000 00FF 0000 0000"
+	$"0000 00FF 0000 00E0 5454 AB2A 2A2A 2AFF"
+	$"00FF 2AAB 5454 54E0 0000 00FF 0000 0000"
+	$"0000 00FF 0000 00E0 5454 AB2A 2A2A 2AFF"
+	$"00FF 2AAB 5454 54E0 0000 00FF 0000 0000"
+	$"0000 00FF 0000 00E0 5454 AB2A 2A2A 2AFA"
+	$"FFFA 2AAB 5454 54E0 0000 00FF 0000 0000"
+	$"0000 00FF 0000 00E0 5454 54AB ABAB ABAB"
+	$"ABAB AB54 5454 54E0 0000 00FF 0000 0000"
+	$"0000 00FF 0000 00E0 5454 5454 5454 5454"
+	$"5454 5454 5454 54E0 0000 00FF 0000 0000"
+	$"0000 00FF 0000 00E0 5454 5454 5454 5454"
+	$"5454 5454 5454 54E0 0000 00FF 0000 0000"
+	$"0000 00FF 0000 00E0 5454 54AB ABAB ABAB"
+	$"ABAB ABAB 5454 54E0 0000 00FF 0000 0000"
+	$"0000 00FF 0000 00E0 5454 AB2A 2A2A 2A2A"
+	$"2A2A 2A2A AB54 54E0 0000 00FF 0000 0000"
+	$"0000 00FF 0000 00E0 5454 AB2A 2A2A 2A2A"
+	$"2A2A 2A2A AB54 54E0 0000 00FF 0000 0000"
+	$"0000 00FF 0000 00E0 5454 AB2A 2A2A EC2A"
+	$"EC2A 2A2A AB54 54E0 0000 00FF 0000 0000"
+	$"0000 00FF 0000 00E0 5454 AB2A 2A2A ECEC"
+	$"2A2A 2A2A AB54 54E0 0000 00FF 0000 0000"
+	$"0000 00FF 0000 00E0 5454 AB2A 2A2A EC2A"
+	$"2A2A 2A2A AB54 54E0 0000 00FF 0000 0000"
+	$"0000 00FF 0000 00E0 5454 AB2A 2A2A 2A2A"
+	$"2A2A 2A2A AB54 54E0 0000 00FF 0000 0000"
+	$"0000 00FF 0000 00F5 FFFF E0E0 E0E0 E0E0"
+	$"E0E0 E0E0 FFE0 E0F5 0000 00FF 0000 0000"
+	$"0000 00FF 0000 0000 0000 0000 0000 0000"
+	$"0000 0000 0000 0000 0000 00FF 0000 0000"
+	$"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFFF FFFF FFFF FFFF"
+};
+#endif
+
+#if ColorIconAPIAvail
+resource 'icl4' (DskIconId, purgeable) {
+	$"000F FFFF FFFF FFFF FFFF F000 0000 0000"
+	$"000F 0000 0000 0000 0000 FF00 0000 0000"
+	$"000F 0000 0000 0000 0000 F0F0 0000 0000"
+	$"000F 0000 0000 0000 0000 FC0F 0000 0000"
+	$"000F 0000 0000 0000 0000 F0C0 F000 0000"
+	$"000F 0000 0000 0000 0000 FC0C 0F00 0000"
+	$"000F 0000 0000 0000 0000 F0C0 C0F0 0000"
+	$"000F 0000 0000 0000 0000 FFFF FFFF 0000"
+	$"000F 0000 0000 0000 0000 0DDD DDDF 0000"
+	$"000F 0000 0000 0000 0000 0000 000F 0000"
+	$"000F 0000 0000 0000 0000 0000 000F 0000"
+	$"000F 0000 0000 0000 0000 0000 000F 0000"
+	$"000F 0000 0000 0000 0000 0000 000F 0000"
+	$"000F 0000 FFFF FFFF FFFF FF00 000F 0000"
+	$"000F 000F CCEC 0C0D FD0E CCF0 000F 0000"
+	$"000F 000F CCE0 C0CF 0FCE CCCF 000F 0000"
+	$"000F 000F CCEC 0C0F 0F0E CCCF 000F 0000"
+	$"000F 000F CCE0 C0CF 0FCE CCCF 000F 0000"
+	$"000F 000F CCEC 0C0D FD0E CCCF 000F 0000"
+	$"000F 000F CCCE EEEE EEEC CCCF 000F 0000"
+	$"000F 000F CCCC CCCC CCCC CCCF 000F 0000"
+	$"000F 000F CCCC CCCC CCCC CCCF 000F 0000"
+	$"000F 000F CCCE EEEE EEEE CCCF 000F 0000"
+	$"000F 000F CCEC 0C0C 0C0C ECCF 000F 0000"
+	$"000F 000F CCE0 C0C0 C0C0 ECCF 000F 0000"
+	$"000F 000F CCEC 0C6C 6C0C ECCF 000F 0000"
+	$"000F 000F CCE0 C066 C0C0 ECCF 000F 0000"
+	$"000F 000F CCEC 0C6C 0C0C ECCF 000F 0000"
+	$"000F 000F CCE0 C0C0 C0C0 ECCF 000F 0000"
+	$"000F 0000 FFFF FFFF FFFF FFF0 000F 0000"
+	$"000F 0000 0000 0000 0000 0000 000F 0000"
+	$"000F FFFF FFFF FFFF FFFF FFFF FFFF"
+};
+#endif
binary files /dev/null b/src/ICONDSKO.icns differ
binary files /dev/null b/src/ICONDSKW.ico differ
--- /dev/null
+++ b/src/ICONROMM.r
@@ -1,0 +1,192 @@
+/*
+	RomIcon.r
+
+	Copyright (C) 2003 Philip Cummins, Richard F. Bannister,
+		Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#if SmallIconAPIAvail
+resource 'ics#' (RomIconId, purgeable) {
+	{ /* array: 2 elements */
+		/* [1] */
+		$"7FE0 4030 4028 403C 4004 5FC4 5FC4 5FC4"
+		$"5FC4 4004 5FC4 5FC4 5FC4 5FC4 4004 7FFC",
+		/* [2] */
+		$"7FE0 7FF0 7FF8 7FFC 7FFC 7FFC 7FFC 7FFC"
+		$"7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC"
+	}
+};
+#endif
+
+#if ColorIconAPIAvail
+resource 'ics8' (RomIconId, purgeable) {
+	$"00FF FFFF FFFF FFFF FFFF FF00 0000 0000"
+	$"00FF F5F5 F5F5 F5F5 F5F5 FFFF 0000 0000"
+	$"00FF F5F5 F5F5 F5F5 F5F5 FF2B FF00 0000"
+	$"00FF F5F5 F5F5 F5F5 F5F5 FFFF FFFF 0000"
+	$"00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000"
+	$"00FF F5FF FFFF FFFF FFFF F5F5 F5FF 0000"
+	$"00FF F5FF FFFF FFFF FFFF F5F5 F5FF 0000"
+	$"00FF F5FF FFFF FFFF FFFF F5F5 F5FF 0000"
+	$"00FF F5FF FFFF FFFF FFFF F5F5 F5FF 0000"
+	$"00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000"
+	$"00FF F5FF FFFF FFFF FFFF F5F5 F5FF 0000"
+	$"00FF F5FF FFFF FFFF FFFF F5F5 F5FF 0000"
+	$"00FF F5FF FFFF FFFF FFFF F5F5 F5FF 0000"
+	$"00FF F5FF FFFF FFFF FFFF F5F5 F5FF 0000"
+	$"00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000"
+	$"00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+};
+#endif
+
+#if ColorIconAPIAvail
+resource 'ics4' (RomIconId, purgeable) {
+	$"0FFF FFFF FFF0 0000 0F0C 0C0C 0CFF 0000"
+	$"0FC0 C0C0 C0FC F000 0F0C 0C0C 0CFF FF00"
+	$"0FC0 C0C0 C0C0 CF00 0F0F FFFF FF0C 0F00"
+	$"0FCF FFFF FFC0 CF00 0F0F FFFF FF0C 0F00"
+	$"0FCF FFFF FFC0 CF00 0F0C 0C0C 0C0C 0F00"
+	$"0FCF FFFF FFC0 CF00 0F0F FFFF FF0C 0F00"
+	$"0FCF FFFF FFC0 CF00 0F0F FFFF FF0C 0F00"
+	$"0FC0 C0C0 C0C0 CF00 0FFF FFFF FFFF FF"
+};
+#endif
+
+resource 'ICN#' (RomIconId, purgeable) {
+	{ /* array: 2 elements */
+		/* [1] */
+		$"1FFF FC00 1000 0600 1000 0500 1000 0480"
+		$"1000 0440 1000 0420 1000 07F0 1000 0010"
+		$"1155 5010 12AA A810 13FF F810 13FF F810"
+		$"13FF F810 13FF F810 13FF F810 13FF F810"
+		$"12AA A810 1155 5010 1000 0010 1155 5010"
+		$"12AA A810 13FF F810 13FF F810 13FF F810"
+		$"13FF F810 13FF F810 13FF F810 12AA A810"
+		$"1155 5010 1000 0010 1000 0010 1FFF FFF0",
+		/* [2] */
+		$"1FFF FC00 1FFF FE00 1FFF FF00 1FFF FF80"
+		$"1FFF FFC0 1FFF FFE0 1FFF FFF0 1FFF FFF0"
+		$"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+		$"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+		$"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+		$"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+		$"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+		$"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0"
+	}
+};
+
+#if ColorIconAPIAvail
+resource 'icl8' (RomIconId, purgeable) {
+	$"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFFF 0000 0000 0000 0000 0000"
+	$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
+	$"F5F5 F5F5 F5FF FF00 0000 0000 0000 0000"
+	$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
+	$"F5F5 F5F5 F5FF 2BFF 0000 0000 0000 0000"
+	$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
+	$"F5F5 F5F5 F5FF 2B2B FF00 0000 0000 0000"
+	$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
+	$"F5F5 F5F5 F5FF 2B2B 2BFF 0000 0000 0000"
+	$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
+	$"F5F5 F5F5 F5FF 2B2B 2B2B FF00 0000 0000"
+	$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
+	$"F5F5 F5F5 F5FF FFFF FFFF FFFF 0000 0000"
+	$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
+	$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 F5FF F5FF F5FF F5FF F5FF"
+	$"F5FF F5FF F5F5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 FF00 FF00 FF00 FF00 FF00"
+	$"FF00 FF00 FFF5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFF5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFF5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFF5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFF5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFF5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFF5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 FF00 FF00 FF00 FF00 FF00"
+	$"FF00 FF00 FFF5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 F5FF F5FF F5FF F5FF F5FF"
+	$"F5FF F5FF F5F5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
+	$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 F5FF F5FF F5FF F5FF F5FF"
+	$"F5FF F5FF F5F5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 FF00 FF00 FF00 FF00 FF00"
+	$"FF00 FF00 FFF5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFF5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFF5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFF5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFF5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFF5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFF5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 FF00 FF00 FF00 FF00 FF00"
+	$"FF00 FF00 FFF5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 F5FF F5FF F5FF F5FF F5FF"
+	$"F5FF F5FF F5F5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
+	$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF F5F5 F5F5 F5F5 F5F5 F5F5 F5F5"
+	$"F5F5 F5F5 F5F5 F5F5 F5F5 F5FF 0000 0000"
+	$"0000 00FF FFFF FFFF FFFF FFFF FFFF FFFF"
+	$"FFFF FFFF FFFF FFFF FFFF FFFF"
+};
+#endif
+
+#if ColorIconAPIAvail
+resource 'icl4' (RomIconId, purgeable) {
+	$"000F FFFF FFFF FFFF FFFF FF00 0000 0000"
+	$"000F 0C0C 0C0C 0C0C 0C0C 0FF0 0000 0000"
+	$"000F C0C0 C0C0 C0C0 C0C0 CFCF 0000 0000"
+	$"000F 0C0C 0C0C 0C0C 0C0C 0FCC F000 0000"
+	$"000F C0C0 C0C0 C0C0 C0C0 CFCC CF00 0000"
+	$"000F 0C0C 0C0C 0C0C 0C0C 0FCC CCF0 0000"
+	$"000F C0C0 C0C0 C0C0 C0C0 CFFF FFFF 0000"
+	$"000F 0C0C 0C0C 0C0C 0C0C 0C0C 0C0F 0000"
+	$"000F C0CF CFCF CFCF CFCF C0C0 C0CF 0000"
+	$"000F 0CF0 F0F0 F0F0 F0F0 FC0C 0C0F 0000"
+	$"000F C0FF FFFF FFFF FFFF F0C0 C0CF 0000"
+	$"000F 0CFF FFFF FFFF FFFF FC0C 0C0F 0000"
+	$"000F C0FF FFFF FFFF FFFF F0C0 C0CF 0000"
+	$"000F 0CFF FFFF FFFF FFFF FC0C 0C0F 0000"
+	$"000F C0FF FFFF FFFF FFFF F0C0 C0CF 0000"
+	$"000F 0CFF FFFF FFFF FFFF FC0C 0C0F 0000"
+	$"000F C0F0 F0F0 F0F0 F0F0 F0C0 C0CF 0000"
+	$"000F 0C0F 0F0F 0F0F 0F0F 0C0C 0C0F 0000"
+	$"000F C0C0 C0C0 C0C0 C0C0 C0C0 C0CF 0000"
+	$"000F 0C0F 0F0F 0F0F 0F0F 0C0C 0C0F 0000"
+	$"000F C0F0 F0F0 F0F0 F0F0 F0C0 C0CF 0000"
+	$"000F 0CFF FFFF FFFF FFFF FC0C 0C0F 0000"
+	$"000F C0FF FFFF FFFF FFFF F0C0 C0CF 0000"
+	$"000F 0CFF FFFF FFFF FFFF FC0C 0C0F 0000"
+	$"000F C0FF FFFF FFFF FFFF F0C0 C0CF 0000"
+	$"000F 0CFF FFFF FFFF FFFF FC0C 0C0F 0000"
+	$"000F C0FF FFFF FFFF FFFF F0C0 C0CF 0000"
+	$"000F 0CF0 F0F0 F0F0 F0F0 FC0C 0C0F 0000"
+	$"000F C0CF CFCF CFCF CFCF C0C0 C0CF 0000"
+	$"000F 0C0C 0C0C 0C0C 0C0C 0C0C 0C0F 0000"
+	$"000F C0C0 C0C0 C0C0 C0C0 C0C0 C0CF 0000"
+	$"000F FFFF FFFF FFFF FFFF FFFF FFFF"
+};
+#endif
binary files /dev/null b/src/ICONROMO.icns differ
binary files /dev/null b/src/ICONROMW.ico differ
--- /dev/null
+++ b/src/INTLCHAR.h
@@ -1,0 +1,2231 @@
+/*
+	INTLCHAR.h
+
+	Copyright (C) 2010 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	InterNaTionAL CHARacters
+*/
+
+/* master copy of private font data */
+/*
+	Data in commments:
+	Mini vMac Cell name
+	Mac Roman (Octal)
+	windows-1252 code page
+	Unicode
+	plain ascii
+	ClStrAppendSubstCStr encoding
+	HTML character entity
+*/
+LOCALVAR const ui3b CellData[] = {
+	/* kCellUpA 101 0x41 0x0041 'A' 'A' A */
+	0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x7E,
+	0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpB 102 0x42 0x0042 'B' 'B' B */
+	0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x7C, 0x42,
+	0x42, 0x42, 0x42, 0x7C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpC 103 0x43 0x0043 'C' 'C' C */
+	0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x40, 0x40,
+	0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpD 104 0x44 0x0044 'D' 'D' D */
+	0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x7C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpE 105 0x45 0x0045 'E' 'E' E */
+	0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C,
+	0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpF 106 0x46 0x0046 'F' 'F' F */
+	0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C,
+	0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpG 107 0x47 0x0047 'G' 'G' G */
+	0x00, 0x00, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x4E,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpH 110 0x48 0x0048 'H' 'H' H */
+	0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7E,
+	0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpI 111 0x49 0x0049 'I' 'I' I */
+	0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08,
+	0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpJ 112 0x4A 0x004A 'J' 'J' J */
+	0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+	0x02, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpK 113 0x4B 0x004B 'K' 'K' K */
+	0x00, 0x00, 0x00, 0x42, 0x44, 0x48, 0x50, 0x60,
+	0x50, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpL 114 0x4C 0x004C 'L' 'L' L */
+	0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40,
+	0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpM 115 0x4D 0x004D 'M' 'M' M */
+	0x00, 0x00, 0x00, 0x82, 0xC6, 0xAA, 0x92, 0x82,
+	0x82, 0x82, 0x82, 0x82, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpN 116 0x4E 0x004E 'N' 'N' N */
+	0x00, 0x00, 0x00, 0x42, 0x42, 0x62, 0x52, 0x4A,
+	0x46, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpO 117 0x4F 0x004F 'O' 'O' O */
+	0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpP 120 0x50 0x0050 'P' 'P' P */
+	0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x7C,
+	0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpQ 121 0x51 0x0051 'Q' 'Q' Q */
+	0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x10, 0x0C, 0x00, 0x00,
+	/* kCellUpR 122 0x52 0x0052 'R' 'R' R */
+	0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x7C,
+	0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpS 123 0x53 0x0053 'S' 'S' S */
+	0x00, 0x00, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x3C,
+	0x02, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpT 124 0x54 0x0054 'T' 'T' T */
+	0x00, 0x00, 0x00, 0x7F, 0x08, 0x08, 0x08, 0x08,
+	0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpU 125 0x55 0x0055 'U' 'U' U */
+	0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpV 126 0x56 0x0056 'V' 'V' V */
+	0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x44,
+	0x48, 0x50, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpW 127 0x57 0x0057 'W' 'W' W */
+	0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42,
+	0x42, 0x5A, 0x66, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpX 130 0x58 0x0058 'X' 'X' X */
+	0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x24, 0x18,
+	0x24, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpY 131 0x59 0x0059 'Y' 'Y' Y */
+	0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x14,
+	0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpZ 132 0x5A 0x005A 'Z' 'Z' Z */
+	0x00, 0x00, 0x00, 0x7E, 0x02, 0x04, 0x08, 0x10,
+	0x20, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoA 141 0x61 0x0061 'a' 'a' a */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x42,
+	0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoB 142 0x62 0x0062 'b' 'b' b */
+	0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7C, 0x42,
+	0x42, 0x42, 0x42, 0x7C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoC 143 0x63 0x0063 'c' 'c' c */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42,
+	0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoD 144 0x64 0x0064 'd' 'd' d */
+	0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x3E, 0x42,
+	0x42, 0x42, 0x42, 0x3E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoE 145 0x65 0x0065 'e' 'e' e */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42,
+	0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoF 146 0x66 0x0066 'f' 'f' f */
+	0x00, 0x00, 0x00, 0x0E, 0x10, 0x10, 0x3C, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoG 147 0x67 0x0067 'g' 'g' g */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x42,
+	0x42, 0x42, 0x42, 0x3E, 0x02, 0x42, 0x3C, 0x00,
+	/* kCellLoH 150 0x68 0x0068 'h' 'h' h */
+	0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7C, 0x42,
+	0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoI 151 0x69 0x0069 'i' 'i' i */
+	0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoJ 152 0x6A 0x006A 'j' 'j' j */
+	0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x08, 0x08,
+	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x70, 0x00,
+	/* kCellLoK 153 0x6B 0x006B 'k' 'k' k */
+	0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x44, 0x48,
+	0x70, 0x48, 0x44, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoL 154 0x6C 0x006C 'l' 'l' l */
+	0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08,
+	0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoM 155 0x6D 0x006D 'm' 'm' m */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x92,
+	0x92, 0x92, 0x92, 0x92, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoN 156 0x6E 0x006E 'n' 'n' n */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x42,
+	0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoO 157 0x6F 0x006F 'o' 'o' o */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoP 160 0x70 0x0070 'p' 'p' p */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x42,
+	0x42, 0x42, 0x42, 0x7C, 0x40, 0x40, 0x00, 0x00,
+	/* kCellLoQ 161 0x71 0x0071 'q' 'q' q */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x42,
+	0x42, 0x42, 0x42, 0x3E, 0x02, 0x02, 0x00, 0x00,
+	/* kCellLoR 162 0x72 0x0072 'r' 'r' r */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5C, 0x62,
+	0x42, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoS 163 0x73 0x0073 's' 's' s */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42,
+	0x3C, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoT 164 0x74 0x0074 't' 't' t */
+	0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x78, 0x20,
+	0x20, 0x20, 0x20, 0x1C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoU 165 0x75 0x0075 'u' 'u' u */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42,
+	0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoV 166 0x76 0x0076 'v' 'v' v */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x44,
+	0x48, 0x50, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoW 167 0x77 0x0077 'w' 'w' w */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x92,
+	0x92, 0x92, 0x92, 0x6C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoX 170 0x78 0x0078 'x' 'x' x */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x24,
+	0x18, 0x18, 0x24, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoY 171 0x79 0x0079 'y' 'y' y */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x3E, 0x02, 0x42, 0x3C, 0x00,
+	/* kCellLoZ 172 0x7A 0x007A 'z' 'z' z */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x04,
+	0x08, 0x10, 0x20, 0x7E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellDigit0 060 0x30 0x0030 '0' '0' 0 */
+	0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellDigit1 061 0x31 0x0031 '1' '1' 1 */
+	0x00, 0x00, 0x00, 0x08, 0x18, 0x08, 0x08, 0x08,
+	0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+	/* kCellDigit2 062 0x32 0x0032 '2' '2' 2 */
+	0x00, 0x00, 0x00, 0x3C, 0x42, 0x02, 0x02, 0x04,
+	0x08, 0x10, 0x20, 0x7E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellDigit3 063 0x33 0x0033 '3' '3' 3 */
+	0x00, 0x00, 0x00, 0x3C, 0x42, 0x02, 0x0C, 0x02,
+	0x02, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellDigit4 064 0x34 0x0034 '4' '4' 4 */
+	0x00, 0x00, 0x00, 0x04, 0x0C, 0x14, 0x24, 0x7E,
+	0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00,
+	/* kCellDigit5 065 0x35 0x0035 '5' '5' 5 */
+	0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x7C, 0x02,
+	0x02, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellDigit6 066 0x36 0x0036 '6' '6' 6 */
+	0x00, 0x00, 0x00, 0x1C, 0x20, 0x40, 0x7C, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellDigit7 067 0x37 0x0037 '7' '7' 7 */
+	0x00, 0x00, 0x00, 0x7E, 0x02, 0x02, 0x04, 0x08,
+	0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+	/* kCellDigit8 070 0x38 0x0038 '8' '8' 8 */
+	0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x3C, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellDigit9 071 0x39 0x0039 '9' '9' 9 */
+	0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42,
+	0x3E, 0x02, 0x04, 0x38, 0x00, 0x00, 0x00, 0x00,
+	/* kCellExclamation 041 0x21 0x0021 '!' '!' ! */
+	0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08,
+	0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+	/* kCellAmpersand 046 0x26 0x0026 '&' '&' amp */
+	0x00, 0x00, 0x00, 0x30, 0x48, 0x48, 0x50, 0x20,
+	0x50, 0x4A, 0x44, 0x3A, 0x00, 0x00, 0x00, 0x00,
+	/* kCellApostrophe 047 0x27 0x0027 '\047' ';la' #39 (apos) */
+	0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLeftParen 050 0x28 0x0028 '(' '(' ( */
+	0x00, 0x00, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10,
+	0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00,
+	/* kCellRightParen 051 0x29 0x0029 ')' ')' ) */
+	0x00, 0x00, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08,
+	0x08, 0x08, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00,
+	/* kCellComma 054 0x2C 0x002C ',' ',' , */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x08, 0x08, 0x10, 0x00, 0x00,
+	/* kCellHyphen 055 0x2D 0x002D '-' '-' - */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* kCellPeriod 056 0x2E 0x002E '.' '.' . */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+	/* kCellSlash 057 0x2F 0x002F '/' '/' / */
+	0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x08, 0x08,
+	0x10, 0x10, 0x20, 0x20, 0x40, 0x00, 0x00, 0x00,
+	/* kCellColon 072 0x3A 0x003A ':' ':' : */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
+	0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+	/* kCellSemicolon 073 0x3B 0x003B ';' ';ls' #59 (semi) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
+	0x00, 0x00, 0x08, 0x08, 0x08, 0x10, 0x00, 0x00,
+	/* kCellQuestion 077 0x3F 0x003F '?' '?' ? */
+	0x00, 0x00, 0x00, 0x38, 0x44, 0x04, 0x08, 0x10,
+	0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+	/* kCellEllipsis 311 0x85 0x2026 '_' ';ll' #8230 (mldr) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUnderscore 137 0x5F 0x005F '_' '_' _ */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLeftDQuote 322 0x93 0x201C '"' ';[' ldquo */
+	0x00, 0x00, 0x00, 0x24, 0x48, 0x6C, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* kCellRightDQuote 323 0x94 0x201D '"' ';{' rdquo */
+	0x00, 0x00, 0x00, 0x36, 0x12, 0x24, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLeftSQuote 324 0x91 0x2018 '\047' ';]' lsquo */
+	0x00, 0x00, 0x00, 0x08, 0x10, 0x18, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* kCellRightSQuote 325 0x92 0x2019 '\047' ';}' rsquo */
+	0x00, 0x00, 0x00, 0x18, 0x08, 0x10, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* kCellCopyright 251 0xA9 0x00A9 'c' ';g' copy */
+	0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x9A, 0xA2,
+	0xA2, 0x9A, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00,
+	/* kCellSpace 040 0x20 0x0020 '\040' '' #32 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+#if NeedIntlChars
+	/* kCellUpADiaeresis 200 0xC4 0x00C4 'A' ';uA' Auml */
+	0x00, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x7E,
+	0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpARing 201 0xC5 0x00C5 'A' ';A' Aring */
+	0x3C, 0x42, 0x42, 0x3C, 0x42, 0x42, 0x42, 0x7E,
+	0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpCCedilla 202 0xC7 0x00C7 'C' ';C' Ccedil */
+	0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x40, 0x40,
+	0x40, 0x40, 0x42, 0x3C, 0x08, 0x08, 0x10, 0x00,
+	/* kCellUpEAcute 203 0xC9 0x00C9 'E' ';eE' Eacute */
+	0x08, 0x10, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C,
+	0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpNTilde 204 0xD1 0x00D1 'N' ';nN' Ntilde */
+	0x32, 0x4C, 0x00, 0x42, 0x42, 0x62, 0x52, 0x4A,
+	0x46, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpODiaeresis 205 0xD6 0x00D6 'O' ';uO' Ouml */
+	0x00, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpUDiaeresis 206 0xDC 0x00DC 'U' ';uU' Uuml */
+	0x00, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoAAcute 207 0xE1 0x00E1 'a' ';ea' aacute */
+	0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3E, 0x42,
+	0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoAGrave 210 0xE0 0x00E0 'a' ';`a' agrave */
+	0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3E, 0x42,
+	0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoACircumflex 211 0xE2 0x00E2 'a' ';ia' acirc */
+	0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3E, 0x42,
+	0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoADiaeresis 212 0xE4 0x00E4 'a' ';ua' auml */
+	0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x3E, 0x42,
+	0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoATilde 213 0xE3 0x00E3 'a' ';na' atilde */
+	0x00, 0x00, 0x00, 0x32, 0x4C, 0x00, 0x3E, 0x42,
+	0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoARing 214 0xE5 0x00E5 'a' ';a' aring */
+	0x00, 0x00, 0x18, 0x24, 0x24, 0x18, 0x3E, 0x42,
+	0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoCCedilla 215 0xE7 0x00E7 'c' ';c' ccedil */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42,
+	0x40, 0x40, 0x42, 0x3C, 0x08, 0x08, 0x10, 0x00,
+	/* kCellLoEAcute 216 0xE9 0x00E9 'e' ';ee' eacute */
+	0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3C, 0x42,
+	0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoEGrave 217 0xE8 0x00E8 'e' ';`e' egrave */
+	0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3C, 0x42,
+	0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoECircumflex 220 0xEA 0x00EA 'e' ';ie' ecirc */
+	0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3C, 0x42,
+	0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoEDiaeresis 221 0xEB 0x00EB 'e' ';ue' euml */
+	0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x3C, 0x42,
+	0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoIAcute 222 0xED 0x00ED 'i' ';ei' iacute */
+	0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoIGrave 223 0xEC 0x00EC 'i' ';`i' igrave */
+	0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoICircumflex 224 0xEE 0x00EE 'i' ';ii' icirc */
+	0x00, 0x00, 0x00, 0x10, 0x28, 0x00, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoIDiaeresis 225 0xEF 0x00EF 'i' ';ui' iuml */
+	0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x10, 0x10,
+	0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoNTilde 226 0xF1 0x00F1 'n' ';nn' ntilde */
+	0x00, 0x00, 0x00, 0x32, 0x4C, 0x00, 0x7C, 0x42,
+	0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoOAcute 227 0xF3 0x00F3 'o' ';eo' oacute */
+	0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3C, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoOGrave 230 0xF2 0x00F2 'o' ';`o' ograve */
+	0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x3C, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoOCircumflex 231 0xF4 0x00F4 'o' ';io' ocirc */
+	0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x3C, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoODiaeresis 232 0xF6 0x00F6 'o' ';uo' ouml */
+	0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x3C, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoOTilde 233 0xF5 0x00F5 'o' ';no' otilde */
+	0x00, 0x00, 0x00, 0x32, 0x4C, 0x00, 0x3C, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoUAcute 234 0xFA 0x00FA 'u' ';eu' uacute */
+	0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x42, 0x42,
+	0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoUGrave 235 0xF9 0x00F9 'u' ';`u' ugrave */
+	0x00, 0x00, 0x00, 0x10, 0x08, 0x00, 0x42, 0x42,
+	0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoUCircumflex 236 0xFB 0x00FB 'u' ';iu' ucirc */
+	0x00, 0x00, 0x00, 0x18, 0x24, 0x00, 0x42, 0x42,
+	0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoUDiaeresis 237 0xFC 0x00FC 'u' ';uu' uuml */
+	0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x42, 0x42,
+	0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00,
+
+	/* kCellUpAE 256 0xC6 0x00C6 '?' ';lE' AElig */
+	0x00, 0x00, 0x00, 0x3E, 0x48, 0x48, 0x48, 0x7C,
+	0x48, 0x48, 0x48, 0x4E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpOStroke 257 0xD8 0x00D8 'O' ';O' Oslash */
+	0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x46, 0x5A,
+	0x62, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+
+	/* kCellLoAE 276 0xE6 0x00E6 '?' ';le' aelig */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x52,
+	0x5E, 0x50, 0x52, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoOStroke 277 0xF8 0x00F8 'o' ';o' oslash */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x46,
+	0x5A, 0x62, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellInvQuestion 300 0xBF 0x00BF '?' ';?' iquest */
+	0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x10, 0x10,
+	0x20, 0x40, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00,
+	/* kCellInvExclam 301 0xA1 0x00A1 '!' ';1' iexcl */
+	0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x08, 0x08,
+	0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+
+	/* kCellUpAGrave 313 0xC0 0x00C0 'A' ';`A' Agrave */
+	0x10, 0x08, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42,
+	0x7E, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpATilde 314 0xC3 0x00C3 'A' ';nA' Atilde */
+	0x32, 0x4C, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42,
+	0x7E, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpOTilde 315 0xD5 0x00D5 'O' ';nO' Otilde */
+	0x32, 0x4C, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpLigatureOE 316 0x8C 0x0152 '?' ';Q' OElig */
+	0x00, 0x00, 0x00, 0x3E, 0x48, 0x48, 0x48, 0x4E,
+	0x48, 0x48, 0x48, 0x3E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoLigatureOE 317 0x9C 0x0153 '?' ';q' oelig */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x52,
+	0x5E, 0x50, 0x52, 0x2C, 0x00, 0x00, 0x00, 0x00,
+
+	/* kCellLoYDiaeresis 330 0xFF 0x00FF 'y' ';uy' yuml */
+	0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x3E, 0x02, 0x42, 0x3C, 0x00,
+	/* kCellUpYDiaeresis 331 0x9F 0x0178 'Y' ';uY' Yuml */
+	0x00, 0x14, 0x00, 0x22, 0x22, 0x22, 0x22, 0x14,
+	0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+
+	/* kCellUpACircumflex 345 0xC2 0x00C2 'A' ';iA' Acirc */
+	0x18, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x7E,
+	0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpECircumflex 346 0xCA 0x00CA 'E' ';iE' Ecirc */
+	0x18, 0x24, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C,
+	0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpAAcute 347 0xC1 0x00C1 'A' ';eA' Aacute */
+	0x08, 0x10, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42,
+	0x7E, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpEDiaeresis 350 0xCB 0x00CB 'E' ';uE' Euml */
+	0x00, 0x24, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C,
+	0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpEGrave 351 0xC8 0x00C8 'E' ';`E' Egrave */
+	0x10, 0x08, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C,
+	0x40, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpIAcute 352 0xCD 0x00CD 'A' ';eI' Iacute */
+	0x04, 0x08, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08,
+	0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpICircumflex 353 0xCE 0x00CE 'I' ';iI' Icirc */
+	0x08, 0x14, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08,
+	0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpIDiaeresis 354 0xCF 0x00CF 'I' ';uI' Iuml */
+	0x00, 0x14, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08,
+	0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpIGrave 355 0xCC 0x00CC 'I' ';`I' Igrave */
+	0x10, 0x08, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08,
+	0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpOAcute 356 0xD3 0x00D3 'O' ';eO' Oacute */
+	0x08, 0x10, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpOCircumflex 357 0xD4 0x00D4 'O' ';iO' Ocirc */
+	0x18, 0x24, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+
+	/* kCellUpOGrave 361 0xD2 0x00D2 'O' ';`O' Ograve */
+	0x10, 0x08, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpUAcute 362 0xDA 0x00DA 'U' ';eU' Uacute */
+	0x08, 0x10, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpUCircumflex 363 0xDB 0x00DB 'U' ';iU' Ucirc */
+	0x18, 0x24, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpUGrave 364 0xD9 0x00D9 'U' ';`U' Ugrave */
+	0x10, 0x08, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellSharpS 247 0xDF 0x00DF 'B' ';s' szlig */
+	0x00, 0x00, 0x00, 0x1C, 0x22, 0x42, 0x44, 0x44,
+	0x42, 0x42, 0x42, 0x5C, 0x40, 0x00, 0x00, 0x00,
+
+	/* kCellUpACedille 260 ? 0x0104 'A' ';dA' #260 (Aogon) */
+	0x00, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x7E,
+	0x42, 0x42, 0x42, 0x42, 0x04, 0x04, 0x02, 0x00,
+	/* kCellLoACedille 261 ? 0x0105 'a' ';da' #261 (aogon) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x42,
+	0x42, 0x42, 0x46, 0x3A, 0x04, 0x04, 0x02, 0x00,
+	/* kCellUpCAcute 262 ? 0x0106 'C' ';eC' #262 (Cacute) */
+	0x08, 0x10, 0x00, 0x3C, 0x42, 0x42, 0x40, 0x40,
+	0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoCAcute 263 ? 0x0107 'c' ';ec' #263 (cacute) */
+	0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3C, 0x42,
+	0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpECedille 264 ? 0x0118 'E' ';dE' #280 (Eogon) */
+	0x00, 0x00, 0x00, 0x7E, 0x40, 0x40, 0x40, 0x7C,
+	0x40, 0x40, 0x40, 0x7E, 0x04, 0x04, 0x02, 0x00,
+	/* kCellLoECedille 265 ? 0x0119 'e' ';de' #281 (eogon) */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42,
+	0x7E, 0x40, 0x42, 0x3C, 0x08, 0x08, 0x04, 0x00,
+	/* kCellUpLBar 266 ? 0x0141 'L' ';dL' #321 (Lstrok) */
+	0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x60, 0x40,
+	0xC0, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoLBar 267 ? 0x0142 'l' ';dl' #322 (lstrok) */
+	0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x0C, 0x08,
+	0x18, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpNAcute 270 ? 0x0143 'N' ';eN' #323 (Nacute) */
+	0x08, 0x10, 0x00, 0x42, 0x42, 0x62, 0x52, 0x4A,
+	0x46, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoNAcute 271 ? 0x0144 'n' ';en' #324 (nacute) */
+	0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x7C, 0x42,
+	0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpSAcute 272 ? 0x015A 'S' ';eS' #346 (Sacute) */
+	0x08, 0x10, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x3C,
+	0x02, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoSAcute 273 ? 0x015B 's' ';es' #347 (sacute) */
+	0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x3C, 0x42,
+	0x3C, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpZAcute 274 ? 0x0179 'Z' ';eZ' #377 (Zacute) */
+	0x08, 0x10, 0x00, 0x7E, 0x02, 0x04, 0x08, 0x10,
+	0x20, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoZAcute 275 ? 0x017A 'z' ';ez' #378 (zacute) */
+	0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x7E, 0x04,
+	0x08, 0x10, 0x20, 0x7E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpZDot 276 ? 0x017B 'Z' ';dZ' #379 (Zdot) */
+	0x10, 0x00, 0x00, 0x7E, 0x02, 0x04, 0x08, 0x10,
+	0x20, 0x40, 0x40, 0x7E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoZDot 277 ? 0x017C 'z' ';dz' #380 (zdot) */
+	0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x7E, 0x04,
+	0x08, 0x10, 0x20, 0x7E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellMidDot 341 0xB7 0x00B7 '.' ';l.' middot */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpCCaron 077 ? 0x010C 'C' ';vC' #268 (Ccaron) */
+	0x14, 0x08, 0x00, 0x3C, 0x42, 0x42, 0x40, 0x40,
+	0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoCCaron 077 ? 0x010D 'c' ';vc' #269 (ccaron) */
+	0x00, 0x00, 0x00, 0x14, 0x08, 0x00, 0x3C, 0x42,
+	0x40, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoECaron 077 ? 0x011B 'e' ';ve' #283 (ecaron) */
+	0x00, 0x00, 0x00, 0x14, 0x08, 0x00, 0x3C, 0x42,
+	0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoRCaron 077 ? 0x0159 'r' ';vr' #345 (rcaron) */
+	0x00, 0x00, 0x00, 0x14, 0x08, 0x00, 0x5C, 0x62,
+	0x42, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoSCaron 077 0x9A 0x0161 's' ';vs' #353 (scaron) */
+	0x00, 0x00, 0x00, 0x14, 0x08, 0x00, 0x3C, 0x42,
+	0x3C, 0x02, 0x42, 0x3C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoTCaron 077 ? 0x0165 't' ';vt' #357 (tcaron) */
+	0x00, 0x14, 0x08, 0x00, 0x20, 0x20, 0x78, 0x20,
+	0x20, 0x20, 0x20, 0x1C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoZCaron 077 0x9E 0x017E 'z' ';vz' #382 (zcaron) */
+	0x00, 0x00, 0x00, 0x14, 0x08, 0x00, 0x7E, 0x04,
+	0x08, 0x10, 0x20, 0x7E, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpYAcute 077 0xDD 0x00DD 'Y' ';eY' Yacute */
+	0x08, 0x10, 0x00, 0x22, 0x22, 0x22, 0x22, 0x14,
+	0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoYAcute 077 0xFD 0x00FD 'y' ';ey' yacute */
+	0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x3E, 0x02, 0x42, 0x3C, 0x00,
+	/* kCellLoUDblac 077 ? 0x0171 'u' ';Eu' #369 (udblac) */
+	0x00, 0x00, 0x00, 0x12, 0x24, 0x00, 0x42, 0x42,
+	0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoURing 077 ? 0x016F 'u' ';ru' #367 (uring) */
+	0x00, 0x00, 0x18, 0x24, 0x24, 0x18, 0x42, 0x42,
+	0x42, 0x42, 0x46, 0x3A, 0x00, 0x00, 0x00, 0x00,
+	/* kCellUpDStroke 077 ? 0x0110 'D' ';dD' #272 (Dstrok) */
+	0x00, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0xF2,
+	0x42, 0x42, 0x42, 0x7C, 0x00, 0x00, 0x00, 0x00,
+	/* kCellLoDStroke 077 ? 0x0111 'd' ';dd' #273 (dstrok) */
+	0x00, 0x00, 0x00, 0x02, 0x0F, 0x02, 0x3E, 0x42,
+	0x42, 0x42, 0x42, 0x3E, 0x00, 0x00, 0x00, 0x00,
+#endif
+
+	/* kCellUpperLeft */
+	0xFF, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+	/* kCellUpperMiddle */
+	0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* kCellMiddleLeft */
+	0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	/* kCellMiddleLeft */
+	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+	/* kCellMiddleRight */
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	/* kCellLowerLeft */
+	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF,
+	/* kCellLowerMiddle */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+	/* kCellLowerRight */
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF,
+	/* kCellGraySep */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* kCellIcon00 */
+	0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09,
+	/* kCellIcon01 */
+	0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x18, 0x18,
+	/* kCellIcon02 */
+	0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x18, 0x30,
+	/* kCellIcon03 */
+	0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0xE0, 0x10, 0x10, 0x10, 0x90, 0x90, 0x90,
+	/* kCellIcon10 */
+	0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+	0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
+	/* kCellIcon11 */
+	0x18, 0x18, 0x19, 0x1B, 0x1E, 0x1C, 0x18, 0x10,
+	0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* kCellIcon12 */
+	0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00,
+	/* kCellIcon13 */
+	0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
+	0x90, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+	/* kCellIcon20 */
+	0x08, 0x08, 0x08, 0x07, 0x04, 0x04, 0x04, 0x07,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* kCellIcon21 */
+	0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* kCellIcon22 */
+	0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* kCellIcon23 */
+	0x10, 0x10, 0x10, 0xE0, 0x20, 0x20, 0x20, 0xE0,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+#if EnableAltKeysMode
+	/* kInsertText00 */
+	0xFF, 0x80, 0x80, 0x80, 0x80, 0x83, 0x80, 0x80,
+	0x80, 0x80, 0x83, 0x80, 0x80, 0x80, 0x80, 0xFF,
+	/* kInsertText01 */
+	0xFF, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x19,
+	0x1B, 0x1E, 0x1C, 0x18, 0x10, 0x00, 0x00, 0xFF,
+	/* kInsertText02 */
+	0xFF, 0x00, 0x00, 0x18, 0x30, 0x60, 0xC0, 0x80,
+	0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFF,
+	/* kInsertText03 */
+	0xFF, 0x01, 0x01, 0x01, 0x01, 0xC1, 0x01, 0x01,
+	0x01, 0x01, 0xC1, 0x01, 0x01, 0x01, 0x01, 0xFF,
+	/* kInsertText04 */
+	0xFF, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00,
+	0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0x00, 0xFF,
+#endif
+#if EnableDemoMsg
+	/* kCellDemo0 */
+	0xFF, 0x80, 0x80, 0x80, 0x80, 0x83, 0x80, 0x80,
+	0x80, 0x80, 0x83, 0x80, 0x80, 0x80, 0x80, 0xFF,
+	/* kCellDemo1 */
+	0xFF, 0x00, 0x00, 0x7C, 0x42, 0x42, 0x42, 0x42,
+	0x42, 0x42, 0x42, 0x7C, 0x00, 0x00, 0x00, 0xFF,
+	/* kCellDemo2 */
+	0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42,
+	0x7E, 0x40, 0x42, 0x3C, 0x00, 0x00, 0x00, 0xFF,
+	/* kCellDemo3 */
+	0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x92,
+	0x92, 0x92, 0x92, 0x92, 0x00, 0x00, 0x00, 0xFF,
+	/* kCellDemo4 */
+	0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42,
+	0x42, 0x42, 0x42, 0x3C, 0x00, 0x00, 0x00, 0xFF,
+	/* kCellDemo5 */
+	0xFF, 0x01, 0x01, 0x01, 0x01, 0xC1, 0x01, 0x01,
+	0x01, 0x01, 0xC1, 0x01, 0x01, 0x01, 0x01, 0xFF,
+	/* kCellDemo6 */
+	0xFF, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00,
+	0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0x00, 0xFF,
+	/* kCellDemo7 */
+	0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+#endif
+
+	0x00 /* just so last above line can end in ',' */
+};
+
+enum {
+	kCellUpA,
+	kCellUpB,
+	kCellUpC,
+	kCellUpD,
+	kCellUpE,
+	kCellUpF,
+	kCellUpG,
+	kCellUpH,
+	kCellUpI,
+	kCellUpJ,
+	kCellUpK,
+	kCellUpL,
+	kCellUpM,
+	kCellUpN,
+	kCellUpO,
+	kCellUpP,
+	kCellUpQ,
+	kCellUpR,
+	kCellUpS,
+	kCellUpT,
+	kCellUpU,
+	kCellUpV,
+	kCellUpW,
+	kCellUpX,
+	kCellUpY,
+	kCellUpZ,
+	kCellLoA,
+	kCellLoB,
+	kCellLoC,
+	kCellLoD,
+	kCellLoE,
+	kCellLoF,
+	kCellLoG,
+	kCellLoH,
+	kCellLoI,
+	kCellLoJ,
+	kCellLoK,
+	kCellLoL,
+	kCellLoM,
+	kCellLoN,
+	kCellLoO,
+	kCellLoP,
+	kCellLoQ,
+	kCellLoR,
+	kCellLoS,
+	kCellLoT,
+	kCellLoU,
+	kCellLoV,
+	kCellLoW,
+	kCellLoX,
+	kCellLoY,
+	kCellLoZ,
+	kCellDigit0,
+	kCellDigit1,
+	kCellDigit2,
+	kCellDigit3,
+	kCellDigit4,
+	kCellDigit5,
+	kCellDigit6,
+	kCellDigit7,
+	kCellDigit8,
+	kCellDigit9,
+	kCellExclamation,
+	kCellAmpersand,
+	kCellApostrophe,
+	kCellLeftParen,
+	kCellRightParen,
+	kCellComma,
+	kCellHyphen,
+	kCellPeriod,
+	kCellSlash,
+	kCellColon,
+	kCellSemicolon,
+	kCellQuestion,
+	kCellEllipsis,
+	kCellUnderscore,
+	kCellLeftDQuote,
+	kCellRightDQuote,
+	kCellLeftSQuote,
+	kCellRightSQuote,
+	kCellCopyright,
+	kCellSpace,
+
+#if NeedIntlChars
+	kCellUpADiaeresis,
+	kCellUpARing,
+	kCellUpCCedilla,
+	kCellUpEAcute,
+	kCellUpNTilde,
+	kCellUpODiaeresis,
+	kCellUpUDiaeresis,
+	kCellLoAAcute,
+	kCellLoAGrave,
+	kCellLoACircumflex,
+	kCellLoADiaeresis,
+	kCellLoATilde,
+	kCellLoARing,
+	kCellLoCCedilla,
+	kCellLoEAcute,
+	kCellLoEGrave,
+	kCellLoECircumflex,
+	kCellLoEDiaeresis,
+	kCellLoIAcute,
+	kCellLoIGrave,
+	kCellLoICircumflex,
+	kCellLoIDiaeresis,
+	kCellLoNTilde,
+	kCellLoOAcute,
+	kCellLoOGrave,
+	kCellLoOCircumflex,
+	kCellLoODiaeresis,
+	kCellLoOTilde,
+	kCellLoUAcute,
+	kCellLoUGrave,
+	kCellLoUCircumflex,
+	kCellLoUDiaeresis,
+
+	kCellUpAE,
+	kCellUpOStroke,
+
+	kCellLoAE,
+	kCellLoOStroke,
+	kCellInvQuestion,
+	kCellInvExclam,
+
+	kCellUpAGrave,
+	kCellUpATilde,
+	kCellUpOTilde,
+	kCellUpLigatureOE,
+	kCellLoLigatureOE,
+
+	kCellLoYDiaeresis,
+	kCellUpYDiaeresis,
+
+	kCellUpACircumflex,
+	kCellUpECircumflex,
+	kCellUpAAcute,
+	kCellUpEDiaeresis,
+	kCellUpEGrave,
+	kCellUpIAcute,
+	kCellUpICircumflex,
+	kCellUpIDiaeresis,
+	kCellUpIGrave,
+	kCellUpOAcute,
+	kCellUpOCircumflex,
+
+	kCellUpOGrave,
+	kCellUpUAcute,
+	kCellUpUCircumflex,
+	kCellUpUGrave,
+	kCellSharpS,
+
+	kCellUpACedille,
+	kCellLoACedille,
+	kCellUpCAcute,
+	kCellLoCAcute,
+	kCellUpECedille,
+	kCellLoECedille,
+	kCellUpLBar,
+	kCellLoLBar,
+	kCellUpNAcute,
+	kCellLoNAcute,
+	kCellUpSAcute,
+	kCellLoSAcute,
+	kCellUpZAcute,
+	kCellLoZAcute,
+	kCellUpZDot,
+	kCellLoZDot,
+	kCellMidDot,
+	kCellUpCCaron,
+	kCellLoCCaron,
+	kCellLoECaron,
+	kCellLoRCaron,
+	kCellLoSCaron,
+	kCellLoTCaron,
+	kCellLoZCaron,
+	kCellUpYAcute,
+	kCellLoYAcute,
+	kCellLoUDblac,
+	kCellLoURing,
+	kCellUpDStroke,
+	kCellLoDStroke,
+#endif
+
+	kCellUpperLeft,
+	kCellUpperMiddle,
+	kCellUpperRight,
+	kCellMiddleLeft,
+	kCellMiddleRight,
+	kCellLowerLeft,
+	kCellLowerMiddle,
+	kCellLowerRight,
+	kCellGraySep,
+	kCellIcon00,
+	kCellIcon01,
+	kCellIcon02,
+	kCellIcon03,
+	kCellIcon10,
+	kCellIcon11,
+	kCellIcon12,
+	kCellIcon13,
+	kCellIcon20,
+	kCellIcon21,
+	kCellIcon22,
+	kCellIcon23,
+#if EnableAltKeysMode
+	kInsertText00,
+	kInsertText01,
+	kInsertText02,
+	kInsertText03,
+	kInsertText04,
+#endif
+#if EnableDemoMsg
+	kCellDemo0,
+	kCellDemo1,
+	kCellDemo2,
+	kCellDemo3,
+	kCellDemo4,
+	kCellDemo5,
+	kCellDemo6,
+	kCellDemo7,
+#endif
+
+	kNumCells
+};
+
+#if UseActvCode && 0
+#define UseActvFile 1
+#else
+#define UseActvFile 0
+#endif
+
+#ifndef NeedCell2MacAsciiMap
+#if 1 /* UseActvCode || EnableDemoMsg */
+#define NeedCell2MacAsciiMap 1
+#else
+#define NeedCell2MacAsciiMap 0
+#endif
+#endif
+
+#if NeedCell2MacAsciiMap
+/* Mac Roman character set */
+LOCALVAR const char Cell2MacAsciiMap[] = {
+	'\101', /* kCellUpA */
+	'\102', /* kCellUpB */
+	'\103', /* kCellUpC */
+	'\104', /* kCellUpD */
+	'\105', /* kCellUpE */
+	'\106', /* kCellUpF */
+	'\107', /* kCellUpG */
+	'\110', /* kCellUpH */
+	'\111', /* kCellUpI */
+	'\112', /* kCellUpJ */
+	'\113', /* kCellUpK */
+	'\114', /* kCellUpL */
+	'\115', /* kCellUpM */
+	'\116', /* kCellUpN */
+	'\117', /* kCellUpO */
+	'\120', /* kCellUpP */
+	'\121', /* kCellUpQ */
+	'\122', /* kCellUpR */
+	'\123', /* kCellUpS */
+	'\124', /* kCellUpT */
+	'\125', /* kCellUpU */
+	'\126', /* kCellUpV */
+	'\127', /* kCellUpW */
+	'\130', /* kCellUpX */
+	'\131', /* kCellUpY */
+	'\132', /* kCellUpZ */
+	'\141', /* kCellLoA */
+	'\142', /* kCellLoB */
+	'\143', /* kCellLoC */
+	'\144', /* kCellLoD */
+	'\145', /* kCellLoE */
+	'\146', /* kCellLoF */
+	'\147', /* kCellLoG */
+	'\150', /* kCellLoH */
+	'\151', /* kCellLoI */
+	'\152', /* kCellLoJ */
+	'\153', /* kCellLoK */
+	'\154', /* kCellLoL */
+	'\155', /* kCellLoM */
+	'\156', /* kCellLoN */
+	'\157', /* kCellLoO */
+	'\160', /* kCellLoP */
+	'\161', /* kCellLoQ */
+	'\162', /* kCellLoR */
+	'\163', /* kCellLoS */
+	'\164', /* kCellLoT */
+	'\165', /* kCellLoU */
+	'\166', /* kCellLoV */
+	'\167', /* kCellLoW */
+	'\170', /* kCellLoX */
+	'\171', /* kCellLoY */
+	'\172', /* kCellLoZ */
+	'\060', /* kCellDigit0 */
+	'\061', /* kCellDigit1 */
+	'\062', /* kCellDigit2 */
+	'\063', /* kCellDigit3 */
+	'\064', /* kCellDigit4 */
+	'\065', /* kCellDigit5 */
+	'\066', /* kCellDigit6 */
+	'\067', /* kCellDigit7 */
+	'\070', /* kCellDigit8 */
+	'\071', /* kCellDigit9 */
+	'\041', /* kCellExclamation */
+	'\046', /* kCellAmpersand */
+	'\047', /* kCellApostrophe */
+	'\050', /* kCellLeftParen */
+	'\051', /* kCellRightParen */
+	'\054', /* kCellComma */
+	'\055', /* kCellHyphen */
+	'\056', /* kCellPeriod */
+	'\057', /* kCellSlash */
+	'\072', /* kCellColon */
+	'\073', /* kCellSemicolon */
+	'\077', /* kCellQuestion */
+	'\311', /* kCellEllipsis */
+	'\137', /* kCellUnderscore */
+	'\322', /* kCellLeftDQuote */
+	'\323', /* kCellRightDQuote */
+	'\324', /* kCellLeftSQuote */
+	'\325', /* kCellRightSQuote */
+	'\251', /* kCellCopyright */
+	'\040', /* kCellSpace */
+
+#if NeedIntlChars
+	'\200', /* kCellUpADiaeresis */
+	'\201', /* kCellUpARing */
+	'\202', /* kCellUpCCedilla */
+	'\203', /* kCellUpEAcute */
+	'\204', /* kCellUpNTilde */
+	'\205', /* kCellUpODiaeresis */
+	'\206', /* kCellUpUDiaeresis */
+	'\207', /* kCellLoAAcute */
+	'\210', /* kCellLoAGrave */
+	'\211', /* kCellLoACircumflex */
+	'\212', /* kCellLoADiaeresis */
+	'\213', /* kCellLoATilde */
+	'\214', /* kCellLoARing */
+	'\215', /* kCellLoCCedilla */
+	'\216', /* kCellLoEAcute */
+	'\217', /* kCellLoEGrave */
+	'\220', /* kCellLoECircumflex */
+	'\221', /* kCellLoEDiaeresis */
+	'\222', /* kCellLoIAcute */
+	'\223', /* kCellLoIGrave */
+	'\224', /* kCellLoICircumflex */
+	'\225', /* kCellLoIDiaeresis */
+	'\226', /* kCellLoNTilde */
+	'\227', /* kCellLoOAcute */
+	'\230', /* kCellLoOGrave */
+	'\231', /* kCellLoOCircumflex */
+	'\232', /* kCellLoODiaeresis */
+	'\233', /* kCellLoOTilde */
+	'\234', /* kCellLoUAcute */
+	'\235', /* kCellLoUGrave */
+	'\236', /* kCellLoUCircumflex */
+	'\237', /* kCellLoUDiaeresis */
+
+	'\256', /* kCellUpAE */
+	'\257', /* kCellUpOStroke */
+
+	'\276', /* kCellLoAE */
+	'\277', /* kCellLoOStroke */
+	'\300', /* kCellInvQuestion */
+	'\301', /* kCellInvExclam */
+
+	'\313', /* kCellUpAGrave */
+	'\314', /* kCellUpATilde */
+	'\315', /* kCellUpOTilde */
+	'\316', /* kCellUpLigatureOE */
+	'\317', /* kCellLoLigatureOE */
+
+	'\330', /* kCellLoYDiaeresis */
+	'\331', /* kCellUpYDiaeresis */
+
+	'\345', /* kCellUpACircumflex */
+	'\346', /* kCellUpECircumflex */
+	'\347', /* kCellUpAAcute */
+	'\350', /* kCellUpEDiaeresis */
+	'\351', /* kCellUpEGrave */
+	'\352', /* kCellUpIAcute */
+	'\353', /* kCellUpICircumflex */
+	'\354', /* kCellUpIDiaeresis */
+	'\355', /* kCellUpIGrave */
+	'\356', /* kCellUpOAcute */
+	'\357', /* kCellUpOCircumflex */
+
+	'\361', /* kCellUpOGrave */
+	'\362', /* kCellUpUAcute */
+	'\363', /* kCellUpUCircumflex */
+	'\364', /* kCellUpUGrave */
+	'\247', /* kCellSharpS */
+
+	'\260', /* kCellUpACedille */
+	'\261', /* kCellLoACedille */
+	'\262', /* kCellUpCAcute */
+	'\263', /* kCellLoCAcute */
+	'\264', /* kCellUpECedille */
+	'\265', /* kCellLoECedille */
+	'\266', /* kCellUpLBar */
+	'\267', /* kCellLoLBar */
+	'\270', /* kCellUpNAcute */
+	'\271', /* kCellLoNAcute */
+	'\272', /* kCellUpSAcute */
+	'\273', /* kCellLoSAcute */
+	'\274', /* kCellUpZAcute */
+	'\275', /* kCellLoZAcute */
+	'\276', /* kCellUpZDot */
+	'\277', /* kCellLoZDot */
+	'\341', /* kCellMidDot */
+	'\103', /* kCellUpCCaron */
+	'\143', /* kCellLoCCaron */
+	'\145', /* kCellLoECaron */
+	'\162', /* kCellLoRCaron */
+	'\163', /* kCellLoSCaron */
+	'\164', /* kCellLoTCaron */
+	'\172', /* kCellLoZCaron */
+	'\131', /* kCellUpYAcute */
+	'\171', /* kCellLoYAcute */
+	'\165', /* kCellLoUDblac */
+	'\165', /* kCellLoURing */
+	'\104', /* kCellUpDStroke */
+	'\144', /* kCellLoDStroke */
+#endif
+
+	'\0' /* just so last above line can end in ',' */
+};
+#endif
+
+#ifndef NeedCell2WinAsciiMap
+#define NeedCell2WinAsciiMap 0
+#endif
+
+#if NeedCell2WinAsciiMap
+/* Windows character set (windows-1252 code page) */
+LOCALVAR const ui3b Cell2WinAsciiMap[] = {
+	0x41, /* kCellUpA */
+	0x42, /* kCellUpB */
+	0x43, /* kCellUpC */
+	0x44, /* kCellUpD */
+	0x45, /* kCellUpE */
+	0x46, /* kCellUpF */
+	0x47, /* kCellUpG */
+	0x48, /* kCellUpH */
+	0x49, /* kCellUpI */
+	0x4A, /* kCellUpJ */
+	0x4B, /* kCellUpK */
+	0x4C, /* kCellUpL */
+	0x4D, /* kCellUpM */
+	0x4E, /* kCellUpN */
+	0x4F, /* kCellUpO */
+	0x50, /* kCellUpP */
+	0x51, /* kCellUpQ */
+	0x52, /* kCellUpR */
+	0x53, /* kCellUpS */
+	0x54, /* kCellUpT */
+	0x55, /* kCellUpU */
+	0x56, /* kCellUpV */
+	0x57, /* kCellUpW */
+	0x58, /* kCellUpX */
+	0x59, /* kCellUpY */
+	0x5A, /* kCellUpZ */
+	0x61, /* kCellLoA */
+	0x62, /* kCellLoB */
+	0x63, /* kCellLoC */
+	0x64, /* kCellLoD */
+	0x65, /* kCellLoE */
+	0x66, /* kCellLoF */
+	0x67, /* kCellLoG */
+	0x68, /* kCellLoH */
+	0x69, /* kCellLoI */
+	0x6A, /* kCellLoJ */
+	0x6B, /* kCellLoK */
+	0x6C, /* kCellLoL */
+	0x6D, /* kCellLoM */
+	0x6E, /* kCellLoN */
+	0x6F, /* kCellLoO */
+	0x70, /* kCellLoP */
+	0x71, /* kCellLoQ */
+	0x72, /* kCellLoR */
+	0x73, /* kCellLoS */
+	0x74, /* kCellLoT */
+	0x75, /* kCellLoU */
+	0x76, /* kCellLoV */
+	0x77, /* kCellLoW */
+	0x78, /* kCellLoX */
+	0x79, /* kCellLoY */
+	0x7A, /* kCellLoZ */
+	0x30, /* kCellDigit0 */
+	0x31, /* kCellDigit1 */
+	0x32, /* kCellDigit2 */
+	0x33, /* kCellDigit3 */
+	0x34, /* kCellDigit4 */
+	0x35, /* kCellDigit5 */
+	0x36, /* kCellDigit6 */
+	0x37, /* kCellDigit7 */
+	0x38, /* kCellDigit8 */
+	0x39, /* kCellDigit9 */
+	0x21, /* kCellExclamation */
+	0x26, /* kCellAmpersand */
+	0x27, /* kCellApostrophe */
+	0x28, /* kCellLeftParen */
+	0x29, /* kCellRightParen */
+	0x2C, /* kCellComma */
+	0x2D, /* kCellHyphen */
+	0x2E, /* kCellPeriod */
+	0x2F, /* kCellSlash */
+	0x3A, /* kCellColon */
+	0x3B, /* kCellSemicolon */
+	0x3F, /* kCellQuestion */
+	0x85, /* kCellEllipsis */
+	0x5F, /* kCellUnderscore */
+	0x93, /* kCellLeftDQuote */
+	0x94, /* kCellRightDQuote */
+	0x91, /* kCellLeftSQuote */
+	0x92, /* kCellRightSQuote */
+	0xA9, /* kCellCopyright */
+	0x20, /* kCellSpace */
+
+#if NeedIntlChars
+	0xC4, /* kCellUpADiaeresis */
+	0xC5, /* kCellUpARing */
+	0xC7, /* kCellUpCCedilla */
+	0xC9, /* kCellUpEAcute */
+	0xD1, /* kCellUpNTilde */
+	0xD6, /* kCellUpODiaeresis */
+	0xDC, /* kCellUpUDiaeresis */
+	0xE1, /* kCellLoAAcute */
+	0xE0, /* kCellLoAGrave */
+	0xE2, /* kCellLoACircumflex */
+	0xE4, /* kCellLoADiaeresis */
+	0xE3, /* kCellLoATilde */
+	0xE5, /* kCellLoARing */
+	0xE7, /* kCellLoCCedilla */
+	0xE9, /* kCellLoEAcute */
+	0xE8, /* kCellLoEGrave */
+	0xEA, /* kCellLoECircumflex */
+	0xEB, /* kCellLoEDiaeresis */
+	0xED, /* kCellLoIAcute */
+	0xEC, /* kCellLoIGrave */
+	0xEE, /* kCellLoICircumflex */
+	0xEF, /* kCellLoIDiaeresis */
+	0xF1, /* kCellLoNTilde */
+	0xF3, /* kCellLoOAcute */
+	0xF2, /* kCellLoOGrave */
+	0xF4, /* kCellLoOCircumflex */
+	0xF6, /* kCellLoODiaeresis */
+	0xF5, /* kCellLoOTilde */
+	0xFA, /* kCellLoUAcute */
+	0xF9, /* kCellLoUGrave */
+	0xFB, /* kCellLoUCircumflex */
+	0xFC, /* kCellLoUDiaeresis */
+
+	0xC6, /* kCellUpAE */
+	0xD8, /* kCellUpOStroke */
+
+	0xE6, /* kCellLoAE */
+	0xF8, /* kCellLoOStroke */
+	0xBF, /* kCellInvQuestion */
+	0xA1, /* kCellInvExclam */
+
+	0xC0, /* kCellUpAGrave */
+	0xC3, /* kCellUpATilde */
+	0xD5, /* kCellUpOTilde */
+	0x8C, /* kCellUpLigatureOE */
+	0x9C, /* kCellLoLigatureOE */
+
+	0xFF, /* kCellLoYDiaeresis */
+	0x9F, /* kCellUpYDiaeresis */
+
+	0xC2, /* kCellUpACircumflex */
+	0xCA, /* kCellUpECircumflex */
+	0xC1, /* kCellUpAAcute */
+	0xCB, /* kCellUpEDiaeresis */
+	0xC8, /* kCellUpEGrave */
+	0xCD, /* kCellUpIAcute */
+	0xCE, /* kCellUpICircumflex */
+	0xCF, /* kCellUpIDiaeresis */
+	0xCC, /* kCellUpIGrave */
+	0xD3, /* kCellUpOAcute */
+	0xD4, /* kCellUpOCircumflex */
+
+	0xD2, /* kCellUpOGrave */
+	0xDA, /* kCellUpUAcute */
+	0xDB, /* kCellUpUCircumflex */
+	0xD9, /* kCellUpUGrave */
+	0xDF, /* kCellSharpS */
+
+	0x41, /* kCellUpACedille */
+	0x61, /* kCellLoACedille */
+	0x43, /* kCellUpCAcute */
+	0x63, /* kCellLoCAcute */
+	0x45, /* kCellUpECedille */
+	0x65, /* kCellLoECedille */
+	0x4C, /* kCellUpLBar */
+	0x6C, /* kCellLoLBar */
+	0x4E, /* kCellUpNAcute */
+	0x6E, /* kCellLoNAcute */
+	0x53, /* kCellUpSAcute */
+	0x73, /* kCellLoSAcute */
+	0x5A, /* kCellUpZAcute */
+	0x7A, /* kCellLoZAcute */
+	0x5A, /* kCellUpZDot */
+	0x7A, /* kCellLoZDot */
+	0xB7, /* kCellMidDot */
+	0x43, /* kCellUpCCaron */
+	0x63, /* kCellLoCCaron */
+	0x65, /* kCellLoECaron */
+	0x61, /* kCellLoRCaron */
+	0x9A, /* kCellLoSCaron */
+	0x74, /* kCellLoTCaron */
+	0x9E, /* kCellLoZCaron */
+	0xDD, /* kCellUpYAcute */
+	0xFD, /* kCellLoYAcute */
+	0x75, /* kCellLoUDblac */
+	0x75, /* kCellLoURing */
+	0x44, /* kCellUpDStroke */
+	0x64, /* kCellLoDStroke */
+#endif
+
+	'\0' /* just so last above line can end in ',' */
+};
+#endif
+
+#ifndef NeedCell2PlainAsciiMap
+#define NeedCell2PlainAsciiMap 0
+#endif
+
+#if NeedCell2PlainAsciiMap
+/* Plain ascii - remove accents when possible */
+LOCALVAR const char Cell2PlainAsciiMap[] = {
+	'A', /* kCellUpA */
+	'B', /* kCellUpB */
+	'C', /* kCellUpC */
+	'D', /* kCellUpD */
+	'E', /* kCellUpE */
+	'F', /* kCellUpF */
+	'G', /* kCellUpG */
+	'H', /* kCellUpH */
+	'I', /* kCellUpI */
+	'J', /* kCellUpJ */
+	'K', /* kCellUpK */
+	'L', /* kCellUpL */
+	'M', /* kCellUpM */
+	'N', /* kCellUpN */
+	'O', /* kCellUpO */
+	'P', /* kCellUpP */
+	'Q', /* kCellUpQ */
+	'R', /* kCellUpR */
+	'S', /* kCellUpS */
+	'T', /* kCellUpT */
+	'U', /* kCellUpU */
+	'V', /* kCellUpV */
+	'W', /* kCellUpW */
+	'X', /* kCellUpX */
+	'Y', /* kCellUpY */
+	'Z', /* kCellUpZ */
+	'a', /* kCellLoA */
+	'b', /* kCellLoB */
+	'c', /* kCellLoC */
+	'd', /* kCellLoD */
+	'e', /* kCellLoE */
+	'f', /* kCellLoF */
+	'g', /* kCellLoG */
+	'h', /* kCellLoH */
+	'i', /* kCellLoI */
+	'j', /* kCellLoJ */
+	'k', /* kCellLoK */
+	'l', /* kCellLoL */
+	'm', /* kCellLoM */
+	'n', /* kCellLoN */
+	'o', /* kCellLoO */
+	'p', /* kCellLoP */
+	'q', /* kCellLoQ */
+	'r', /* kCellLoR */
+	's', /* kCellLoS */
+	't', /* kCellLoT */
+	'u', /* kCellLoU */
+	'v', /* kCellLoV */
+	'w', /* kCellLoW */
+	'x', /* kCellLoX */
+	'y', /* kCellLoY */
+	'z', /* kCellLoZ */
+	'0', /* kCellDigit0 */
+	'1', /* kCellDigit1 */
+	'2', /* kCellDigit2 */
+	'3', /* kCellDigit3 */
+	'4', /* kCellDigit4 */
+	'5', /* kCellDigit5 */
+	'6', /* kCellDigit6 */
+	'7', /* kCellDigit7 */
+	'8', /* kCellDigit8 */
+	'9', /* kCellDigit9 */
+	'!', /* kCellExclamation */
+	'&', /* kCellAmpersand */
+	'\047', /* kCellApostrophe */
+	'(', /* kCellLeftParen */
+	')', /* kCellRightParen */
+	',', /* kCellComma */
+	'-', /* kCellHyphen */
+	'.', /* kCellPeriod */
+	'/', /* kCellSlash */
+	':', /* kCellColon */
+	';', /* kCellSemicolon */
+	'?', /* kCellQuestion */
+	'_', /* kCellEllipsis */
+	'_', /* kCellUnderscore */
+	'"', /* kCellLeftDQuote */
+	'"', /* kCellRightDQuote */
+	'\047', /* kCellLeftSQuote */
+	'\047', /* kCellRightSQuote */
+	'c', /* kCellCopyright */
+	' ', /* kCellSpace */
+
+#if NeedIntlChars
+	'A', /* kCellUpADiaeresis */
+	'A', /* kCellUpARing */
+	'C', /* kCellUpCCedilla */
+	'E', /* kCellUpEAcute */
+	'N', /* kCellUpNTilde */
+	'O', /* kCellUpODiaeresis */
+	'U', /* kCellUpUDiaeresis */
+	'a', /* kCellLoAAcute */
+	'a', /* kCellLoAGrave */
+	'a', /* kCellLoACircumflex */
+	'a', /* kCellLoADiaeresis */
+	'a', /* kCellLoATilde */
+	'a', /* kCellLoARing */
+	'c', /* kCellLoCCedilla */
+	'e', /* kCellLoEAcute */
+	'e', /* kCellLoEGrave */
+	'e', /* kCellLoECircumflex */
+	'e', /* kCellLoEDiaeresis */
+	'i', /* kCellLoIAcute */
+	'i', /* kCellLoIGrave */
+	'i', /* kCellLoICircumflex */
+	'i', /* kCellLoIDiaeresis */
+	'n', /* kCellLoNTilde */
+	'o', /* kCellLoOAcute */
+	'o', /* kCellLoOGrave */
+	'o', /* kCellLoOCircumflex */
+	'o', /* kCellLoODiaeresis */
+	'o', /* kCellLoOTilde */
+	'u', /* kCellLoUAcute */
+	'u', /* kCellLoUGrave */
+	'u', /* kCellLoUCircumflex */
+	'u', /* kCellLoUDiaeresis */
+
+	'?', /* kCellUpAE */
+	'O', /* kCellUpOStroke */
+
+	'?', /* kCellLoAE */
+	'o', /* kCellLoOStroke */
+	'?', /* kCellInvQuestion */
+	'!', /* kCellInvExclam */
+
+	'A', /* kCellUpAGrave */
+	'A', /* kCellUpATilde */
+	'O', /* kCellUpOTilde */
+	'?', /* kCellUpLigatureOE */
+	'?', /* kCellLoLigatureOE */
+
+	'y', /* kCellLoYDiaeresis */
+	'Y', /* kCellUpYDiaeresis */
+
+	'A', /* kCellUpACircumflex */
+	'E', /* kCellUpECircumflex */
+	'A', /* kCellUpAAcute */
+	'E', /* kCellUpEDiaeresis */
+	'E', /* kCellUpEGrave */
+	'A', /* kCellUpIAcute */
+	'I', /* kCellUpICircumflex */
+	'I', /* kCellUpIDiaeresis */
+	'I', /* kCellUpIGrave */
+	'O', /* kCellUpOAcute */
+	'O', /* kCellUpOCircumflex */
+
+	'O', /* kCellUpOGrave */
+	'U', /* kCellUpUAcute */
+	'U', /* kCellUpUCircumflex */
+	'U', /* kCellUpUGrave */
+	'B', /* kCellSharpS */
+
+	'A', /* kCellUpACedille */
+	'a', /* kCellLoACedille */
+	'C', /* kCellUpCAcute */
+	'c', /* kCellLoCAcute */
+	'E', /* kCellUpECedille */
+	'e', /* kCellLoECedille */
+	'L', /* kCellUpLBar */
+	'l', /* kCellLoLBar */
+	'N', /* kCellUpNAcute */
+	'n', /* kCellLoNAcute */
+	'S', /* kCellUpSAcute */
+	's', /* kCellLoSAcute */
+	'Z', /* kCellUpZAcute */
+	'z', /* kCellLoZAcute */
+	'Z', /* kCellUpZDot */
+	'z', /* kCellLoZDot */
+	'.', /* kCellMidDot */
+	'C', /* kCellUpCCaron */
+	'c', /* kCellLoCCaron */
+	'e', /* kCellLoECaron */
+	'r', /* kCellLoRCaron */
+	's', /* kCellLoSCaron */
+	't', /* kCellLoTCaron */
+	'z', /* kCellLoZCaron */
+	'Y', /* kCellUpYAcute */
+	'y', /* kCellLoYAcute */
+	'u', /* kCellLoUDblac */
+	'u', /* kCellLoURing */
+	'D', /* kCellUpDStroke */
+	'd', /* kCellLoDStroke */
+#endif
+
+	'\0' /* just so last above line can end in ',' */
+};
+#endif
+
+#ifndef NeedCell2UnicodeMap
+#define NeedCell2UnicodeMap 0
+#endif
+
+#if NeedCell2UnicodeMap
+/* Unicode character set */
+LOCALVAR const ui4b Cell2UnicodeMap[] = {
+	0x0041, /* kCellUpA */
+	0x0042, /* kCellUpB */
+	0x0043, /* kCellUpC */
+	0x0044, /* kCellUpD */
+	0x0045, /* kCellUpE */
+	0x0046, /* kCellUpF */
+	0x0047, /* kCellUpG */
+	0x0048, /* kCellUpH */
+	0x0049, /* kCellUpI */
+	0x004A, /* kCellUpJ */
+	0x004B, /* kCellUpK */
+	0x004C, /* kCellUpL */
+	0x004D, /* kCellUpM */
+	0x004E, /* kCellUpN */
+	0x004F, /* kCellUpO */
+	0x0050, /* kCellUpP */
+	0x0051, /* kCellUpQ */
+	0x0052, /* kCellUpR */
+	0x0053, /* kCellUpS */
+	0x0054, /* kCellUpT */
+	0x0055, /* kCellUpU */
+	0x0056, /* kCellUpV */
+	0x0057, /* kCellUpW */
+	0x0058, /* kCellUpX */
+	0x0059, /* kCellUpY */
+	0x005A, /* kCellUpZ */
+	0x0061, /* kCellLoA */
+	0x0062, /* kCellLoB */
+	0x0063, /* kCellLoC */
+	0x0064, /* kCellLoD */
+	0x0065, /* kCellLoE */
+	0x0066, /* kCellLoF */
+	0x0067, /* kCellLoG */
+	0x0068, /* kCellLoH */
+	0x0069, /* kCellLoI */
+	0x006A, /* kCellLoJ */
+	0x006B, /* kCellLoK */
+	0x006C, /* kCellLoL */
+	0x006D, /* kCellLoM */
+	0x006E, /* kCellLoN */
+	0x006F, /* kCellLoO */
+	0x0070, /* kCellLoP */
+	0x0071, /* kCellLoQ */
+	0x0072, /* kCellLoR */
+	0x0073, /* kCellLoS */
+	0x0074, /* kCellLoT */
+	0x0075, /* kCellLoU */
+	0x0076, /* kCellLoV */
+	0x0077, /* kCellLoW */
+	0x0078, /* kCellLoX */
+	0x0079, /* kCellLoY */
+	0x007A, /* kCellLoZ */
+	0x0030, /* kCellDigit0 */
+	0x0031, /* kCellDigit1 */
+	0x0032, /* kCellDigit2 */
+	0x0033, /* kCellDigit3 */
+	0x0034, /* kCellDigit4 */
+	0x0035, /* kCellDigit5 */
+	0x0036, /* kCellDigit6 */
+	0x0037, /* kCellDigit7 */
+	0x0038, /* kCellDigit8 */
+	0x0039, /* kCellDigit9 */
+	0x0021, /* kCellExclamation */
+	0x0026, /* kCellAmpersand */
+	0x0027, /* kCellApostrophe */
+	0x0028, /* kCellLeftParen */
+	0x0029, /* kCellRightParen */
+	0x002C, /* kCellComma */
+	0x002D, /* kCellHyphen */
+	0x002E, /* kCellPeriod */
+	0x002F, /* kCellSlash */
+	0x003A, /* kCellColon */
+	0x003B, /* kCellSemicolon */
+	0x003F, /* kCellQuestion */
+	0x2026, /* kCellEllipsis */
+	0x005F, /* kCellUnderscore */
+	0x201C, /* kCellLeftDQuote */
+	0x201D, /* kCellRightDQuote */
+	0x2018, /* kCellLeftSQuote */
+	0x2019, /* kCellRightSQuote */
+	0x00A9, /* kCellCopyright */
+	0x0020, /* kCellSpace */
+
+#if NeedIntlChars
+	0x00C4, /* kCellUpADiaeresis */
+	0x00C5, /* kCellUpARing */
+	0x00C7, /* kCellUpCCedilla */
+	0x00C9, /* kCellUpEAcute */
+	0x00D1, /* kCellUpNTilde */
+	0x00D6, /* kCellUpODiaeresis */
+	0x00DC, /* kCellUpUDiaeresis */
+	0x00E1, /* kCellLoAAcute */
+	0x00E0, /* kCellLoAGrave */
+	0x00E2, /* kCellLoACircumflex */
+	0x00E4, /* kCellLoADiaeresis */
+	0x00E3, /* kCellLoATilde */
+	0x00E5, /* kCellLoARing */
+	0x00E7, /* kCellLoCCedilla */
+	0x00E9, /* kCellLoEAcute */
+	0x00E8, /* kCellLoEGrave */
+	0x00EA, /* kCellLoECircumflex */
+	0x00EB, /* kCellLoEDiaeresis */
+	0x00ED, /* kCellLoIAcute */
+	0x00EC, /* kCellLoIGrave */
+	0x00EE, /* kCellLoICircumflex */
+	0x00EF, /* kCellLoIDiaeresis */
+	0x00F1, /* kCellLoNTilde */
+	0x00F3, /* kCellLoOAcute */
+	0x00F2, /* kCellLoOGrave */
+	0x00F4, /* kCellLoOCircumflex */
+	0x00F6, /* kCellLoODiaeresis */
+	0x00F5, /* kCellLoOTilde */
+	0x00FA, /* kCellLoUAcute */
+	0x00F9, /* kCellLoUGrave */
+	0x00FB, /* kCellLoUCircumflex */
+	0x00FC, /* kCellLoUDiaeresis */
+
+	0x00C6, /* kCellUpAE */
+	0x00D8, /* kCellUpOStroke */
+
+	0x00E6, /* kCellLoAE */
+	0x00F8, /* kCellLoOStroke */
+	0x00BF, /* kCellInvQuestion */
+	0x00A1, /* kCellInvExclam */
+
+	0x00C0, /* kCellUpAGrave */
+	0x00C3, /* kCellUpATilde */
+	0x00D5, /* kCellUpOTilde */
+	0x0152, /* kCellUpLigatureOE */
+	0x0153, /* kCellLoLigatureOE */
+
+	0x00FF, /* kCellLoYDiaeresis */
+	0x0178, /* kCellUpYDiaeresis */
+
+	0x00C2, /* kCellUpACircumflex */
+	0x00CA, /* kCellUpECircumflex */
+	0x00C1, /* kCellUpAAcute */
+	0x00CB, /* kCellUpEDiaeresis */
+	0x00C8, /* kCellUpEGrave */
+	0x00CD, /* kCellUpIAcute */
+	0x00CE, /* kCellUpICircumflex */
+	0x00CF, /* kCellUpIDiaeresis */
+	0x00CC, /* kCellUpIGrave */
+	0x00D3, /* kCellUpOAcute */
+	0x00D4, /* kCellUpOCircumflex */
+
+	0x00D2, /* kCellUpOGrave */
+	0x00DA, /* kCellUpUAcute */
+	0x00DB, /* kCellUpUCircumflex */
+	0x00D9, /* kCellUpUGrave */
+	0x00DF, /* kCellSharpS */
+
+	0x0104, /* kCellUpACedille */
+	0x0105, /* kCellLoACedille */
+	0x0106, /* kCellUpCAcute */
+	0x0107, /* kCellLoCAcute */
+	0x0118, /* kCellUpECedille */
+	0x0119, /* kCellLoECedille */
+	0x0141, /* kCellUpLBar */
+	0x0142, /* kCellLoLBar */
+	0x0143, /* kCellUpNAcute */
+	0x0144, /* kCellLoNAcute */
+	0x015A, /* kCellUpSAcute */
+	0x015B, /* kCellLoSAcute */
+	0x0179, /* kCellUpZAcute */
+	0x017A, /* kCellLoZAcute */
+	0x017B, /* kCellUpZDot */
+	0x017C, /* kCellLoZDot */
+	0x00B7, /* kCellMidDot */
+	0x010C, /* kCellUpCCaron */
+	0x010D, /* kCellLoCCaron */
+	0x011B, /* kCellLoECaron */
+	0x0159, /* kCellLoRCaron */
+	0x0161, /* kCellLoSCaron */
+	0x0165, /* kCellLoTCaron */
+	0x017E, /* kCellLoZCaron */
+	0x00DD, /* kCellUpYAcute */
+	0x00FD, /* kCellLoYAcute */
+	0x0171, /* kCellLoUDblac */
+	0x016F, /* kCellLoURing */
+	0x0110, /* kCellUpDStroke */
+	0x0111, /* kCellLoDStroke */
+#endif
+
+	'\0' /* just so last above line can end in ',' */
+};
+#endif
+
+LOCALVAR blnr SpeedStopped = falseblnr;
+
+LOCALVAR blnr RunInBackground = (WantInitRunInBackground != 0);
+
+#if VarFullScreen
+LOCALVAR blnr WantFullScreen = (WantInitFullScreen != 0);
+#endif
+
+#if EnableMagnify
+LOCALVAR blnr WantMagnify = (WantInitMagnify != 0);
+#endif
+
+#if NeedRequestInsertDisk
+LOCALVAR blnr RequestInsertDisk = falseblnr;
+#endif
+
+#ifndef NeedRequestIthDisk
+#define NeedRequestIthDisk 0
+#endif
+
+#if NeedRequestIthDisk
+LOCALVAR ui3r RequestIthDisk = 0;
+#endif
+
+#if UseControlKeys
+LOCALVAR blnr ControlKeyPressed = falseblnr;
+#endif
+
+#ifndef kStrCntrlKyName
+#define kStrCntrlKyName "control"
+#endif
+
+#ifndef kControlModeKey
+#define kControlModeKey kStrCntrlKyName
+#endif
+
+#ifndef kUnMappedKey
+#define kUnMappedKey kStrCntrlKyName
+#endif
+
+LOCALFUNC char * GetSubstitutionStr(char x)
+{
+	char *s;
+
+	switch (x) {
+		case 'w':
+			s = kStrHomePage;
+			break;
+		case 'y':
+			s = kStrCopyrightYear;
+			break;
+		case 'p':
+			s = kStrAppName;
+			break;
+		case 'v':
+			s = kAppVariationStr;
+			break;
+		case 'r':
+			s = RomFileName;
+			break;
+		case 'c':
+			s = kControlModeKey;
+			break;
+		case 'm':
+			s = kUnMappedKey;
+			break;
+#if UseControlKeys
+		case 'k':
+			if (ControlKeyPressed) {
+				s = kStrPressed;
+			} else {
+				s = kStrReleased;
+			}
+			break;
+#endif
+#if EnableMagnify
+		case 'g':
+			if (WantMagnify) {
+				s = kStrOn;
+			} else {
+				s = kStrOff;
+			}
+			break;
+#endif
+#if VarFullScreen
+		case 'f':
+			if (WantFullScreen) {
+				s = kStrOn;
+			} else {
+				s = kStrOff;
+			}
+			break;
+#endif
+		case 'b':
+			if (RunInBackground) {
+				s = kStrOn;
+			} else {
+				s = kStrOff;
+			}
+			break;
+		case 'h':
+			if (SpeedStopped) {
+				s = kStrStoppedOn;
+			} else {
+				s = kStrStoppedOff;
+			}
+			break;
+#if EnableAutoSlow
+		case 'l':
+			if (WantNotAutoSlow) {
+				s = kStrStoppedOff;
+			} else {
+				s = kStrStoppedOn;
+			}
+			break;
+#endif
+		case 's':
+			switch (SpeedValue) {
+				case 0:
+					s = "1x";
+					break;
+				case 1:
+					s = "2x";
+					break;
+				case 2:
+					s = "4x";
+					break;
+				case 3:
+					s = "8x";
+					break;
+				case 4:
+					s = "16x";
+					break;
+				case 5:
+					s = "32x";
+					break;
+				default:
+					s = kStrSpeedValueAllOut;
+					break;
+			}
+			break;
+		default:
+			s = "???";
+			break;
+	}
+	return s;
+}
+
+LOCALFUNC int ClStrSizeSubstCStr(char *s)
+{
+	/* must match ClStrAppendSubstCStr ! */
+
+	char *p = s;
+	char c;
+	int L = 0;
+
+	while (0 != (c = *p++)) {
+		if ('^' == c) {
+			if (0 == (c = *p++)) {
+				goto l_exit; /* oops, unexpected end of string, abort */
+			} else if ('^' == c) {
+				++L;
+			} else {
+				L += ClStrSizeSubstCStr(GetSubstitutionStr(c));
+			}
+		} else if (';' == c) {
+			if (0 == (c = *p++)) {
+				goto l_exit; /* oops, unexpected end of string, abort */
+			}
+
+			switch (c) {
+				case 'l':
+#if NeedIntlChars
+				case '`':
+				case 'd':
+				case 'e':
+				case 'i':
+				case 'n':
+				case 'u':
+				case 'v':
+				case 'E':
+				case 'r':
+#endif
+					if (0 == (c = *p++)) {
+						/* oops, unexpected end of string, abort */
+						goto l_exit;
+					}
+					break;
+				default:
+					break;
+			}
+			++L;
+		} else {
+			++L;
+		}
+	}
+
+l_exit:
+	return L;
+}
+
+LOCALPROC ClStrAppendChar(int *L0, ui3b *r, ui3b c)
+{
+	int L = *L0;
+
+	r[L] = c;
+	L++;
+	*L0 = L;
+}
+
+LOCALPROC ClStrAppendSubstCStr(int *L, ui3b *r, char *s)
+{
+	/* must match ClStrSizeSubstCStr ! */
+
+	char *p = s;
+	char c;
+	ui3b x;
+
+	while (0 != (c = *p++)) {
+		if ('^' == c) {
+			if (0 == (c = *p++)) {
+				return; /* oops, unexpected end of string, abort */
+			} else if ('^' == c) {
+				ClStrAppendChar(L, r, c);
+			} else {
+				ClStrAppendSubstCStr(L, r, GetSubstitutionStr(c));
+			}
+		} else if (';' == c) {
+			if (0 == (c = *p++)) {
+				return; /* oops, unexpected end of string, abort */
+			}
+
+			switch (c) {
+				case 'g': x = kCellCopyright; break;
+				case 'l':
+					if (0 == (c = *p++)) {
+						/* oops, unexpected end of string, abort */
+						return;
+					}
+
+					switch (c) {
+						case 'a': x = kCellApostrophe; break;
+						case 'l': x = kCellEllipsis; break;
+						case 's': x = kCellSemicolon; break;
+#if NeedIntlChars
+						case 'E': x = kCellUpAE; break;
+						case 'e': x = kCellLoAE; break;
+						case '.': x = kCellMidDot; break;
+#endif
+						default: x = kCellQuestion; break;
+					}
+					break;
+				case '[': x = kCellLeftDQuote; break;
+				case '{': x = kCellRightDQuote; break;
+				case ']': x = kCellLeftSQuote; break;
+				case '}': x = kCellRightSQuote; break;
+#if NeedIntlChars
+				case '?': x = kCellInvQuestion; break;
+				case 'A': x = kCellUpARing; break;
+				case 'C': x = kCellUpCCedilla; break;
+				case 'O': x = kCellUpOStroke; break;
+				case 'Q': x = kCellUpLigatureOE; break;
+				case '`':
+					if (0 == (c = *p++)) {
+						/* oops, unexpected end of string, abort */
+						return;
+					}
+
+					switch (c) {
+						case 'A': x = kCellUpAGrave; break;
+						case 'E': x = kCellUpEGrave; break;
+						case 'I': x = kCellUpIGrave; break;
+						case 'O': x = kCellUpOGrave; break;
+						case 'U': x = kCellUpUGrave; break;
+						case 'a': x = kCellLoAGrave; break;
+						case 'e': x = kCellLoEGrave; break;
+						case 'i': x = kCellLoIGrave; break;
+						case 'o': x = kCellLoOGrave; break;
+						case 'u': x = kCellLoUGrave; break;
+						default: x = kCellQuestion; break;
+					}
+					break;
+				case 'a': x = kCellLoARing; break;
+				case 'c': x = kCellLoCCedilla; break;
+				case 'd':
+					if (0 == (c = *p++)) {
+						/* oops, unexpected end of string, abort */
+						return;
+					}
+
+					switch (c) {
+						case 'A': x = kCellUpACedille; break;
+						case 'a': x = kCellLoACedille; break;
+						case 'D': x = kCellUpDStroke; break;
+						case 'd': x = kCellLoDStroke; break;
+						case 'E': x = kCellUpECedille; break;
+						case 'e': x = kCellLoECedille; break;
+						case 'L': x = kCellUpLBar; break;
+						case 'l': x = kCellLoLBar; break;
+						case 'Z': x = kCellUpZDot; break;
+						case 'z': x = kCellLoZDot; break;
+						default: x = kCellQuestion; break;
+					}
+					break;
+				case 'e':
+					if (0 == (c = *p++)) {
+						/* oops, unexpected end of string, abort */
+						return;
+					}
+
+					switch (c) {
+						case 'A': x = kCellUpAAcute; break;
+						case 'E': x = kCellUpEAcute; break;
+						case 'I': x = kCellUpIAcute; break;
+						case 'O': x = kCellUpOAcute; break;
+						case 'U': x = kCellUpUAcute; break;
+						case 'a': x = kCellLoAAcute; break;
+						case 'e': x = kCellLoEAcute; break;
+						case 'i': x = kCellLoIAcute; break;
+						case 'o': x = kCellLoOAcute; break;
+						case 'u': x = kCellLoUAcute; break;
+
+						case 'C': x = kCellUpCAcute; break;
+						case 'c': x = kCellLoCAcute; break;
+						case 'N': x = kCellUpNAcute; break;
+						case 'n': x = kCellLoNAcute; break;
+						case 'S': x = kCellUpSAcute; break;
+						case 's': x = kCellLoSAcute; break;
+						case 'Z': x = kCellUpZAcute; break;
+						case 'z': x = kCellLoZAcute; break;
+						case 'Y': x = kCellUpYAcute; break;
+						case 'y': x = kCellLoYAcute; break;
+
+						default: x = kCellQuestion; break;
+					}
+					break;
+				case 'i':
+					if (0 == (c = *p++)) {
+						/* oops, unexpected end of string, abort */
+						return;
+					}
+
+					switch (c) {
+						case 'A': x = kCellUpACircumflex; break;
+						case 'E': x = kCellUpECircumflex; break;
+						case 'I': x = kCellUpICircumflex; break;
+						case 'O': x = kCellUpOCircumflex; break;
+						case 'U': x = kCellUpUCircumflex; break;
+						case 'a': x = kCellLoACircumflex; break;
+						case 'e': x = kCellLoECircumflex; break;
+						case 'i': x = kCellLoICircumflex; break;
+						case 'o': x = kCellLoOCircumflex; break;
+						case 'u': x = kCellLoUCircumflex; break;
+						default: x = kCellQuestion; break;
+					}
+					break;
+				case 'n':
+					if (0 == (c = *p++)) {
+						/* oops, unexpected end of string, abort */
+						return;
+					}
+
+					switch (c) {
+						case 'A': x = kCellUpATilde; break;
+						case 'N': x = kCellUpNTilde; break;
+						case 'O': x = kCellUpOTilde; break;
+						case 'a': x = kCellLoATilde; break;
+						case 'n': x = kCellLoNTilde; break;
+						case 'o': x = kCellLoOTilde; break;
+						default: x = kCellQuestion; break;
+					}
+					break;
+				case 'o': x = kCellLoOStroke; break;
+				case 'q': x = kCellLoLigatureOE; break;
+				case 's': x = kCellSharpS; break;
+				case 'u':
+					if (0 == (c = *p++)) {
+						/* oops, unexpected end of string, abort */
+						return;
+					}
+
+					switch (c) {
+						case 'A': x = kCellUpADiaeresis; break;
+						case 'E': x = kCellUpEDiaeresis; break;
+						case 'I': x = kCellUpIDiaeresis; break;
+						case 'O': x = kCellUpODiaeresis; break;
+						case 'U': x = kCellUpUDiaeresis; break;
+						case 'Y': x = kCellUpYDiaeresis; break;
+						case 'a': x = kCellLoADiaeresis; break;
+						case 'e': x = kCellLoEDiaeresis; break;
+						case 'i': x = kCellLoIDiaeresis; break;
+						case 'o': x = kCellLoODiaeresis; break;
+						case 'u': x = kCellLoUDiaeresis; break;
+						case 'y': x = kCellLoYDiaeresis; break;
+						default: x = kCellQuestion; break;
+					}
+					break;
+				case 'v':
+					if (0 == (c = *p++)) {
+						/* oops, unexpected end of string, abort */
+						return;
+					}
+
+					switch (c) {
+						case 'C': x = kCellUpCCaron; break;
+						case 'c': x = kCellLoCCaron; break;
+						case 'e': x = kCellLoECaron; break;
+						case 'r': x = kCellLoRCaron; break;
+						case 's': x = kCellLoSCaron; break;
+						case 't': x = kCellLoTCaron; break;
+						case 'z': x = kCellLoZCaron; break;
+						default: x = kCellQuestion; break;
+					}
+					break;
+				case 'E':
+					if (0 == (c = *p++)) {
+						/* oops, unexpected end of string, abort */
+						return;
+					}
+
+					switch (c) {
+						case 'u': x = kCellLoUDblac; break;
+						default: x = kCellQuestion; break;
+					}
+					break;
+				case 'r':
+					if (0 == (c = *p++)) {
+						/* oops, unexpected end of string, abort */
+						return;
+					}
+
+					switch (c) {
+						case 'u': x = kCellLoURing; break;
+						default: x = kCellQuestion; break;
+					}
+					break;
+#endif
+				default: x = kCellQuestion; break;
+			}
+			ClStrAppendChar(L, r, x);
+		} else {
+			switch (c) {
+				case 'A': x = kCellUpA; break;
+				case 'B': x = kCellUpB; break;
+				case 'C': x = kCellUpC; break;
+				case 'D': x = kCellUpD; break;
+				case 'E': x = kCellUpE; break;
+				case 'F': x = kCellUpF; break;
+				case 'G': x = kCellUpG; break;
+				case 'H': x = kCellUpH; break;
+				case 'I': x = kCellUpI; break;
+				case 'J': x = kCellUpJ; break;
+				case 'K': x = kCellUpK; break;
+				case 'L': x = kCellUpL; break;
+				case 'M': x = kCellUpM; break;
+				case 'N': x = kCellUpN; break;
+				case 'O': x = kCellUpO; break;
+				case 'P': x = kCellUpP; break;
+				case 'Q': x = kCellUpQ; break;
+				case 'R': x = kCellUpR; break;
+				case 'S': x = kCellUpS; break;
+				case 'T': x = kCellUpT; break;
+				case 'U': x = kCellUpU; break;
+				case 'V': x = kCellUpV; break;
+				case 'W': x = kCellUpW; break;
+				case 'X': x = kCellUpX; break;
+				case 'Y': x = kCellUpY; break;
+				case 'Z': x = kCellUpZ; break;
+				case 'a': x = kCellLoA; break;
+				case 'b': x = kCellLoB; break;
+				case 'c': x = kCellLoC; break;
+				case 'd': x = kCellLoD; break;
+				case 'e': x = kCellLoE; break;
+				case 'f': x = kCellLoF; break;
+				case 'g': x = kCellLoG; break;
+				case 'h': x = kCellLoH; break;
+				case 'i': x = kCellLoI; break;
+				case 'j': x = kCellLoJ; break;
+				case 'k': x = kCellLoK; break;
+				case 'l': x = kCellLoL; break;
+				case 'm': x = kCellLoM; break;
+				case 'n': x = kCellLoN; break;
+				case 'o': x = kCellLoO; break;
+				case 'p': x = kCellLoP; break;
+				case 'q': x = kCellLoQ; break;
+				case 'r': x = kCellLoR; break;
+				case 's': x = kCellLoS; break;
+				case 't': x = kCellLoT; break;
+				case 'u': x = kCellLoU; break;
+				case 'v': x = kCellLoV; break;
+				case 'w': x = kCellLoW; break;
+				case 'x': x = kCellLoX; break;
+				case 'y': x = kCellLoY; break;
+				case 'z': x = kCellLoZ; break;
+				case '0': x = kCellDigit0; break;
+				case '1': x = kCellDigit1; break;
+				case '2': x = kCellDigit2; break;
+				case '3': x = kCellDigit3; break;
+				case '4': x = kCellDigit4; break;
+				case '5': x = kCellDigit5; break;
+				case '6': x = kCellDigit6; break;
+				case '7': x = kCellDigit7; break;
+				case '8': x = kCellDigit8; break;
+				case '9': x = kCellDigit9; break;
+				case '!': x = kCellExclamation; break;
+				case '&': x = kCellAmpersand; break;
+				case '(': x = kCellLeftParen; break;
+				case ')': x = kCellRightParen; break;
+				case ',': x = kCellComma; break;
+				case '-': x = kCellHyphen; break;
+				case '.': x = kCellPeriod; break;
+				case '/': x = kCellSlash; break;
+				case ':': x = kCellColon; break;
+				case ';': x = kCellSemicolon; break;
+				case '?': x = kCellQuestion; break;
+				case '_': x = kCellUnderscore; break;
+				case ' ': x = kCellSpace; break;
+				case '\047': x = kCellApostrophe; break;
+
+				default: x = kCellQuestion; break;
+			}
+			ClStrAppendChar(L, r, x);
+		}
+	}
+}
+
+#define ClStrMaxLength 512
+
+LOCALPROC ClStrFromSubstCStr(int *L, ui3b *r, char *s)
+{
+	int n = ClStrSizeSubstCStr(s);
+
+	*L = 0;
+	if (n <= ClStrMaxLength) {
+		ClStrAppendSubstCStr(L, r, s);
+
+		if (n != *L) {
+			/* try to ensure mismatch is noticed */
+			*L = 0;
+		}
+	}
+}
--- /dev/null
+++ b/src/IWMEMDEV.c
@@ -1,0 +1,214 @@
+/*
+	IWMEVDEV.c
+
+	Copyright (C) 2006 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Integrated Woz Machine EMulated DEVice
+
+	Emulates the IWM found in the Mac Plus.
+
+	This code is adapted from "IWM.c" in vMac by Philip Cummins.
+*/
+
+/*
+	This is the emulation for the IWM, the Integrated Woz Machine.
+	It's basically a serial to parallel converter with some timing
+	in-built into it to perform handshaking. Emulation so far just
+	includes Status and Mode Register Accesses.
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+
+#include "MYOSGLUE.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+#endif
+
+#include "IWMEMDEV.h"
+
+/*
+	ReportAbnormalID unused 0x0603 - 0x06FF
+*/
+
+#define kph0L     0x00 /* CA0 off (0) */
+#define kph0H     0x01 /* CA0 on (1) */
+#define kph1L     0x02 /* CA1 off (0) */
+#define kph1H     0x03 /* CA1 on (1) */
+#define kph2L     0x04 /* CA2 off (0) */
+#define kph2H     0x05 /* CA2 on (1) */
+#define kph3L     0x06 /* LSTRB off (low) */
+#define kph3H     0x07 /* LSTRB on (high) */
+#define kmtrOff   0x08 /* disk enable off */
+#define kmtrOn    0x09 /* disk enable on */
+#define kintDrive 0x0A /* select internal drive */
+#define kextDrive 0x0B /* select external drive */
+#define kq6L      0x0C /* Q6 off */
+#define kq6H      0x0D /* Q6 on */
+#define kq7L      0x0E /* Q7 off */
+#define kq7H      0x0F /* Q7 on */
+
+#define kph0 0x01
+#define kph1 0x02
+#define kph2 0x04
+#define kph3 0x08
+#define kmtr 0x10
+#define kdrv 0x20
+#define kq6  0x40
+#define kq7  0x80
+
+typedef struct
+{
+	ui3b DataIn;    /* Read Data Register */
+	ui3b Handshake; /* Read Handshake Register */
+	ui3b Status;    /* Read Status Register */
+	ui3b Mode;
+		/* Drive Off : Write Mode Register */
+		/* Drive On  : Write Data Register */
+	ui3b DataOut;   /* Write Data Register */
+	ui3b Lines;     /* Used to Access Disk Drive Registers */
+} IWM_Ty;
+
+IWM_Ty IWM;
+
+GLOBALPROC IWM_Reset(void)
+{
+	IWM.DataIn = IWM.Handshake = IWM.Status = IWM.Mode =
+		IWM.DataOut = IWM.Lines = 0;
+}
+
+typedef enum {On, Off} Mode_Ty;
+
+LOCALPROC IWM_Set_Lines(ui3b line, Mode_Ty the_mode)
+{
+	if (the_mode == Off) {
+		IWM.Lines &= (0xFF - line);
+	} else {
+		IWM.Lines |= line;
+	}
+}
+
+LOCALFUNC ui3b IWM_Read_Reg(void)
+{
+	switch ((IWM.Lines & (kq6 + kq7)) >> 6) {
+		case 0 :
+#if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx)
+			/* don't report */
+#else
+			ReportAbnormalID(0x0601, "IWM Data Read");
+#endif
+#ifdef _IWM_Debug
+			printf("IWM Data Read\n");
+#endif
+			return IWM.DataIn;
+			break;
+		case 1 :
+#ifdef _IWM_Debug
+			printf("IWM Status Read\n");
+#endif
+			return IWM.Status;
+			break;
+		case 2 :
+			ReportAbnormalID(0x0602, "IWM Handshake Read");
+#ifdef _IWM_Debug
+			printf("IWM Handshake Read\n");
+#endif
+			return IWM.Handshake;
+			break;
+		case 3 :
+		default :
+			/*
+				should alway be in 0-3,
+				but compiler warnings don't know that
+			*/
+			return 0;
+			break;
+	}
+}
+
+LOCALPROC IWM_Write_Reg(ui3b in)
+{
+	if (((IWM.Lines & kmtr) >> 4) == 0) {
+#ifdef _IWM_Debug
+		printf("IWM Mode Register Write\n");
+#endif
+		IWM.Mode = in;
+		IWM.Status = ((IWM.Status & 0xE0) + (IWM.Mode & 0x1F));
+	}
+}
+
+GLOBALFUNC ui5b IWM_Access(ui5b Data, blnr WriteMem, CPTR addr)
+{
+	switch (addr) {
+		case kph0L :
+			IWM_Set_Lines(kph0, Off);
+			break;
+		case kph0H :
+			IWM_Set_Lines(kph0, On);
+			break;
+		case kph1L :
+			IWM_Set_Lines(kph1, Off);
+			break;
+		case kph1H :
+			IWM_Set_Lines(kph1, On);
+			break;
+		case kph2L :
+			IWM_Set_Lines(kph2, Off);
+			break;
+		case kph2H :
+			IWM_Set_Lines(kph2, On);
+			break;
+		case kph3L :
+			IWM_Set_Lines(kph3, Off);
+			break;
+		case kph3H :
+			IWM_Set_Lines(kph3, On);
+			break;
+		case kmtrOff :
+			IWM.Status &= 0xDF;
+			IWM_Set_Lines(kmtr, Off);
+			break;
+		case kmtrOn :
+			IWM.Status |= 0x20;
+			IWM_Set_Lines(kmtr, On);
+			break;
+		case kintDrive :
+			IWM_Set_Lines(kdrv, Off);
+			break;
+		case kextDrive :
+			IWM_Set_Lines(kdrv, On);
+			break;
+		case kq6L :
+			IWM_Set_Lines(kq6, Off);
+			break;
+		case kq6H :
+			IWM_Set_Lines(kq6, On);
+			break;
+		case kq7L :
+			if (! WriteMem) {
+				Data = IWM_Read_Reg();
+			}
+			IWM_Set_Lines(kq7, Off);
+			break;
+		case kq7H :
+			if (WriteMem) {
+				IWM_Write_Reg(Data);
+			}
+			IWM_Set_Lines(kq7, On);
+			break;
+	}
+
+	return Data;
+}
--- /dev/null
+++ b/src/IWMEMDEV.h
@@ -1,0 +1,25 @@
+/*
+	IWMEVDEV.h
+
+	Copyright (C) 2004 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef IWMEVDEV_H
+#error "header already included"
+#else
+#define IWMEVDEV_H
+#endif
+
+EXPORTPROC IWM_Reset(void);
+
+EXPORTFUNC ui5b IWM_Access(ui5b Data, blnr WriteMem, CPTR addr);
--- /dev/null
+++ b/src/KBRDEMDV.c
@@ -1,0 +1,214 @@
+/*
+	KBRDEMDV.c
+
+	Copyright (C) 2006 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	KeyBoaRD EMulated DeVice
+
+	Emulation of the keyboard in the Mac Plus.
+
+	This code adapted from "Keyboard.c" in vMac by Philip Cummins.
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+#include "MYOSGLUE.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+#endif
+
+#include "KBRDEMDV.h"
+
+#ifdef _VIA_Debug
+#include <stdio.h>
+#endif
+
+/*
+	ReportAbnormalID unused 0x0B03 - 0x0BFF
+*/
+
+IMPORTPROC KYBD_ShiftOutData(ui3b v);
+IMPORTFUNC ui3b KYBD_ShiftInData(void);
+
+enum {
+	kKybdStateIdle,
+	kKybdStateRecievingCommand,
+	kKybdStateRecievedCommand,
+	kKybdStateRecievingEndCommand,
+
+	kKybdStates
+};
+
+LOCALVAR int KybdState = kKybdStateIdle;
+
+LOCALVAR blnr HaveKeyBoardResult = falseblnr;
+LOCALVAR ui3b KeyBoardResult;
+
+LOCALPROC GotKeyBoardData(ui3b v)
+{
+	if (KybdState != kKybdStateIdle) {
+		HaveKeyBoardResult = trueblnr;
+		KeyBoardResult = v;
+	} else {
+		KYBD_ShiftOutData(v);
+		VIA1_iCB2 = 1;
+	}
+}
+
+LOCALVAR ui3b InstantCommandData = 0x7B;
+
+LOCALFUNC blnr AttemptToFinishInquiry(void)
+{
+	int i;
+	blnr KeyDown;
+	ui3b Keyboard_Data;
+
+	if (FindKeyEvent(&i, &KeyDown)) {
+		if (i < 64) {
+			Keyboard_Data = i << 1;
+			if (! KeyDown) {
+				Keyboard_Data += 128;
+			}
+		} else {
+			Keyboard_Data = 121;
+			InstantCommandData = (i - 64) << 1;
+			if (! KeyDown) {
+				InstantCommandData += 128;
+			}
+		}
+		GotKeyBoardData(Keyboard_Data);
+		return trueblnr;
+	} else {
+		return falseblnr;
+	}
+}
+
+#define MaxKeyboardWait 16 /* in 60ths of a second */
+	/*
+		Code in the mac rom will reset the keyboard if
+		it hasn't been heard from in 32/60th of a second.
+		So time out and send something before that
+		to keep connection.
+	*/
+
+LOCALVAR int InquiryCommandTimer = 0;
+
+GLOBALPROC DoKybd_ReceiveCommand(void)
+{
+	if (KybdState != kKybdStateRecievingCommand) {
+		ReportAbnormalID(0x0B01,
+			"KybdState != kKybdStateRecievingCommand");
+	} else {
+		ui3b in = KYBD_ShiftInData();
+
+		KybdState = kKybdStateRecievedCommand;
+
+		switch (in) {
+			case 0x10 : /* Inquiry Command */
+				if (! AttemptToFinishInquiry()) {
+					InquiryCommandTimer = MaxKeyboardWait;
+				}
+				break;
+			case 0x14 : /* Instant Command */
+				GotKeyBoardData(InstantCommandData);
+				InstantCommandData = 0x7B;
+				break;
+			case 0x16 : /* Model Command */
+				GotKeyBoardData(0x0b /* 0x01 */);
+					/* Test value, means Model 0, no extra devices */
+				/*
+					Fixed by Hoshi Takanori -
+						it uses the proper keyboard type now
+				*/
+				break;
+			case 0x36 : /* Test Command */
+				GotKeyBoardData(0x7D);
+				break;
+			case 0x00:
+				GotKeyBoardData(0);
+				break;
+			default :
+				/* Debugger(); */
+				GotKeyBoardData(0);
+				break;
+		}
+	}
+}
+
+GLOBALPROC DoKybd_ReceiveEndCommand(void)
+{
+	if (KybdState != kKybdStateRecievingEndCommand) {
+		ReportAbnormalID(0x0B02,
+			"KybdState != kKybdStateRecievingEndCommand");
+	} else {
+		KybdState = kKybdStateIdle;
+#ifdef _VIA_Debug
+		fprintf(stderr, "enter DoKybd_ReceiveEndCommand\n");
+#endif
+		if (HaveKeyBoardResult) {
+#ifdef _VIA_Debug
+			fprintf(stderr, "HaveKeyBoardResult: %d\n", KeyBoardResult);
+#endif
+			HaveKeyBoardResult = falseblnr;
+			KYBD_ShiftOutData(KeyBoardResult);
+			VIA1_iCB2 = 1;
+		}
+	}
+}
+
+GLOBALPROC Kybd_DataLineChngNtfy(void)
+{
+	switch (KybdState) {
+		case kKybdStateIdle:
+			if (VIA1_iCB2 == 0) {
+				KybdState = kKybdStateRecievingCommand;
+#ifdef _VIA_Debug
+				fprintf(stderr, "posting kICT_Kybd_ReceiveCommand\n");
+#endif
+				ICT_add(kICT_Kybd_ReceiveCommand,
+					6800UL * kCycleScale / 64 * kMyClockMult);
+
+				if (InquiryCommandTimer != 0) {
+					InquiryCommandTimer = 0; /* abort Inquiry */
+				}
+			}
+			break;
+		case kKybdStateRecievedCommand:
+			if (VIA1_iCB2 == 1) {
+				KybdState = kKybdStateRecievingEndCommand;
+#ifdef _VIA_Debug
+				fprintf(stderr,
+					"posting kICT_Kybd_ReceiveEndCommand\n");
+#endif
+				ICT_add(kICT_Kybd_ReceiveEndCommand,
+					6800UL * kCycleScale / 64 * kMyClockMult);
+			}
+			break;
+	}
+}
+
+GLOBALPROC KeyBoard_Update(void)
+{
+	if (InquiryCommandTimer != 0) {
+		if (AttemptToFinishInquiry()) {
+			InquiryCommandTimer = 0;
+		} else {
+			--InquiryCommandTimer;
+			if (InquiryCommandTimer == 0) {
+				GotKeyBoardData(0x7B);
+			}
+		}
+	}
+}
--- /dev/null
+++ b/src/KBRDEMDV.h
@@ -1,0 +1,27 @@
+/*
+	KBRDEMDV.h
+
+	Copyright (C) 2003 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef KBRDEMDV_H
+#error "header already included"
+#else
+#define KBRDEMDV_H
+#endif
+
+
+EXPORTPROC Kybd_DataLineChngNtfy(void);
+EXPORTPROC DoKybd_ReceiveEndCommand(void);
+EXPORTPROC DoKybd_ReceiveCommand(void);
+EXPORTPROC KeyBoard_Update(void);
--- /dev/null
+++ b/src/M68KITAB.c
@@ -1,0 +1,3072 @@
+/*
+	M68KITAB.c
+
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Motorola 68K Instructions TABle
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+#endif
+
+#include "MYOSGLUE.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+
+#include "M68KITAB.h"
+
+struct WorkR {
+	/* expected size : 8 bytes */
+	ui5b opcode;
+	ui5b opsize;
+	ui4r MainClass;
+#if WantCycByPriOp
+	ui4r Cycles;
+#endif
+	DecOpR DecOp;
+};
+typedef struct WorkR WorkR;
+
+#define b76(p) ((p->opcode >> 6) & 3)
+#define b8(p) ((p->opcode >> 8) & 1)
+#define mode(p) ((p->opcode >> 3) & 7)
+#define reg(p) (p->opcode & 7)
+#define md6(p) ((p->opcode >> 6) & 7)
+#define rg9(p) ((p->opcode >> 9) & 7)
+
+enum {
+	kAddrValidAny,
+	kAddrValidData,
+	kAddrValidDataAlt,
+	kAddrValidControl,
+	kAddrValidControlAlt,
+	kAddrValidAltMem,
+	kAddrValidDataNoCn, /* no constants (immediate data) */
+
+	kNumAddrValids
+};
+
+#define kAddrValidMaskAny        (1 << kAddrValidAny)
+#define kAddrValidMaskData       (1 << kAddrValidData)
+#define kAddrValidMaskDataAlt    (1 << kAddrValidDataAlt)
+#define kAddrValidMaskControl    (1 << kAddrValidControl)
+#define kAddrValidMaskControlAlt (1 << kAddrValidControlAlt)
+#define kAddrValidMaskAltMem     (1 << kAddrValidAltMem)
+#define kAddrValidMaskDataNoCn   (1 << kAddrValidDataNoCn)
+
+#define CheckInSet(v, m) (0 != ((1 << (v)) & (m)))
+
+#define kMyAvgCycPerInstr (10 * kCycleScale + (40 * kCycleScale / 64))
+
+LOCALFUNC ui3r GetAMdRegSz(WorkR *p)
+{
+	ui3r CurAMd;
+
+	switch (p->opsize) {
+		case 1:
+			CurAMd = kAMdRegB;
+			break;
+		case 2:
+		default: /* keep compiler happy */
+			CurAMd = kAMdRegW;
+			break;
+		case 4:
+			CurAMd = kAMdRegL;
+			break;
+	}
+
+	return CurAMd;
+}
+
+LOCALFUNC ui3r GetAMdIndirectSz(WorkR *p)
+{
+	ui3r CurAMd;
+
+	switch (p->opsize) {
+		case 1:
+			CurAMd = kAMdIndirectB;
+			break;
+		case 2:
+		default: /* keep compiler happy */
+			CurAMd = kAMdIndirectW;
+			break;
+		case 4:
+			CurAMd = kAMdIndirectL;
+			break;
+	}
+
+	return CurAMd;
+}
+
+#if WantCycByPriOp
+LOCALFUNC ui4r OpEACalcCyc(WorkR *p, ui3r m, ui3r r)
+{
+	ui4r v;
+
+	switch (m) {
+		case 0:
+		case 1:
+			v = 0;
+			break;
+		case 2:
+			v = ((4 == p->opsize)
+				? (8 * kCycleScale + 2 * RdAvgXtraCyc)
+				: (4 * kCycleScale + RdAvgXtraCyc));
+			break;
+		case 3:
+			v = ((4 == p->opsize)
+				? (8 * kCycleScale + 2 * RdAvgXtraCyc)
+				: (4 * kCycleScale + RdAvgXtraCyc));
+			break;
+		case 4:
+			v = ((4 == p->opsize)
+				? (10 * kCycleScale + 2 * RdAvgXtraCyc)
+				: (6 * kCycleScale + RdAvgXtraCyc));
+			break;
+		case 5:
+			v = ((4 == p->opsize)
+				? (12 * kCycleScale + 3 * RdAvgXtraCyc)
+				: (8 * kCycleScale + 2 * RdAvgXtraCyc));
+			break;
+		case 6:
+			v = ((4 == p->opsize)
+				? (14 * kCycleScale + 3 * RdAvgXtraCyc)
+				: (10 * kCycleScale + 2 * RdAvgXtraCyc));
+			break;
+		case 7:
+			switch (r) {
+				case 0:
+					v = ((4 == p->opsize)
+						? (12 * kCycleScale + 3 * RdAvgXtraCyc)
+						: (8 * kCycleScale + 2 * RdAvgXtraCyc));
+					break;
+				case 1:
+					v = ((4 == p->opsize)
+						? (16 * kCycleScale + 4 * RdAvgXtraCyc)
+						: (12 * kCycleScale + 3 * RdAvgXtraCyc));
+					break;
+				case 2:
+					v = ((4 == p->opsize)
+						? (12 * kCycleScale + 3 * RdAvgXtraCyc)
+						: (8 * kCycleScale + 2 * RdAvgXtraCyc));
+					break;
+				case 3:
+					v = ((4 == p->opsize)
+						? (14 * kCycleScale + 3 * RdAvgXtraCyc)
+						: (10 * kCycleScale + 2 * RdAvgXtraCyc));
+					break;
+				case 4:
+					v = ((4 == p->opsize)
+						? (8 * kCycleScale + 2 * RdAvgXtraCyc)
+						: (4 * kCycleScale + RdAvgXtraCyc));
+					break;
+				default:
+					v = 0;
+					break;
+			}
+			break;
+		default: /* keep compiler happy */
+			v = 0;
+			break;
+	}
+
+	return v;
+}
+#endif
+
+#if WantCycByPriOp
+LOCALFUNC ui4r OpEADestCalcCyc(WorkR *p, ui3r m, ui3r r)
+{
+	ui4r v;
+
+	switch (m) {
+		case 0:
+		case 1:
+			v = 0;
+			break;
+		case 2:
+			v = ((4 == p->opsize)
+				? (8 * kCycleScale + 2 * WrAvgXtraCyc)
+				: (4 * kCycleScale + WrAvgXtraCyc));
+			break;
+		case 3:
+			v = ((4 == p->opsize)
+				? (8 * kCycleScale + 2 * WrAvgXtraCyc)
+				: (4 * kCycleScale + WrAvgXtraCyc));
+			break;
+		case 4:
+			v = ((4 == p->opsize)
+				? (8 * kCycleScale + 2 * WrAvgXtraCyc)
+				: (4 * kCycleScale + WrAvgXtraCyc));
+			break;
+		case 5:
+			v = ((4 == p->opsize)
+				? (12 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc)
+				: (8 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc));
+			break;
+		case 6:
+			v = ((4 == p->opsize)
+				? (14 * kCycleScale + RdAvgXtraCyc + 2 * WrAvgXtraCyc)
+				: (10 * kCycleScale + RdAvgXtraCyc + WrAvgXtraCyc));
+			break;
+		case 7:
+			switch (r) {
+				case 0:
+					v = ((4 == p->opsize)
+						? (12 * kCycleScale
+							+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
+						: (8 * kCycleScale
+							+ RdAvgXtraCyc + WrAvgXtraCyc));
+					break;
+				case 1:
+					v = ((4 == p->opsize)
+						? (16 * kCycleScale
+							+ 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc)
+						: (12 * kCycleScale
+							+ 2 * RdAvgXtraCyc + WrAvgXtraCyc));
+					break;
+				default:
+					v = 0;
+					break;
+			}
+			break;
+		default: /* keep compiler happy */
+			v = 0;
+			break;
+	}
+
+	return v;
+}
+#endif
+
+LOCALPROC SetDcoArgFields(WorkR *p, blnr src,
+	ui3r CurAMd, ui3r CurArgDat)
+{
+	if (src) {
+		p->DecOp.y.v[0].AMd = CurAMd;
+		p->DecOp.y.v[0].ArgDat = CurArgDat;
+	} else {
+		p->DecOp.y.v[1].AMd = CurAMd;
+		p->DecOp.y.v[1].ArgDat = CurArgDat;
+	}
+}
+
+LOCALFUNC blnr CheckValidAddrMode(WorkR *p,
+	ui3r m, ui3r r, ui3r v, blnr src)
+{
+	ui3r CurAMd = 0; /* init to keep compiler happy */
+	ui3r CurArgDat = 0;
+	blnr IsOk;
+
+	switch (m) {
+		case 0:
+			CurAMd = GetAMdRegSz(p);
+			CurArgDat = r;
+			IsOk = CheckInSet(v,
+				kAddrValidMaskAny | kAddrValidMaskData
+					| kAddrValidMaskDataAlt | kAddrValidMaskDataNoCn);
+			break;
+		case 1:
+			CurAMd = GetAMdRegSz(p);
+			CurArgDat = r + 8;
+			IsOk = CheckInSet(v, kAddrValidMaskAny);
+			break;
+		case 2:
+			CurAMd = GetAMdIndirectSz(p);
+			CurArgDat = r + 8;
+			IsOk = CheckInSet(v,
+				kAddrValidMaskAny | kAddrValidMaskData
+					| kAddrValidMaskDataAlt | kAddrValidMaskControl
+					| kAddrValidMaskControlAlt | kAddrValidMaskAltMem
+					| kAddrValidMaskDataNoCn);
+			break;
+		case 3:
+			switch (p->opsize) {
+				case 1:
+					if (7 == r) {
+						CurAMd = kAMdAPosInc7B;
+					} else {
+						CurAMd = kAMdAPosIncB;
+					}
+					break;
+				case 2:
+				default: /* keep compiler happy */
+					CurAMd = kAMdAPosIncW;
+					break;
+				case 4:
+					CurAMd = kAMdAPosIncL;
+					break;
+			}
+			CurArgDat = r + 8;
+			IsOk = CheckInSet(v,
+				kAddrValidMaskAny | kAddrValidMaskData
+					| kAddrValidMaskDataAlt | kAddrValidMaskAltMem
+					| kAddrValidMaskDataNoCn);
+			break;
+		case 4:
+			switch (p->opsize) {
+				case 1:
+					if (7 == r) {
+						CurAMd = kAMdAPreDec7B;
+					} else {
+						CurAMd = kAMdAPreDecB;
+					}
+					break;
+				case 2:
+				default: /* keep compiler happy */
+					CurAMd = kAMdAPreDecW;
+					break;
+				case 4:
+					CurAMd = kAMdAPreDecL;
+					break;
+			}
+			CurArgDat = r + 8;
+			IsOk = CheckInSet(v,
+				kAddrValidMaskAny | kAddrValidMaskData
+					| kAddrValidMaskDataAlt | kAddrValidMaskAltMem
+					| kAddrValidMaskDataNoCn);
+			break;
+		case 5:
+			switch (p->opsize) {
+				case 1:
+					CurAMd = kAMdADispB;
+					break;
+				case 2:
+				default: /* keep compiler happy */
+					CurAMd = kAMdADispW;
+					break;
+				case 4:
+					CurAMd = kAMdADispL;
+					break;
+			}
+			CurArgDat = r + 8;
+			IsOk = CheckInSet(v,
+				kAddrValidMaskAny | kAddrValidMaskData
+					| kAddrValidMaskDataAlt | kAddrValidMaskControl
+					| kAddrValidMaskControlAlt | kAddrValidMaskAltMem
+					| kAddrValidMaskDataNoCn);
+			break;
+		case 6:
+			switch (p->opsize) {
+				case 1:
+					CurAMd = kAMdAIndexB;
+					break;
+				case 2:
+				default: /* keep compiler happy */
+					CurAMd = kAMdAIndexW;
+					break;
+				case 4:
+					CurAMd = kAMdAIndexL;
+					break;
+			}
+			CurArgDat = r + 8;
+			IsOk = CheckInSet(v,
+				kAddrValidMaskAny | kAddrValidMaskData
+					| kAddrValidMaskDataAlt | kAddrValidMaskControl
+					| kAddrValidMaskControlAlt | kAddrValidMaskAltMem
+					| kAddrValidMaskDataNoCn);
+			break;
+		case 7:
+			switch (r) {
+				case 0:
+					switch (p->opsize) {
+						case 1:
+							CurAMd = kAMdAbsWB;
+							break;
+						case 2:
+						default: /* keep compiler happy */
+							CurAMd = kAMdAbsWW;
+							break;
+						case 4:
+							CurAMd = kAMdAbsWL;
+							break;
+					}
+					IsOk = CheckInSet(v,
+						kAddrValidMaskAny | kAddrValidMaskData
+							| kAddrValidMaskDataAlt
+							| kAddrValidMaskControl
+							| kAddrValidMaskControlAlt
+							| kAddrValidMaskAltMem
+							| kAddrValidMaskDataNoCn);
+					break;
+				case 1:
+					switch (p->opsize) {
+						case 1:
+							CurAMd = kAMdAbsLB;
+							break;
+						case 2:
+						default: /* keep compiler happy */
+							CurAMd = kAMdAbsLW;
+							break;
+						case 4:
+							CurAMd = kAMdAbsLL;
+							break;
+					}
+					IsOk = CheckInSet(v,
+						kAddrValidMaskAny | kAddrValidMaskData
+							| kAddrValidMaskDataAlt
+							| kAddrValidMaskControl
+							| kAddrValidMaskControlAlt
+							| kAddrValidMaskAltMem
+							| kAddrValidMaskDataNoCn);
+					break;
+				case 2:
+					switch (p->opsize) {
+						case 1:
+							CurAMd = kAMdPCDispB;
+							break;
+						case 2:
+						default: /* keep compiler happy */
+							CurAMd = kAMdPCDispW;
+							break;
+						case 4:
+							CurAMd = kAMdPCDispL;
+							break;
+					}
+					IsOk = CheckInSet(v,
+						kAddrValidMaskAny | kAddrValidMaskData
+							| kAddrValidMaskControl
+							| kAddrValidMaskDataNoCn);
+					break;
+				case 3:
+					switch (p->opsize) {
+						case 1:
+							CurAMd = kAMdPCIndexB;
+							break;
+						case 2:
+						default: /* keep compiler happy */
+							CurAMd = kAMdPCIndexW;
+							break;
+						case 4:
+							CurAMd = kAMdPCIndexL;
+							break;
+					}
+					IsOk = CheckInSet(v,
+						kAddrValidMaskAny | kAddrValidMaskData
+							| kAddrValidMaskControl
+							| kAddrValidMaskDataNoCn);
+					break;
+				case 4:
+					switch (p->opsize) {
+						case 1:
+							CurAMd = kAMdImmedB;
+							break;
+						case 2:
+						default: /* keep compiler happy */
+							CurAMd = kAMdImmedW;
+							break;
+						case 4:
+							CurAMd = kAMdImmedL;
+							break;
+					}
+					IsOk = CheckInSet(v,
+						kAddrValidMaskAny | kAddrValidMaskData);
+					break;
+				default:
+					IsOk = falseblnr;
+					break;
+			}
+			break;
+		default: /* keep compiler happy */
+			IsOk = falseblnr;
+			break;
+	}
+
+	if (IsOk) {
+		SetDcoArgFields(p, src, CurAMd, CurArgDat);
+	}
+
+	return IsOk;
+}
+
+#if WantCycByPriOp
+LOCALFUNC blnr LeaPeaEACalcCyc(WorkR *p, ui3r m, ui3r r)
+{
+	ui4r v;
+
+	UnusedParam(p);
+	switch (m) {
+		case 2:
+			v = 0;
+			break;
+		case 5:
+			v = (4 * kCycleScale + RdAvgXtraCyc);
+			break;
+		case 6:
+			v = (8 * kCycleScale + RdAvgXtraCyc);
+			break;
+		case 7:
+			switch (r) {
+				case 0:
+					v = (4 * kCycleScale + RdAvgXtraCyc);
+					break;
+				case 1:
+					v = (8 * kCycleScale + 2 * RdAvgXtraCyc);
+					break;
+				case 2:
+					v = (4 * kCycleScale + RdAvgXtraCyc);
+					break;
+				case 3:
+					v = (8 * kCycleScale + RdAvgXtraCyc);
+					break;
+				default:
+					v = 0;
+					break;
+			}
+			break;
+		default: /* keep compiler happy */
+			v = 0;
+			break;
+	}
+
+	return v;
+}
+#endif
+
+LOCALFUNC blnr IsValidAddrMode(WorkR *p)
+{
+	return CheckValidAddrMode(p,
+		mode(p), reg(p), kAddrValidAny, falseblnr);
+}
+
+LOCALFUNC blnr CheckDataAltAddrMode(WorkR *p)
+{
+	return CheckValidAddrMode(p,
+		mode(p), reg(p), kAddrValidDataAlt, falseblnr);
+}
+
+LOCALFUNC blnr CheckDataAddrMode(WorkR *p)
+{
+	return CheckValidAddrMode(p,
+		mode(p), reg(p), kAddrValidData, falseblnr);
+}
+
+LOCALFUNC blnr CheckControlAddrMode(WorkR *p)
+{
+	return CheckValidAddrMode(p,
+		mode(p), reg(p), kAddrValidControl, falseblnr);
+}
+
+LOCALFUNC blnr CheckControlAltAddrMode(WorkR *p)
+{
+	return CheckValidAddrMode(p,
+		mode(p), reg(p), kAddrValidControlAlt, falseblnr);
+}
+
+LOCALFUNC blnr CheckAltMemAddrMode(WorkR *p)
+{
+	return CheckValidAddrMode(p,
+		mode(p), reg(p), kAddrValidAltMem, falseblnr);
+}
+
+LOCALPROC FindOpSizeFromb76(WorkR *p)
+{
+	p->opsize = 1 << b76(p);
+#if 0
+	switch (b76(p)) {
+		case 0 :
+			p->opsize = 1;
+			break;
+		case 1 :
+			p->opsize = 2;
+			break;
+		case 2 :
+			p->opsize = 4;
+			break;
+	}
+#endif
+}
+
+LOCALFUNC ui3r OpSizeOffset(WorkR *p)
+{
+	ui3r v;
+
+	switch (p->opsize) {
+		case 1 :
+			v = 0;
+			break;
+		case 2 :
+			v = 1;
+			break;
+		case 4 :
+		default :
+			v = 2;
+			break;
+	}
+
+	return v;
+}
+
+
+LOCALFUNC ui5r octdat(ui5r x)
+{
+	if (x == 0) {
+		return 8;
+	} else {
+		return x;
+	}
+}
+
+LOCALPROCUSEDONCE DeCode0(WorkR *p)
+{
+	if (b8(p) == 1) {
+		if (mode(p) == 1) {
+			/* MoveP 0000ddd1mm001aaa */
+#if WantCycByPriOp
+			switch (b76(p)) {
+				case 0:
+					p->Cycles = (16 * kCycleScale + 4 * RdAvgXtraCyc);
+					break;
+				case 1:
+					p->Cycles = (24 * kCycleScale + 6 * RdAvgXtraCyc);
+					break;
+				case 2:
+					p->Cycles = (16 * kCycleScale
+						+ 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc);
+					break;
+				case 3:
+				default: /* keep compiler happy */
+					p->Cycles = (24 * kCycleScale
+						+ 2 * RdAvgXtraCyc + 4 * WrAvgXtraCyc);
+					break;
+			}
+#endif
+			if (CheckValidAddrMode(p, 1, reg(p),
+				kAddrValidAny, trueblnr))
+			if (CheckValidAddrMode(p, 0, rg9(p),
+				kAddrValidAny, falseblnr))
+			{
+				p->MainClass = kIKindMoveP0 + b76(p);
+			}
+		} else {
+			/* dynamic bit, Opcode = 0000ddd1ttmmmrrr */
+			if (mode(p) == 0) {
+				p->opsize = 4;
+#if WantCycByPriOp
+				switch (b76(p)) {
+					case 0: /* BTst */
+						p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
+						break;
+					case 1: /* BChg */
+						p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
+						break;
+					case 2: /* BClr */
+						p->Cycles = (10 * kCycleScale + RdAvgXtraCyc);
+						break;
+					case 3: /* BSet */
+						p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
+						break;
+				}
+#endif
+				p->MainClass = kIKindBTstL + b76(p);
+				SetDcoArgFields(p, trueblnr, kAMdRegL, rg9(p));
+				SetDcoArgFields(p, falseblnr, kAMdRegL, reg(p));
+			} else {
+				p->opsize = 1;
+				p->MainClass = kIKindBTstB + b76(p);
+				SetDcoArgFields(p, trueblnr, kAMdRegB, rg9(p));
+				if (b76(p) == 0) { /* BTst */
+					if (CheckDataAddrMode(p)) {
+#if WantCycByPriOp
+						p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
+						p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+					}
+				} else {
+					if (CheckDataAltAddrMode(p)) {
+#if WantCycByPriOp
+						p->Cycles = (8 * kCycleScale
+							+ RdAvgXtraCyc + WrAvgXtraCyc);
+						p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+					}
+				}
+			}
+		}
+	} else {
+		if (rg9(p) == 4) {
+			/* static bit 00001010ssmmmrrr */
+			if (mode(p) == 0) {
+				p->opsize = 4;
+#if WantCycByPriOp
+				switch (b76(p)) {
+					case 0: /* BTst */
+						p->Cycles =
+							(10 * kCycleScale + 2 * RdAvgXtraCyc);
+						break;
+					case 1: /* BChg */
+						p->Cycles =
+							(12 * kCycleScale + 2 * RdAvgXtraCyc);
+						break;
+					case 2: /* BClr */
+						p->Cycles =
+							(14 * kCycleScale + 2 * RdAvgXtraCyc);
+						break;
+					case 3: /* BSet */
+						p->Cycles =
+							(12 * kCycleScale + 2 * RdAvgXtraCyc);
+						break;
+				}
+#endif
+				SetDcoArgFields(p, trueblnr, kAMdImmedB, 0);
+				SetDcoArgFields(p, falseblnr, kAMdRegL, reg(p));
+				p->MainClass = kIKindBTstL + b76(p);
+			} else {
+				p->opsize = 1;
+				SetDcoArgFields(p, trueblnr, kAMdImmedB, 0);
+				p->MainClass = kIKindBTstB + b76(p);
+				if (b76(p) == 0) { /* BTst */
+					if (CheckValidAddrMode(p,
+						mode(p), reg(p), kAddrValidDataNoCn, falseblnr))
+					{
+#if WantCycByPriOp
+						p->Cycles =
+							(8 * kCycleScale + 2 * RdAvgXtraCyc);
+						p->Cycles +=
+							OpEACalcCyc(p, mode(p), reg(p));
+#endif
+					}
+				} else {
+					if (CheckDataAltAddrMode(p)) {
+#if WantCycByPriOp
+						p->Cycles = (12 * kCycleScale
+							+ 2 * RdAvgXtraCyc + WrAvgXtraCyc);
+						p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+					}
+				}
+			}
+		} else
+		if (b76(p) == 3) {
+#if Use68020
+			if (rg9(p) < 3) {
+				/* CHK2 or CMP2 00000ss011mmmrrr */
+				switch ((p->opcode >> 9) & 3) {
+					case 0 :
+						p->opsize = 1;
+						break;
+					case 1 :
+						p->opsize = 2;
+						break;
+					case 2 :
+						p->opsize = 4;
+						break;
+				}
+				p->DecOp.y.v[0].ArgDat = p->opsize;
+					/* size */
+				if (CheckControlAddrMode(p)) {
+#if WantCycByPriOp
+					p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+					p->MainClass = kIKindCHK2orCMP2;
+				}
+			} else
+			if (rg9(p) >= 5) {
+				switch ((p->opcode >> 9) & 3) {
+					case 1 :
+						p->opsize = 1;
+						break;
+					case 2 :
+						p->opsize = 2;
+						break;
+					case 3 :
+						p->opsize = 4;
+						break;
+				}
+				p->DecOp.y.v[0].ArgDat = p->opsize;
+				if ((mode(p) == 7) && (reg(p) == 4)) {
+					/* CAS2 00001ss011111100 */
+					p->MainClass = kIKindCAS2;
+				} else {
+					/* CAS 00001ss011mmmrrr */
+					if (CheckDataAltAddrMode(p)) {
+						p->MainClass = kIKindCAS;
+					}
+				}
+			} else
+			if (rg9(p) == 3) {
+				/* CALLM or RTM 0000011011mmmrrr */
+				p->MainClass = kIKindCallMorRtm;
+			} else
+#endif
+			{
+				p->MainClass = kIKindIllegal;
+			}
+		} else
+		if (rg9(p) == 6) {
+			/* CMPI 00001100ssmmmrrr */
+#if 0
+			if (CheckDataAltAddrMode(p)) {
+				p->MainClass = kIKindCmpI;
+			}
+#endif
+			FindOpSizeFromb76(p);
+			if (CheckValidAddrMode(p, 7, 4, kAddrValidAny, trueblnr))
+			if (CheckValidAddrMode(p,
+				mode(p), reg(p), kAddrValidDataNoCn, falseblnr))
+			{
+#if WantCycByPriOp
+				if (0 == mode(p)) {
+					p->Cycles = (4 == p->opsize)
+						? (14 * kCycleScale + 3 * RdAvgXtraCyc)
+						: (8 * kCycleScale + 2 * RdAvgXtraCyc);
+				} else {
+					p->Cycles = (4 == p->opsize)
+						? (12 * kCycleScale + 3 * RdAvgXtraCyc)
+						: (8 * kCycleScale + 2 * RdAvgXtraCyc);
+				}
+				p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+				p->MainClass = kIKindCmpB + OpSizeOffset(p);
+			}
+		} else if (rg9(p) == 7) {
+#if Use68020
+			/* MoveS 00001110ssmmmrrr */
+			FindOpSizeFromb76(p);
+			p->DecOp.y.v[0].ArgDat = p->opsize;
+			if (CheckAltMemAddrMode(p)) {
+#if WantCycByPriOp
+				p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+				p->MainClass = kIKindMoveS;
+			}
+#else
+			p->MainClass = kIKindIllegal;
+#endif
+		} else {
+			if ((mode(p) == 7) && (reg(p) == 4)) {
+				switch (rg9(p)) {
+					case 0:
+#if WantCycByPriOp
+						p->Cycles =
+							(20 * kCycleScale + 3 * RdAvgXtraCyc);
+#endif
+						p->MainClass = (0 != b76(p))
+							? kIKindOrISR : kIKindOrICCR;
+						break;
+					case 1:
+#if WantCycByPriOp
+						p->Cycles =
+							(20 * kCycleScale + 3 * RdAvgXtraCyc);
+#endif
+						p->MainClass = (0 != b76(p))
+							? kIKindAndISR : kIKindAndICCR;
+						break;
+					case 5:
+#if WantCycByPriOp
+						p->Cycles =
+							(20 * kCycleScale + 3 * RdAvgXtraCyc);
+#endif
+						p->MainClass = (0 != b76(p))
+							? kIKindEorISR : kIKindEorICCR;
+						break;
+					default:
+						p->MainClass = kIKindIllegal;
+						break;
+				}
+			} else {
+				switch (rg9(p)) {
+					case 0:
+#if 0
+						if (CheckDataAltAddrMode(p)) {
+							p->MainClass = kIKindOrI;
+						}
+#endif
+						FindOpSizeFromb76(p);
+						if (CheckValidAddrMode(p, 7, 4,
+							kAddrValidAny, trueblnr))
+						if (CheckValidAddrMode(p, mode(p), reg(p),
+							kAddrValidDataAlt, falseblnr))
+						{
+#if WantCycByPriOp
+							if (0 != mode(p)) {
+								p->Cycles = (4 == p->opsize)
+									? (20 * kCycleScale
+										+ 3 * RdAvgXtraCyc
+										+ 2 * WrAvgXtraCyc)
+									: (12 * kCycleScale
+										+ 2 * RdAvgXtraCyc
+										+ WrAvgXtraCyc);
+							} else {
+								p->Cycles = (4 == p->opsize)
+									? (16 * kCycleScale
+										+ 3 * RdAvgXtraCyc)
+									: (8 * kCycleScale
+										+ 2 * RdAvgXtraCyc);
+							}
+							p->Cycles +=
+								OpEACalcCyc(p, mode(p), reg(p));
+#endif
+							p->MainClass = kIKindOrI;
+						}
+						break;
+					case 1:
+#if 0
+						if (CheckDataAltAddrMode(p)) {
+							p->MainClass = kIKindAndI;
+						}
+#endif
+						FindOpSizeFromb76(p);
+						if (CheckValidAddrMode(p, 7, 4,
+							kAddrValidAny, trueblnr))
+						if (CheckValidAddrMode(p, mode(p), reg(p),
+							kAddrValidDataAlt, falseblnr))
+						{
+#if WantCycByPriOp
+							if (0 != mode(p)) {
+								p->Cycles = (4 == p->opsize)
+									? (20 * kCycleScale
+										+ 3 * RdAvgXtraCyc
+										+ 2 * WrAvgXtraCyc)
+									: (12 * kCycleScale
+										+ 2 * RdAvgXtraCyc
+										+ WrAvgXtraCyc);
+							} else {
+								p->Cycles = (4 == p->opsize)
+									? (14 * kCycleScale
+										+ 3 * RdAvgXtraCyc)
+									: (8 * kCycleScale
+										+ 2 * RdAvgXtraCyc);
+							}
+							p->Cycles +=
+								OpEACalcCyc(p, mode(p), reg(p));
+#endif
+							p->MainClass = kIKindAndI;
+						}
+						break;
+					case 2:
+#if 0
+						if (CheckDataAltAddrMode(p)) {
+							p->MainClass = kIKindSubI;
+						}
+#endif
+						FindOpSizeFromb76(p);
+						if (CheckValidAddrMode(p, 7, 4,
+							kAddrValidAny, trueblnr))
+						if (CheckValidAddrMode(p, mode(p), reg(p),
+							kAddrValidDataAlt, falseblnr))
+						{
+#if WantCycByPriOp
+							if (0 != mode(p)) {
+								p->Cycles = (4 == p->opsize)
+									? (20 * kCycleScale
+										+ 3 * RdAvgXtraCyc
+										+ 2 * WrAvgXtraCyc)
+									: (12 * kCycleScale
+										+ 2 * RdAvgXtraCyc
+										+ WrAvgXtraCyc);
+							} else {
+								p->Cycles = (4 == p->opsize)
+									? (16 * kCycleScale
+										+ 3 * RdAvgXtraCyc)
+									: (8 * kCycleScale
+										+ 2 * RdAvgXtraCyc);
+							}
+							p->Cycles +=
+								OpEACalcCyc(p, mode(p), reg(p));
+#endif
+							p->MainClass = kIKindSubB + OpSizeOffset(p);
+						}
+						break;
+					case 3:
+#if 0
+						if (CheckDataAltAddrMode(p)) {
+							p->MainClass = kIKindAddI;
+						}
+#endif
+						FindOpSizeFromb76(p);
+						if (CheckValidAddrMode(p, 7, 4,
+							kAddrValidAny, trueblnr))
+						if (CheckValidAddrMode(p, mode(p), reg(p),
+							kAddrValidDataAlt, falseblnr))
+						{
+#if WantCycByPriOp
+							if (0 != mode(p)) {
+								p->Cycles = (4 == p->opsize)
+									? (20 * kCycleScale
+										+ 3 * RdAvgXtraCyc
+										+ 2 * WrAvgXtraCyc)
+									: (12 * kCycleScale
+										+ 2 * RdAvgXtraCyc
+										+ WrAvgXtraCyc);
+							} else {
+								p->Cycles = (4 == p->opsize)
+									? (16 * kCycleScale
+										+ 3 * RdAvgXtraCyc)
+									: (8 * kCycleScale
+										+ 2 * RdAvgXtraCyc);
+							}
+							p->Cycles +=
+								OpEACalcCyc(p, mode(p), reg(p));
+#endif
+							p->MainClass = kIKindAddB + OpSizeOffset(p);
+						}
+						break;
+					case 5:
+#if 0
+						if (CheckDataAltAddrMode(p)) {
+							p->MainClass = kIKindEorI;
+						}
+#endif
+						FindOpSizeFromb76(p);
+						if (CheckValidAddrMode(p, 7, 4,
+							kAddrValidAny, trueblnr))
+						if (CheckValidAddrMode(p, mode(p), reg(p),
+							kAddrValidDataAlt, falseblnr))
+						{
+#if WantCycByPriOp
+							if (0 != mode(p)) {
+								p->Cycles = (4 == p->opsize)
+									? (20 * kCycleScale
+										+ 3 * RdAvgXtraCyc
+										+ 2 * WrAvgXtraCyc)
+									: (12 * kCycleScale
+										+ 2 * RdAvgXtraCyc
+										+ WrAvgXtraCyc);
+							} else {
+								p->Cycles = (4 == p->opsize)
+									? (16 * kCycleScale
+										+ 3 * RdAvgXtraCyc)
+									: (8 * kCycleScale
+										+ 2 * RdAvgXtraCyc);
+							}
+							p->Cycles +=
+								OpEACalcCyc(p, mode(p), reg(p));
+#endif
+							p->MainClass = kIKindEorI;
+						}
+						break;
+					default:
+						/* for compiler. should be 0, 1, 2, 3, or 5 */
+						p->MainClass = kIKindIllegal;
+						break;
+				}
+			}
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DeCode1(WorkR *p)
+{
+	p->opsize = 1;
+	if (md6(p) == 1) { /* MOVEA */
+		p->MainClass = kIKindIllegal;
+	} else if (mode(p) == 1) {
+		/* not allowed for byte sized move */
+		p->MainClass = kIKindIllegal;
+	} else {
+		if (CheckValidAddrMode(p, mode(p), reg(p),
+			kAddrValidAny, trueblnr))
+		if (CheckValidAddrMode(p, md6(p), rg9(p),
+			kAddrValidDataAlt, falseblnr))
+		{
+#if WantCycByPriOp
+			p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
+			p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+			p->Cycles += OpEADestCalcCyc(p, md6(p), rg9(p));
+#endif
+			p->MainClass = kIKindMoveB;
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DeCode2(WorkR *p)
+{
+	p->opsize = 4;
+	if (md6(p) == 1) { /* MOVEA */
+		if (CheckValidAddrMode(p, mode(p), reg(p),
+			kAddrValidAny, trueblnr))
+		if (CheckValidAddrMode(p, 1, rg9(p),
+			kAddrValidAny, falseblnr))
+		{
+#if WantCycByPriOp
+			p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
+			p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+			p->MainClass = kIKindMoveAL;
+			p->DecOp.y.v[1].ArgDat = rg9(p);
+		}
+	} else {
+		if (CheckValidAddrMode(p, mode(p), reg(p),
+			kAddrValidAny, trueblnr))
+		if (CheckValidAddrMode(p, md6(p), rg9(p),
+			kAddrValidDataAlt, falseblnr))
+		{
+#if WantCycByPriOp
+			p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
+			p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+			p->Cycles += OpEADestCalcCyc(p, md6(p), rg9(p));
+#endif
+			p->MainClass = kIKindMoveL;
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DeCode3(WorkR *p)
+{
+	p->opsize = 2;
+	if (md6(p) == 1) { /* MOVEA */
+		if (CheckValidAddrMode(p, mode(p), reg(p),
+			kAddrValidAny, trueblnr))
+		if (CheckValidAddrMode(p, 1, rg9(p),
+			kAddrValidAny, falseblnr))
+		{
+#if WantCycByPriOp
+			p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
+			p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+			p->MainClass = kIKindMoveAW;
+			p->DecOp.y.v[1].ArgDat = rg9(p);
+		}
+	} else {
+		if (CheckValidAddrMode(p, mode(p), reg(p),
+			kAddrValidAny, trueblnr))
+		if (CheckValidAddrMode(p, md6(p), rg9(p),
+			kAddrValidDataAlt, falseblnr))
+		{
+#if WantCycByPriOp
+			p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
+			p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+			p->Cycles += OpEADestCalcCyc(p, md6(p), rg9(p));
+#endif
+			p->MainClass = kIKindMoveW;
+		}
+	}
+}
+
+#if WantCycByPriOp
+
+#if WantCloserCyc
+#define MoveAvgN 0
+#else
+#define MoveAvgN 3
+#endif
+
+LOCALFUNC ui4r MoveMEACalcCyc(WorkR *p, ui3r m, ui3r r)
+{
+	ui4r v;
+
+	UnusedParam(p);
+	switch (m) {
+		case 2:
+		case 3:
+		case 4:
+			v = (8 * kCycleScale + 2 * RdAvgXtraCyc);
+			break;
+		case 5:
+			v = (12 * kCycleScale + 3 * RdAvgXtraCyc);
+			break;
+		case 6:
+			v = (14 * kCycleScale + 3 * RdAvgXtraCyc);
+			break;
+		case 7:
+			switch (r) {
+				case 0:
+					v = (12 * kCycleScale + 3 * RdAvgXtraCyc);
+					break;
+				case 1:
+					v = (16 * kCycleScale + 4 * RdAvgXtraCyc);
+					break;
+				default:
+					v = 0;
+					break;
+			}
+			break;
+		default: /* keep compiler happy */
+			v = 0;
+			break;
+	}
+
+	return v;
+}
+
+#endif
+
+LOCALPROCUSEDONCE DeCode4(WorkR *p)
+{
+	if (b8(p) != 0) {
+		switch (b76(p)) {
+			case 0:
+#if Use68020
+				/* Chk.L 0100ddd100mmmrrr */
+				p->opsize = 4;
+				if (CheckValidAddrMode(p, mode(p), reg(p),
+					kAddrValidData, falseblnr))
+				if (CheckValidAddrMode(p, 0, rg9(p),
+					kAddrValidAny, trueblnr))
+				{
+#if WantCycByPriOp
+					p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+					p->MainClass = kIKindChkL;
+				}
+#else
+				p->MainClass = kIKindIllegal;
+#endif
+				break;
+			case 1:
+				p->MainClass = kIKindIllegal;
+				break;
+			case 2:
+				/* Chk.W 0100ddd110mmmrrr */
+				p->opsize = 2;
+				if (CheckValidAddrMode(p, mode(p), reg(p),
+					kAddrValidData, falseblnr))
+				if (CheckValidAddrMode(p, 0, rg9(p),
+					kAddrValidAny, trueblnr))
+				{
+#if WantCycByPriOp
+					p->Cycles = (10 * kCycleScale + RdAvgXtraCyc);
+					p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+					p->MainClass = kIKindChkW;
+				}
+				break;
+			case 3:
+			default: /* keep compiler happy */
+#if Use68020
+				if ((0 == mode(p)) && (4 == rg9(p))) {
+					/* EXTB.L */
+					SetDcoArgFields(p, falseblnr,
+						kAMdRegL, reg(p));
+					p->MainClass = kIKindEXTBL;
+				} else
+#endif
+				{
+					/* Lea 0100aaa111mmmrrr */
+					if (CheckControlAddrMode(p)) {
+#if WantCycByPriOp
+						p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
+						p->Cycles +=
+							LeaPeaEACalcCyc(p, mode(p), reg(p));
+#endif
+						p->MainClass = kIKindLea;
+						p->DecOp.y.v[0].ArgDat = rg9(p);
+					}
+				}
+				break;
+		}
+	} else {
+		switch (rg9(p)) {
+			case 0:
+				if (b76(p) != 3) {
+					/* NegX 01000000ssmmmrrr */
+					FindOpSizeFromb76(p);
+					if (CheckDataAltAddrMode(p)) {
+#if WantCycByPriOp
+						if (0 != mode(p)) {
+							p->Cycles = (4 == p->opsize)
+								? (12 * kCycleScale
+									+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
+								: (8 * kCycleScale
+									+ RdAvgXtraCyc + WrAvgXtraCyc);
+						} else {
+							p->Cycles = (4 == p->opsize)
+								? (6 * kCycleScale + RdAvgXtraCyc)
+								: (4 * kCycleScale + RdAvgXtraCyc);
+						}
+						p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+						p->MainClass = kIKindNegXB + OpSizeOffset(p);
+					}
+				} else {
+#if Use68020
+/* reference seems incorrect to say not for 68000 */
+#endif
+					/* Move from SR 0100000011mmmrrr */
+					p->opsize = 2;
+					if (CheckDataAltAddrMode(p)) {
+#if WantCycByPriOp
+						p->Cycles =
+							(12 * kCycleScale + 2 * RdAvgXtraCyc);
+						p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+						p->MainClass = kIKindMoveSREa;
+					}
+				}
+				break;
+			case 1:
+				if (b76(p) != 3) {
+					/* Clr 01000010ssmmmrrr */
+					FindOpSizeFromb76(p);
+					if (CheckDataAltAddrMode(p)) {
+#if WantCycByPriOp
+						if (0 != mode(p)) {
+							p->Cycles = (4 == p->opsize)
+								? (12 * kCycleScale
+									+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
+								: (8 * kCycleScale
+									+ RdAvgXtraCyc + WrAvgXtraCyc);
+						} else {
+							p->Cycles = (4 == p->opsize)
+								? (6 * kCycleScale + RdAvgXtraCyc)
+								: (4 * kCycleScale + RdAvgXtraCyc);
+						}
+						p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+						p->MainClass = kIKindClr;
+					}
+				} else {
+#if Use68020
+					/* Move from CCR 0100001011mmmrrr */
+					p->opsize = 2;
+					if (CheckDataAltAddrMode(p)) {
+#if WantCycByPriOp
+						p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+						p->MainClass = kIKindMoveCCREa;
+					}
+#else
+					p->MainClass = kIKindIllegal;
+#endif
+				}
+				break;
+			case 2:
+				if (b76(p) != 3) {
+					/* Neg 01000100ssmmmrrr */
+					FindOpSizeFromb76(p);
+					if (CheckDataAltAddrMode(p)) {
+#if WantCycByPriOp
+						if (0 != mode(p)) {
+							p->Cycles = (4 == p->opsize)
+								? (12 * kCycleScale
+									+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
+								: (8 * kCycleScale
+									+ RdAvgXtraCyc + WrAvgXtraCyc);
+						} else {
+							p->Cycles = (4 == p->opsize)
+								? (6 * kCycleScale + RdAvgXtraCyc)
+								: (4 * kCycleScale + RdAvgXtraCyc);
+						}
+						p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+						p->MainClass = kIKindNegB + OpSizeOffset(p);
+					}
+				} else {
+					/* Move to CCR 0100010011mmmrrr */
+					p->opsize = 2;
+					if (CheckDataAddrMode(p)) {
+#if WantCycByPriOp
+						p->Cycles = (12 * kCycleScale + RdAvgXtraCyc);
+						p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+						p->MainClass = kIKindMoveEaCCR;
+					}
+				}
+				break;
+			case 3:
+				if (b76(p) != 3) {
+					/* Not 01000110ssmmmrrr */
+					FindOpSizeFromb76(p);
+					if (CheckDataAltAddrMode(p)) {
+#if WantCycByPriOp
+						if (0 != mode(p)) {
+							p->Cycles = (4 == p->opsize)
+								? (12 * kCycleScale
+									+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
+								: (8 * kCycleScale
+									+ RdAvgXtraCyc + WrAvgXtraCyc);
+						} else {
+							p->Cycles = (4 == p->opsize)
+								? (6 * kCycleScale + RdAvgXtraCyc)
+								: (4 * kCycleScale + RdAvgXtraCyc);
+						}
+						p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+						p->MainClass = kIKindNot;
+					}
+				} else {
+					/* Move from SR 0100011011mmmrrr */
+					p->opsize = 2;
+					if (CheckDataAddrMode(p)) {
+#if WantCycByPriOp
+						if (0 != mode(p)) {
+							p->Cycles = (8 * kCycleScale
+								+ RdAvgXtraCyc + WrAvgXtraCyc);
+						} else {
+							p->Cycles =
+								(6 * kCycleScale + RdAvgXtraCyc);
+						}
+						p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+						p->MainClass = kIKindMoveEaSR;
+					}
+				}
+				break;
+			case 4:
+				switch (b76(p)) {
+					case 0:
+#if Use68020
+						if (mode(p) == 1) {
+							/* Link.L 0100100000001rrr */
+							SetDcoArgFields(p, falseblnr,
+								kAMdRegL, reg(p) + 8);
+							p->MainClass = kIKindLinkL;
+						} else
+#endif
+						{
+							/* Nbcd 0100100000mmmrrr */
+							p->opsize = 1;
+							if (CheckDataAltAddrMode(p)) {
+#if WantCycByPriOp
+								if (0 != mode(p)) {
+									p->Cycles = (8 * kCycleScale
+										+ RdAvgXtraCyc + WrAvgXtraCyc);
+								} else {
+									p->Cycles = (6 * kCycleScale
+										+ RdAvgXtraCyc);
+								}
+								p->Cycles +=
+									OpEACalcCyc(p, mode(p), reg(p));
+#endif
+								p->MainClass = kIKindNbcd;
+							}
+						}
+						break;
+					case 1:
+						if (mode(p) == 0) {
+							/* Swap 0100100001000rrr */
+#if WantCycByPriOp
+							p->Cycles =
+								(4 * kCycleScale + RdAvgXtraCyc);
+#endif
+							p->MainClass = kIKindSwap;
+							SetDcoArgFields(p, falseblnr,
+								kAMdRegL, reg(p));
+						} else
+#if Use68020
+						if (mode(p) == 1) {
+							p->MainClass = kIKindBkpt;
+						} else
+#endif
+						{
+							/* PEA 0100100001mmmrrr */
+							if (CheckControlAddrMode(p)) {
+#if WantCycByPriOp
+								p->Cycles = (12 * kCycleScale
+										+ RdAvgXtraCyc
+										+ 2 * WrAvgXtraCyc);
+								p->Cycles +=
+									LeaPeaEACalcCyc(p, mode(p), reg(p));
+#endif
+								p->MainClass = kIKindPEA;
+							}
+						}
+						break;
+					case 2:
+						if (mode(p) == 0) {
+							/* EXT.W */
+#if WantCycByPriOp
+							p->Cycles =
+								(4 * kCycleScale + RdAvgXtraCyc);
+#endif
+							SetDcoArgFields(p, falseblnr,
+								kAMdRegW, reg(p));
+							p->MainClass = kIKindEXTW;
+						} else {
+							/* MOVEM reg to mem 01001d001ssmmmrrr */
+							p->opsize = 2;
+							if (mode(p) == 4) {
+#if WantCycByPriOp
+								p->Cycles =
+									MoveMEACalcCyc(p, mode(p), reg(p));
+								p->Cycles += MoveAvgN * 4 * kCycleScale
+									+ MoveAvgN * WrAvgXtraCyc;
+#endif
+								SetDcoArgFields(p, falseblnr,
+									kAMdAPreDecL, reg(p) + 8);
+								p->MainClass = kIKindMOVEMRmMW;
+							} else {
+								if (CheckControlAltAddrMode(p)) {
+#if WantCycByPriOp
+									p->Cycles = MoveMEACalcCyc(p,
+										mode(p), reg(p));
+									p->Cycles +=
+										MoveAvgN * 4 * kCycleScale
+											+ MoveAvgN * WrAvgXtraCyc;
+#endif
+									p->MainClass = kIKindMOVEMrmW;
+								}
+							}
+						}
+						break;
+					case 3:
+					default: /* keep compiler happy */
+						if (mode(p) == 0) {
+							/* EXT.L */
+#if WantCycByPriOp
+							p->Cycles =
+								(4 * kCycleScale + RdAvgXtraCyc);
+#endif
+							SetDcoArgFields(p, falseblnr,
+								kAMdRegL, reg(p));
+							p->MainClass = kIKindEXTL;
+						} else {
+							/* MOVEM reg to mem 01001d001ssmmmrrr */
+#if WantCycByPriOp
+							p->Cycles = MoveMEACalcCyc(p,
+								mode(p), reg(p));
+							p->Cycles += MoveAvgN * 8 * kCycleScale
+								+ MoveAvgN * 2 * WrAvgXtraCyc;
+#endif
+							p->opsize = 4;
+							if (mode(p) == 4) {
+								SetDcoArgFields(p, falseblnr,
+									kAMdAPreDecL, reg(p) + 8);
+								p->MainClass = kIKindMOVEMRmML;
+							} else {
+								if (CheckControlAltAddrMode(p)) {
+									p->MainClass = kIKindMOVEMrmL;
+								}
+							}
+						}
+						break;
+				}
+				break;
+			case 5:
+				if (b76(p) == 3) {
+					if ((mode(p) == 7) && (reg(p) == 4)) {
+						/* the ILLEGAL instruction */
+						p->MainClass = kIKindIllegal;
+					} else {
+						/* Tas 0100101011mmmrrr */
+						p->opsize = 1;
+						if (CheckDataAltAddrMode(p)) {
+#if WantCycByPriOp
+							if (0 != mode(p)) {
+								p->Cycles = (14 * kCycleScale
+									+ 2 * RdAvgXtraCyc + WrAvgXtraCyc);
+							} else {
+								p->Cycles = (4 * kCycleScale
+									+ RdAvgXtraCyc);
+							}
+							p->Cycles +=
+								OpEACalcCyc(p, mode(p), reg(p));
+#endif
+							p->MainClass = kIKindTas;
+						}
+					}
+				} else {
+					/* Tst 01001010ssmmmrrr */
+					FindOpSizeFromb76(p);
+					if (b76(p) == 0) {
+						if (CheckDataAltAddrMode(p)) {
+#if WantCycByPriOp
+							p->Cycles =
+								(4 * kCycleScale + RdAvgXtraCyc);
+							p->Cycles +=
+								OpEACalcCyc(p, mode(p), reg(p));
+#endif
+							p->MainClass = kIKindTst;
+						}
+					} else {
+						if (IsValidAddrMode(p)) {
+#if WantCycByPriOp
+							p->Cycles =
+								(4 * kCycleScale + RdAvgXtraCyc);
+							p->Cycles +=
+								OpEACalcCyc(p, mode(p), reg(p));
+#endif
+							p->MainClass = kIKindTst;
+						}
+					}
+				}
+				break;
+			case 6:
+				if (((p->opcode >> 7) & 1) == 1) {
+					/* MOVEM mem to reg 0100110011smmmrrr */
+					p->opsize = 2 * b76(p) - 2;
+					if (mode(p) == 3) {
+#if WantCycByPriOp
+						p->Cycles = 4 * kCycleScale + RdAvgXtraCyc;
+						p->Cycles += MoveMEACalcCyc(p, mode(p), reg(p));
+						if (4 == p->opsize) {
+							p->Cycles += MoveAvgN * 8 * kCycleScale
+								+ 2 * MoveAvgN * RdAvgXtraCyc;
+						} else {
+							p->Cycles += MoveAvgN * 4 * kCycleScale
+								+ MoveAvgN * RdAvgXtraCyc;
+						}
+#endif
+						SetDcoArgFields(p, falseblnr,
+							kAMdAPosIncL, reg(p) + 8);
+						if (b76(p) == 2) {
+							p->MainClass = kIKindMOVEMApRW;
+						} else {
+							p->MainClass = kIKindMOVEMApRL;
+						}
+					} else {
+						if (CheckControlAddrMode(p)) {
+#if WantCycByPriOp
+							p->Cycles = 4 * kCycleScale + RdAvgXtraCyc;
+							p->Cycles += MoveMEACalcCyc(p,
+								mode(p), reg(p));
+							if (4 == p->opsize) {
+								p->Cycles += MoveAvgN * 8 * kCycleScale
+									+ 2 * MoveAvgN * RdAvgXtraCyc;
+							} else {
+								p->Cycles += MoveAvgN * 4 * kCycleScale
+									+ MoveAvgN * RdAvgXtraCyc;
+							}
+#endif
+							if (4 == p->opsize) {
+								p->MainClass = kIKindMOVEMmrL;
+							} else {
+								p->MainClass = kIKindMOVEMmrW;
+							}
+						}
+					}
+				} else {
+#if Use68020
+					p->opsize = 4;
+
+					if (CheckDataAddrMode(p)) {
+						if (((p->opcode >> 6) & 1) == 1) {
+							/* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */
+							/* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */
+							p->MainClass = kIKindDivL;
+						} else {
+							/* MULU 0100110000mmmrrr 0rrr0s0000000rrr */
+							/* MULS 0100110000mmmrrr 0rrr1s0000000rrr */
+							p->MainClass = kIKindMulL;
+						}
+					}
+#else
+					p->MainClass = kIKindIllegal;
+#endif
+				}
+				break;
+			case 7:
+			default: /* keep compiler happy */
+				switch (b76(p)) {
+					case 0:
+						p->MainClass = kIKindIllegal;
+						break;
+					case 1:
+						switch (mode(p)) {
+							case 0:
+							case 1:
+								/* Trap 010011100100vvvv */
+#if WantCycByPriOp
+								p->Cycles = (34 * kCycleScale
+									+ 4 * RdAvgXtraCyc
+									+ 3 * WrAvgXtraCyc);
+#endif
+								SetDcoArgFields(p, falseblnr,
+									kAMdDat4, (p->opcode & 15) + 32);
+								p->MainClass = kIKindTrap;
+								break;
+							case 2:
+								/* Link */
+#if WantCycByPriOp
+								p->Cycles = (16 * kCycleScale
+									+ 2 * RdAvgXtraCyc
+									+ 2 * WrAvgXtraCyc);
+#endif
+								SetDcoArgFields(p, falseblnr,
+									kAMdRegL, reg(p) + 8);
+								if (reg(p) == 6) {
+									p->MainClass = kIKindLinkA6;
+								} else {
+									p->MainClass = kIKindLink;
+								}
+								break;
+							case 3:
+								/* Unlk */
+#if WantCycByPriOp
+								p->Cycles = (12 * kCycleScale
+									+ 3 * RdAvgXtraCyc);
+#endif
+								SetDcoArgFields(p, falseblnr,
+									kAMdRegL, reg(p) + 8);
+								if (reg(p) == 6) {
+									p->MainClass = kIKindUnlkA6;
+								} else {
+									p->MainClass = kIKindUnlk;
+								}
+								break;
+							case 4:
+								/* MOVE USP 0100111001100aaa */
+#if WantCycByPriOp
+								p->Cycles =
+									(4 * kCycleScale + RdAvgXtraCyc);
+#endif
+								SetDcoArgFields(p, falseblnr,
+									kAMdRegL, reg(p) + 8);
+								p->MainClass = kIKindMoveRUSP;
+								break;
+							case 5:
+								/* MOVE USP 0100111001101aaa */
+#if WantCycByPriOp
+								p->Cycles =
+									(4 * kCycleScale + RdAvgXtraCyc);
+#endif
+								SetDcoArgFields(p, falseblnr,
+									kAMdRegL, reg(p) + 8);
+								p->MainClass = kIKindMoveUSPR;
+								break;
+							case 6:
+								switch (reg(p)) {
+									case 0:
+										/* Reset 0100111001100000 */
+#if WantCycByPriOp
+										p->Cycles = (132 * kCycleScale
+											+ RdAvgXtraCyc);
+#endif
+										p->MainClass = kIKindReset;
+										break;
+									case 1:
+										/* Nop = 0100111001110001 */
+#if WantCycByPriOp
+										p->Cycles = (4 * kCycleScale
+											+ RdAvgXtraCyc);
+#endif
+										p->MainClass = kIKindNop;
+										break;
+									case 2:
+										/* Stop 0100111001110010 */
+#if WantCycByPriOp
+										p->Cycles = (4 * kCycleScale);
+#endif
+										p->MainClass = kIKindStop;
+										break;
+									case 3:
+										/* Rte 0100111001110011 */
+#if WantCycByPriOp
+										p->Cycles = (20 * kCycleScale
+											+ 5 * RdAvgXtraCyc);
+#endif
+										p->MainClass = kIKindRte;
+										break;
+									case 4:
+										/* Rtd 0100111001110100 */
+#if Use68020
+										p->MainClass = kIKindRtd;
+#else
+										p->MainClass = kIKindIllegal;
+#endif
+										break;
+									case 5:
+										/* Rts 0100111001110101 */
+#if WantCycByPriOp
+										p->Cycles = (16 * kCycleScale
+											+ 4 * RdAvgXtraCyc);
+#endif
+										p->MainClass = kIKindRts;
+										break;
+									case 6:
+										/* TrapV 0100111001110110 */
+#if WantCycByPriOp
+										p->Cycles = (4 * kCycleScale
+											+ RdAvgXtraCyc);
+#endif
+										p->MainClass = kIKindTrapV;
+										break;
+									case 7:
+									default: /* keep compiler happy */
+										/* Rtr 0100111001110111 */
+#if WantCycByPriOp
+										p->Cycles = (20 * kCycleScale
+											+ 2 * RdAvgXtraCyc);
+#endif
+										p->MainClass = kIKindRtr;
+										break;
+								}
+								break;
+							case 7:
+							default: /* keep compiler happy */
+#if Use68020
+								/* MOVEC 010011100111101m */
+								switch (reg(p)) {
+									case 2:
+										p->MainClass = kIKindMoveCEa;
+										break;
+									case 3:
+										p->MainClass = kIKindMoveEaC;
+										break;
+									default:
+										p->MainClass = kIKindIllegal;
+										break;
+								}
+#else
+								p->MainClass = kIKindIllegal;
+#endif
+								break;
+						}
+						break;
+					case 2:
+						/* Jsr 0100111010mmmrrr */
+						if (CheckControlAddrMode(p)) {
+#if WantCycByPriOp
+							switch (mode(p)) {
+								case 2:
+									p->Cycles = (16 * kCycleScale
+										+ 2 * RdAvgXtraCyc
+										+ 2 * WrAvgXtraCyc);
+									break;
+								case 5:
+									p->Cycles = (18 * kCycleScale
+										+ 2 * RdAvgXtraCyc
+										+ 2 * WrAvgXtraCyc);
+									break;
+								case 6:
+									p->Cycles = (22 * kCycleScale
+										+ 2 * RdAvgXtraCyc
+										+ 2 * WrAvgXtraCyc);
+									break;
+								case 7:
+								default: /* keep compiler happy */
+									switch (reg(p)) {
+										case 0:
+											p->Cycles =
+												(18 * kCycleScale
+													+ 2 * RdAvgXtraCyc
+													+ 2 * WrAvgXtraCyc);
+											break;
+										case 1:
+											p->Cycles =
+												(20 * kCycleScale
+													+ 3 * RdAvgXtraCyc
+													+ 2 * WrAvgXtraCyc);
+											break;
+										case 2:
+											p->Cycles =
+												(18 * kCycleScale
+													+ 2 * RdAvgXtraCyc
+													+ 2 * WrAvgXtraCyc);
+											break;
+										case 3:
+										default:
+											/* keep compiler happy */
+											p->Cycles =
+												(22 * kCycleScale
+													+ 2 * RdAvgXtraCyc
+													+ 2 * WrAvgXtraCyc);
+											break;
+									}
+									break;
+							}
+#endif
+							p->MainClass = kIKindJsr;
+						}
+						break;
+					case 3:
+					default: /* keep compiler happy */
+						/* JMP 0100111011mmmrrr */
+						if (CheckControlAddrMode(p)) {
+#if WantCycByPriOp
+							switch (mode(p)) {
+								case 2:
+									p->Cycles = (8 * kCycleScale
+										+ 2 * RdAvgXtraCyc);
+									break;
+								case 5:
+									p->Cycles = (10 * kCycleScale
+										+ 2 * RdAvgXtraCyc);
+									break;
+								case 6:
+									p->Cycles = (14 * kCycleScale
+										+ 2 * RdAvgXtraCyc);
+									break;
+								case 7:
+								default: /* keep compiler happy */
+									switch (reg(p)) {
+										case 0:
+											p->Cycles =
+												(10 * kCycleScale
+													+ 2 * RdAvgXtraCyc);
+											break;
+										case 1:
+											p->Cycles =
+												(12 * kCycleScale
+													+ 3 * RdAvgXtraCyc);
+											break;
+										case 2:
+											p->Cycles =
+												(10 * kCycleScale
+													+ 2 * RdAvgXtraCyc);
+											break;
+										case 3:
+										default:
+											/* keep compiler happy */
+											p->Cycles =
+												(14 * kCycleScale
+													+ 3 * RdAvgXtraCyc);
+											break;
+									}
+									break;
+							}
+#endif
+							p->MainClass = kIKindJmp;
+						}
+						break;
+				}
+				break;
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DeCode5(WorkR *p)
+{
+	if (b76(p) == 3) {
+		p->DecOp.y.v[0].ArgDat = (p->opcode >> 8) & 15;
+		if (mode(p) == 1) {
+			/* DBcc 0101cccc11001ddd */
+#if WantCycByPriOp
+#if WantCloserCyc
+			p->Cycles = 0;
+#else
+			p->Cycles = (11 * kCycleScale + 2 * RdAvgXtraCyc);
+				/*
+					average of cc true 12(2/0),
+					cc false taken 10(2/0),
+					and not 14(3/0)
+				*/
+#endif
+#endif
+			SetDcoArgFields(p, falseblnr, kAMdRegW, reg(p));
+			if (1 == ((p->opcode >> 8) & 15)) {
+				p->MainClass = kIKindDBF;
+			} else {
+				p->MainClass = kIKindDBcc;
+			}
+		} else {
+#if Use68020
+			if ((mode(p) == 7) && (reg(p) >= 2)) {
+				/* TRAPcc 0101cccc11111sss */
+				p->DecOp.y.v[1].ArgDat = reg(p);
+				p->MainClass = kIKindTRAPcc;
+			} else
+#endif
+			{
+				p->opsize = 1;
+				/* Scc 0101cccc11mmmrrr */
+				if (CheckDataAltAddrMode(p)) {
+#if WantCycByPriOp
+					if (0 != mode(p)) {
+						p->Cycles = (8 * kCycleScale
+							+ RdAvgXtraCyc + WrAvgXtraCyc);
+					} else {
+#if WantCloserCyc
+						p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
+#else
+						p->Cycles = (5 * kCycleScale + RdAvgXtraCyc);
+							/* 4 when false, 6 when true */
+#endif
+					}
+					p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+					p->MainClass = kIKindScc;
+				}
+			}
+		}
+	} else {
+		if (mode(p) == 1) {
+			p->opsize = b8(p) * 2 + 2;
+			SetDcoArgFields(p, trueblnr, kAMdDat4,
+				octdat(rg9(p)));
+			SetDcoArgFields(p, falseblnr, kAMdRegL,
+				reg(p) + 8);
+				/* always long, regardless of opsize */
+			if (b8(p) == 0) {
+#if WantCycByPriOp
+				p->Cycles = (4 == p->opsize)
+					? (8 * kCycleScale + RdAvgXtraCyc)
+					: (4 * kCycleScale + RdAvgXtraCyc);
+#endif
+				p->MainClass = kIKindAddQA; /* AddQA 0101nnn0ss001rrr */
+			} else {
+#if WantCycByPriOp
+				p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
+#endif
+				p->MainClass = kIKindSubQA; /* SubQA 0101nnn1ss001rrr */
+			}
+		} else {
+			FindOpSizeFromb76(p);
+			SetDcoArgFields(p, trueblnr, kAMdDat4,
+				octdat(rg9(p)));
+			if (CheckValidAddrMode(p,
+				mode(p), reg(p), kAddrValidDataAlt, falseblnr))
+			{
+#if WantCycByPriOp
+				if (0 != mode(p)) {
+					p->Cycles = (4 == p->opsize)
+						? (12 * kCycleScale
+							+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
+						: (8 * kCycleScale
+							+ RdAvgXtraCyc + WrAvgXtraCyc);
+				} else {
+					p->Cycles = (4 == p->opsize)
+						? (8 * kCycleScale + RdAvgXtraCyc)
+						: (4 * kCycleScale + RdAvgXtraCyc);
+				}
+				p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+				if (b8(p) == 0) {
+					/* AddQ 0101nnn0ssmmmrrr */
+#if 0
+					if (CheckDataAltAddrMode(p)) {
+						p->MainClass = kIKindAddQ;
+					}
+#endif
+					p->MainClass = kIKindAddB + OpSizeOffset(p);
+				} else {
+					/* SubQ 0101nnn1ssmmmrrr */
+#if 0
+					if (CheckDataAltAddrMode(p)) {
+						p->MainClass = kIKindSubQ;
+					}
+#endif
+					p->MainClass = kIKindSubB + OpSizeOffset(p);
+				}
+			}
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DeCode6(WorkR *p)
+{
+	ui5b cond = (p->opcode >> 8) & 15;
+
+	if (cond == 1) {
+		/* Bsr 01100001nnnnnnnn */
+#if WantCycByPriOp
+		p->Cycles = (18 * kCycleScale
+			+ 2 * RdAvgXtraCyc + 2 * WrAvgXtraCyc);
+#endif
+		if (0 == (p->opcode & 255)) {
+			p->MainClass = kIKindBsrW;
+		} else
+#if Use68020
+		if (255 == (p->opcode & 255)) {
+			p->MainClass = kIKindBsrL;
+		} else
+#endif
+		{
+			p->MainClass = kIKindBsrB;
+			p->DecOp.y.v[1].ArgDat = p->opcode & 255;
+		}
+	} else if (cond == 0) {
+		/* Bra 01100000nnnnnnnn */
+#if WantCycByPriOp
+		p->Cycles = (10 * kCycleScale + 2 * RdAvgXtraCyc);
+#endif
+		if (0 == (p->opcode & 255)) {
+			p->MainClass = kIKindBraW;
+		} else
+#if Use68020
+		if (255 == (p->opcode & 255)) {
+			p->MainClass = kIKindBraL;
+		} else
+#endif
+		{
+			p->MainClass = kIKindBraB;
+			p->DecOp.y.v[1].ArgDat = p->opcode & 255;
+		}
+	} else {
+		p->DecOp.y.v[0].ArgDat = cond;
+		/* Bcc 0110ccccnnnnnnnn */
+		if (0 == (p->opcode & 255)) {
+#if WantCycByPriOp
+#if WantCloserCyc
+			p->Cycles = 0;
+#else
+			p->Cycles = (11 * kCycleScale + 2 * RdAvgXtraCyc);
+				/* average of branch taken 10(2/0) and not 12(2/0) */
+#endif
+#endif
+			p->MainClass = kIKindBccW;
+		} else
+#if Use68020
+		if (255 == (p->opcode & 255)) {
+			p->MainClass = kIKindBccL;
+		} else
+#endif
+		{
+#if WantCycByPriOp
+#if WantCloserCyc
+			p->Cycles = 0;
+#else
+			p->Cycles = (9 * kCycleScale
+				+ RdAvgXtraCyc + (RdAvgXtraCyc / 2));
+				/* average of branch taken 10(2/0) and not 8(1/0) */
+#endif
+#endif
+			p->MainClass = kIKindBccB;
+			p->DecOp.y.v[1].ArgDat = p->opcode & 255;
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DeCode7(WorkR *p)
+{
+	if (b8(p) == 0) {
+		p->opsize = 4;
+#if WantCycByPriOp
+		p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
+#endif
+		p->MainClass = kIKindMoveQ;
+		p->DecOp.y.v[0].ArgDat = p->opcode & 255;
+		p->DecOp.y.v[1].ArgDat = rg9(p);
+	} else {
+		p->MainClass = kIKindIllegal;
+	}
+}
+
+LOCALPROCUSEDONCE DeCode8(WorkR *p)
+{
+	if (b76(p) == 3) {
+		p->opsize = 2;
+		if (CheckValidAddrMode(p, mode(p), reg(p),
+			kAddrValidData, trueblnr))
+		if (CheckValidAddrMode(p, 0, rg9(p),
+			kAddrValidAny, falseblnr))
+		{
+			if (b8(p) == 0) {
+				/* DivU 1000ddd011mmmrrr */
+#if WantCycByPriOp
+				p->Cycles = RdAvgXtraCyc;
+				p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#if ! WantCloserCyc
+				p->Cycles += 133 * kCycleScale;
+					/*
+						worse case 140, less than ten percent
+						different from best case
+					*/
+#endif
+#endif
+				p->MainClass = kIKindDivU;
+			} else {
+				/* DivS 1000ddd111mmmrrr */
+#if WantCycByPriOp
+				p->Cycles = RdAvgXtraCyc;
+				p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#if ! WantCloserCyc
+				p->Cycles += 150 * kCycleScale;
+					/*
+						worse case 158, less than ten percent different
+						from best case
+					*/
+#endif
+#endif
+				p->MainClass = kIKindDivS;
+			}
+		}
+	} else {
+		if (b8(p) == 0) {
+			/* OR 1000ddd0ssmmmrrr */
+#if 0
+			if (CheckDataAddrMode(p)) {
+				p->MainClass = kIKindOrEaD;
+			}
+#endif
+			FindOpSizeFromb76(p);
+			if (CheckValidAddrMode(p, mode(p), reg(p),
+				kAddrValidData, trueblnr))
+			if (CheckValidAddrMode(p, 0, rg9(p),
+				kAddrValidAny, falseblnr))
+			{
+#if WantCycByPriOp
+				if (4 == p->opsize) {
+					if ((mode(p) < 2)
+						|| ((7 == mode(p)) && (reg(p) == 4)))
+					{
+						p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
+					} else {
+						p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
+					}
+				} else {
+					p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
+				}
+				p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+				p->MainClass = kIKindOrEaD;
+			}
+		} else {
+			if (mode(p) < 2) {
+				switch (b76(p)) {
+					case 0:
+						/* SBCD 1000xxx10000mxxx */
+#if WantCycByPriOp
+						if (0 != mode(p)) {
+							p->Cycles = (18 * kCycleScale
+								+ 3 * RdAvgXtraCyc + WrAvgXtraCyc);
+						} else {
+							p->Cycles = (6 * kCycleScale
+								+ RdAvgXtraCyc);
+						}
+#endif
+						p->opsize = 1;
+						if (mode(p) == 0) {
+							if (CheckValidAddrMode(p, 0, reg(p),
+								kAddrValidAny, trueblnr))
+							if (CheckValidAddrMode(p, 0, rg9(p),
+								kAddrValidAny, falseblnr))
+							{
+								p->MainClass = kIKindSbcd;
+							}
+						} else {
+							if (CheckValidAddrMode(p, 4, reg(p),
+								kAddrValidAny, trueblnr))
+							if (CheckValidAddrMode(p, 4, rg9(p),
+								kAddrValidAny, falseblnr))
+							{
+								p->MainClass = kIKindSbcd;
+							}
+						}
+						break;
+#if Use68020
+					case 1:
+						/* PACK 1000rrr10100mrrr */
+						if (mode(p) == 0) {
+							p->opsize = 2;
+							if (CheckValidAddrMode(p, 0, reg(p),
+								kAddrValidAny, trueblnr))
+							{
+								p->opsize = 1;
+								if (CheckValidAddrMode(p, 0, rg9(p),
+									kAddrValidAny, falseblnr))
+								{
+									p->MainClass = kIKindPack;
+								}
+							}
+						} else {
+							p->opsize = 2;
+							if (CheckValidAddrMode(p, 4, reg(p),
+								kAddrValidAny, trueblnr))
+							{
+								p->opsize = 1;
+								if (CheckValidAddrMode(p, 4, rg9(p),
+									kAddrValidAny, falseblnr))
+								{
+									p->MainClass = kIKindPack;
+								}
+							}
+						}
+						break;
+					case 2:
+						/* UNPK 1000rrr11000mrrr */
+						if (mode(p) == 0) {
+							p->opsize = 1;
+							if (CheckValidAddrMode(p, 0, reg(p),
+								kAddrValidAny, trueblnr))
+							{
+								p->opsize = 2;
+								if (CheckValidAddrMode(p, 0, rg9(p),
+									kAddrValidAny, falseblnr))
+								{
+									p->MainClass = kIKindUnpk;
+								}
+							}
+						} else {
+							p->opsize = 1;
+							if (CheckValidAddrMode(p, 4, reg(p),
+								kAddrValidAny, trueblnr))
+							{
+								p->opsize = 2;
+								if (CheckValidAddrMode(p, 4, rg9(p),
+									kAddrValidAny, falseblnr))
+								{
+									p->MainClass = kIKindUnpk;
+								}
+							}
+						}
+						break;
+#endif
+					default:
+						p->MainClass = kIKindIllegal;
+						break;
+				}
+			} else {
+				/* OR 1000ddd1ssmmmrrr */
+#if 0
+				if (CheckDataAltAddrMode(p)) {
+					p->MainClass = kIKindOrDEa;
+				}
+#endif
+				FindOpSizeFromb76(p);
+				if (CheckValidAddrMode(p, 0, rg9(p),
+					kAddrValidAny, trueblnr))
+				if (CheckValidAddrMode(p, mode(p), reg(p),
+					kAddrValidAltMem, falseblnr))
+				{
+#if WantCycByPriOp
+					p->Cycles = (4 == p->opsize)
+						? (12 * kCycleScale
+							+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
+						: (8 * kCycleScale
+							+ RdAvgXtraCyc + WrAvgXtraCyc);
+					p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+					p->MainClass = kIKindOrDEa;
+				}
+			}
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DeCode9(WorkR *p)
+{
+	if (b76(p) == 3) {
+		/* SUBA 1001dddm11mmmrrr */
+#if 0
+		if (IsValidAddrMode(p)) {
+			p->MainClass = kIKindSubA;
+		}
+#endif
+		p->opsize = b8(p) * 2 + 2;
+		SetDcoArgFields(p, falseblnr, kAMdRegL, rg9(p) + 8);
+			/* always long, regardless of opsize */
+		if (CheckValidAddrMode(p, mode(p), reg(p),
+			kAddrValidAny, trueblnr))
+		{
+#if WantCycByPriOp
+			if (4 == p->opsize) {
+				if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4)))
+				{
+					p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
+				} else {
+					p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
+				}
+			} else {
+				p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
+			}
+			p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+			p->MainClass = kIKindSubA;
+		}
+	} else {
+		if (b8(p) == 0) {
+			/* SUB 1001ddd0ssmmmrrr */
+#if 0
+			if (IsValidAddrMode(p)) {
+				p->MainClass = kIKindSubEaR;
+			}
+#endif
+			FindOpSizeFromb76(p);
+			if (CheckValidAddrMode(p, mode(p), reg(p),
+				kAddrValidAny, trueblnr))
+			if (CheckValidAddrMode(p, 0, rg9(p),
+				kAddrValidAny, falseblnr))
+			{
+#if WantCycByPriOp
+				if (4 == p->opsize) {
+					if ((mode(p) < 2)
+						|| ((7 == mode(p)) && (reg(p) == 4)))
+					{
+						p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
+					} else {
+						p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
+					}
+				} else {
+					p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
+				}
+				p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+				p->MainClass = kIKindSubB + OpSizeOffset(p);
+			}
+		} else {
+			if (mode(p) == 0) {
+				/* SUBX 1001ddd1ss000rrr */
+				/* p->MainClass = kIKindSubXd; */
+				FindOpSizeFromb76(p);
+				if (CheckValidAddrMode(p, 0, reg(p),
+					kAddrValidAny, trueblnr))
+				if (CheckValidAddrMode(p, 0, rg9(p),
+					kAddrValidAny, falseblnr))
+				{
+#if WantCycByPriOp
+					p->Cycles = (4 == p->opsize)
+						? (8 * kCycleScale + RdAvgXtraCyc)
+						: (4 * kCycleScale + RdAvgXtraCyc);
+#endif
+					p->MainClass = kIKindSubXB + OpSizeOffset(p);
+				}
+			} else if (mode(p) == 1) {
+				/* SUBX 1001ddd1ss001rrr */
+				/* p->MainClass = kIKindSubXm; */
+				FindOpSizeFromb76(p);
+				if (CheckValidAddrMode(p, 4, reg(p),
+					kAddrValidAny, trueblnr))
+				if (CheckValidAddrMode(p, 4, rg9(p),
+					kAddrValidAny, falseblnr))
+				{
+#if WantCycByPriOp
+					p->Cycles = (4 == p->opsize)
+						? (30 * kCycleScale
+							+ 5 * RdAvgXtraCyc + 2 * WrAvgXtraCyc)
+						: (18 * kCycleScale
+							+ 3 * RdAvgXtraCyc + 1 * WrAvgXtraCyc);
+#endif
+					p->MainClass = kIKindSubXB + OpSizeOffset(p);
+				}
+			} else {
+				/* SUB 1001ddd1ssmmmrrr */
+#if 0
+				if (CheckAltMemAddrMode(p)) {
+					p->MainClass = kIKindSubREa;
+				}
+#endif
+				FindOpSizeFromb76(p);
+				if (CheckValidAddrMode(p, 0, rg9(p),
+					kAddrValidAny, trueblnr))
+				if (CheckValidAddrMode(p, mode(p),
+					reg(p), kAddrValidAltMem, falseblnr))
+				{
+#if WantCycByPriOp
+					p->Cycles = (4 == p->opsize)
+						? (12 * kCycleScale
+							+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
+						: (8 * kCycleScale
+							+ RdAvgXtraCyc + WrAvgXtraCyc);
+					p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+					p->MainClass = kIKindSubB + OpSizeOffset(p);
+				}
+			}
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DeCodeA(WorkR *p)
+{
+#if WantCycByPriOp
+	p->Cycles = (34 * kCycleScale
+		+ 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
+#endif
+	p->MainClass = kIKindA;
+}
+
+LOCALPROCUSEDONCE DeCodeB(WorkR *p)
+{
+	if (b76(p) == 3) {
+		/* CMPA 1011ddds11mmmrrr */
+#if 0
+		if (IsValidAddrMode(p)) {
+			p->MainClass = kIKindCmpA;
+		}
+#endif
+		p->opsize = b8(p) * 2 + 2;
+		SetDcoArgFields(p, falseblnr, kAMdRegL, rg9(p) + 8);
+			/* always long, regardless of opsize */
+		if (CheckValidAddrMode(p, mode(p), reg(p),
+			kAddrValidAny, trueblnr))
+		{
+#if WantCycByPriOp
+			p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
+			p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+			p->MainClass = kIKindCmpA;
+		}
+	} else if (b8(p) == 1) {
+		if (mode(p) == 1) {
+			/* CmpM 1011ddd1ss001rrr */
+#if 0
+			p->MainClass = kIKindCmpM;
+#endif
+			FindOpSizeFromb76(p);
+			if (CheckValidAddrMode(p, 3, reg(p),
+				kAddrValidAny, trueblnr))
+			if (CheckValidAddrMode(p, 3, rg9(p),
+				kAddrValidAny, falseblnr))
+			{
+#if WantCycByPriOp
+				p->Cycles = (4 == p->opsize)
+					? (20 * kCycleScale + 5 * RdAvgXtraCyc)
+					: (12 * kCycleScale + 3 * RdAvgXtraCyc);
+#endif
+				p->MainClass = kIKindCmpB + OpSizeOffset(p);
+			}
+		} else {
+#if 0
+			/* Eor 1011ddd1ssmmmrrr */
+			if (CheckDataAltAddrMode(p)) {
+				p->MainClass = kIKindEor;
+			}
+#endif
+			FindOpSizeFromb76(p);
+			if (CheckValidAddrMode(p, 0, rg9(p),
+				kAddrValidAny, trueblnr))
+			if (CheckValidAddrMode(p, mode(p), reg(p),
+				kAddrValidDataAlt, falseblnr))
+			{
+#if WantCycByPriOp
+				if (0 != mode(p)) {
+					p->Cycles = (4 == p->opsize)
+						? (12 * kCycleScale
+							+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
+						: (8 * kCycleScale
+							+ RdAvgXtraCyc + WrAvgXtraCyc);
+				} else {
+					p->Cycles = (4 == p->opsize)
+						? (8 * kCycleScale + RdAvgXtraCyc)
+						: (4 * kCycleScale + RdAvgXtraCyc);
+				}
+				p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+				p->MainClass = kIKindEor;
+			}
+		}
+	} else {
+		/* Cmp 1011ddd0ssmmmrrr */
+#if 0
+		if (IsValidAddrMode(p)) {
+			p->MainClass = kIKindCmp;
+		}
+#endif
+		FindOpSizeFromb76(p);
+		if (CheckValidAddrMode(p, mode(p), reg(p),
+			kAddrValidAny, trueblnr))
+		if (CheckValidAddrMode(p, 0, rg9(p),
+			kAddrValidAny, falseblnr))
+		{
+#if WantCycByPriOp
+			p->Cycles = (4 == p->opsize)
+				? (6 * kCycleScale + RdAvgXtraCyc)
+				: (4 * kCycleScale + RdAvgXtraCyc);
+			p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+			p->MainClass = kIKindCmpB + OpSizeOffset(p);
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DeCodeC(WorkR *p)
+{
+	if (b76(p) == 3) {
+		p->opsize = 2;
+		if (CheckValidAddrMode(p, mode(p), reg(p),
+			kAddrValidData, trueblnr))
+		if (CheckValidAddrMode(p, 0, rg9(p),
+			kAddrValidAny, falseblnr))
+		{
+#if WantCycByPriOp
+#if WantCloserCyc
+			p->Cycles = (38 * kCycleScale + RdAvgXtraCyc);
+#else
+			p->Cycles = (54 * kCycleScale + RdAvgXtraCyc);
+				/* worst case 70, best case 38 */
+#endif
+			p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+			if (b8(p) == 0) {
+				/* MulU 1100ddd011mmmrrr */
+				p->MainClass = kIKindMulU;
+			} else {
+				/* MulS 1100ddd111mmmrrr */
+				p->MainClass = kIKindMulS;
+			}
+		}
+	} else {
+		if (b8(p) == 0) {
+			/* And 1100ddd0ssmmmrrr */
+#if 0
+			if (CheckDataAddrMode(p)) {
+				p->MainClass = kIKindAndEaD;
+			}
+#endif
+			FindOpSizeFromb76(p);
+			if (CheckValidAddrMode(p, mode(p), reg(p),
+				kAddrValidData, trueblnr))
+			if (CheckValidAddrMode(p, 0, rg9(p),
+				kAddrValidAny, falseblnr))
+			{
+#if WantCycByPriOp
+				if (4 == p->opsize) {
+					if ((mode(p) < 2)
+						|| ((7 == mode(p)) && (reg(p) == 4)))
+					{
+						p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
+					} else {
+						p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
+					}
+				} else {
+					p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
+				}
+				p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+				p->MainClass = kIKindAndEaD;
+			}
+		} else {
+			if (mode(p) < 2) {
+				switch (b76(p)) {
+					case 0:
+						/* ABCD 1100ddd10000mrrr */
+#if WantCycByPriOp
+						if (0 != mode(p)) {
+							p->Cycles = (18 * kCycleScale
+								+ 3 * RdAvgXtraCyc + WrAvgXtraCyc);
+						} else {
+							p->Cycles = (6 * kCycleScale
+								+ RdAvgXtraCyc);
+						}
+#endif
+						p->opsize = 1;
+						if (mode(p) == 0) {
+							if (CheckValidAddrMode(p, 0, reg(p),
+								kAddrValidAny, trueblnr))
+							if (CheckValidAddrMode(p, 0, rg9(p),
+								kAddrValidAny, falseblnr))
+							{
+								p->MainClass = kIKindAbcd;
+							}
+						} else {
+							if (CheckValidAddrMode(p, 4, reg(p),
+								kAddrValidAny, trueblnr))
+							if (CheckValidAddrMode(p, 4, rg9(p),
+								kAddrValidAny, falseblnr))
+							{
+								p->MainClass = kIKindAbcd;
+							}
+						}
+						break;
+					case 1:
+						/* Exg 1100ddd10100trrr */
+#if WantCycByPriOp
+						p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
+#endif
+						p->opsize = 4;
+						if (mode(p) == 0) {
+							if (CheckValidAddrMode(p, 0, rg9(p),
+								kAddrValidAny, trueblnr))
+							if (CheckValidAddrMode(p, 0, reg(p),
+								kAddrValidAny, falseblnr))
+							{
+								p->MainClass = kIKindExg;
+							}
+						} else {
+							if (CheckValidAddrMode(p, 1, rg9(p),
+								kAddrValidAny, trueblnr))
+							if (CheckValidAddrMode(p, 1, reg(p),
+								kAddrValidAny, falseblnr))
+							{
+								p->MainClass = kIKindExg;
+							}
+						}
+						break;
+					case 2:
+					default: /* keep compiler happy */
+						if (mode(p) == 0) {
+							p->MainClass = kIKindIllegal;
+						} else {
+							/* Exg 1100ddd110001rrr */
+#if WantCycByPriOp
+							p->Cycles = (6 * kCycleScale
+								+ RdAvgXtraCyc);
+#endif
+							if (CheckValidAddrMode(p, 0, rg9(p),
+								kAddrValidAny, trueblnr))
+							if (CheckValidAddrMode(p, 1, reg(p),
+								kAddrValidAny, falseblnr))
+							{
+								p->MainClass = kIKindExg;
+							}
+						}
+						break;
+				}
+			} else {
+				/* And 1100ddd1ssmmmrrr */
+#if 0
+				if (CheckAltMemAddrMode(p)) {
+					p->MainClass = kIKindAndDEa;
+				}
+#endif
+				FindOpSizeFromb76(p);
+				if (CheckValidAddrMode(p, 0, rg9(p),
+					kAddrValidAny, trueblnr))
+				if (CheckValidAddrMode(p, mode(p), reg(p),
+					kAddrValidAltMem, falseblnr))
+				{
+#if WantCycByPriOp
+					p->Cycles = (4 == p->opsize)
+						? (12 * kCycleScale
+							+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
+						: (8 * kCycleScale
+							+ RdAvgXtraCyc + WrAvgXtraCyc);
+					p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+					p->MainClass = kIKindAndDEa;
+				}
+			}
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DeCodeD(WorkR *p)
+{
+	if (b76(p) == 3) {
+		/* ADDA 1101dddm11mmmrrr */
+		p->opsize = b8(p) * 2 + 2;
+		SetDcoArgFields(p, falseblnr, kAMdRegL, rg9(p) + 8);
+			/* always long, regardless of opsize */
+		if (CheckValidAddrMode(p, mode(p), reg(p),
+			kAddrValidAny, trueblnr))
+		{
+#if WantCycByPriOp
+			if (4 == p->opsize) {
+				if ((mode(p) < 2) || ((7 == mode(p)) && (reg(p) == 4)))
+				{
+					p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
+				} else {
+					p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
+				}
+			} else {
+				p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
+			}
+			p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+			p->MainClass = kIKindAddA;
+		}
+	} else {
+		if (b8(p) == 0) {
+			/* ADD 1101ddd0ssmmmrrr */
+			FindOpSizeFromb76(p);
+			if (CheckValidAddrMode(p, mode(p), reg(p),
+				kAddrValidAny, trueblnr))
+			if (CheckValidAddrMode(p, 0, rg9(p),
+				kAddrValidAny, falseblnr))
+			{
+#if WantCycByPriOp
+				if (4 == p->opsize) {
+					if ((mode(p) < 2)
+						|| ((7 == mode(p)) && (reg(p) == 4)))
+					{
+						p->Cycles = (8 * kCycleScale + RdAvgXtraCyc);
+					} else {
+						p->Cycles = (6 * kCycleScale + RdAvgXtraCyc);
+					}
+				} else {
+					p->Cycles = (4 * kCycleScale + RdAvgXtraCyc);
+				}
+				p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+				p->MainClass = kIKindAddB + OpSizeOffset(p);
+			}
+		} else {
+			if (mode(p) == 0) {
+				/* ADDX 1101ddd1ss000rrr */
+				/* p->MainClass = kIKindAddXd; */
+				FindOpSizeFromb76(p);
+				if (CheckValidAddrMode(p, 0, reg(p),
+					kAddrValidAny, trueblnr))
+				if (CheckValidAddrMode(p, 0, rg9(p),
+					kAddrValidAny, falseblnr))
+				{
+#if WantCycByPriOp
+					p->Cycles = (4 == p->opsize)
+						? (8 * kCycleScale + RdAvgXtraCyc)
+						: (4 * kCycleScale + RdAvgXtraCyc);
+#endif
+					p->MainClass = kIKindAddXB + OpSizeOffset(p);
+				}
+			} else if (mode(p) == 1) {
+				/* p->MainClass = kIKindAddXm; */
+				FindOpSizeFromb76(p);
+				if (CheckValidAddrMode(p, 4, reg(p),
+					kAddrValidAny, trueblnr))
+				if (CheckValidAddrMode(p, 4, rg9(p),
+					kAddrValidAny, falseblnr))
+				{
+#if WantCycByPriOp
+					p->Cycles = (4 == p->opsize)
+						? (30 * kCycleScale
+							+ 5 * RdAvgXtraCyc + 2 * WrAvgXtraCyc)
+						: (18 * kCycleScale
+							+ 3 * RdAvgXtraCyc + 1 * WrAvgXtraCyc);
+#endif
+					p->MainClass = kIKindAddXB + OpSizeOffset(p);
+				}
+			} else {
+				/* ADD 1101ddd1ssmmmrrr */
+				FindOpSizeFromb76(p);
+				if (CheckValidAddrMode(p, 0, rg9(p),
+					kAddrValidAny, trueblnr))
+				if (CheckValidAddrMode(p, mode(p), reg(p),
+					kAddrValidAltMem, falseblnr))
+				{
+#if WantCycByPriOp
+					p->Cycles = (4 == p->opsize)
+						? (12 * kCycleScale
+							+ RdAvgXtraCyc + 2 * WrAvgXtraCyc)
+						: (8 * kCycleScale
+							+ RdAvgXtraCyc + WrAvgXtraCyc);
+					p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+					p->MainClass = kIKindAddB + OpSizeOffset(p);
+				}
+			}
+		}
+	}
+}
+
+LOCALFUNC ui5r rolops(WorkR *p, ui5r x)
+{
+	ui5r binop;
+
+	binop = (x << 1);
+	if (! b8(p)) {
+		binop++; /* 'R' */
+	} /* else 'L' */
+
+	return kIKindAslB + 3 * binop + OpSizeOffset(p);
+}
+
+LOCALPROCUSEDONCE DeCodeE(WorkR *p)
+{
+	if (b76(p) == 3) {
+		if ((p->opcode & 0x0800) != 0) {
+#if Use68020
+			/* 11101???11mmmrrr */
+			p->DecOp.y.v[0].AMd = mode(p);
+			p->DecOp.y.v[0].ArgDat = (p->opcode >> 8) & 7;
+			if (0 == mode(p)) {
+				SetDcoArgFields(p, falseblnr, kAMdRegL, reg(p));
+				p->MainClass = kIKindBitField;
+			} else {
+				switch ((p->opcode >> 8) & 7) {
+					case 0: /* BFTST */
+					case 1: /* BFEXTU */
+					case 3: /* BFEXTS */
+					case 5: /* BFFFO */
+						if (CheckControlAddrMode(p)) {
+							p->MainClass = kIKindBitField;
+						}
+						break;
+					default: /* BFCHG, BFCLR, BFSET, BFINS */
+						if (CheckControlAltAddrMode(p)) {
+							p->MainClass = kIKindBitField;
+						}
+						break;
+				}
+			}
+#else
+			p->MainClass = kIKindIllegal;
+#endif
+		} else {
+			p->opsize = 2;
+			/* 11100ttd11mmmddd */
+			if (CheckAltMemAddrMode(p)) {
+#if WantCycByPriOp
+				p->Cycles = (6 * kCycleScale
+#if ! WantCloserCyc
+					+ 2 * kCycleScale
+#endif
+					+ RdAvgXtraCyc + WrAvgXtraCyc);
+				p->Cycles += OpEACalcCyc(p, mode(p), reg(p));
+#endif
+				p->MainClass = rolops(p, rg9(p));
+				SetDcoArgFields(p, trueblnr, kAMdDat4, 1);
+			}
+		}
+	} else {
+		FindOpSizeFromb76(p);
+		if (mode(p) < 4) {
+			/* 1110cccdss0ttddd */
+			if (CheckValidAddrMode(p, 0, reg(p),
+				kAddrValidAny, falseblnr))
+			{
+#if WantCycByPriOp
+				p->Cycles = ((4 == p->opsize)
+						? (8 * kCycleScale + RdAvgXtraCyc)
+						: (6 * kCycleScale + RdAvgXtraCyc))
+#if ! WantCloserCyc
+					+ (octdat(rg9(p)) * (2 * kCycleScale))
+#endif
+					;
+#endif
+				p->MainClass = rolops(p, mode(p) & 3);
+				SetDcoArgFields(p, trueblnr, kAMdDat4, octdat(rg9(p)));
+			}
+		} else {
+			/* 1110rrrdss1ttddd */
+			if (CheckValidAddrMode(p, 0, rg9(p),
+				kAddrValidAny, trueblnr))
+			if (CheckValidAddrMode(p, 0, reg(p),
+				kAddrValidAny, falseblnr))
+			{
+#if WantCycByPriOp
+#if WantCloserCyc
+				p->Cycles = ((4 == p->opsize)
+						? (8 * kCycleScale + RdAvgXtraCyc)
+						: (6 * kCycleScale + RdAvgXtraCyc));
+#else
+				p->Cycles = (4 == p->opsize)
+					? ((8 * kCycleScale)
+						+ RdAvgXtraCyc + (8 * (2 * kCycleScale)))
+						/* say average shift count of 8 */
+					: ((6 * kCycleScale)
+						+ RdAvgXtraCyc + (4 * (2 * kCycleScale)));
+						/* say average shift count of 4 */
+#endif
+#endif
+				p->MainClass = rolops(p, mode(p) & 3);
+			}
+		}
+	}
+}
+
+LOCALPROCUSEDONCE DeCodeF(WorkR *p)
+{
+#if WantCycByPriOp
+	p->Cycles =
+		(34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
+#endif
+	p->DecOp.y.v[0].AMd =    (p->opcode >> 8) & 0xFF;
+	p->DecOp.y.v[0].ArgDat = (p->opcode     ) & 0xFF;
+#if EmMMU || EmFPU
+	switch (rg9(p)) {
+#if EmMMU
+		case 0:
+			p->MainClass = kIKindMMU;
+			break;
+#endif
+#if EmFPU
+		case 1:
+			switch (md6(p)) {
+				case 0:
+					p->MainClass = kIKindFPUmd60;
+					break;
+				case 1:
+					if (mode(p) == 1) {
+						p->MainClass = kIKindFPUDBcc;
+					} else if (mode(p) == 7) {
+						p->MainClass = kIKindFPUTrapcc;
+					} else {
+						p->MainClass = kIKindFPUScc;
+					}
+					break;
+				case 2:
+					p->MainClass = kIKindFPUFBccW;
+					break;
+				case 3:
+					p->MainClass = kIKindFPUFBccL;
+					break;
+				case 4:
+					p->MainClass = kIKindFPUSave;
+					break;
+				case 5:
+					p->MainClass = kIKindFPURestore;
+					break;
+				default:
+					p->MainClass = kIKindFPUdflt;
+					break;
+			}
+			break;
+#endif
+		default:
+			p->MainClass = kIKindFdflt;
+			break;
+	}
+#else
+	p->MainClass = kIKindFdflt;
+#endif
+}
+
+LOCALPROC DeCodeOneOp(WorkR *p)
+{
+	switch (p->opcode >> 12) {
+		case 0x0:
+			DeCode0(p);
+			break;
+		case 0x1:
+			DeCode1(p);
+			break;
+		case 0x2:
+			DeCode2(p);
+			break;
+		case 0x3:
+			DeCode3(p);
+			break;
+		case 0x4:
+			DeCode4(p);
+			break;
+		case 0x5:
+			DeCode5(p);
+			break;
+		case 0x6:
+			DeCode6(p);
+			break;
+		case 0x7:
+			DeCode7(p);
+			break;
+		case 0x8:
+			DeCode8(p);
+			break;
+		case 0x9:
+			DeCode9(p);
+			break;
+		case 0xA:
+			DeCodeA(p);
+			break;
+		case 0xB:
+			DeCodeB(p);
+			break;
+		case 0xC:
+			DeCodeC(p);
+			break;
+		case 0xD:
+			DeCodeD(p);
+			break;
+		case 0xE:
+			DeCodeE(p);
+			break;
+		case 0xF:
+		default: /* keep compiler happy */
+			DeCodeF(p);
+			break;
+	}
+
+	if (kIKindIllegal == p->MainClass) {
+#if WantCycByPriOp
+		p->Cycles = (34 * kCycleScale
+			+ 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
+#endif
+		p->DecOp.y.v[0].AMd = 0;
+		p->DecOp.y.v[0].ArgDat = 0;
+		p->DecOp.y.v[1].AMd = 0;
+		p->DecOp.y.v[1].ArgDat = 0;
+	}
+
+	SetDcoMainClas(&(p->DecOp), p->MainClass);
+#if WantCycByPriOp
+	SetDcoCycles(&(p->DecOp), p->Cycles);
+#else
+	SetDcoCycles(&(p->DecOp), kMyAvgCycPerInstr);
+#endif
+}
+
+GLOBALPROC M68KITAB_setup(DecOpR *p)
+{
+	ui5b i;
+	WorkR r;
+
+	for (i = 0; i < (ui5b)256 * 256; ++i) {
+		r.opcode = i;
+		r.MainClass = kIKindIllegal;
+
+		r.DecOp.y.v[0].AMd = 0;
+		r.DecOp.y.v[0].ArgDat = 0;
+		r.DecOp.y.v[1].AMd = 0;
+		r.DecOp.y.v[1].ArgDat = 0;
+#if WantCycByPriOp
+		r.Cycles = kMyAvgCycPerInstr;
+#endif
+
+		DeCodeOneOp(&r);
+
+		p[i] = r.DecOp;
+	}
+}
--- /dev/null
+++ b/src/M68KITAB.h
@@ -1,0 +1,279 @@
+/*
+	M68KITAB.h
+
+	Copyright (C) 2007, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef M68KITAB_H
+#error "header already included"
+#else
+#define M68KITAB_H
+#endif
+
+enum {
+	kIKindTst,
+	kIKindCmpB,
+	kIKindCmpW,
+	kIKindCmpL,
+	kIKindBccB,
+	kIKindBccW,
+	kIKindBraB,
+	kIKindBraW,
+	kIKindDBcc,
+	kIKindDBF,
+	kIKindSwap,
+	kIKindMoveL,
+	kIKindMoveW,
+	kIKindMoveB,
+	kIKindMoveAL,
+	kIKindMoveAW,
+	kIKindMoveQ,
+	kIKindAddB,
+	kIKindAddW,
+	kIKindAddL,
+	kIKindSubB,
+	kIKindSubW,
+	kIKindSubL,
+	kIKindLea,
+	kIKindPEA,
+	kIKindA,
+	kIKindBsrB,
+	kIKindBsrW,
+	kIKindJsr,
+	kIKindLinkA6,
+	kIKindMOVEMRmML,
+	kIKindMOVEMApRL,
+	kIKindUnlkA6,
+	kIKindRts,
+	kIKindJmp,
+	kIKindClr,
+	kIKindAddA,
+	kIKindAddQA,
+	kIKindSubA,
+	kIKindSubQA,
+	kIKindCmpA,
+	kIKindAddXB,
+	kIKindAddXW,
+	kIKindAddXL,
+	kIKindSubXB,
+	kIKindSubXW,
+	kIKindSubXL,
+	kIKindAslB,
+	kIKindAslW,
+	kIKindAslL,
+	kIKindAsrB,
+	kIKindAsrW,
+	kIKindAsrL,
+	kIKindLslB,
+	kIKindLslW,
+	kIKindLslL,
+	kIKindLsrB,
+	kIKindLsrW,
+	kIKindLsrL,
+	kIKindRxlB,
+	kIKindRxlW,
+	kIKindRxlL,
+	kIKindRxrB,
+	kIKindRxrW,
+	kIKindRxrL,
+	kIKindRolB,
+	kIKindRolW,
+	kIKindRolL,
+	kIKindRorB,
+	kIKindRorW,
+	kIKindRorL,
+	kIKindBTstB,
+	kIKindBChgB,
+	kIKindBClrB,
+	kIKindBSetB,
+	kIKindBTstL,
+	kIKindBChgL,
+	kIKindBClrL,
+	kIKindBSetL,
+	kIKindAndI,
+	kIKindAndEaD,
+	kIKindAndDEa,
+	kIKindOrI,
+	kIKindOrDEa,
+	kIKindOrEaD,
+	kIKindEor,
+	kIKindEorI,
+	kIKindNot,
+	kIKindScc,
+	kIKindNegXB,
+	kIKindNegXW,
+	kIKindNegXL,
+	kIKindNegB,
+	kIKindNegW,
+	kIKindNegL,
+	kIKindEXTW,
+	kIKindEXTL,
+	kIKindMulU,
+	kIKindMulS,
+	kIKindDivU,
+	kIKindDivS,
+	kIKindExg,
+	kIKindMoveEaCCR,
+	kIKindMoveSREa,
+	kIKindMoveEaSR,
+	kIKindOrISR,
+	kIKindAndISR,
+	kIKindEorISR,
+	kIKindOrICCR,
+	kIKindAndICCR,
+	kIKindEorICCR,
+	kIKindMOVEMApRW,
+	kIKindMOVEMRmMW,
+	kIKindMOVEMrmW,
+	kIKindMOVEMrmL,
+	kIKindMOVEMmrW,
+	kIKindMOVEMmrL,
+	kIKindAbcd,
+	kIKindSbcd,
+	kIKindNbcd,
+	kIKindRte,
+	kIKindNop,
+	kIKindMoveP0,
+	kIKindMoveP1,
+	kIKindMoveP2,
+	kIKindMoveP3,
+	kIKindIllegal,
+	kIKindChkW,
+	kIKindTrap,
+	kIKindTrapV,
+	kIKindRtr,
+	kIKindLink,
+	kIKindUnlk,
+	kIKindMoveRUSP,
+	kIKindMoveUSPR,
+	kIKindTas,
+	kIKindFdflt,
+	kIKindStop,
+	kIKindReset,
+
+#if Use68020
+	kIKindCallMorRtm,
+	kIKindBraL,
+	kIKindBccL,
+	kIKindBsrL,
+	kIKindEXTBL,
+	kIKindTRAPcc,
+	kIKindChkL,
+	kIKindBkpt,
+	kIKindDivL,
+	kIKindMulL,
+	kIKindRtd,
+	kIKindMoveCCREa,
+	kIKindMoveCEa,
+	kIKindMoveEaC,
+	kIKindLinkL,
+	kIKindPack,
+	kIKindUnpk,
+	kIKindCHK2orCMP2,
+	kIKindCAS2,
+	kIKindCAS,
+	kIKindMoveS,
+	kIKindBitField,
+#endif
+#if EmMMU
+	kIKindMMU,
+#endif
+#if EmFPU
+	kIKindFPUmd60,
+	kIKindFPUDBcc,
+	kIKindFPUTrapcc,
+	kIKindFPUScc,
+	kIKindFPUFBccW,
+	kIKindFPUFBccL,
+	kIKindFPUSave,
+	kIKindFPURestore,
+	kIKindFPUdflt,
+#endif
+
+	kNumIKinds
+};
+
+enum {
+	kAMdRegB,
+	kAMdRegW,
+	kAMdRegL,
+	kAMdIndirectB,
+	kAMdIndirectW,
+	kAMdIndirectL,
+	kAMdAPosIncB,
+	kAMdAPosIncW,
+	kAMdAPosIncL,
+	kAMdAPosInc7B,
+	kAMdAPreDecB,
+	kAMdAPreDecW,
+	kAMdAPreDecL,
+	kAMdAPreDec7B,
+	kAMdADispB,
+	kAMdADispW,
+	kAMdADispL,
+	kAMdAIndexB,
+	kAMdAIndexW,
+	kAMdAIndexL,
+	kAMdAbsWB,
+	kAMdAbsWW,
+	kAMdAbsWL,
+	kAMdAbsLB,
+	kAMdAbsLW,
+	kAMdAbsLL,
+	kAMdPCDispB,
+	kAMdPCDispW,
+	kAMdPCDispL,
+	kAMdPCIndexB,
+	kAMdPCIndexW,
+	kAMdPCIndexL,
+	kAMdImmedB,
+	kAMdImmedW,
+	kAMdImmedL,
+	kAMdDat4,
+
+	kNumAMds
+};
+
+struct DecOpXR {
+	/* expected size : 4 bytes */
+	ui4b MainClas;
+	ui4b Cycles;
+};
+typedef struct DecOpXR DecOpXR;
+
+struct DecArgR {
+	/* expected size : 2 bytes */
+	ui3b AMd;
+	ui3b ArgDat;
+};
+typedef struct DecArgR DecArgR;
+
+struct DecOpYR {
+	/* expected size : 4 bytes */
+	DecArgR v[2];
+};
+typedef struct DecOpYR DecOpYR;
+
+struct DecOpR {
+	/* expected size : 8 bytes */
+	DecOpXR x;
+	DecOpYR y;
+} my_align_8;
+typedef struct DecOpR DecOpR;
+
+#define GetDcoCycles(p) ((p)->x.Cycles)
+
+#define SetDcoMainClas(p, xx) ((p)->x.MainClas = (xx))
+#define SetDcoCycles(p, xx) ((p)->x.Cycles = (xx))
+
+EXPORTPROC M68KITAB_setup(DecOpR *p);
--- /dev/null
+++ b/src/MINEM68K.c
@@ -1,0 +1,8924 @@
+/*
+	MINEM68K.c
+
+	Copyright (C) 2009 Bernd Schmidt, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	EMulator of 68K cpu with GENeric c code (not assembly)
+
+	This code descends from a simple 68000 emulator that I
+	(Paul C. Pratt) wrote long ago. That emulator ran on a 680x0,
+	and used the cpu it ran on to do some of the work. This
+	descendent fills in those holes with code from the
+	Un*x Amiga Emulator by Bernd Schmidt, as found being used in vMac.
+
+	This emulator is about 10 times smaller than the UAE,
+	at the cost of being 2 to 3 times slower.
+
+	FPU Emulation added 9/12/2009 by Ross Martin
+		(this code now located in "FPCPEMDV.h")
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+
+#include "MYOSGLUE.h"
+#include "ENDIANAC.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+
+#include "M68KITAB.h"
+
+#if WantDisasm
+#include "DISAM68K.h"
+#endif
+#endif
+
+#include "MINEM68K.h"
+
+/*
+	ReportAbnormalID unused 0x0123 - 0x01FF
+*/
+
+#ifndef DisableLazyFlagAll
+#define DisableLazyFlagAll 0
+#endif
+	/*
+		useful for debugging, to tell if an observed bug is
+		being cause by lazy flag evaluation stuff.
+		Can also disable parts of it individually:
+	*/
+
+#ifndef ForceFlagsEval
+#if DisableLazyFlagAll
+#define ForceFlagsEval 1
+#else
+#define ForceFlagsEval 0
+#endif
+#endif
+
+#ifndef UseLazyZ
+#if DisableLazyFlagAll || ForceFlagsEval
+#define UseLazyZ 0
+#else
+#define UseLazyZ 1
+#endif
+#endif
+
+#ifndef UseLazyCC
+#if DisableLazyFlagAll
+#define UseLazyCC 0
+#else
+#define UseLazyCC 1
+#endif
+#endif
+
+
+typedef unsigned char flagtype; /* must be 0 or 1, not boolean */
+
+
+/* Memory Address Translation Cache record */
+
+struct MATCr {
+	ui5r cmpmask;
+	ui5r cmpvalu;
+	ui5r usemask;
+	ui3p usebase;
+};
+typedef struct MATCr MATCr;
+typedef MATCr *MATCp;
+
+#ifndef USE_PCLIMIT
+#define USE_PCLIMIT 1
+#endif
+
+#define AKMemory 0
+#define AKRegister 1
+
+union ArgAddrT {
+	ui5r mem;
+	ui5r *rga;
+};
+typedef union ArgAddrT ArgAddrT;
+
+enum {
+	kLazyFlagsDefault,
+	kLazyFlagsTstB,
+	kLazyFlagsTstW,
+	kLazyFlagsTstL,
+	kLazyFlagsCmpB,
+	kLazyFlagsCmpW,
+	kLazyFlagsCmpL,
+	kLazyFlagsSubB,
+	kLazyFlagsSubW,
+	kLazyFlagsSubL,
+	kLazyFlagsAddB,
+	kLazyFlagsAddW,
+	kLazyFlagsAddL,
+	kLazyFlagsNegB,
+	kLazyFlagsNegW,
+	kLazyFlagsNegL,
+	kLazyFlagsAsrB,
+	kLazyFlagsAsrW,
+	kLazyFlagsAsrL,
+	kLazyFlagsAslB,
+	kLazyFlagsAslW,
+	kLazyFlagsAslL,
+#if UseLazyZ
+	kLazyFlagsZSet,
+#endif
+
+	kNumLazyFlagsKinds
+};
+
+typedef void (my_reg_call *ArgSetDstP)(ui5r f);
+
+#define FasterAlignedL 0
+	/*
+		If most long memory access is long aligned,
+		this should be faster. But on the Mac, this
+		doesn't seem to be the case, so an
+		unpredictable branch slows it down.
+	*/
+
+#ifndef HaveGlbReg
+#define HaveGlbReg 0
+#endif
+
+LOCALVAR struct regstruct
+{
+	ui5r regs[16]; /* Data and Address registers */
+
+	ui3p pc_p;
+	ui3p pc_pHi;
+	si5rr MaxCyclesToGo;
+
+#if WantCloserCyc
+	DecOpR *CurDecOp;
+#endif
+	DecOpYR CurDecOpY;
+
+	ui3r LazyFlagKind;
+	ui3r LazyXFlagKind;
+#if UseLazyZ
+	ui3r LazyFlagZSavedKind;
+#endif
+	ui5r LazyFlagArgSrc;
+	ui5r LazyFlagArgDst;
+	ui5r LazyXFlagArgSrc;
+	ui5r LazyXFlagArgDst;
+
+	ArgAddrT ArgAddr;
+	ArgSetDstP ArgSetDst;
+	ui5b SrcVal;
+
+	ui3p pc_pLo;
+	ui5r pc; /* Program Counter */
+
+	MATCr MATCrdB;
+	MATCr MATCwrB;
+	MATCr MATCrdW;
+	MATCr MATCwrW;
+#if FasterAlignedL
+	MATCr MATCrdL;
+	MATCr MATCwrL;
+#endif
+	ATTep HeadATTel;
+
+	si5r MoreCyclesToGo;
+	si5r ResidualCycles;
+	ui3b fakeword[2];
+
+	/* Status Register */
+	ui5r intmask; /* bits 10-8 : interrupt priority mask */
+	flagtype t1; /* bit 15: Trace mode 1 */
+#if Use68020
+	flagtype t0; /* bit 14: Trace mode 0 */
+#endif
+	flagtype s; /* bit 13: Supervisor or user privilege level */
+#if Use68020
+	flagtype m; /* bit 12: Master or interrupt mode */
+#endif
+
+	flagtype x; /* bit 4: eXtend */
+	flagtype n; /* bit 3: Negative */
+	flagtype z; /* bit 2: Zero */
+	flagtype v; /* bit 1: oVerflow */
+	flagtype c; /* bit 0: Carry */
+
+#if EmMMU | EmFPU
+	ui5b ArgKind;
+#endif
+
+	blnr TracePending;
+	blnr ExternalInterruptPending;
+#if 0
+	blnr ResetPending;
+#endif
+	ui3b *fIPL;
+#ifdef r_regs
+	struct regstruct *save_regs;
+#endif
+
+	CPTR usp; /* User Stack Pointer */
+	CPTR isp; /* Interrupt Stack Pointer */
+#if Use68020
+	CPTR msp; /* Master Stack Pointer */
+	ui5b sfc; /* Source Function Code register */
+	ui5b dfc; /* Destination Function Code register */
+	ui5b vbr; /* Vector Base Register */
+	ui5b cacr; /* Cache Control Register */
+		/*
+			bit 0 : Enable Cache
+			bit 1 : Freeze Cache
+			bit 2 : Clear Entry In Cache (write only)
+			bit 3 : Clear Cache (write only)
+		*/
+	ui5b caar; /* Cache Address Register */
+#endif
+
+#define disp_table_sz (256 * 256)
+#if SmallGlobals
+	DecOpR *disp_table;
+#else
+	DecOpR disp_table[disp_table_sz];
+#endif
+} regs;
+
+#define ui5r_MSBisSet(x) (((si5r)(x)) < 0)
+
+#define Bool2Bit(x) ((x) ? 1 : 0)
+
+
+#ifdef r_regs
+register struct regstruct *g_regs asm (r_regs);
+#define V_regs (*g_regs)
+#else
+#define V_regs regs
+#endif
+
+#ifdef r_pc_p
+register ui3p g_pc_p asm (r_pc_p);
+#define V_pc_p g_pc_p
+#else
+#define V_pc_p V_regs.pc_p
+#endif
+
+#ifdef r_MaxCyclesToGo
+register si5rr g_MaxCyclesToGo asm (r_MaxCyclesToGo);
+#define V_MaxCyclesToGo g_MaxCyclesToGo
+#else
+#define V_MaxCyclesToGo V_regs.MaxCyclesToGo
+#endif
+
+#ifdef r_pc_pHi
+register ui3p g_pc_pHi asm (r_pc_pHi);
+#define V_pc_pHi g_pc_pHi
+#else
+#define V_pc_pHi V_regs.pc_pHi
+#endif
+
+#define ZFLG V_regs.z
+#define NFLG V_regs.n
+#define CFLG V_regs.c
+#define VFLG V_regs.v
+#define XFLG V_regs.x
+
+#define m68k_dreg(num) (V_regs.regs[(num)])
+#define m68k_areg(num) (V_regs.regs[(num) + 8])
+
+
+#ifndef WantDumpTable
+#define WantDumpTable 0
+#endif
+
+#if WantDumpTable
+LOCALVAR ui5b DumpTable[kNumIKinds];
+#endif
+
+#if USE_PCLIMIT
+FORWARDPROC Recalc_PC_Block(void);
+FORWARDFUNC ui5r my_reg_call Recalc_PC_BlockReturnUi5r(ui5r v);
+#endif
+
+LOCALINLINEFUNC ui4r nextiword(void)
+/* NOT sign extended */
+{
+	ui4r r = do_get_mem_word(V_pc_p);
+	V_pc_p += 2;
+
+#if USE_PCLIMIT
+	if (my_cond_rare(V_pc_p >= V_pc_pHi)) {
+		Recalc_PC_Block();
+	}
+#endif
+
+	return r;
+}
+
+LOCALINLINEFUNC ui5r nextiSByte(void)
+{
+	ui5r r = ui5r_FromSByte(do_get_mem_byte(V_pc_p + 1));
+	V_pc_p += 2;
+
+#if USE_PCLIMIT
+	if (my_cond_rare(V_pc_p >= V_pc_pHi)) {
+		return Recalc_PC_BlockReturnUi5r(r);
+	}
+#endif
+
+	return r;
+}
+
+LOCALINLINEFUNC ui5r nextiSWord(void)
+/* NOT sign extended */
+{
+	ui5r r = ui5r_FromSWord(do_get_mem_word(V_pc_p));
+	V_pc_p += 2;
+
+#if USE_PCLIMIT
+	if (my_cond_rare(V_pc_p >= V_pc_pHi)) {
+		return Recalc_PC_BlockReturnUi5r(r);
+	}
+#endif
+
+	return r;
+}
+
+FORWARDFUNC ui5r nextilong_ext(void);
+
+LOCALINLINEFUNC ui5r nextilong(void)
+{
+	ui5r r = do_get_mem_long(V_pc_p);
+	V_pc_p += 4;
+
+#if USE_PCLIMIT
+	/* could be two words in different blocks */
+	if (my_cond_rare(V_pc_p >= V_pc_pHi)) {
+		r = nextilong_ext();
+	}
+#endif
+
+	return r;
+}
+
+LOCALINLINEPROC BackupPC(void)
+{
+	V_pc_p -= 2;
+
+#if USE_PCLIMIT
+	if (my_cond_rare(V_pc_p < V_regs.pc_pLo)) {
+		Recalc_PC_Block();
+	}
+#endif
+}
+
+LOCALINLINEFUNC CPTR m68k_getpc(void)
+{
+	return V_regs.pc + (V_pc_p - V_regs.pc_pLo);
+}
+
+
+FORWARDPROC DoCodeTst(void);
+FORWARDPROC DoCodeCmpB(void);
+FORWARDPROC DoCodeCmpW(void);
+FORWARDPROC DoCodeCmpL(void);
+FORWARDPROC DoCodeBccB(void);
+FORWARDPROC DoCodeBccW(void);
+FORWARDPROC DoCodeBraB(void);
+FORWARDPROC DoCodeBraW(void);
+FORWARDPROC DoCodeDBcc(void);
+FORWARDPROC DoCodeDBF(void);
+FORWARDPROC DoCodeSwap(void);
+FORWARDPROC DoCodeMoveL(void);
+FORWARDPROC DoCodeMoveW(void);
+FORWARDPROC DoCodeMoveB(void);
+FORWARDPROC DoCodeMoveA(void);
+FORWARDPROC DoCodeMoveQ(void);
+FORWARDPROC DoCodeAddB(void);
+FORWARDPROC DoCodeAddW(void);
+FORWARDPROC DoCodeAddL(void);
+FORWARDPROC DoCodeSubB(void);
+FORWARDPROC DoCodeSubW(void);
+FORWARDPROC DoCodeSubL(void);
+FORWARDPROC DoCodeLea(void);
+FORWARDPROC DoCodePEA(void);
+FORWARDPROC DoCodeA(void);
+FORWARDPROC DoCodeBsrB(void);
+FORWARDPROC DoCodeBsrW(void);
+FORWARDPROC DoCodeJsr(void);
+FORWARDPROC DoCodeLinkA6(void);
+FORWARDPROC DoCodeMOVEMRmML(void);
+FORWARDPROC DoCodeMOVEMApRL(void);
+FORWARDPROC DoCodeUnlkA6(void);
+FORWARDPROC DoCodeRts(void);
+FORWARDPROC DoCodeJmp(void);
+FORWARDPROC DoCodeClr(void);
+FORWARDPROC DoCodeAddA(void);
+FORWARDPROC DoCodeSubA(void);
+FORWARDPROC DoCodeCmpA(void);
+FORWARDPROC DoCodeAddXB(void);
+FORWARDPROC DoCodeAddXW(void);
+FORWARDPROC DoCodeAddXL(void);
+FORWARDPROC DoCodeSubXB(void);
+FORWARDPROC DoCodeSubXW(void);
+FORWARDPROC DoCodeSubXL(void);
+FORWARDPROC DoCodeAslB(void);
+FORWARDPROC DoCodeAslW(void);
+FORWARDPROC DoCodeAslL(void);
+FORWARDPROC DoCodeAsrB(void);
+FORWARDPROC DoCodeAsrW(void);
+FORWARDPROC DoCodeAsrL(void);
+FORWARDPROC DoCodeLslB(void);
+FORWARDPROC DoCodeLslW(void);
+FORWARDPROC DoCodeLslL(void);
+FORWARDPROC DoCodeLsrB(void);
+FORWARDPROC DoCodeLsrW(void);
+FORWARDPROC DoCodeLsrL(void);
+FORWARDPROC DoCodeRxlB(void);
+FORWARDPROC DoCodeRxlW(void);
+FORWARDPROC DoCodeRxlL(void);
+FORWARDPROC DoCodeRxrB(void);
+FORWARDPROC DoCodeRxrW(void);
+FORWARDPROC DoCodeRxrL(void);
+FORWARDPROC DoCodeRolB(void);
+FORWARDPROC DoCodeRolW(void);
+FORWARDPROC DoCodeRolL(void);
+FORWARDPROC DoCodeRorB(void);
+FORWARDPROC DoCodeRorW(void);
+FORWARDPROC DoCodeRorL(void);
+FORWARDPROC DoCodeBTstB(void);
+FORWARDPROC DoCodeBChgB(void);
+FORWARDPROC DoCodeBClrB(void);
+FORWARDPROC DoCodeBSetB(void);
+FORWARDPROC DoCodeBTstL(void);
+FORWARDPROC DoCodeBChgL(void);
+FORWARDPROC DoCodeBClrL(void);
+FORWARDPROC DoCodeBSetL(void);
+FORWARDPROC DoCodeAnd(void);
+FORWARDPROC DoCodeOr(void);
+FORWARDPROC DoCodeEor(void);
+FORWARDPROC DoCodeNot(void);
+FORWARDPROC DoCodeScc(void);
+FORWARDPROC DoCodeNegXB(void);
+FORWARDPROC DoCodeNegXW(void);
+FORWARDPROC DoCodeNegXL(void);
+FORWARDPROC DoCodeNegB(void);
+FORWARDPROC DoCodeNegW(void);
+FORWARDPROC DoCodeNegL(void);
+FORWARDPROC DoCodeEXTW(void);
+FORWARDPROC DoCodeEXTL(void);
+FORWARDPROC DoCodeMulU(void);
+FORWARDPROC DoCodeMulS(void);
+FORWARDPROC DoCodeDivU(void);
+FORWARDPROC DoCodeDivS(void);
+FORWARDPROC DoCodeExg(void);
+FORWARDPROC DoCodeMoveEaCR(void);
+FORWARDPROC DoCodeMoveSREa(void);
+FORWARDPROC DoCodeMoveEaSR(void);
+FORWARDPROC DoCodeOrISR(void);
+FORWARDPROC DoCodeAndISR(void);
+FORWARDPROC DoCodeEorISR(void);
+FORWARDPROC DoCodeOrICCR(void);
+FORWARDPROC DoCodeAndICCR(void);
+FORWARDPROC DoCodeEorICCR(void);
+FORWARDPROC DoCodeMOVEMApRW(void);
+FORWARDPROC DoCodeMOVEMRmMW(void);
+FORWARDPROC DoCodeMOVEMrmW(void);
+FORWARDPROC DoCodeMOVEMrmL(void);
+FORWARDPROC DoCodeMOVEMmrW(void);
+FORWARDPROC DoCodeMOVEMmrL(void);
+FORWARDPROC DoCodeAbcd(void);
+FORWARDPROC DoCodeSbcd(void);
+FORWARDPROC DoCodeNbcd(void);
+FORWARDPROC DoCodeRte(void);
+FORWARDPROC DoCodeNop(void);
+FORWARDPROC DoCodeMoveP0(void);
+FORWARDPROC DoCodeMoveP1(void);
+FORWARDPROC DoCodeMoveP2(void);
+FORWARDPROC DoCodeMoveP3(void);
+FORWARDPROC op_illg(void);
+FORWARDPROC DoCodeChk(void);
+FORWARDPROC DoCodeTrap(void);
+FORWARDPROC DoCodeTrapV(void);
+FORWARDPROC DoCodeRtr(void);
+FORWARDPROC DoCodeLink(void);
+FORWARDPROC DoCodeUnlk(void);
+FORWARDPROC DoCodeMoveRUSP(void);
+FORWARDPROC DoCodeMoveUSPR(void);
+FORWARDPROC DoCodeTas(void);
+FORWARDPROC DoCodeFdefault(void);
+FORWARDPROC DoCodeStop(void);
+FORWARDPROC DoCodeReset(void);
+
+#if Use68020
+FORWARDPROC DoCodeCallMorRtm(void);
+FORWARDPROC DoCodeBraL(void);
+FORWARDPROC DoCodeBccL(void);
+FORWARDPROC DoCodeBsrL(void);
+FORWARDPROC DoCodeEXTBL(void);
+FORWARDPROC DoCodeTRAPcc(void);
+FORWARDPROC DoCodeBkpt(void);
+FORWARDPROC DoCodeDivL(void);
+FORWARDPROC DoCodeMulL(void);
+FORWARDPROC DoCodeRtd(void);
+FORWARDPROC DoCodeMoveCCREa(void);
+FORWARDPROC DoMoveFromControl(void);
+FORWARDPROC DoMoveToControl(void);
+FORWARDPROC DoCodeLinkL(void);
+FORWARDPROC DoCodePack(void);
+FORWARDPROC DoCodeUnpk(void);
+FORWARDPROC DoCHK2orCMP2(void);
+FORWARDPROC DoCAS2(void);
+FORWARDPROC DoCAS(void);
+FORWARDPROC DoMOVES(void);
+FORWARDPROC DoBitField(void);
+#endif
+
+#if EmMMU
+FORWARDPROC DoCodeMMU(void);
+#endif
+
+#if EmFPU
+FORWARDPROC DoCodeFPU_md60(void);
+FORWARDPROC DoCodeFPU_DBcc(void);
+FORWARDPROC DoCodeFPU_Trapcc(void);
+FORWARDPROC DoCodeFPU_Scc(void);
+FORWARDPROC DoCodeFPU_FBccW(void);
+FORWARDPROC DoCodeFPU_FBccL(void);
+FORWARDPROC DoCodeFPU_Save(void);
+FORWARDPROC DoCodeFPU_Restore(void);
+FORWARDPROC DoCodeFPU_dflt(void);
+#endif
+
+typedef void (*func_pointer_t)(void);
+
+LOCALVAR const func_pointer_t OpDispatch[kNumIKinds + 1] = {
+	DoCodeTst /* kIKindTst */,
+	DoCodeCmpB /* kIKindCmpB */,
+	DoCodeCmpW /* kIKindCmpW */,
+	DoCodeCmpL /* kIKindCmpL */,
+	DoCodeBccB /* kIKindBccB */,
+	DoCodeBccW /* kIKindBccW */,
+	DoCodeBraB /* kIKindBraB */,
+	DoCodeBraW /* kIKindBraW */,
+	DoCodeDBcc /* kIKindDBcc */,
+	DoCodeDBF /* kIKindDBF */,
+	DoCodeSwap /* kIKindSwap */,
+	DoCodeMoveL /* kIKindMoveL */,
+	DoCodeMoveW /* kIKindMoveW */,
+	DoCodeMoveB /* kIKindMoveB */,
+	DoCodeMoveA /* kIKindMoveAL */,
+	DoCodeMoveA /* kIKindMoveAW */,
+	DoCodeMoveQ /* kIKindMoveQ */,
+	DoCodeAddB /* kIKindAddB */,
+	DoCodeAddW /* kIKindAddW */,
+	DoCodeAddL /* kIKindAddL */,
+	DoCodeSubB /* kIKindSubB */,
+	DoCodeSubW /* kIKindSubW */,
+	DoCodeSubL /* kIKindSubL */,
+	DoCodeLea /* kIKindLea */,
+	DoCodePEA /* kIKindPEA */,
+	DoCodeA /* kIKindA */,
+	DoCodeBsrB /* kIKindBsrB */,
+	DoCodeBsrW /* kIKindBsrW */,
+	DoCodeJsr /* kIKindJsr */,
+	DoCodeLinkA6 /* kIKindLinkA6 */,
+	DoCodeMOVEMRmML /* kIKindMOVEMRmML */,
+	DoCodeMOVEMApRL /* kIKindMOVEMApRL */,
+	DoCodeUnlkA6 /* kIKindUnlkA6 */,
+	DoCodeRts /* kIKindRts */,
+	DoCodeJmp /* kIKindJmp */,
+	DoCodeClr /* kIKindClr */,
+	DoCodeAddA /* kIKindAddA */,
+	DoCodeAddA /* kIKindAddQA */,
+	DoCodeSubA /* kIKindSubA */,
+	DoCodeSubA /* kIKindSubQA */,
+	DoCodeCmpA /* kIKindCmpA */,
+	DoCodeAddXB /* kIKindAddXB */,
+	DoCodeAddXW /* kIKindAddXW */,
+	DoCodeAddXL /* kIKindAddXL */,
+	DoCodeSubXB /* kIKindSubXB */,
+	DoCodeSubXW /* kIKindSubXW */,
+	DoCodeSubXL /* kIKindSubXL */,
+	DoCodeAslB /* kIKindAslB */,
+	DoCodeAslW /* kIKindAslW */,
+	DoCodeAslL /* kIKindAslL */,
+	DoCodeAsrB /* kIKindAsrB */,
+	DoCodeAsrW /* kIKindAsrW */,
+	DoCodeAsrL /* kIKindAsrL */,
+	DoCodeLslB /* kIKindLslB */,
+	DoCodeLslW /* kIKindLslW */,
+	DoCodeLslL /* kIKindLslL */,
+	DoCodeLsrB /* kIKindLsrB */,
+	DoCodeLsrW /* kIKindLsrW */,
+	DoCodeLsrL /* kIKindLsrL */,
+	DoCodeRxlB /* kIKindRxlB */,
+	DoCodeRxlW /* kIKindRxlW */,
+	DoCodeRxlL /* kIKindRxlL */,
+	DoCodeRxrB /* kIKindRxrB */,
+	DoCodeRxrW /* kIKindRxrW */,
+	DoCodeRxrL /* kIKindRxrL */,
+	DoCodeRolB /* kIKindRolB */,
+	DoCodeRolW /* kIKindRolW */,
+	DoCodeRolL /* kIKindRolL */,
+	DoCodeRorB /* kIKindRorB */,
+	DoCodeRorW /* kIKindRorW */,
+	DoCodeRorL /* kIKindRorL */,
+	DoCodeBTstB /* kIKindBTstB */,
+	DoCodeBChgB /* kIKindBChgB */,
+	DoCodeBClrB /* kIKindBClrB */,
+	DoCodeBSetB /* kIKindBSetB */,
+	DoCodeBTstL /* kIKindBTstL */,
+	DoCodeBChgL /* kIKindBChgL */,
+	DoCodeBClrL /* kIKindBClrL */,
+	DoCodeBSetL /* kIKindBSetL */,
+	DoCodeAnd /* kIKindAndI */,
+	DoCodeAnd /* kIKindAndEaD */,
+	DoCodeAnd /* kIKindAndDEa */,
+	DoCodeOr /* kIKindOrI */,
+	DoCodeOr /* kIKindOrDEa */,
+	DoCodeOr /* kIKindOrEaD */,
+	DoCodeEor /* kIKindEor */,
+	DoCodeEor /* kIKindEorI */,
+	DoCodeNot /* kIKindNot */,
+	DoCodeScc /* kIKindScc */,
+	DoCodeNegXB /* kIKindNegXB */,
+	DoCodeNegXW /* kIKindNegXW */,
+	DoCodeNegXL /* kIKindNegXL */,
+	DoCodeNegB /* kIKindNegB */,
+	DoCodeNegW /* kIKindNegW */,
+	DoCodeNegL /* kIKindNegL */,
+	DoCodeEXTW /* kIKindEXTW */,
+	DoCodeEXTL /* kIKindEXTL */,
+	DoCodeMulU /* kIKindMulU */,
+	DoCodeMulS /* kIKindMulS */,
+	DoCodeDivU /* kIKindDivU */,
+	DoCodeDivS /* kIKindDivS */,
+	DoCodeExg /* kIKindExg */,
+	DoCodeMoveEaCR /* kIKindMoveEaCCR */,
+	DoCodeMoveSREa /* kIKindMoveSREa */,
+	DoCodeMoveEaSR /* kIKindMoveEaSR */,
+	DoCodeOrISR /* kIKindOrISR */,
+	DoCodeAndISR /* kIKindAndISR */,
+	DoCodeEorISR /* kIKindEorISR */,
+	DoCodeOrICCR /* kIKindOrICCR */,
+	DoCodeAndICCR /* kIKindAndICCR */,
+	DoCodeEorICCR /* kIKindEorICCR */,
+	DoCodeMOVEMApRW /* kIKindMOVEMApRW */,
+	DoCodeMOVEMRmMW /* kIKindMOVEMRmMW */,
+	DoCodeMOVEMrmW /* kIKindMOVEMrmW */,
+	DoCodeMOVEMrmL /* kIKindMOVEMrmL */,
+	DoCodeMOVEMmrW /* kIKindMOVEMmrW */,
+	DoCodeMOVEMmrL /* kIKindMOVEMmrL */,
+	DoCodeAbcd /* kIKindAbcd */,
+	DoCodeSbcd /* kIKindSbcd */,
+	DoCodeNbcd /* kIKindNbcd */,
+	DoCodeRte /* kIKindRte */,
+	DoCodeNop /* kIKindNop */,
+	DoCodeMoveP0 /* kIKindMoveP0 */,
+	DoCodeMoveP1 /* kIKindMoveP1 */,
+	DoCodeMoveP2 /* kIKindMoveP2 */,
+	DoCodeMoveP3 /* kIKindMoveP3 */,
+	op_illg /* kIKindIllegal */,
+	DoCodeChk /* kIKindChkW */,
+	DoCodeTrap /* kIKindTrap */,
+	DoCodeTrapV /* kIKindTrapV */,
+	DoCodeRtr /* kIKindRtr */,
+	DoCodeLink /* kIKindLink */,
+	DoCodeUnlk /* kIKindUnlk */,
+	DoCodeMoveRUSP /* kIKindMoveRUSP */,
+	DoCodeMoveUSPR /* kIKindMoveUSPR */,
+	DoCodeTas /* kIKindTas */,
+	DoCodeFdefault /* kIKindFdflt */,
+	DoCodeStop /* kIKindStop */,
+	DoCodeReset /* kIKindReset */,
+
+#if Use68020
+	DoCodeCallMorRtm /* kIKindCallMorRtm */,
+	DoCodeBraL /* kIKindBraL */,
+	DoCodeBccL /* kIKindBccL */,
+	DoCodeBsrL /* kIKindBsrL */,
+	DoCodeEXTBL /* kIKindEXTBL */,
+	DoCodeTRAPcc /* kIKindTRAPcc */,
+	DoCodeChk /* kIKindChkL */,
+	DoCodeBkpt /* kIKindBkpt */,
+	DoCodeDivL /* kIKindDivL */,
+	DoCodeMulL /* kIKindMulL */,
+	DoCodeRtd /* kIKindRtd */,
+	DoCodeMoveCCREa /* kIKindMoveCCREa */,
+	DoMoveFromControl /* kIKindMoveCEa */,
+	DoMoveToControl /* kIKindMoveEaC */,
+	DoCodeLinkL /* kIKindLinkL */,
+	DoCodePack /* kIKindPack */,
+	DoCodeUnpk /* kIKindUnpk */,
+	DoCHK2orCMP2 /* kIKindCHK2orCMP2 */,
+	DoCAS2 /* kIKindCAS2 */,
+	DoCAS /* kIKindCAS */,
+	DoMOVES /* kIKindMoveS */,
+	DoBitField /* kIKindBitField */,
+#endif
+#if EmMMU
+	DoCodeMMU /* kIKindMMU */,
+#endif
+#if EmFPU
+	DoCodeFPU_md60 /* kIKindFPUmd60 */,
+	DoCodeFPU_DBcc /* kIKindFPUDBcc */,
+	DoCodeFPU_Trapcc /* kIKindFPUTrapcc */,
+	DoCodeFPU_Scc /* kIKindFPUScc */,
+	DoCodeFPU_FBccW /* kIKindFPUFBccW */,
+	DoCodeFPU_FBccL /* kIKindFPUFBccL */,
+	DoCodeFPU_Save /* kIKindFPUSave */,
+	DoCodeFPU_Restore /* kIKindFPURestore */,
+	DoCodeFPU_dflt /* kIKindFPUdflt */,
+#endif
+
+	0
+};
+
+#ifndef WantBreakPoint
+#define WantBreakPoint 0
+#endif
+
+#if WantBreakPoint
+
+#define BreakPointAddress 0xD198
+
+LOCALPROC BreakPointAction(void)
+{
+	dbglog_StartLine();
+	dbglog_writeCStr("breakpoint A0=");
+	dbglog_writeHex(m68k_areg(0));
+	dbglog_writeCStr(" A1=");
+	dbglog_writeHex(m68k_areg(1));
+	dbglog_writeReturn();
+}
+
+#endif
+
+LOCALINLINEPROC DecodeNextInstruction(func_pointer_t *d, ui4rr *Cycles,
+	DecOpYR *y)
+{
+	ui5r opcode;
+	DecOpR *p;
+	ui4rr MainClas;
+
+	opcode = nextiword();
+
+	p = &V_regs.disp_table[opcode];
+
+#if WantCloserCyc
+	V_regs.CurDecOp = p;
+#endif
+	MainClas = p->x.MainClas;
+	*Cycles = p->x.Cycles;
+	*y = p->y;
+#if WantDumpTable
+	DumpTable[MainClas] ++;
+#endif
+	*d = OpDispatch[MainClas];
+}
+
+LOCALINLINEPROC UnDecodeNextInstruction(ui4rr Cycles)
+{
+	V_MaxCyclesToGo += Cycles;
+
+	BackupPC();
+
+#if WantDumpTable
+	{
+		ui5r opcode = do_get_mem_word(V_pc_p);
+		DecOpR *p = &V_regs.disp_table[opcode];
+		ui4rr MainClas = p->x.MainClas;
+
+		DumpTable[MainClas] --;
+	}
+#endif
+}
+
+LOCALPROC m68k_go_MaxCycles(void)
+{
+	ui4rr Cycles;
+	DecOpYR y;
+	func_pointer_t d;
+
+	/*
+		Main loop of emulator.
+
+		Always execute at least one instruction,
+		even if V_regs.MaxInstructionsToGo == 0.
+		Needed for trace flag to work.
+	*/
+
+	DecodeNextInstruction(&d, &Cycles, &y);
+
+	V_MaxCyclesToGo -= Cycles;
+
+	do {
+		V_regs.CurDecOpY = y;
+
+#if WantDisasm || WantBreakPoint
+		{
+			CPTR pc = m68k_getpc() - 2;
+#if WantDisasm
+			DisasmOneOrSave(pc);
+#endif
+#if WantBreakPoint
+			if (BreakPointAddress == pc) {
+				BreakPointAction();
+			}
+#endif
+		}
+#endif
+
+		d();
+
+		DecodeNextInstruction(&d, &Cycles, &y);
+
+	} while (((si5rr)(V_MaxCyclesToGo -= Cycles)) > 0);
+
+	/* abort instruction that have started to decode */
+
+	UnDecodeNextInstruction(Cycles);
+}
+
+FORWARDFUNC ui5r my_reg_call get_byte_ext(CPTR addr);
+
+LOCALFUNC ui5r my_reg_call get_byte(CPTR addr)
+{
+	ui3p m = (addr & V_regs.MATCrdB.usemask) + V_regs.MATCrdB.usebase;
+
+	if ((addr & V_regs.MATCrdB.cmpmask) == V_regs.MATCrdB.cmpvalu) {
+		return ui5r_FromSByte(*m);
+	} else {
+		return get_byte_ext(addr);
+	}
+}
+
+FORWARDPROC my_reg_call put_byte_ext(CPTR addr, ui5r b);
+
+LOCALPROC my_reg_call put_byte(CPTR addr, ui5r b)
+{
+	ui3p m = (addr & V_regs.MATCwrB.usemask) + V_regs.MATCwrB.usebase;
+	if ((addr & V_regs.MATCwrB.cmpmask) == V_regs.MATCwrB.cmpvalu) {
+		*m = b;
+	} else {
+		put_byte_ext(addr, b);
+	}
+}
+
+FORWARDFUNC ui5r my_reg_call get_word_ext(CPTR addr);
+
+LOCALFUNC ui5r my_reg_call get_word(CPTR addr)
+{
+	ui3p m = (addr & V_regs.MATCrdW.usemask) + V_regs.MATCrdW.usebase;
+	if ((addr & V_regs.MATCrdW.cmpmask) == V_regs.MATCrdW.cmpvalu) {
+		return ui5r_FromSWord(do_get_mem_word(m));
+	} else {
+		return get_word_ext(addr);
+	}
+}
+
+FORWARDPROC my_reg_call put_word_ext(CPTR addr, ui5r w);
+
+LOCALPROC my_reg_call put_word(CPTR addr, ui5r w)
+{
+	ui3p m = (addr & V_regs.MATCwrW.usemask) + V_regs.MATCwrW.usebase;
+	if ((addr & V_regs.MATCwrW.cmpmask) == V_regs.MATCwrW.cmpvalu) {
+		do_put_mem_word(m, w);
+	} else {
+		put_word_ext(addr, w);
+	}
+}
+
+FORWARDFUNC ui5r my_reg_call get_long_misaligned_ext(CPTR addr);
+
+LOCALFUNC ui5r my_reg_call get_long_misaligned(CPTR addr)
+{
+	CPTR addr2 = addr + 2;
+	ui3p m = (addr & V_regs.MATCrdW.usemask) + V_regs.MATCrdW.usebase;
+	ui3p m2 = (addr2 & V_regs.MATCrdW.usemask) + V_regs.MATCrdW.usebase;
+	if (((addr & V_regs.MATCrdW.cmpmask) == V_regs.MATCrdW.cmpvalu)
+		&& ((addr2 & V_regs.MATCrdW.cmpmask) == V_regs.MATCrdW.cmpvalu))
+	{
+		ui5r hi = do_get_mem_word(m);
+		ui5r lo = do_get_mem_word(m2);
+		ui5r Data = ((hi << 16) & 0xFFFF0000)
+			| (lo & 0x0000FFFF);
+
+		return ui5r_FromSLong(Data);
+	} else {
+		return get_long_misaligned_ext(addr);
+	}
+}
+
+#if FasterAlignedL
+FORWARDFUNC ui5r my_reg_call get_long_ext(CPTR addr);
+#endif
+
+#if FasterAlignedL
+LOCALFUNC ui5r my_reg_call get_long(CPTR addr)
+{
+	if (0 == (addr & 0x03)) {
+		ui3p m = (addr & V_regs.MATCrdL.usemask)
+			+ V_regs.MATCrdL.usebase;
+		if ((addr & V_regs.MATCrdL.cmpmask) == V_regs.MATCrdL.cmpvalu) {
+			return ui5r_FromSLong(do_get_mem_long(m));
+		} else {
+			return get_long_ext(addr);
+		}
+	} else {
+		return get_long_misaligned(addr);
+	}
+}
+#else
+#define get_long get_long_misaligned
+#endif
+
+FORWARDPROC my_reg_call put_long_misaligned_ext(CPTR addr, ui5r l);
+
+LOCALPROC my_reg_call put_long_misaligned(CPTR addr, ui5r l)
+{
+	CPTR addr2 = addr + 2;
+	ui3p m = (addr & V_regs.MATCwrW.usemask) + V_regs.MATCwrW.usebase;
+	ui3p m2 = (addr2 & V_regs.MATCwrW.usemask) + V_regs.MATCwrW.usebase;
+	if (((addr & V_regs.MATCwrW.cmpmask) == V_regs.MATCwrW.cmpvalu)
+		&& ((addr2 & V_regs.MATCwrW.cmpmask) == V_regs.MATCwrW.cmpvalu))
+	{
+		do_put_mem_word(m, l >> 16);
+		do_put_mem_word(m2, l);
+	} else {
+		put_long_misaligned_ext(addr, l);
+	}
+}
+
+#if FasterAlignedL
+FORWARDPROC my_reg_call put_long_ext(CPTR addr, ui5r l);
+#endif
+
+#if FasterAlignedL
+LOCALPROC my_reg_call put_long(CPTR addr, ui5r l)
+{
+	if (0 == (addr & 0x03)) {
+		ui3p m = (addr & V_regs.MATCwrL.usemask)
+			+ V_regs.MATCwrL.usebase;
+		if ((addr & V_regs.MATCwrL.cmpmask) == V_regs.MATCwrL.cmpvalu) {
+			do_put_mem_long(m, l);
+		} else {
+			put_long_ext(addr, l);
+		}
+	} else {
+		put_long_misaligned(addr, l);
+	}
+}
+#else
+#define put_long put_long_misaligned
+#endif
+
+LOCALFUNC ui5b my_reg_call get_disp_ea(ui5b base)
+{
+	ui4b dp = nextiword();
+	int regno = (dp >> 12) & 0x0F;
+	si5b regd = V_regs.regs[regno];
+	if ((dp & 0x0800) == 0) {
+		regd = (si5b)(si4b)regd;
+	}
+#if Use68020
+	regd <<= (dp >> 9) & 3;
+#if ExtraAbnormalReports
+	if (((dp >> 9) & 3) != 0) {
+		/* ReportAbnormal("Have scale in Extension Word"); */
+		/* apparently can happen in Sys 7.5.5 boot on 68000 */
+	}
+#endif
+	if (dp & 0x0100) {
+		if ((dp & 0x80) != 0) {
+			base = 0;
+			/* ReportAbnormal("Extension Word: suppress base"); */
+			/* used by Sys 7.5.5 boot */
+		}
+		if ((dp & 0x40) != 0) {
+			regd = 0;
+			/* ReportAbnormal("Extension Word: suppress regd"); */
+			/* used by Mac II boot */
+		}
+
+		switch ((dp >> 4) & 0x03) {
+			case 0:
+				/* reserved */
+				ReportAbnormalID(0x0101, "Extension Word: dp reserved");
+				break;
+			case 1:
+				/* no displacement */
+				/* ReportAbnormal("Extension Word: no displacement"); */
+				/* used by Sys 7.5.5 boot */
+				break;
+			case 2:
+				base += nextiSWord();
+				/*
+					ReportAbnormal("Extension Word: word displacement");
+				*/
+				/* used by Sys 7.5.5 boot */
+				break;
+			case 3:
+				base += nextilong();
+				/*
+					ReportAbnormal("Extension Word: long displacement");
+				*/
+				/* used by Mac II boot from system 6.0.8? */
+				break;
+		}
+
+		if ((dp & 0x03) == 0) {
+			base += regd;
+			if ((dp & 0x04) != 0) {
+				ReportAbnormalID(0x0102,
+					"Extension Word: reserved dp form");
+			}
+			/* ReportAbnormal("Extension Word: noindex"); */
+			/* used by Sys 7.5.5 boot */
+		} else {
+			if ((dp & 0x04) != 0) {
+				base = get_long(base);
+				base += regd;
+				/* ReportAbnormal("Extension Word: postindex"); */
+				/* used by Sys 7.5.5 boot */
+			} else {
+				base += regd;
+				base = get_long(base);
+				/* ReportAbnormal("Extension Word: preindex"); */
+				/* used by Sys 7.5.5 boot */
+			}
+			switch (dp & 0x03) {
+				case 1:
+					/* null outer displacement */
+					/*
+						ReportAbnormal(
+							"Extension Word: null outer displacement");
+					*/
+					/* used by Sys 7.5.5 boot */
+					break;
+				case 2:
+					base += nextiSWord();
+					/*
+						ReportAbnormal(
+							"Extension Word: word outer displacement");
+					*/
+					/* used by Mac II boot from system 6.0.8? */
+					break;
+				case 3:
+					base += nextilong();
+					/*
+						ReportAbnormal(
+							"Extension Word: long outer displacement");
+					*/
+					/* used by Mac II boot from system 6.0.8? */
+					break;
+			}
+		}
+
+		return base;
+	} else
+#endif
+	{
+		return base + (si3b)(dp) + regd;
+	}
+}
+
+LOCALFUNC ui5r my_reg_call DecodeAddr_Indirect(ui3rr ArgDat)
+{
+	return V_regs.regs[ArgDat];
+}
+
+LOCALFUNC ui5r my_reg_call DecodeAddr_APosIncB(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p;
+
+	*p = a + 1;
+
+	return a;
+}
+
+LOCALFUNC ui5r my_reg_call DecodeAddr_APosIncW(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p;
+
+	*p = a + 2;
+
+	return a;
+}
+
+LOCALFUNC ui5r my_reg_call DecodeAddr_APosIncL(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p;
+
+	*p = a + 4;
+
+	return a;
+}
+
+LOCALFUNC ui5r my_reg_call DecodeAddr_APreDecB(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p - 1;
+
+	*p = a;
+
+	return a;
+}
+
+LOCALFUNC ui5r my_reg_call DecodeAddr_APreDecW(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p - 2;
+
+	*p = a;
+
+	return a;
+}
+
+LOCALFUNC ui5r my_reg_call DecodeAddr_APreDecL(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p - 4;
+
+	*p = a;
+
+	return a;
+}
+
+LOCALFUNC ui5r my_reg_call DecodeAddr_ADisp(ui3rr ArgDat)
+{
+	return V_regs.regs[ArgDat] + nextiSWord();
+}
+
+LOCALFUNC ui5r my_reg_call DecodeAddr_AIndex(ui3rr ArgDat)
+{
+	return get_disp_ea(V_regs.regs[ArgDat]);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeAddr_AbsW(ui3rr ArgDat)
+{
+	UnusedParam(ArgDat);
+	return nextiSWord();
+}
+
+LOCALFUNC ui5r my_reg_call DecodeAddr_AbsL(ui3rr ArgDat)
+{
+	UnusedParam(ArgDat);
+	return nextilong();
+}
+
+LOCALFUNC ui5r my_reg_call DecodeAddr_PCDisp(ui3rr ArgDat)
+{
+	CPTR pc = m68k_getpc();
+
+	UnusedParam(ArgDat);
+	return pc + nextiSWord();
+}
+
+LOCALFUNC ui5r my_reg_call DecodeAddr_PCIndex(ui3rr ArgDat)
+{
+	UnusedParam(ArgDat);
+	return get_disp_ea(m68k_getpc());
+}
+
+typedef ui5r (my_reg_call *DecodeAddrP)(ui3rr ArgDat);
+
+LOCALVAR const DecodeAddrP DecodeAddrDispatch[kNumAMds] = {
+	(DecodeAddrP)nullpr /* kAMdRegB */,
+	(DecodeAddrP)nullpr /* kAMdRegW */,
+	(DecodeAddrP)nullpr /* kAMdRegL */,
+	DecodeAddr_Indirect /* kAMdIndirectB */,
+	DecodeAddr_Indirect /* kAMdIndirectW */,
+	DecodeAddr_Indirect /* kAMdIndirectL */,
+	DecodeAddr_APosIncB /* kAMdAPosIncB */,
+	DecodeAddr_APosIncW /* kAMdAPosIncW */,
+	DecodeAddr_APosIncL /* kAMdAPosIncL */,
+	DecodeAddr_APosIncW /* kAMdAPosInc7B */,
+	DecodeAddr_APreDecB /* kAMdAPreDecB */,
+	DecodeAddr_APreDecW /* kAMdAPreDecW */,
+	DecodeAddr_APreDecL /* kAMdAPreDecL */,
+	DecodeAddr_APreDecW /* kAMdAPreDec7B */,
+	DecodeAddr_ADisp /* kAMdADispB */,
+	DecodeAddr_ADisp /* kAMdADispW */,
+	DecodeAddr_ADisp /* kAMdADispL */,
+	DecodeAddr_AIndex /* kAMdAIndexB */,
+	DecodeAddr_AIndex /* kAMdAIndexW */,
+	DecodeAddr_AIndex /* kAMdAIndexL */,
+	DecodeAddr_AbsW /* kAMdAbsWB */,
+	DecodeAddr_AbsW /* kAMdAbsWW */,
+	DecodeAddr_AbsW /* kAMdAbsWL */,
+	DecodeAddr_AbsL /* kAMdAbsLB */,
+	DecodeAddr_AbsL /* kAMdAbsLW */,
+	DecodeAddr_AbsL /* kAMdAbsLL */,
+	DecodeAddr_PCDisp /* kAMdPCDispB */,
+	DecodeAddr_PCDisp /* kAMdPCDispW */,
+	DecodeAddr_PCDisp /* kAMdPCDispL */,
+	DecodeAddr_PCIndex /* kAMdPCIndexB */,
+	DecodeAddr_PCIndex /* kAMdPCIndexW */,
+	DecodeAddr_PCIndex /* kAMdPCIndexL */,
+	(DecodeAddrP)nullpr /* kAMdImmedB */,
+	(DecodeAddrP)nullpr /* kAMdImmedW */,
+	(DecodeAddrP)nullpr /* kAMdImmedL */,
+	(DecodeAddrP)nullpr /* kAMdDat4 */
+};
+
+LOCALINLINEFUNC ui5r DecodeAddrSrcDst(DecArgR *f)
+{
+	return (DecodeAddrDispatch[f->AMd])(f->ArgDat);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_RegB(ui3rr ArgDat)
+{
+	return ui5r_FromSByte(V_regs.regs[ArgDat]);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_RegW(ui3rr ArgDat)
+{
+	return ui5r_FromSWord(V_regs.regs[ArgDat]);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_RegL(ui3rr ArgDat)
+{
+	return ui5r_FromSLong(V_regs.regs[ArgDat]);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_IndirectB(ui3rr ArgDat)
+{
+	return get_byte(V_regs.regs[ArgDat]);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_IndirectW(ui3rr ArgDat)
+{
+	return get_word(V_regs.regs[ArgDat]);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_IndirectL(ui3rr ArgDat)
+{
+	return get_long(V_regs.regs[ArgDat]);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_APosIncB(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p;
+
+	*p = a + 1;
+
+	return get_byte(a);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_APosIncW(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p;
+
+	*p = a + 2;
+
+	return get_word(a);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_APosIncL(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p;
+
+	*p = a + 4;
+
+	return get_long(a);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_APosInc7B(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p;
+
+	*p = a + 2;
+
+	return get_byte(a);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_APreDecB(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p - 1;
+
+	*p = a;
+
+	return get_byte(a);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_APreDecW(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p - 2;
+
+	*p = a;
+
+	return get_word(a);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_APreDecL(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p - 4;
+
+	*p = a;
+
+	return get_long(a);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_APreDec7B(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p - 2;
+
+	*p = a;
+
+	return get_byte(a);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_ADispB(ui3rr ArgDat)
+{
+	return get_byte(DecodeAddr_ADisp(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_ADispW(ui3rr ArgDat)
+{
+	return get_word(DecodeAddr_ADisp(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_ADispL(ui3rr ArgDat)
+{
+	return get_long(DecodeAddr_ADisp(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AIndexB(ui3rr ArgDat)
+{
+	return get_byte(get_disp_ea(V_regs.regs[ArgDat]));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AIndexW(ui3rr ArgDat)
+{
+	return get_word(get_disp_ea(V_regs.regs[ArgDat]));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AIndexL(ui3rr ArgDat)
+{
+	return get_long(get_disp_ea(V_regs.regs[ArgDat]));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AbsWB(ui3rr ArgDat)
+{
+	return get_byte(DecodeAddr_AbsW(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AbsWW(ui3rr ArgDat)
+{
+	return get_word(DecodeAddr_AbsW(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AbsWL(ui3rr ArgDat)
+{
+	return get_long(DecodeAddr_AbsW(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AbsLB(ui3rr ArgDat)
+{
+	return get_byte(DecodeAddr_AbsL(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AbsLW(ui3rr ArgDat)
+{
+	return get_word(DecodeAddr_AbsL(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_AbsLL(ui3rr ArgDat)
+{
+	return get_long(DecodeAddr_AbsL(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_PCDispB(ui3rr ArgDat)
+{
+	return get_byte(DecodeAddr_PCDisp(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_PCDispW(ui3rr ArgDat)
+{
+	return get_word(DecodeAddr_PCDisp(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_PCDispL(ui3rr ArgDat)
+{
+	return get_long(DecodeAddr_PCDisp(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_PCIndexB(ui3rr ArgDat)
+{
+	return get_byte(DecodeAddr_PCIndex(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_PCIndexW(ui3rr ArgDat)
+{
+	return get_word(DecodeAddr_PCIndex(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_PCIndexL(ui3rr ArgDat)
+{
+	return get_long(DecodeAddr_PCIndex(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_ImmedB(ui3rr ArgDat)
+{
+	UnusedParam(ArgDat);
+	return nextiSByte();
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_ImmedW(ui3rr ArgDat)
+{
+	UnusedParam(ArgDat);
+	return nextiSWord();
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_ImmedL(ui3rr ArgDat)
+{
+	UnusedParam(ArgDat);
+	return ui5r_FromSLong(nextilong());
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSrcDst_Dat4(ui3rr ArgDat)
+{
+	return ArgDat;
+}
+
+typedef ui5r (my_reg_call *DecodeGetSrcDstP)(ui3rr ArgDat);
+
+LOCALVAR const DecodeGetSrcDstP DecodeGetSrcDstDispatch[kNumAMds] = {
+	DecodeGetSrcDst_RegB /* kAMdRegB */,
+	DecodeGetSrcDst_RegW /* kAMdRegW */,
+	DecodeGetSrcDst_RegL /* kAMdRegL */,
+	DecodeGetSrcDst_IndirectB /* kAMdIndirectB */,
+	DecodeGetSrcDst_IndirectW /* kAMdIndirectW */,
+	DecodeGetSrcDst_IndirectL /* kAMdIndirectL */,
+	DecodeGetSrcDst_APosIncB /* kAMdAPosIncB */,
+	DecodeGetSrcDst_APosIncW /* kAMdAPosIncW */,
+	DecodeGetSrcDst_APosIncL /* kAMdAPosIncL */,
+	DecodeGetSrcDst_APosInc7B /* kAMdAPosInc7B */,
+	DecodeGetSrcDst_APreDecB /* kAMdAPreDecB */,
+	DecodeGetSrcDst_APreDecW /* kAMdAPreDecW */,
+	DecodeGetSrcDst_APreDecL /* kAMdAPreDecL */,
+	DecodeGetSrcDst_APreDec7B /* kAMdAPreDec7B */,
+	DecodeGetSrcDst_ADispB /* kAMdADispB */,
+	DecodeGetSrcDst_ADispW /* kAMdADispW */,
+	DecodeGetSrcDst_ADispL /* kAMdADispL */,
+	DecodeGetSrcDst_AIndexB /* kAMdAIndexB */,
+	DecodeGetSrcDst_AIndexW /* kAMdAIndexW */,
+	DecodeGetSrcDst_AIndexL /* kAMdAIndexL */,
+	DecodeGetSrcDst_AbsWB /* kAMdAbsWB */,
+	DecodeGetSrcDst_AbsWW /* kAMdAbsWW */,
+	DecodeGetSrcDst_AbsWL /* kAMdAbsWL */,
+	DecodeGetSrcDst_AbsLB /* kAMdAbsLB */,
+	DecodeGetSrcDst_AbsLW /* kAMdAbsLW */,
+	DecodeGetSrcDst_AbsLL /* kAMdAbsLL */,
+	DecodeGetSrcDst_PCDispB /* kAMdPCDispB */,
+	DecodeGetSrcDst_PCDispW /* kAMdPCDispW */,
+	DecodeGetSrcDst_PCDispL /* kAMdPCDispL */,
+	DecodeGetSrcDst_PCIndexB /* kAMdPCIndexB */,
+	DecodeGetSrcDst_PCIndexW /* kAMdPCIndexW */,
+	DecodeGetSrcDst_PCIndexL /* kAMdPCIndexL */,
+	DecodeGetSrcDst_ImmedB /* kAMdImmedB */,
+	DecodeGetSrcDst_ImmedW /* kAMdImmedW */,
+	DecodeGetSrcDst_ImmedL /* kAMdImmedL */,
+	DecodeGetSrcDst_Dat4 /* kAMdDat4 */
+};
+
+LOCALINLINEFUNC ui5r DecodeGetSrcDst(DecArgR *f)
+{
+	return (DecodeGetSrcDstDispatch[f->AMd])(f->ArgDat);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_RegB(ui5r v, ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+
+#if LittleEndianUnaligned
+	*(ui3b *)p = v;
+#else
+	*p = (*p & ~ 0xff) | ((v) & 0xff);
+#endif
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_RegW(ui5r v, ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+
+#if LittleEndianUnaligned
+	*(ui4b *)p = v;
+#else
+	*p = (*p & ~ 0xffff) | ((v) & 0xffff);
+#endif
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_RegL(ui5r v, ui3rr ArgDat)
+{
+	V_regs.regs[ArgDat] = v;
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_IndirectB(ui5r v, ui3rr ArgDat)
+{
+	put_byte(V_regs.regs[ArgDat], v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_IndirectW(ui5r v, ui3rr ArgDat)
+{
+	put_word(V_regs.regs[ArgDat], v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_IndirectL(ui5r v, ui3rr ArgDat)
+{
+	put_long(V_regs.regs[ArgDat], v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_APosIncB(ui5r v, ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p;
+
+	*p = a + 1;
+
+	put_byte(a, v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_APosIncW(ui5r v, ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p;
+
+	*p = a + 2;
+
+	put_word(a, v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_APosIncL(ui5r v, ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p;
+
+	*p = a + 4;
+
+	put_long(a, v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_APosInc7B(ui5r v, ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p;
+
+	*p = a + 2;
+
+	put_byte(a, v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_APreDecB(ui5r v, ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p - 1;
+
+	*p = a;
+
+	put_byte(a, v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_APreDecW(ui5r v, ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p - 2;
+
+	*p = a;
+
+	put_word(a, v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_APreDecL(ui5r v, ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p - 4;
+
+	*p = a;
+
+	put_long(a, v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_APreDec7B(ui5r v, ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p - 2;
+
+	*p = a;
+
+	put_byte(a, v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_ADispB(ui5r v, ui3rr ArgDat)
+{
+	put_byte(V_regs.regs[ArgDat]
+		+ nextiSWord(), v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_ADispW(ui5r v, ui3rr ArgDat)
+{
+	put_word(V_regs.regs[ArgDat]
+		+ nextiSWord(), v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_ADispL(ui5r v, ui3rr ArgDat)
+{
+	put_long(V_regs.regs[ArgDat]
+		+ nextiSWord(), v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_AIndexB(ui5r v, ui3rr ArgDat)
+{
+	put_byte(get_disp_ea(V_regs.regs[ArgDat]), v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_AIndexW(ui5r v, ui3rr ArgDat)
+{
+	put_word(get_disp_ea(V_regs.regs[ArgDat]), v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_AIndexL(ui5r v, ui3rr ArgDat)
+{
+	put_long(get_disp_ea(V_regs.regs[ArgDat]), v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_AbsWB(ui5r v, ui3rr ArgDat)
+{
+	put_byte(DecodeAddr_AbsW(ArgDat), v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_AbsWW(ui5r v, ui3rr ArgDat)
+{
+	put_word(DecodeAddr_AbsW(ArgDat), v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_AbsWL(ui5r v, ui3rr ArgDat)
+{
+	put_long(DecodeAddr_AbsW(ArgDat), v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_AbsLB(ui5r v, ui3rr ArgDat)
+{
+	put_byte(DecodeAddr_AbsL(ArgDat), v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_AbsLW(ui5r v, ui3rr ArgDat)
+{
+	put_word(DecodeAddr_AbsL(ArgDat), v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_AbsLL(ui5r v, ui3rr ArgDat)
+{
+	put_long(DecodeAddr_AbsL(ArgDat), v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_PCDispB(ui5r v, ui3rr ArgDat)
+{
+	put_byte(DecodeAddr_PCDisp(ArgDat), v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_PCDispW(ui5r v, ui3rr ArgDat)
+{
+	put_word(DecodeAddr_PCDisp(ArgDat), v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_PCDispL(ui5r v, ui3rr ArgDat)
+{
+	put_long(DecodeAddr_PCDisp(ArgDat), v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_PCIndexB(ui5r v, ui3rr ArgDat)
+{
+	put_byte(DecodeAddr_PCIndex(ArgDat), v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_PCIndexW(ui5r v, ui3rr ArgDat)
+{
+	put_word(DecodeAddr_PCIndex(ArgDat), v);
+}
+
+LOCALPROC my_reg_call DecodeSetSrcDst_PCIndexL(ui5r v, ui3rr ArgDat)
+{
+	put_long(DecodeAddr_PCIndex(ArgDat), v);
+}
+
+typedef void (my_reg_call *DecodeSetSrcDstP)(ui5r v, ui3rr ArgDat);
+
+LOCALVAR const DecodeSetSrcDstP DecodeSetSrcDstDispatch[kNumAMds] = {
+	DecodeSetSrcDst_RegB /* kAMdRegB */,
+	DecodeSetSrcDst_RegW /* kAMdRegW */,
+	DecodeSetSrcDst_RegL /* kAMdRegL */,
+	DecodeSetSrcDst_IndirectB /* kAMdIndirectB */,
+	DecodeSetSrcDst_IndirectW /* kAMdIndirectW */,
+	DecodeSetSrcDst_IndirectL /* kAMdIndirectL*/,
+	DecodeSetSrcDst_APosIncB /* kAMdAPosIncB */,
+	DecodeSetSrcDst_APosIncW /* kAMdAPosIncW */,
+	DecodeSetSrcDst_APosIncL /* kAMdAPosIncL */,
+	DecodeSetSrcDst_APosInc7B /* kAMdAPosInc7B */,
+	DecodeSetSrcDst_APreDecB /* kAMdAPreDecB */,
+	DecodeSetSrcDst_APreDecW /* kAMdAPreDecW */,
+	DecodeSetSrcDst_APreDecL /* kAMdAPreDecL */,
+	DecodeSetSrcDst_APreDec7B /* kAMdAPreDec7B */,
+	DecodeSetSrcDst_ADispB /* kAMdADispB */,
+	DecodeSetSrcDst_ADispW /* kAMdADispW */,
+	DecodeSetSrcDst_ADispL /* kAMdADispL */,
+	DecodeSetSrcDst_AIndexB /* kAMdAIndexB */,
+	DecodeSetSrcDst_AIndexW /* kAMdAIndexW */,
+	DecodeSetSrcDst_AIndexL /* kAMdAIndexL */,
+	DecodeSetSrcDst_AbsWB /* kAMdAbsWB */,
+	DecodeSetSrcDst_AbsWW /* kAMdAbsWW */,
+	DecodeSetSrcDst_AbsWL /* kAMdAbsWL */,
+	DecodeSetSrcDst_AbsLB /* kAMdAbsLB */,
+	DecodeSetSrcDst_AbsLW /* kAMdAbsLW */,
+	DecodeSetSrcDst_AbsLL /* kAMdAbsLL */,
+	DecodeSetSrcDst_PCDispB /* kAMdPCDispB */,
+	DecodeSetSrcDst_PCDispW /* kAMdPCDispW */,
+	DecodeSetSrcDst_PCDispL /* kAMdPCDispL */,
+	DecodeSetSrcDst_PCIndexB /* kAMdPCIndexB */,
+	DecodeSetSrcDst_PCIndexW /* kAMdPCIndexW */,
+	DecodeSetSrcDst_PCIndexL /* kAMdPCIndexL */,
+	(DecodeSetSrcDstP)nullpr /* kAMdImmedB */,
+	(DecodeSetSrcDstP)nullpr /* kAMdImmedW */,
+	(DecodeSetSrcDstP)nullpr /* kAMdImmedL */,
+	(DecodeSetSrcDstP)nullpr /* kAMdDat4 */
+};
+
+LOCALINLINEPROC DecodeSetSrcDst(ui5r v, DecArgR *f)
+{
+	(DecodeSetSrcDstDispatch[f->AMd])(v, f->ArgDat);
+}
+
+LOCALPROC my_reg_call ArgSetDstRegBValue(ui5r v)
+{
+	ui5r *p = V_regs.ArgAddr.rga;
+
+#if LittleEndianUnaligned
+	*(ui3b *)p = v;
+#else
+	*p = (*p & ~ 0xff) | ((v) & 0xff);
+#endif
+}
+
+LOCALPROC my_reg_call ArgSetDstRegWValue(ui5r v)
+{
+	ui5r *p = V_regs.ArgAddr.rga;
+
+#if LittleEndianUnaligned
+	*(ui4b *)p = v;
+#else
+	*p = (*p & ~ 0xffff) | ((v) & 0xffff);
+#endif
+}
+
+LOCALPROC my_reg_call ArgSetDstRegLValue(ui5r v)
+{
+	ui5r *p = V_regs.ArgAddr.rga;
+
+	*p = v;
+}
+
+LOCALPROC my_reg_call ArgSetDstMemBValue(ui5r v)
+{
+	put_byte(V_regs.ArgAddr.mem, v);
+}
+
+LOCALPROC my_reg_call ArgSetDstMemWValue(ui5r v)
+{
+	put_word(V_regs.ArgAddr.mem, v);
+}
+
+LOCALPROC my_reg_call ArgSetDstMemLValue(ui5r v)
+{
+	put_long(V_regs.ArgAddr.mem, v);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_RegB(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+
+	V_regs.ArgAddr.rga = p;
+	V_regs.ArgSetDst = ArgSetDstRegBValue;
+
+	return ui5r_FromSByte(*p);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_RegW(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+
+	V_regs.ArgAddr.rga = p;
+	V_regs.ArgSetDst = ArgSetDstRegWValue;
+
+	return ui5r_FromSWord(*p);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_RegL(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+
+	V_regs.ArgAddr.rga = p;
+	V_regs.ArgSetDst = ArgSetDstRegLValue;
+
+	return ui5r_FromSLong(*p);
+}
+
+LOCALFUNC ui5r my_reg_call getarg_byte(ui5r a)
+{
+	V_regs.ArgAddr.mem = a;
+	V_regs.ArgSetDst = ArgSetDstMemBValue;
+
+	return get_byte(a);
+}
+
+LOCALFUNC ui5r my_reg_call getarg_word(ui5r a)
+{
+	V_regs.ArgAddr.mem = a;
+	V_regs.ArgSetDst = ArgSetDstMemWValue;
+
+	return get_word(a);
+}
+
+LOCALFUNC ui5r my_reg_call getarg_long(ui5r a)
+{
+	V_regs.ArgAddr.mem = a;
+	V_regs.ArgSetDst = ArgSetDstMemLValue;
+
+	return get_long(a);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_IndirectB(ui3rr ArgDat)
+{
+	return getarg_byte(V_regs.regs[ArgDat]);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_IndirectW(ui3rr ArgDat)
+{
+	return getarg_word(V_regs.regs[ArgDat]);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_IndirectL(ui3rr ArgDat)
+{
+	return getarg_long(V_regs.regs[ArgDat]);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_APosIncB(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p;
+
+	*p = a + 1;
+
+	return getarg_byte(a);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_APosIncW(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p;
+
+	*p = a + 2;
+
+	return getarg_word(a);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_APosIncL(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p;
+
+	*p = a + 4;
+
+	return getarg_long(a);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_APosInc7B(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p;
+
+	*p = a + 2;
+
+	return getarg_byte(a);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_APreDecB(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p - 1;
+
+	*p = a;
+
+	return getarg_byte(a);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_APreDecW(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p - 2;
+
+	*p = a;
+
+	return getarg_word(a);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_APreDecL(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p - 4;
+
+	*p = a;
+
+	return getarg_long(a);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_APreDec7B(ui3rr ArgDat)
+{
+	ui5r *p = &V_regs.regs[ArgDat];
+	ui5r a = *p - 2;
+
+	*p = a;
+
+	return getarg_byte(a);
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_ADispB(ui3rr ArgDat)
+{
+	return getarg_byte(V_regs.regs[ArgDat]
+		+ nextiSWord());
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_ADispW(ui3rr ArgDat)
+{
+	return getarg_word(V_regs.regs[ArgDat]
+		+ nextiSWord());
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_ADispL(ui3rr ArgDat)
+{
+	return getarg_long(V_regs.regs[ArgDat]
+		+ nextiSWord());
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AIndexB(ui3rr ArgDat)
+{
+	return getarg_byte(get_disp_ea(V_regs.regs[ArgDat]));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AIndexW(ui3rr ArgDat)
+{
+	return getarg_word(get_disp_ea(V_regs.regs[ArgDat]));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AIndexL(ui3rr ArgDat)
+{
+	return getarg_long(get_disp_ea(V_regs.regs[ArgDat]));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AbsWB(ui3rr ArgDat)
+{
+	return getarg_byte(DecodeAddr_AbsW(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AbsWW(ui3rr ArgDat)
+{
+	return getarg_word(DecodeAddr_AbsW(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AbsWL(ui3rr ArgDat)
+{
+	return getarg_long(DecodeAddr_AbsW(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AbsLB(ui3rr ArgDat)
+{
+	return getarg_byte(DecodeAddr_AbsL(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AbsLW(ui3rr ArgDat)
+{
+	return getarg_word(DecodeAddr_AbsL(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_AbsLL(ui3rr ArgDat)
+{
+	return getarg_long(DecodeAddr_AbsL(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_PCDispB(ui3rr ArgDat)
+{
+	return getarg_byte(DecodeAddr_PCDisp(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_PCDispW(ui3rr ArgDat)
+{
+	return getarg_word(DecodeAddr_PCDisp(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_PCDispL(ui3rr ArgDat)
+{
+	return getarg_long(DecodeAddr_PCDisp(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_PCIndexB(ui3rr ArgDat)
+{
+	return getarg_byte(DecodeAddr_PCIndex(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_PCIndexW(ui3rr ArgDat)
+{
+	return getarg_word(DecodeAddr_PCIndex(ArgDat));
+}
+
+LOCALFUNC ui5r my_reg_call DecodeGetSetSrcDst_PCIndexL(ui3rr ArgDat)
+{
+	return getarg_long(DecodeAddr_PCIndex(ArgDat));
+}
+
+typedef ui5r (my_reg_call *DecodeGetSetSrcDstP)(ui3rr ArgDat);
+
+LOCALVAR const DecodeGetSetSrcDstP
+	DecodeGetSetSrcDstDispatch[kNumAMds] =
+{
+	DecodeGetSetSrcDst_RegB /* kAMdRegB */,
+	DecodeGetSetSrcDst_RegW /* kAMdRegW */,
+	DecodeGetSetSrcDst_RegL /* kAMdRegL */,
+	DecodeGetSetSrcDst_IndirectB /* kAMdIndirectB */,
+	DecodeGetSetSrcDst_IndirectW /* kAMdIndirectW */,
+	DecodeGetSetSrcDst_IndirectL /* kAMdIndirectL*/,
+	DecodeGetSetSrcDst_APosIncB /* kAMdAPosIncB */,
+	DecodeGetSetSrcDst_APosIncW /* kAMdAPosIncW */,
+	DecodeGetSetSrcDst_APosIncL /* kAMdAPosIncL */,
+	DecodeGetSetSrcDst_APosInc7B /* kAMdAPosInc7B */,
+	DecodeGetSetSrcDst_APreDecB /* kAMdAPreDecB */,
+	DecodeGetSetSrcDst_APreDecW /* kAMdAPreDecW */,
+	DecodeGetSetSrcDst_APreDecL /* kAMdAPreDecL */,
+	DecodeGetSetSrcDst_APreDec7B /* kAMdAPreDec7B */,
+	DecodeGetSetSrcDst_ADispB /* kAMdADispB */,
+	DecodeGetSetSrcDst_ADispW /* kAMdADispW */,
+	DecodeGetSetSrcDst_ADispL /* kAMdADispL */,
+	DecodeGetSetSrcDst_AIndexB /* kAMdAIndexB */,
+	DecodeGetSetSrcDst_AIndexW /* kAMdAIndexW */,
+	DecodeGetSetSrcDst_AIndexL /* kAMdAIndexL */,
+	DecodeGetSetSrcDst_AbsWB /* kAMdAbsWB */,
+	DecodeGetSetSrcDst_AbsWW /* kAMdAbsWW */,
+	DecodeGetSetSrcDst_AbsWL /* kAMdAbsWL */,
+	DecodeGetSetSrcDst_AbsLB /* kAMdAbsLB */,
+	DecodeGetSetSrcDst_AbsLW /* kAMdAbsLW */,
+	DecodeGetSetSrcDst_AbsLL /* kAMdAbsLL */,
+	DecodeGetSetSrcDst_PCDispB /* kAMdPCDispB */,
+	DecodeGetSetSrcDst_PCDispW /* kAMdPCDispW */,
+	DecodeGetSetSrcDst_PCDispL /* kAMdPCDispL */,
+	DecodeGetSetSrcDst_PCIndexB /* kAMdPCIndexB */,
+	DecodeGetSetSrcDst_PCIndexW /* kAMdPCIndexW */,
+	DecodeGetSetSrcDst_PCIndexL /* kAMdPCIndexL */,
+	(DecodeGetSetSrcDstP)nullpr /* kAMdImmedB */,
+	(DecodeGetSetSrcDstP)nullpr /* kAMdImmedW */,
+	(DecodeGetSetSrcDstP)nullpr /* kAMdImmedL */,
+	(DecodeGetSetSrcDstP)nullpr /* kAMdDat4 */
+};
+
+LOCALINLINEFUNC ui5r DecodeGetSetSrcDst(DecArgR *f)
+{
+	return (DecodeGetSetSrcDstDispatch[f->AMd])(f->ArgDat);
+}
+
+
+LOCALINLINEFUNC ui5r DecodeDst(void)
+{
+	return DecodeAddrSrcDst(&V_regs.CurDecOpY.v[1]);
+}
+
+LOCALINLINEFUNC ui5r DecodeGetSetDstValue(void)
+{
+	return DecodeGetSetSrcDst(&V_regs.CurDecOpY.v[1]);
+}
+
+LOCALINLINEPROC ArgSetDstValue(ui5r v)
+{
+	V_regs.ArgSetDst(v);
+}
+
+LOCALINLINEPROC DecodeSetDstValue(ui5r v)
+{
+	DecodeSetSrcDst(v, &V_regs.CurDecOpY.v[1]);
+}
+
+LOCALINLINEFUNC ui5r DecodeGetSrcValue(void)
+{
+	return DecodeGetSrcDst(&V_regs.CurDecOpY.v[0]);
+}
+
+LOCALINLINEFUNC ui5r DecodeGetDstValue(void)
+{
+	return DecodeGetSrcDst(&V_regs.CurDecOpY.v[1]);
+}
+
+LOCALINLINEFUNC ui5r DecodeGetSrcSetDstValue(void)
+{
+	V_regs.SrcVal = DecodeGetSrcValue();
+
+	return DecodeGetSetDstValue();
+}
+
+LOCALINLINEFUNC ui5r DecodeGetSrcGetDstValue(void)
+{
+	V_regs.SrcVal = DecodeGetSrcValue();
+
+	return DecodeGetDstValue();
+}
+
+
+typedef void (*cond_actP)(void);
+
+LOCALPROC my_reg_call cctrue_T(cond_actP t_act, cond_actP f_act)
+{
+	UnusedParam(f_act);
+	t_act();
+}
+
+LOCALPROC my_reg_call cctrue_F(cond_actP t_act, cond_actP f_act)
+{
+	UnusedParam(t_act);
+	f_act();
+}
+
+LOCALPROC my_reg_call cctrue_HI(cond_actP t_act, cond_actP f_act)
+{
+	if (0 == (CFLG | ZFLG)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_LS(cond_actP t_act, cond_actP f_act)
+{
+	if (0 != (CFLG | ZFLG)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CC(cond_actP t_act, cond_actP f_act)
+{
+	if (0 == (CFLG)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CS(cond_actP t_act, cond_actP f_act)
+{
+	if (0 != (CFLG)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_NE(cond_actP t_act, cond_actP f_act)
+{
+	if (0 == (ZFLG)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_EQ(cond_actP t_act, cond_actP f_act)
+{
+	if (0 != (ZFLG)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_VC(cond_actP t_act, cond_actP f_act)
+{
+	if (0 == (VFLG)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_VS(cond_actP t_act, cond_actP f_act)
+{
+	if (0 != (VFLG)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_PL(cond_actP t_act, cond_actP f_act)
+{
+	if (0 == (NFLG)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_MI(cond_actP t_act, cond_actP f_act)
+{
+	if (0 != (NFLG)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_GE(cond_actP t_act, cond_actP f_act)
+{
+	if (0 == (NFLG ^ VFLG)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_LT(cond_actP t_act, cond_actP f_act)
+{
+	if (0 != (NFLG ^ VFLG)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_GT(cond_actP t_act, cond_actP f_act)
+{
+	if (0 == (ZFLG | (NFLG ^ VFLG))) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_LE(cond_actP t_act, cond_actP f_act)
+{
+	if (0 != (ZFLG | (NFLG ^ VFLG))) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+#if Have_ASR
+#define Ui5rASR(x, s) ((ui5r)(((si5r)(x)) >> (s)))
+#else
+LOCALFUNC ui5r Ui5rASR(ui5r x, ui5r s)
+{
+	ui5r v;
+
+	if (ui5r_MSBisSet(x)) {
+		v = ~ ((~ x) >> s);
+	} else {
+		v = x >> s;
+	}
+
+	return v;
+}
+#endif
+
+#if UseLazyCC
+
+LOCALPROC my_reg_call cctrue_TstL_HI(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui5b)V_regs.LazyFlagArgDst) > ((ui5b)0)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_TstL_LS(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui5b)V_regs.LazyFlagArgDst) <= ((ui5b)0)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+#if 0 /* always true */
+LOCALPROC my_reg_call cctrue_TstL_CC(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui5b)V_regs.LazyFlagArgDst) >= ((ui5b)0)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+#endif
+
+#if 0 /* always false */
+LOCALPROC my_reg_call cctrue_TstL_CS(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui5b)V_regs.LazyFlagArgDst) < ((ui5b)0)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+#endif
+
+LOCALPROC my_reg_call cctrue_TstL_NE(cond_actP t_act, cond_actP f_act)
+{
+	if (V_regs.LazyFlagArgDst != 0) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_TstL_EQ(cond_actP t_act, cond_actP f_act)
+{
+	if (V_regs.LazyFlagArgDst == 0) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_TstL_PL(cond_actP t_act, cond_actP f_act)
+{
+	if (((si5b)(V_regs.LazyFlagArgDst)) >= 0) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_TstL_MI(cond_actP t_act, cond_actP f_act)
+{
+	if (((si5b)(V_regs.LazyFlagArgDst)) < 0) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_TstL_GE(cond_actP t_act, cond_actP f_act)
+{
+	if (((si5b)V_regs.LazyFlagArgDst) >= ((si5b)0)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_TstL_LT(cond_actP t_act, cond_actP f_act)
+{
+	if (((si5b)V_regs.LazyFlagArgDst) < ((si5b)0)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_TstL_GT(cond_actP t_act, cond_actP f_act)
+{
+	if (((si5b)V_regs.LazyFlagArgDst) > ((si5b)0)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_TstL_LE(cond_actP t_act, cond_actP f_act)
+{
+	if (((si5b)V_regs.LazyFlagArgDst) <= ((si5b)0)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpB_HI(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui3b)V_regs.LazyFlagArgDst) > ((ui3b)V_regs.LazyFlagArgSrc)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpB_LS(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui3b)V_regs.LazyFlagArgDst) <= ((ui3b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpB_CC(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui3b)V_regs.LazyFlagArgDst) >= ((ui3b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpB_CS(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui3b)V_regs.LazyFlagArgDst) < ((ui3b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpB_NE(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui3b)V_regs.LazyFlagArgDst) != ((ui3b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpB_EQ(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui3b)V_regs.LazyFlagArgDst) == ((ui3b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpB_PL(cond_actP t_act, cond_actP f_act)
+{
+	if (((si3b)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) >= 0) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpB_MI(cond_actP t_act, cond_actP f_act)
+{
+	if (((si3b)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) < 0) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpB_GE(cond_actP t_act, cond_actP f_act)
+{
+	if (((si3b)V_regs.LazyFlagArgDst) >= ((si3b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpB_LT(cond_actP t_act, cond_actP f_act)
+{
+	if (((si3b)V_regs.LazyFlagArgDst) < ((si3b)V_regs.LazyFlagArgSrc)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpB_GT(cond_actP t_act, cond_actP f_act)
+{
+	if (((si3b)V_regs.LazyFlagArgDst) > ((si3b)V_regs.LazyFlagArgSrc)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpB_LE(cond_actP t_act, cond_actP f_act)
+{
+	if (((si3b)V_regs.LazyFlagArgDst) <= ((si3b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpW_HI(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui4b)V_regs.LazyFlagArgDst) > ((ui4b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpW_LS(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui4b)V_regs.LazyFlagArgDst) <= ((ui4b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpW_CC(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui4b)V_regs.LazyFlagArgDst) >= ((ui4b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpW_CS(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui4b)V_regs.LazyFlagArgDst) < ((ui4b)V_regs.LazyFlagArgSrc)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpW_NE(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui4b)V_regs.LazyFlagArgDst) != ((ui4b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpW_EQ(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui4b)V_regs.LazyFlagArgDst) == ((ui4b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpW_PL(cond_actP t_act, cond_actP f_act)
+{
+	if (((si4b)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) >= 0) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpW_MI(cond_actP t_act, cond_actP f_act)
+{
+	if (((si4b)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) < 0) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpW_GE(cond_actP t_act, cond_actP f_act)
+{
+	if (((si4b)V_regs.LazyFlagArgDst) >= ((si4b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpW_LT(cond_actP t_act, cond_actP f_act)
+{
+	if (((si4b)V_regs.LazyFlagArgDst) < ((si4b)V_regs.LazyFlagArgSrc)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpW_GT(cond_actP t_act, cond_actP f_act)
+{
+	if (((si4b)V_regs.LazyFlagArgDst) > ((si4b)V_regs.LazyFlagArgSrc)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpW_LE(cond_actP t_act, cond_actP f_act)
+{
+	if (((si4b)V_regs.LazyFlagArgDst) <= ((si4b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpL_HI(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui5b)V_regs.LazyFlagArgDst) > ((ui5b)V_regs.LazyFlagArgSrc)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpL_LS(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui5b)V_regs.LazyFlagArgDst) <= ((ui5b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpL_CC(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui5b)V_regs.LazyFlagArgDst) >= ((ui5b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpL_CS(cond_actP t_act, cond_actP f_act)
+{
+	if (((ui5b)V_regs.LazyFlagArgDst) < ((ui5b)V_regs.LazyFlagArgSrc)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpL_NE(cond_actP t_act, cond_actP f_act)
+{
+	if (V_regs.LazyFlagArgDst != V_regs.LazyFlagArgSrc) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpL_EQ(cond_actP t_act, cond_actP f_act)
+{
+	if (V_regs.LazyFlagArgDst == V_regs.LazyFlagArgSrc) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpL_PL(cond_actP t_act, cond_actP f_act)
+{
+	if ((((si5b)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) >= 0))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpL_MI(cond_actP t_act, cond_actP f_act)
+{
+	if ((((si5b)(V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc)) < 0)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpL_GE(cond_actP t_act, cond_actP f_act)
+{
+	if (((si5b)V_regs.LazyFlagArgDst) >= ((si5b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpL_LT(cond_actP t_act, cond_actP f_act)
+{
+	if (((si5b)V_regs.LazyFlagArgDst) < ((si5b)V_regs.LazyFlagArgSrc)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpL_GT(cond_actP t_act, cond_actP f_act)
+{
+	if (((si5b)V_regs.LazyFlagArgDst) > ((si5b)V_regs.LazyFlagArgSrc)) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_CmpL_LE(cond_actP t_act, cond_actP f_act)
+{
+	if (((si5b)V_regs.LazyFlagArgDst) <= ((si5b)V_regs.LazyFlagArgSrc))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_Asr_CC(cond_actP t_act, cond_actP f_act)
+{
+	if (0 ==
+		((V_regs.LazyFlagArgDst >> (V_regs.LazyFlagArgSrc - 1)) & 1))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_Asr_CS(cond_actP t_act, cond_actP f_act)
+{
+	if (0 !=
+		((V_regs.LazyFlagArgDst >> (V_regs.LazyFlagArgSrc - 1)) & 1))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_AslB_CC(cond_actP t_act, cond_actP f_act)
+{
+	if (0 ==
+		((V_regs.LazyFlagArgDst >> (8 - V_regs.LazyFlagArgSrc)) & 1))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_AslB_CS(cond_actP t_act, cond_actP f_act)
+{
+	if (0 !=
+		((V_regs.LazyFlagArgDst >> (8 - V_regs.LazyFlagArgSrc)) & 1))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_AslB_VC(cond_actP t_act, cond_actP f_act)
+{
+	ui5r cnt = V_regs.LazyFlagArgSrc;
+	ui5r dst = ui5r_FromSByte(V_regs.LazyFlagArgDst << cnt);
+
+	if (Ui5rASR(dst, cnt) == V_regs.LazyFlagArgDst) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_AslB_VS(cond_actP t_act, cond_actP f_act)
+{
+	ui5r cnt = V_regs.LazyFlagArgSrc;
+	ui5r dst = ui5r_FromSByte(V_regs.LazyFlagArgDst << cnt);
+
+	if (Ui5rASR(dst, cnt) != V_regs.LazyFlagArgDst) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_AslW_CC(cond_actP t_act, cond_actP f_act)
+{
+	if (0 ==
+		((V_regs.LazyFlagArgDst >> (16 - V_regs.LazyFlagArgSrc)) & 1))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_AslW_CS(cond_actP t_act, cond_actP f_act)
+{
+	if (0 !=
+		((V_regs.LazyFlagArgDst >> (16 - V_regs.LazyFlagArgSrc)) & 1))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_AslW_VC(cond_actP t_act, cond_actP f_act)
+{
+	ui5r cnt = V_regs.LazyFlagArgSrc;
+	ui5r dst = ui5r_FromSWord(V_regs.LazyFlagArgDst << cnt);
+
+	if (Ui5rASR(dst, cnt) == V_regs.LazyFlagArgDst) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_AslW_VS(cond_actP t_act, cond_actP f_act)
+{
+	ui5r cnt = V_regs.LazyFlagArgSrc;
+	ui5r dst = ui5r_FromSWord(V_regs.LazyFlagArgDst << cnt);
+
+	if (Ui5rASR(dst, cnt) != V_regs.LazyFlagArgDst) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_AslL_CC(cond_actP t_act, cond_actP f_act)
+{
+	if (0 ==
+		((V_regs.LazyFlagArgDst >> (32 - V_regs.LazyFlagArgSrc)) & 1))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_AslL_CS(cond_actP t_act, cond_actP f_act)
+{
+	if (0 !=
+		((V_regs.LazyFlagArgDst >> (32 - V_regs.LazyFlagArgSrc)) & 1))
+	{
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_AslL_VC(cond_actP t_act, cond_actP f_act)
+{
+	ui5r cnt = V_regs.LazyFlagArgSrc;
+	ui5r dst = ui5r_FromSLong(V_regs.LazyFlagArgDst << cnt);
+
+	if (Ui5rASR(dst, cnt) == V_regs.LazyFlagArgDst) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+LOCALPROC my_reg_call cctrue_AslL_VS(cond_actP t_act, cond_actP f_act)
+{
+	ui5r cnt = V_regs.LazyFlagArgSrc;
+	ui5r dst = ui5r_FromSLong(V_regs.LazyFlagArgDst << cnt);
+
+	if (Ui5rASR(dst, cnt) != V_regs.LazyFlagArgDst) {
+		t_act();
+	} else {
+		f_act();
+	}
+}
+
+FORWARDPROC my_reg_call cctrue_Dflt(cond_actP t_act, cond_actP f_act);
+
+#endif /* UseLazyCC */
+
+#if UseLazyCC
+#define CCdispSz (16 * kNumLazyFlagsKinds)
+#else
+#define CCdispSz kNumLazyFlagsKinds
+#endif
+
+typedef void (my_reg_call *cctrueP)(cond_actP t_act, cond_actP f_act);
+
+LOCALVAR const cctrueP cctrueDispatch[CCdispSz + 1] = {
+	cctrue_T /* kLazyFlagsDefault T */,
+	cctrue_F /* kLazyFlagsDefault F */,
+	cctrue_HI /* kLazyFlagsDefault HI */,
+	cctrue_LS /* kLazyFlagsDefault LS */,
+	cctrue_CC /* kLazyFlagsDefault CC */,
+	cctrue_CS /* kLazyFlagsDefault CS */,
+	cctrue_NE /* kLazyFlagsDefault NE */,
+	cctrue_EQ /* kLazyFlagsDefault EQ */,
+	cctrue_VC /* kLazyFlagsDefault VC */,
+	cctrue_VS /* kLazyFlagsDefault VS */,
+	cctrue_PL /* kLazyFlagsDefault PL */,
+	cctrue_MI /* kLazyFlagsDefault MI */,
+	cctrue_GE /* kLazyFlagsDefault GE */,
+	cctrue_LT /* kLazyFlagsDefault LT */,
+	cctrue_GT /* kLazyFlagsDefault GT */,
+	cctrue_LE /* kLazyFlagsDefault LE */,
+
+#if UseLazyCC
+	cctrue_T /* kLazyFlagsTstB T */,
+	cctrue_F /* kLazyFlagsTstB F */,
+	cctrue_Dflt /* kLazyFlagsTstB HI */,
+	cctrue_Dflt /* kLazyFlagsTstB LS */,
+	cctrue_Dflt /* kLazyFlagsTstB CC */,
+	cctrue_Dflt /* kLazyFlagsTstB CS */,
+	cctrue_Dflt /* kLazyFlagsTstB NE */,
+	cctrue_Dflt /* kLazyFlagsTstB EQ */,
+	cctrue_Dflt /* kLazyFlagsTstB VC */,
+	cctrue_Dflt /* kLazyFlagsTstB VS */,
+	cctrue_Dflt /* kLazyFlagsTstB PL */,
+	cctrue_Dflt /* kLazyFlagsTstB MI */,
+	cctrue_Dflt /* kLazyFlagsTstB GE */,
+	cctrue_Dflt /* kLazyFlagsTstB LT */,
+	cctrue_Dflt /* kLazyFlagsTstB GT */,
+	cctrue_Dflt /* kLazyFlagsTstB LE */,
+
+	cctrue_T /* kLazyFlagsTstW T */,
+	cctrue_F /* kLazyFlagsTstW F */,
+	cctrue_Dflt /* kLazyFlagsTstW HI */,
+	cctrue_Dflt /* kLazyFlagsTstW LS */,
+	cctrue_Dflt /* kLazyFlagsTstW CC */,
+	cctrue_Dflt /* kLazyFlagsTstW CS */,
+	cctrue_Dflt /* kLazyFlagsTstW NE */,
+	cctrue_Dflt /* kLazyFlagsTstW EQ */,
+	cctrue_Dflt /* kLazyFlagsTstW VC */,
+	cctrue_Dflt /* kLazyFlagsTstW VS */,
+	cctrue_Dflt /* kLazyFlagsTstW PL */,
+	cctrue_Dflt /* kLazyFlagsTstW MI */,
+	cctrue_Dflt /* kLazyFlagsTstW GE */,
+	cctrue_Dflt /* kLazyFlagsTstW LT */,
+	cctrue_Dflt /* kLazyFlagsTstW GT */,
+	cctrue_Dflt /* kLazyFlagsTstW LE */,
+
+	cctrue_T /* kLazyFlagsTstL T */,
+	cctrue_F /* kLazyFlagsTstL F */,
+	cctrue_TstL_HI /* kLazyFlagsTstL HI */,
+	cctrue_TstL_LS /* kLazyFlagsTstL LS */,
+	cctrue_T /* cctrue_TstL_CC */ /* kLazyFlagsTstL CC */,
+	cctrue_F /* cctrue_TstL_CS */ /* kLazyFlagsTstL CS */,
+	cctrue_TstL_NE /* kLazyFlagsTstL NE */,
+	cctrue_TstL_EQ /* kLazyFlagsTstL EQ */,
+	cctrue_T /* cctrue_Dflt */ /* kLazyFlagsTstL VC */,
+	cctrue_F /* cctrue_Dflt */ /* kLazyFlagsTstL VS */,
+	cctrue_TstL_PL /* kLazyFlagsTstL PL */,
+	cctrue_TstL_MI /* kLazyFlagsTstL MI */,
+	cctrue_TstL_GE /* kLazyFlagsTstL GE */,
+	cctrue_TstL_LT /* kLazyFlagsTstL LT */,
+	cctrue_TstL_GT /* kLazyFlagsTstL GT */,
+	cctrue_TstL_LE /* kLazyFlagsTstL LE */,
+
+	cctrue_T /* kLazyFlagsCmpB T */,
+	cctrue_F /* kLazyFlagsCmpB F */,
+	cctrue_CmpB_HI /* kLazyFlagsCmpB HI */,
+	cctrue_CmpB_LS /* kLazyFlagsCmpB LS */,
+	cctrue_CmpB_CC /* kLazyFlagsCmpB CC */,
+	cctrue_CmpB_CS /* kLazyFlagsCmpB CS */,
+	cctrue_CmpB_NE /* kLazyFlagsCmpB NE */,
+	cctrue_CmpB_EQ /* kLazyFlagsCmpB EQ */,
+	cctrue_Dflt /* kLazyFlagsCmpB VC */,
+	cctrue_Dflt /* kLazyFlagsCmpB VS */,
+	cctrue_CmpB_PL /* kLazyFlagsCmpB PL */,
+	cctrue_CmpB_MI /* kLazyFlagsCmpB MI */,
+	cctrue_CmpB_GE /* kLazyFlagsCmpB GE */,
+	cctrue_CmpB_LT /* kLazyFlagsCmpB LT */,
+	cctrue_CmpB_GT /* kLazyFlagsCmpB GT */,
+	cctrue_CmpB_LE /* kLazyFlagsCmpB LE */,
+
+	cctrue_T /* kLazyFlagsCmpW T */,
+	cctrue_F /* kLazyFlagsCmpW F */,
+	cctrue_CmpW_HI /* kLazyFlagsCmpW HI */,
+	cctrue_CmpW_LS /* kLazyFlagsCmpW LS */,
+	cctrue_CmpW_CC /* kLazyFlagsCmpW CC */,
+	cctrue_CmpW_CS /* kLazyFlagsCmpW CS */,
+	cctrue_CmpW_NE /* kLazyFlagsCmpW NE */,
+	cctrue_CmpW_EQ /* kLazyFlagsCmpW EQ */,
+	cctrue_Dflt /* kLazyFlagsCmpW VC */,
+	cctrue_Dflt /* kLazyFlagsCmpW VS */,
+	cctrue_CmpW_PL /* kLazyFlagsCmpW PL */,
+	cctrue_CmpW_MI /* kLazyFlagsCmpW MI */,
+	cctrue_CmpW_GE /* kLazyFlagsCmpW GE */,
+	cctrue_CmpW_LT /* kLazyFlagsCmpW LT */,
+	cctrue_CmpW_GT /* kLazyFlagsCmpW GT */,
+	cctrue_CmpW_LE /* kLazyFlagsCmpW LE */,
+
+	cctrue_T /* kLazyFlagsCmpL T */,
+	cctrue_F /* kLazyFlagsCmpL F */,
+	cctrue_CmpL_HI /* kLazyFlagsCmpL HI */,
+	cctrue_CmpL_LS /* kLazyFlagsCmpL LS */,
+	cctrue_CmpL_CC /* kLazyFlagsCmpL CC */,
+	cctrue_CmpL_CS /* kLazyFlagsCmpL CS */,
+	cctrue_CmpL_NE /* kLazyFlagsCmpL NE */,
+	cctrue_CmpL_EQ /* kLazyFlagsCmpL EQ */,
+	cctrue_Dflt /* kLazyFlagsCmpL VC */,
+	cctrue_Dflt /* kLazyFlagsCmpL VS */,
+	cctrue_CmpL_PL /* kLazyFlagsCmpL PL */,
+	cctrue_CmpL_MI /* kLazyFlagsCmpL MI */,
+	cctrue_CmpL_GE /* kLazyFlagsCmpL GE */,
+	cctrue_CmpL_LT /* kLazyFlagsCmpL LT */,
+	cctrue_CmpL_GT /* kLazyFlagsCmpL GT */,
+	cctrue_CmpL_LE /* kLazyFlagsCmpL LE */,
+
+	cctrue_T /* kLazyFlagsSubB T */,
+	cctrue_F /* kLazyFlagsSubB F */,
+	cctrue_CmpB_HI /* kLazyFlagsSubB HI */,
+	cctrue_CmpB_LS /* kLazyFlagsSubB LS */,
+	cctrue_CmpB_CC /* kLazyFlagsSubB CC */,
+	cctrue_CmpB_CS /* kLazyFlagsSubB CS */,
+	cctrue_CmpB_NE /* kLazyFlagsSubB NE */,
+	cctrue_CmpB_EQ /* kLazyFlagsSubB EQ */,
+	cctrue_Dflt /* kLazyFlagsSubB VC */,
+	cctrue_Dflt /* kLazyFlagsSubB VS */,
+	cctrue_CmpB_PL /* kLazyFlagsSubB PL */,
+	cctrue_CmpB_MI /* kLazyFlagsSubB MI */,
+	cctrue_CmpB_GE /* kLazyFlagsSubB GE */,
+	cctrue_CmpB_LT /* kLazyFlagsSubB LT */,
+	cctrue_CmpB_GT /* kLazyFlagsSubB GT */,
+	cctrue_CmpB_LE /* kLazyFlagsSubB LE */,
+
+	cctrue_T /* kLazyFlagsSubW T */,
+	cctrue_F /* kLazyFlagsSubW F */,
+	cctrue_CmpW_HI /* kLazyFlagsSubW HI */,
+	cctrue_CmpW_LS /* kLazyFlagsSubW LS */,
+	cctrue_CmpW_CC /* kLazyFlagsSubW CC */,
+	cctrue_CmpW_CS /* kLazyFlagsSubW CS */,
+	cctrue_CmpW_NE /* kLazyFlagsSubW NE */,
+	cctrue_CmpW_EQ /* kLazyFlagsSubW EQ */,
+	cctrue_Dflt /* kLazyFlagsSubW VC */,
+	cctrue_Dflt /* kLazyFlagsSubW VS */,
+	cctrue_CmpW_PL /* kLazyFlagsSubW PL */,
+	cctrue_CmpW_MI /* kLazyFlagsSubW MI */,
+	cctrue_CmpW_GE /* kLazyFlagsSubW GE */,
+	cctrue_CmpW_LT /* kLazyFlagsSubW LT */,
+	cctrue_CmpW_GT /* kLazyFlagsSubW GT */,
+	cctrue_CmpW_LE /* kLazyFlagsSubW LE */,
+
+	cctrue_T /* kLazyFlagsSubL T */,
+	cctrue_F /* kLazyFlagsSubL F */,
+	cctrue_CmpL_HI /* kLazyFlagsSubL HI */,
+	cctrue_CmpL_LS /* kLazyFlagsSubL LS */,
+	cctrue_CmpL_CC /* kLazyFlagsSubL CC */,
+	cctrue_CmpL_CS /* kLazyFlagsSubL CS */,
+	cctrue_CmpL_NE /* kLazyFlagsSubL NE */,
+	cctrue_CmpL_EQ /* kLazyFlagsSubL EQ */,
+	cctrue_Dflt /* kLazyFlagsSubL VC */,
+	cctrue_Dflt /* kLazyFlagsSubL VS */,
+	cctrue_CmpL_PL /* kLazyFlagsSubL PL */,
+	cctrue_CmpL_MI /* kLazyFlagsSubL MI */,
+	cctrue_CmpL_GE /* kLazyFlagsSubL GE */,
+	cctrue_CmpL_LT /* kLazyFlagsSubL LT */,
+	cctrue_CmpL_GT /* kLazyFlagsSubL GT */,
+	cctrue_CmpL_LE /* kLazyFlagsSubL LE */,
+
+	cctrue_T /* kLazyFlagsAddB T */,
+	cctrue_F /* kLazyFlagsAddB F */,
+	cctrue_Dflt /* kLazyFlagsAddB HI */,
+	cctrue_Dflt /* kLazyFlagsAddB LS */,
+	cctrue_Dflt /* kLazyFlagsAddB CC */,
+	cctrue_Dflt /* kLazyFlagsAddB CS */,
+	cctrue_Dflt /* kLazyFlagsAddB NE */,
+	cctrue_Dflt /* kLazyFlagsAddB EQ */,
+	cctrue_Dflt /* kLazyFlagsAddB VC */,
+	cctrue_Dflt /* kLazyFlagsAddB VS */,
+	cctrue_Dflt /* kLazyFlagsAddB PL */,
+	cctrue_Dflt /* kLazyFlagsAddB MI */,
+	cctrue_Dflt /* kLazyFlagsAddB GE */,
+	cctrue_Dflt /* kLazyFlagsAddB LT */,
+	cctrue_Dflt /* kLazyFlagsAddB GT */,
+	cctrue_Dflt /* kLazyFlagsAddB LE */,
+
+	cctrue_T /* kLazyFlagsAddW T */,
+	cctrue_F /* kLazyFlagsAddW F */,
+	cctrue_Dflt /* kLazyFlagsAddW HI */,
+	cctrue_Dflt /* kLazyFlagsAddW LS */,
+	cctrue_Dflt /* kLazyFlagsAddW CC */,
+	cctrue_Dflt /* kLazyFlagsAddW CS */,
+	cctrue_Dflt /* kLazyFlagsAddW NE */,
+	cctrue_Dflt /* kLazyFlagsAddW EQ */,
+	cctrue_Dflt /* kLazyFlagsAddW VC */,
+	cctrue_Dflt /* kLazyFlagsAddW VS */,
+	cctrue_Dflt /* kLazyFlagsAddW PL */,
+	cctrue_Dflt /* kLazyFlagsAddW MI */,
+	cctrue_Dflt /* kLazyFlagsAddW GE */,
+	cctrue_Dflt /* kLazyFlagsAddW LT */,
+	cctrue_Dflt /* kLazyFlagsAddW GT */,
+	cctrue_Dflt /* kLazyFlagsAddW LE */,
+
+	cctrue_T /* kLazyFlagsAddL T */,
+	cctrue_F /* kLazyFlagsAddL F */,
+	cctrue_Dflt /* kLazyFlagsAddL HI */,
+	cctrue_Dflt /* kLazyFlagsAddL LS */,
+	cctrue_Dflt /* kLazyFlagsAddL CC */,
+	cctrue_Dflt /* kLazyFlagsAddL CS */,
+	cctrue_Dflt /* kLazyFlagsAddL NE */,
+	cctrue_Dflt /* kLazyFlagsAddL EQ */,
+	cctrue_Dflt /* kLazyFlagsAddL VC */,
+	cctrue_Dflt /* kLazyFlagsAddL VS */,
+	cctrue_Dflt /* kLazyFlagsAddL PL */,
+	cctrue_Dflt /* kLazyFlagsAddL MI */,
+	cctrue_Dflt /* kLazyFlagsAddL GE */,
+	cctrue_Dflt /* kLazyFlagsAddL LT */,
+	cctrue_Dflt /* kLazyFlagsAddL GT */,
+	cctrue_Dflt /* kLazyFlagsAddL LE */,
+
+	cctrue_T /* kLazyFlagsNegB T */,
+	cctrue_F /* kLazyFlagsNegB F */,
+	cctrue_Dflt /* kLazyFlagsNegB HI */,
+	cctrue_Dflt /* kLazyFlagsNegB LS */,
+	cctrue_Dflt /* kLazyFlagsNegB CC */,
+	cctrue_Dflt /* kLazyFlagsNegB CS */,
+	cctrue_Dflt /* kLazyFlagsNegB NE */,
+	cctrue_Dflt /* kLazyFlagsNegB EQ */,
+	cctrue_Dflt /* kLazyFlagsNegB VC */,
+	cctrue_Dflt /* kLazyFlagsNegB VS */,
+	cctrue_Dflt /* kLazyFlagsNegB PL */,
+	cctrue_Dflt /* kLazyFlagsNegB MI */,
+	cctrue_Dflt /* kLazyFlagsNegB GE */,
+	cctrue_Dflt /* kLazyFlagsNegB LT */,
+	cctrue_Dflt /* kLazyFlagsNegB GT */,
+	cctrue_Dflt /* kLazyFlagsNegB LE */,
+
+	cctrue_T /* kLazyFlagsNegW T */,
+	cctrue_F /* kLazyFlagsNegW F */,
+	cctrue_Dflt /* kLazyFlagsNegW HI */,
+	cctrue_Dflt /* kLazyFlagsNegW LS */,
+	cctrue_Dflt /* kLazyFlagsNegW CC */,
+	cctrue_Dflt /* kLazyFlagsNegW CS */,
+	cctrue_Dflt /* kLazyFlagsNegW NE */,
+	cctrue_Dflt /* kLazyFlagsNegW EQ */,
+	cctrue_Dflt /* kLazyFlagsNegW VC */,
+	cctrue_Dflt /* kLazyFlagsNegW VS */,
+	cctrue_Dflt /* kLazyFlagsNegW PL */,
+	cctrue_Dflt /* kLazyFlagsNegW MI */,
+	cctrue_Dflt /* kLazyFlagsNegW GE */,
+	cctrue_Dflt /* kLazyFlagsNegW LT */,
+	cctrue_Dflt /* kLazyFlagsNegW GT */,
+	cctrue_Dflt /* kLazyFlagsNegW LE */,
+
+	cctrue_T /* kLazyFlagsNegL T */,
+	cctrue_F /* kLazyFlagsNegL F */,
+	cctrue_Dflt /* kLazyFlagsNegL HI */,
+	cctrue_Dflt /* kLazyFlagsNegL LS */,
+	cctrue_Dflt /* kLazyFlagsNegL CC */,
+	cctrue_Dflt /* kLazyFlagsNegL CS */,
+	cctrue_Dflt /* kLazyFlagsNegL NE */,
+	cctrue_Dflt /* kLazyFlagsNegL EQ */,
+	cctrue_Dflt /* kLazyFlagsNegL VC */,
+	cctrue_Dflt /* kLazyFlagsNegL VS */,
+	cctrue_Dflt /* kLazyFlagsNegL PL */,
+	cctrue_Dflt /* kLazyFlagsNegL MI */,
+	cctrue_Dflt /* kLazyFlagsNegL GE */,
+	cctrue_Dflt /* kLazyFlagsNegL LT */,
+	cctrue_Dflt /* kLazyFlagsNegL GT */,
+	cctrue_Dflt /* kLazyFlagsNegL LE */,
+
+	cctrue_T /* kLazyFlagsAsrB T */,
+	cctrue_F /* kLazyFlagsAsrB F */,
+	cctrue_Dflt /* kLazyFlagsAsrB HI */,
+	cctrue_Dflt /* kLazyFlagsAsrB LS */,
+	cctrue_Asr_CC /* kLazyFlagsAsrB CC */,
+	cctrue_Asr_CS /* kLazyFlagsAsrB CS */,
+	cctrue_Dflt /* kLazyFlagsAsrB NE */,
+	cctrue_Dflt /* kLazyFlagsAsrB EQ */,
+	cctrue_Dflt /* kLazyFlagsAsrB VC */,
+	cctrue_Dflt /* kLazyFlagsAsrB VS */,
+	cctrue_Dflt /* kLazyFlagsAsrB PL */,
+	cctrue_Dflt /* kLazyFlagsAsrB MI */,
+	cctrue_Dflt /* kLazyFlagsAsrB GE */,
+	cctrue_Dflt /* kLazyFlagsAsrB LT */,
+	cctrue_Dflt /* kLazyFlagsAsrB GT */,
+	cctrue_Dflt /* kLazyFlagsAsrB LE */,
+
+	cctrue_T /* kLazyFlagsAsrW T */,
+	cctrue_F /* kLazyFlagsAsrW F */,
+	cctrue_Dflt /* kLazyFlagsAsrW HI */,
+	cctrue_Dflt /* kLazyFlagsAsrW LS */,
+	cctrue_Asr_CC /* kLazyFlagsAsrW CC */,
+	cctrue_Asr_CS /* kLazyFlagsAsrW CS */,
+	cctrue_Dflt /* kLazyFlagsAsrW NE */,
+	cctrue_Dflt /* kLazyFlagsAsrW EQ */,
+	cctrue_Dflt /* kLazyFlagsAsrW VC */,
+	cctrue_Dflt /* kLazyFlagsAsrW VS */,
+	cctrue_Dflt /* kLazyFlagsAsrW PL */,
+	cctrue_Dflt /* kLazyFlagsAsrW MI */,
+	cctrue_Dflt /* kLazyFlagsAsrW GE */,
+	cctrue_Dflt /* kLazyFlagsAsrW LT */,
+	cctrue_Dflt /* kLazyFlagsAsrW GT */,
+	cctrue_Dflt /* kLazyFlagsAsrW LE */,
+
+	cctrue_T /* kLazyFlagsAsrL T */,
+	cctrue_F /* kLazyFlagsAsrL F */,
+	cctrue_Dflt /* kLazyFlagsAsrL HI */,
+	cctrue_Dflt /* kLazyFlagsAsrL LS */,
+	cctrue_Asr_CC /* kLazyFlagsAsrL CC */,
+	cctrue_Asr_CS /* kLazyFlagsAsrL CS */,
+	cctrue_Dflt /* kLazyFlagsAsrL NE */,
+	cctrue_Dflt /* kLazyFlagsAsrL EQ */,
+	cctrue_Dflt /* kLazyFlagsAsrL VC */,
+	cctrue_Dflt /* kLazyFlagsAsrL VS */,
+	cctrue_Dflt /* kLazyFlagsAsrL PL */,
+	cctrue_Dflt /* kLazyFlagsAsrL MI */,
+	cctrue_Dflt /* kLazyFlagsAsrL GE */,
+	cctrue_Dflt /* kLazyFlagsAsrL LT */,
+	cctrue_Dflt /* kLazyFlagsAsrL GT */,
+	cctrue_Dflt /* kLazyFlagsAsrL LE */,
+
+	cctrue_T /* kLazyFlagsAslB T */,
+	cctrue_F /* kLazyFlagsAslB F */,
+	cctrue_Dflt /* kLazyFlagsAslB HI */,
+	cctrue_Dflt /* kLazyFlagsAslB LS */,
+	cctrue_AslB_CC /* kLazyFlagsAslB CC */,
+	cctrue_AslB_CS /* kLazyFlagsAslB CS */,
+	cctrue_Dflt /* kLazyFlagsAslB NE */,
+	cctrue_Dflt /* kLazyFlagsAslB EQ */,
+	cctrue_AslB_VC /* kLazyFlagsAslB VC */,
+	cctrue_AslB_VS /* kLazyFlagsAslB VS */,
+	cctrue_Dflt /* kLazyFlagsAslB PL */,
+	cctrue_Dflt /* kLazyFlagsAslB MI */,
+	cctrue_Dflt /* kLazyFlagsAslB GE */,
+	cctrue_Dflt /* kLazyFlagsAslB LT */,
+	cctrue_Dflt /* kLazyFlagsAslB GT */,
+	cctrue_Dflt /* kLazyFlagsAslB LE */,
+
+	cctrue_T /* kLazyFlagsAslW T */,
+	cctrue_F /* kLazyFlagsAslW F */,
+	cctrue_Dflt /* kLazyFlagsAslW HI */,
+	cctrue_Dflt /* kLazyFlagsAslW LS */,
+	cctrue_AslW_CC /* kLazyFlagsAslW CC */,
+	cctrue_AslW_CS /* kLazyFlagsAslW CS */,
+	cctrue_Dflt /* kLazyFlagsAslW NE */,
+	cctrue_Dflt /* kLazyFlagsAslW EQ */,
+	cctrue_AslW_VC /* kLazyFlagsAslW VC */,
+	cctrue_AslW_VS /* kLazyFlagsAslW VS */,
+	cctrue_Dflt /* kLazyFlagsAslW PL */,
+	cctrue_Dflt /* kLazyFlagsAslW MI */,
+	cctrue_Dflt /* kLazyFlagsAslW GE */,
+	cctrue_Dflt /* kLazyFlagsAslW LT */,
+	cctrue_Dflt /* kLazyFlagsAslW GT */,
+	cctrue_Dflt /* kLazyFlagsAslW LE */,
+
+	cctrue_T /* kLazyFlagsAslL T */,
+	cctrue_F /* kLazyFlagsAslL F */,
+	cctrue_Dflt /* kLazyFlagsAslL HI */,
+	cctrue_Dflt /* kLazyFlagsAslL LS */,
+	cctrue_AslL_CC /* kLazyFlagsAslL CC */,
+	cctrue_AslL_CS /* kLazyFlagsAslL CS */,
+	cctrue_Dflt /* kLazyFlagsAslL NE */,
+	cctrue_Dflt /* kLazyFlagsAslL EQ */,
+	cctrue_AslL_VC /* kLazyFlagsAslL VC */,
+	cctrue_AslL_VS /* kLazyFlagsAslL VS */,
+	cctrue_Dflt /* kLazyFlagsAslL PL */,
+	cctrue_Dflt /* kLazyFlagsAslL MI */,
+	cctrue_Dflt /* kLazyFlagsAslL GE */,
+	cctrue_Dflt /* kLazyFlagsAslL LT */,
+	cctrue_Dflt /* kLazyFlagsAslL GT */,
+	cctrue_Dflt /* kLazyFlagsAslL LE */,
+
+#if UseLazyZ
+	cctrue_T /* kLazyFlagsZSet T */,
+	cctrue_F /* kLazyFlagsZSet F */,
+	cctrue_Dflt /* kLazyFlagsZSet HI */,
+	cctrue_Dflt /* kLazyFlagsZSet LS */,
+	cctrue_Dflt /* kLazyFlagsZSet CC */,
+	cctrue_Dflt /* kLazyFlagsZSet CS */,
+	cctrue_NE /* kLazyFlagsZSet NE */,
+	cctrue_EQ /* kLazyFlagsZSet EQ */,
+	cctrue_Dflt /* kLazyFlagsZSet VC */,
+	cctrue_Dflt /* kLazyFlagsZSet VS */,
+	cctrue_Dflt /* kLazyFlagsZSet PL */,
+	cctrue_Dflt /* kLazyFlagsZSet MI */,
+	cctrue_Dflt /* kLazyFlagsZSet GE */,
+	cctrue_Dflt /* kLazyFlagsZSet LT */,
+	cctrue_Dflt /* kLazyFlagsZSet GT */,
+	cctrue_Dflt /* kLazyFlagsZSet LE */,
+#endif
+#endif /* UseLazyCC */
+
+	0
+};
+
+#if UseLazyCC
+LOCALINLINEPROC cctrue(cond_actP t_act, cond_actP f_act)
+{
+	(cctrueDispatch[V_regs.LazyFlagKind * 16
+		+ V_regs.CurDecOpY.v[0].ArgDat])(t_act, f_act);
+}
+#endif
+
+
+LOCALPROC NeedDefaultLazyXFlagSubB(void)
+{
+	XFLG = Bool2Bit(((ui3b)V_regs.LazyXFlagArgDst)
+		< ((ui3b)V_regs.LazyXFlagArgSrc));
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyXFlagSubW(void)
+{
+	XFLG = Bool2Bit(((ui4b)V_regs.LazyXFlagArgDst)
+		< ((ui4b)V_regs.LazyXFlagArgSrc));
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyXFlagSubL(void)
+{
+	XFLG = Bool2Bit(((ui5b)V_regs.LazyXFlagArgDst)
+		< ((ui5b)V_regs.LazyXFlagArgSrc));
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyXFlagAddB(void)
+{
+	ui3b src = (ui3b)V_regs.LazyXFlagArgSrc;
+	ui3b dst = (ui3b)V_regs.LazyXFlagArgDst;
+	ui3b result = dst + src;
+
+	XFLG = Bool2Bit(result < src);
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyXFlagAddW(void)
+{
+	ui4b src = (ui4b)V_regs.LazyXFlagArgSrc;
+	ui4b dst = (ui4b)V_regs.LazyXFlagArgDst;
+	ui4b result = dst + src;
+
+	XFLG = Bool2Bit(result < src);
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyXFlagAddL(void)
+{
+	ui5b src = (ui5b)V_regs.LazyXFlagArgSrc;
+	ui5b dst = (ui5b)V_regs.LazyXFlagArgDst;
+	ui5b result = dst + src;
+
+	XFLG = Bool2Bit(result < src);
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyXFlagNegB(void)
+{
+	XFLG = Bool2Bit(((ui3b)0)
+		< ((ui3b)V_regs.LazyXFlagArgDst));
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyXFlagNegW(void)
+{
+	XFLG = Bool2Bit(((ui4b)0)
+		< ((ui4b)V_regs.LazyXFlagArgDst));
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyXFlagNegL(void)
+{
+	XFLG = Bool2Bit(((ui5b)0)
+		< ((ui5b)V_regs.LazyXFlagArgDst));
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyXFlagAsr(void)
+{
+	ui5r cnt = V_regs.LazyFlagArgSrc;
+	ui5r dst = V_regs.LazyFlagArgDst;
+
+	XFLG = ((dst >> (cnt - 1)) & 1);
+
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyXFlagAslB(void)
+{
+	XFLG = (V_regs.LazyFlagArgDst >> (8 - V_regs.LazyFlagArgSrc)) & 1;
+
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyXFlagAslW(void)
+{
+	XFLG = (V_regs.LazyFlagArgDst >> (16 - V_regs.LazyFlagArgSrc)) & 1;
+
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyXFlagAslL(void)
+{
+	XFLG = (V_regs.LazyFlagArgDst >> (32 - V_regs.LazyFlagArgSrc)) & 1;
+
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyXFlagDefault(void)
+{
+}
+
+typedef void (*NeedLazyFlagP)(void);
+
+LOCALVAR const NeedLazyFlagP
+	NeedLazyXFlagDispatch[kNumLazyFlagsKinds + 1] =
+{
+	NeedDefaultLazyXFlagDefault /* kLazyFlagsDefault */,
+	0 /* kLazyFlagsTstB */,
+	0 /* kLazyFlagsTstW */,
+	0 /* kLazyFlagsTstL */,
+	0 /* kLazyFlagsCmpB */,
+	0 /* kLazyFlagsCmpW */,
+	0 /* kLazyFlagsCmpL */,
+	NeedDefaultLazyXFlagSubB /* kLazyFlagsSubB */,
+	NeedDefaultLazyXFlagSubW /* kLazyFlagsSubW */,
+	NeedDefaultLazyXFlagSubL /* kLazyFlagsSubL */,
+	NeedDefaultLazyXFlagAddB /* kLazyFlagsAddB */,
+	NeedDefaultLazyXFlagAddW /* kLazyFlagsAddW */,
+	NeedDefaultLazyXFlagAddL /* kLazyFlagsAddL */,
+	NeedDefaultLazyXFlagNegB /* kLazyFlagsNegB */,
+	NeedDefaultLazyXFlagNegW /* kLazyFlagsNegW */,
+	NeedDefaultLazyXFlagNegL /* kLazyFlagsNegL */,
+	NeedDefaultLazyXFlagAsr  /* kLazyFlagsAsrB */,
+	NeedDefaultLazyXFlagAsr  /* kLazyFlagsAsrW */,
+	NeedDefaultLazyXFlagAsr  /* kLazyFlagsAsrL */,
+	NeedDefaultLazyXFlagAslB /* kLazyFlagsAslB */,
+	NeedDefaultLazyXFlagAslW /* kLazyFlagsAslW */,
+	NeedDefaultLazyXFlagAslL /* kLazyFlagsAslL */,
+#if UseLazyZ
+	0 /* kLazyFlagsZSet */,
+#endif
+
+	0
+};
+
+LOCALPROC NeedDefaultLazyXFlag(void)
+{
+#if ForceFlagsEval
+	if (kLazyFlagsDefault != V_regs.LazyXFlagKind) {
+		ReportAbnormalID(0x0103,
+			"not kLazyFlagsDefault in NeedDefaultLazyXFlag");
+	}
+#else
+	(NeedLazyXFlagDispatch[V_regs.LazyXFlagKind])();
+#endif
+}
+
+LOCALPROC NeedDefaultLazyFlagsTstL(void)
+{
+	ui5r dst = V_regs.LazyFlagArgDst;
+
+	VFLG = CFLG = 0;
+	ZFLG = Bool2Bit(dst == 0);
+	NFLG = Bool2Bit(ui5r_MSBisSet(dst));
+
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+	NeedDefaultLazyXFlag();
+}
+
+LOCALPROC NeedDefaultLazyFlagsCmpB(void)
+{
+	ui5r src = V_regs.LazyFlagArgSrc;
+	ui5r dst = V_regs.LazyFlagArgDst;
+	ui5r result0 = dst - src;
+	ui5r result1 = ui5r_FromUByte(dst)
+		- ui5r_FromUByte(src);
+	ui5r result = ui5r_FromSByte(result0);
+
+	ZFLG = Bool2Bit(result == 0);
+	NFLG = Bool2Bit(ui5r_MSBisSet(result));
+	VFLG = (((result0 >> 1) ^ result0) >> 7) & 1;
+	CFLG = (result1 >> 8) & 1;
+
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+	NeedDefaultLazyXFlag();
+}
+
+LOCALPROC NeedDefaultLazyFlagsCmpW(void)
+{
+	ui5r result0 = V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc;
+	ui5r result = ui5r_FromSWord(result0);
+
+	ZFLG = Bool2Bit(result == 0);
+	NFLG = Bool2Bit(ui5r_MSBisSet(result));
+
+	VFLG = (((result0 >> 1) ^ result0) >> 15) & 1;
+	{
+		ui5r result1 = ui5r_FromUWord(V_regs.LazyFlagArgDst)
+			- ui5r_FromUWord(V_regs.LazyFlagArgSrc);
+
+		CFLG = (result1 >> 16) & 1;
+	}
+
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+	NeedDefaultLazyXFlag();
+}
+
+LOCALPROC NeedDefaultLazyFlagsCmpL(void)
+{
+	ui5r src = V_regs.LazyFlagArgSrc;
+	ui5r dst = V_regs.LazyFlagArgDst;
+	ui5r result = ui5r_FromSLong(dst - src);
+
+	ZFLG = Bool2Bit(result == 0);
+
+	{
+		flagtype flgn = Bool2Bit(ui5r_MSBisSet(result));
+		flagtype flgs = Bool2Bit(ui5r_MSBisSet(src));
+		flagtype flgo = Bool2Bit(ui5r_MSBisSet(dst)) ^ 1;
+		flagtype flgsando = flgs & flgo;
+		flagtype flgsoro = flgs | flgo;
+
+		NFLG = flgn;
+		VFLG = ((flgn | flgsoro) ^ 1) | (flgn & flgsando);
+		CFLG = flgsando | (flgn & flgsoro);
+	}
+
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+	NeedDefaultLazyXFlag();
+}
+
+LOCALPROC NeedDefaultLazyFlagsSubB(void)
+{
+	ui5r src = V_regs.LazyFlagArgSrc;
+	ui5r dst = V_regs.LazyFlagArgDst;
+	ui5r result0 = dst - src;
+	ui5r result1 = ui5r_FromUByte(dst)
+		- ui5r_FromUByte(src);
+	ui5r result = ui5r_FromSByte(result0);
+
+	ZFLG = Bool2Bit(result == 0);
+	NFLG = Bool2Bit(ui5r_MSBisSet(result));
+	VFLG = (((result0 >> 1) ^ result0) >> 7) & 1;
+	CFLG = (result1 >> 8) & 1;
+
+	XFLG = CFLG;
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyFlagsSubW(void)
+{
+	ui5r result0 = V_regs.LazyFlagArgDst - V_regs.LazyFlagArgSrc;
+	ui5r result = ui5r_FromSWord(result0);
+
+	ZFLG = Bool2Bit(result == 0);
+	NFLG = Bool2Bit(ui5r_MSBisSet(result));
+
+	VFLG = (((result0 >> 1) ^ result0) >> 15) & 1;
+	{
+		ui5r result1 = ui5r_FromUWord(V_regs.LazyFlagArgDst)
+			- ui5r_FromUWord(V_regs.LazyFlagArgSrc);
+
+		CFLG = (result1 >> 16) & 1;
+	}
+
+	XFLG = CFLG;
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyFlagsSubL(void)
+{
+	ui5r src = V_regs.LazyFlagArgSrc;
+	ui5r dst = V_regs.LazyFlagArgDst;
+	ui5r result = ui5r_FromSLong(dst - src);
+
+	ZFLG = Bool2Bit(result == 0);
+
+	{
+		flagtype flgn = Bool2Bit(ui5r_MSBisSet(result));
+		flagtype flgs = Bool2Bit(ui5r_MSBisSet(src));
+		flagtype flgo = Bool2Bit(ui5r_MSBisSet(dst)) ^ 1;
+		flagtype flgsando = flgs & flgo;
+		flagtype flgsoro = flgs | flgo;
+
+		NFLG = flgn;
+		VFLG = ((flgn | flgsoro) ^ 1) | (flgn & flgsando);
+		CFLG = flgsando | (flgn & flgsoro);
+	}
+
+	XFLG = CFLG;
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyFlagsAddB(void)
+{
+	ui5r src = V_regs.LazyFlagArgSrc;
+	ui5r dst = V_regs.LazyFlagArgDst;
+	ui5r result0 = dst + src;
+	ui5r result1 = ui5r_FromUByte(dst)
+		+ ui5r_FromUByte(src);
+	ui5r result = ui5r_FromSByte(result0);
+
+	ZFLG = Bool2Bit(result == 0);
+	NFLG = Bool2Bit(ui5r_MSBisSet(result));
+	VFLG = (((result0 >> 1) ^ result0) >> 7) & 1;
+	CFLG = (result1 >> 8);
+
+	XFLG = CFLG;
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyFlagsAddW(void)
+{
+	ui5r src = V_regs.LazyFlagArgSrc;
+	ui5r dst = V_regs.LazyFlagArgDst;
+	ui5r result0 = dst + src;
+	ui5r result1 = ui5r_FromUWord(dst)
+		+ ui5r_FromUWord(src);
+	ui5r result = ui5r_FromSWord(result0);
+
+	ZFLG = Bool2Bit(result == 0);
+	NFLG = Bool2Bit(ui5r_MSBisSet(result));
+	VFLG = (((result0 >> 1) ^ result0) >> 15) & 1;
+	CFLG = (result1 >> 16);
+
+	XFLG = CFLG;
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+#if 0
+LOCALPROC NeedDefaultLazyFlagsAddCommon(ui5r result)
+{
+	ZFLG = Bool2Bit(result == 0);
+	{
+		flagtype flgn = Bool2Bit(ui5r_MSBisSet(result));
+		flagtype flgs = Bool2Bit(ui5r_MSBisSet(V_regs.LazyFlagArgSrc));
+		flagtype flgo = Bool2Bit(ui5r_MSBisSet(V_regs.LazyFlagArgDst));
+		flagtype flgsando = flgs & flgo;
+		flagtype flgsoro = flgs | flgo;
+
+		NFLG = flgn;
+		flgn ^= 1;
+		VFLG = ((flgn | flgsoro) ^ 1) | (flgn & flgsando);
+		CFLG = flgsando | (flgn & flgsoro);
+	}
+
+	XFLG = CFLG;
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+#endif
+
+LOCALPROC NeedDefaultLazyFlagsAddL(void)
+{
+#if 1
+	ui5r src = V_regs.LazyFlagArgSrc;
+	ui5r dst = V_regs.LazyFlagArgDst;
+	ui5r result = ui5r_FromSLong(dst + src);
+
+	ZFLG = Bool2Bit(result == 0);
+	NFLG = Bool2Bit(ui5r_MSBisSet(result));
+
+	{
+		ui5r result1;
+		ui5r result0;
+		ui5r MidCarry = (ui5r_FromUWord(dst)
+			+ ui5r_FromUWord(src)) >> 16;
+
+		dst >>= 16;
+		src >>= 16;
+
+		result1 = ui5r_FromUWord(dst)
+			+ ui5r_FromUWord(src)
+			+ MidCarry;
+		CFLG = (result1 >> 16);
+		result0 = ui5r_FromSWord(dst)
+			+ ui5r_FromSWord(src)
+			+ MidCarry;
+		VFLG = (((result0 >> 1) ^ result0) >> 15) & 1;
+	}
+
+	XFLG = CFLG;
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+#else
+	ui5r result = ui5r_FromSLong(V_regs.LazyFlagArgDst
+		+ V_regs.LazyFlagArgSrc);
+
+	NeedDefaultLazyFlagsAddCommon(result);
+#endif
+}
+
+LOCALPROC NeedDefaultLazyFlagsNegCommon(ui5r dstvalue, ui5r result)
+{
+	flagtype flgs = Bool2Bit(ui5r_MSBisSet(dstvalue));
+	flagtype flgn = Bool2Bit(ui5r_MSBisSet(result));
+
+	ZFLG = Bool2Bit(result == 0);
+	NFLG = flgn;
+	VFLG = flgs & flgn;
+	CFLG = flgs | flgn;
+
+	XFLG = CFLG;
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyFlagsNegB(void)
+{
+	ui5r dstvalue = V_regs.LazyFlagArgDst;
+	ui5r result = ui5r_FromSByte(0 - dstvalue);
+
+	NeedDefaultLazyFlagsNegCommon(dstvalue, result);
+}
+
+LOCALPROC NeedDefaultLazyFlagsNegW(void)
+{
+	ui5r dstvalue = V_regs.LazyFlagArgDst;
+	ui5r result = ui5r_FromSWord(0 - dstvalue);
+
+	NeedDefaultLazyFlagsNegCommon(dstvalue, result);
+}
+
+LOCALPROC NeedDefaultLazyFlagsNegL(void)
+{
+	ui5r dstvalue = V_regs.LazyFlagArgDst;
+	ui5r result = ui5r_FromSLong(0 - dstvalue);
+
+	NeedDefaultLazyFlagsNegCommon(dstvalue, result);
+}
+
+LOCALPROC NeedDefaultLazyFlagsAsr(void)
+{
+	ui5r cnt = V_regs.LazyFlagArgSrc;
+	ui5r dst = V_regs.LazyFlagArgDst;
+
+	NFLG = Bool2Bit(ui5r_MSBisSet(dst));
+	VFLG = 0;
+
+	CFLG = ((dst >> (cnt - 1)) & 1);
+	dst = Ui5rASR(dst, cnt);
+	ZFLG = Bool2Bit(dst == 0);
+
+	XFLG = CFLG;
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyFlagsAslB(void)
+{
+	ui5r cnt = V_regs.LazyFlagArgSrc;
+	ui5r dst = V_regs.LazyFlagArgDst;
+	ui5r dstvalue0 = dst;
+	ui5r comparevalue;
+
+	dst = dst << (cnt - 1);
+	dst = ui5r_FromSByte(dst);
+	CFLG = Bool2Bit(ui5r_MSBisSet(dst));
+	dst = dst << 1;
+	dst = ui5r_FromSByte(dst);
+	comparevalue = Ui5rASR(dst, cnt);
+	VFLG = Bool2Bit(comparevalue != dstvalue0);
+	ZFLG = Bool2Bit(dst == 0);
+	NFLG = Bool2Bit(ui5r_MSBisSet(dst));
+
+	XFLG = CFLG;
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyFlagsAslW(void)
+{
+	ui5r cnt = V_regs.LazyFlagArgSrc;
+	ui5r dst = V_regs.LazyFlagArgDst;
+	ui5r dstvalue0 = dst;
+	ui5r comparevalue;
+
+	dst = dst << (cnt - 1);
+	dst = ui5r_FromSWord(dst);
+	CFLG = Bool2Bit(ui5r_MSBisSet(dst));
+	dst = dst << 1;
+	dst = ui5r_FromSWord(dst);
+	comparevalue = Ui5rASR(dst, cnt);
+	VFLG = Bool2Bit(comparevalue != dstvalue0);
+	ZFLG = Bool2Bit(dst == 0);
+	NFLG = Bool2Bit(ui5r_MSBisSet(dst));
+
+	XFLG = CFLG;
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+LOCALPROC NeedDefaultLazyFlagsAslL(void)
+{
+	ui5r cnt = V_regs.LazyFlagArgSrc;
+	ui5r dst = V_regs.LazyFlagArgDst;
+	ui5r dstvalue0 = dst;
+	ui5r comparevalue;
+
+	dst = dst << (cnt - 1);
+	dst = ui5r_FromSLong(dst);
+	CFLG = Bool2Bit(ui5r_MSBisSet(dst));
+	dst = dst << 1;
+	dst = ui5r_FromSLong(dst);
+	comparevalue = Ui5rASR(dst, cnt);
+	VFLG = Bool2Bit(comparevalue != dstvalue0);
+	ZFLG = Bool2Bit(dst == 0);
+	NFLG = Bool2Bit(ui5r_MSBisSet(dst));
+
+	XFLG = CFLG;
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+#if UseLazyZ
+FORWARDPROC NeedDefaultLazyFlagsZSet(void);
+#endif
+
+LOCALVAR const NeedLazyFlagP
+	NeedLazyFlagDispatch[kNumLazyFlagsKinds + 1] =
+{
+	NeedDefaultLazyXFlag /* kLazyFlagsDefault */,
+	0 /* kLazyFlagsTstB */,
+	0 /* kLazyFlagsTstW */,
+	NeedDefaultLazyFlagsTstL /* kLazyFlagsTstL */,
+	NeedDefaultLazyFlagsCmpB /* kLazyFlagsCmpB */,
+	NeedDefaultLazyFlagsCmpW /* kLazyFlagsCmpW */,
+	NeedDefaultLazyFlagsCmpL /* kLazyFlagsCmpL */,
+	NeedDefaultLazyFlagsSubB /* kLazyFlagsSubB */,
+	NeedDefaultLazyFlagsSubW /* kLazyFlagsSubW */,
+	NeedDefaultLazyFlagsSubL /* kLazyFlagsSubL */,
+	NeedDefaultLazyFlagsAddB /* kLazyFlagsAddB */,
+	NeedDefaultLazyFlagsAddW /* kLazyFlagsAddW */,
+	NeedDefaultLazyFlagsAddL /* kLazyFlagsAddL */,
+	NeedDefaultLazyFlagsNegB /* kLazyFlagsNegB */,
+	NeedDefaultLazyFlagsNegW /* kLazyFlagsNegW */,
+	NeedDefaultLazyFlagsNegL /* kLazyFlagsNegL */,
+	NeedDefaultLazyFlagsAsr  /* kLazyFlagsAsrB */,
+	NeedDefaultLazyFlagsAsr  /* kLazyFlagsAsrW */,
+	NeedDefaultLazyFlagsAsr  /* kLazyFlagsAsrL */,
+	NeedDefaultLazyFlagsAslB /* kLazyFlagsAslB */,
+	NeedDefaultLazyFlagsAslW /* kLazyFlagsAslW */,
+	NeedDefaultLazyFlagsAslL /* kLazyFlagsAslL */,
+#if UseLazyZ
+	NeedDefaultLazyFlagsZSet /* kLazyFlagsZSet */,
+#endif
+
+	0
+};
+
+LOCALPROC NeedDefaultLazyAllFlags0(void)
+{
+	(NeedLazyFlagDispatch[V_regs.LazyFlagKind])();
+}
+
+#if ForceFlagsEval
+LOCALPROC NeedDefaultLazyAllFlags(void)
+{
+	if (kLazyFlagsDefault != V_regs.LazyFlagKind) {
+		ReportAbnormalID(0x0104,
+			"not kLazyFlagsDefault in NeedDefaultLazyAllFlags");
+#if dbglog_HAVE
+		dbglog_writelnNum("LazyFlagKind", V_regs.LazyFlagKind);
+#endif
+	}
+}
+#else
+#define NeedDefaultLazyAllFlags NeedDefaultLazyAllFlags0
+#endif
+
+#if ForceFlagsEval
+#define HaveSetUpFlags NeedDefaultLazyAllFlags0
+#else
+#define HaveSetUpFlags()
+#endif
+
+#if UseLazyZ
+LOCALPROC NeedDefaultLazyFlagsZSet(void)
+{
+	flagtype SaveZFLG = ZFLG;
+
+	V_regs.LazyFlagKind = V_regs.LazyFlagZSavedKind;
+	NeedDefaultLazyAllFlags();
+
+	ZFLG = SaveZFLG;
+}
+#endif
+
+#if UseLazyCC
+LOCALPROC my_reg_call cctrue_Dflt(cond_actP t_act, cond_actP f_act)
+{
+	NeedDefaultLazyAllFlags();
+	cctrue(t_act, f_act);
+}
+#endif
+
+#if ! UseLazyCC
+LOCALINLINEPROC cctrue(cond_actP t_act, cond_actP f_act)
+{
+	NeedDefaultLazyAllFlags();
+	(cctrueDispatch[V_regs.CurDecOpY.v[0].ArgDat])(t_act, f_act);
+}
+#endif
+
+
+#define LOCALIPROC LOCALPROC /* LOCALPROCUSEDONCE */
+
+LOCALIPROC DoCodeCmpB(void)
+{
+	ui5r dstvalue = DecodeGetSrcGetDstValue();
+
+	V_regs.LazyFlagKind = kLazyFlagsCmpB;
+	V_regs.LazyFlagArgSrc = V_regs.SrcVal;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+}
+
+LOCALIPROC DoCodeCmpW(void)
+{
+	ui5r dstvalue = DecodeGetSrcGetDstValue();
+
+	V_regs.LazyFlagKind = kLazyFlagsCmpW;
+	V_regs.LazyFlagArgSrc = V_regs.SrcVal;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+}
+
+LOCALIPROC DoCodeCmpL(void)
+{
+	ui5r dstvalue = DecodeGetSrcGetDstValue();
+
+	V_regs.LazyFlagKind = kLazyFlagsCmpL;
+	V_regs.LazyFlagArgSrc = V_regs.SrcVal;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+}
+
+LOCALIPROC DoCodeMoveL(void)
+{
+	ui5r src = DecodeGetSrcValue();
+
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = src;
+
+	HaveSetUpFlags();
+
+	DecodeSetDstValue(src);
+}
+
+LOCALIPROC DoCodeMoveW(void)
+{
+	ui5r src = DecodeGetSrcValue();
+
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = src;
+
+	HaveSetUpFlags();
+
+	DecodeSetDstValue(src);
+}
+
+LOCALIPROC DoCodeMoveB(void)
+{
+	ui5r src = DecodeGetSrcValue();
+
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = src;
+
+	HaveSetUpFlags();
+
+	DecodeSetDstValue(src);
+}
+
+LOCALIPROC DoCodeTst(void)
+{
+	/* Tst 01001010ssmmmrrr */
+
+	ui5r srcvalue = DecodeGetDstValue();
+
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = srcvalue;
+
+	HaveSetUpFlags();
+}
+
+LOCALIPROC DoCodeBraB(void)
+{
+	si5r offset = (si5r)(si3b)(ui3b)(V_regs.CurDecOpY.v[1].ArgDat);
+	ui3p s = V_pc_p + offset;
+
+	V_pc_p = s;
+
+#if USE_PCLIMIT
+	if (my_cond_rare(s >= V_pc_pHi)
+		|| my_cond_rare(s < V_regs.pc_pLo))
+	{
+		Recalc_PC_Block();
+	}
+#endif
+}
+
+LOCALIPROC DoCodeBraW(void)
+{
+	si5r offset = (si5r)(si4b)(ui4b)do_get_mem_word(V_pc_p);
+		/* note that pc not incremented here */
+	ui3p s = V_pc_p + offset;
+
+	V_pc_p = s;
+
+#if USE_PCLIMIT
+	if (my_cond_rare(s >= V_pc_pHi)
+		|| my_cond_rare(s < V_regs.pc_pLo))
+	{
+		Recalc_PC_Block();
+	}
+#endif
+}
+
+#if WantCloserCyc
+LOCALPROC DoCodeBccB_t(void)
+{
+	V_MaxCyclesToGo -= (10 * kCycleScale + 2 * RdAvgXtraCyc);
+	DoCodeBraB();
+}
+#else
+#define DoCodeBccB_t DoCodeBraB
+#endif
+
+LOCALPROC DoCodeBccB_f(void)
+{
+#if WantCloserCyc
+	V_MaxCyclesToGo -= (8 * kCycleScale + RdAvgXtraCyc);
+#endif
+		/* do nothing */
+}
+
+LOCALIPROC DoCodeBccB(void)
+{
+	/* Bcc 0110ccccnnnnnnnn */
+	cctrue(DoCodeBccB_t, DoCodeBccB_f);
+}
+
+LOCALPROC SkipiWord(void)
+{
+	V_pc_p += 2;
+
+#if USE_PCLIMIT
+	if (my_cond_rare(V_pc_p >= V_pc_pHi)) {
+		Recalc_PC_Block();
+	}
+#endif
+}
+
+#if WantCloserCyc
+LOCALPROC DoCodeBccW_t(void)
+{
+	V_MaxCyclesToGo -= (10 * kCycleScale + 2 * RdAvgXtraCyc);
+	DoCodeBraW();
+}
+#else
+#define DoCodeBccW_t DoCodeBraW
+#endif
+
+#if WantCloserCyc
+LOCALPROC DoCodeBccW_f(void)
+{
+	V_MaxCyclesToGo -= (12 * kCycleScale + 2 * RdAvgXtraCyc);
+	SkipiWord();
+}
+#else
+#define DoCodeBccW_f SkipiWord
+#endif
+
+LOCALIPROC DoCodeBccW(void)
+{
+	/* Bcc 0110ccccnnnnnnnn */
+	cctrue(DoCodeBccW_t, DoCodeBccW_f);
+}
+
+
+LOCALIPROC DoCodeDBF(void)
+{
+	/* DBcc 0101cccc11001ddd */
+
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+	ui5r dstvalue = ui5r_FromSWord(*dstp);
+
+	--dstvalue;
+#if LittleEndianUnaligned
+	*(ui4b *)dstp = dstvalue;
+#else
+	*dstp = (*dstp & ~ 0xffff) | ((dstvalue) & 0xffff);
+#endif
+
+	if ((si5b)dstvalue == -1) {
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (14 * kCycleScale + 3 * RdAvgXtraCyc);
+#endif
+		SkipiWord();
+	} else {
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (10 * kCycleScale + 2 * RdAvgXtraCyc);
+#endif
+		DoCodeBraW();
+	}
+}
+
+#if WantCloserCyc
+LOCALPROC DoCodeDBcc_t(void)
+{
+	V_MaxCyclesToGo -= (12 * kCycleScale + 2 * RdAvgXtraCyc);
+	SkipiWord();
+}
+#else
+#define DoCodeDBcc_t SkipiWord
+#endif
+
+LOCALIPROC DoCodeDBcc(void)
+{
+	/* DBcc 0101cccc11001ddd */
+
+	cctrue(DoCodeDBcc_t, DoCodeDBF);
+}
+
+LOCALIPROC DoCodeSwap(void)
+{
+	/* Swap 0100100001000rrr */
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+	ui5r src = *dstp;
+	ui5r dst = ui5r_FromSLong(((src >> 16) & 0xFFFF)
+		| ((src & 0xFFFF) << 16));
+
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = dst;
+
+	HaveSetUpFlags();
+
+	*dstp = dst;
+}
+
+LOCALIPROC DoCodeMoveA(void) /* MOVE */
+{
+	ui5r src = DecodeGetSrcValue();
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+
+	m68k_areg(dstreg) = src;
+}
+
+LOCALIPROC DoCodeMoveQ(void)
+{
+	/* MoveQ 0111ddd0nnnnnnnn */
+	ui5r src = ui5r_FromSByte(V_regs.CurDecOpY.v[0].ArgDat);
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = src;
+
+	HaveSetUpFlags();
+
+	m68k_dreg(dstreg) = src;
+}
+
+LOCALIPROC DoCodeAddB(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r srcvalue = V_regs.SrcVal;
+	ui5r result = ui5r_FromSByte(dstvalue + srcvalue);
+
+	V_regs.LazyFlagKind = kLazyFlagsAddB;
+	V_regs.LazyFlagArgSrc = srcvalue;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	V_regs.LazyXFlagKind = kLazyFlagsAddB;
+	V_regs.LazyXFlagArgSrc = srcvalue;
+	V_regs.LazyXFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	ArgSetDstValue(result);
+}
+
+LOCALIPROC DoCodeAddW(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r srcvalue = V_regs.SrcVal;
+	ui5r result = ui5r_FromSWord(dstvalue + srcvalue);
+
+	V_regs.LazyFlagKind = kLazyFlagsAddW;
+	V_regs.LazyFlagArgSrc = srcvalue;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	V_regs.LazyXFlagKind = kLazyFlagsAddW;
+	V_regs.LazyXFlagArgSrc = srcvalue;
+	V_regs.LazyXFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	ArgSetDstValue(result);
+}
+
+LOCALIPROC DoCodeAddL(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r srcvalue = V_regs.SrcVal;
+	ui5r result = ui5r_FromSLong(dstvalue + srcvalue);
+
+	V_regs.LazyFlagKind = kLazyFlagsAddL;
+	V_regs.LazyFlagArgSrc = srcvalue;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	V_regs.LazyXFlagKind = kLazyFlagsAddL;
+	V_regs.LazyXFlagArgSrc = srcvalue;
+	V_regs.LazyXFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	ArgSetDstValue(result);
+}
+
+LOCALIPROC DoCodeSubB(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r srcvalue = V_regs.SrcVal;
+	ui5r result = ui5r_FromSByte(dstvalue - srcvalue);
+
+	V_regs.LazyFlagKind = kLazyFlagsSubB;
+	V_regs.LazyFlagArgSrc = srcvalue;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	V_regs.LazyXFlagKind = kLazyFlagsSubB;
+	V_regs.LazyXFlagArgSrc = srcvalue;
+	V_regs.LazyXFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	ArgSetDstValue(result);
+}
+
+LOCALIPROC DoCodeSubW(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r srcvalue = V_regs.SrcVal;
+	ui5r result = ui5r_FromSWord(dstvalue - srcvalue);
+
+	V_regs.LazyFlagKind = kLazyFlagsSubW;
+	V_regs.LazyFlagArgSrc = srcvalue;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	V_regs.LazyXFlagKind = kLazyFlagsSubW;
+	V_regs.LazyXFlagArgSrc = srcvalue;
+	V_regs.LazyXFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	ArgSetDstValue(result);
+}
+
+LOCALIPROC DoCodeSubL(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r srcvalue = V_regs.SrcVal;
+	ui5r result = ui5r_FromSLong(dstvalue - srcvalue);
+
+	V_regs.LazyFlagKind = kLazyFlagsSubL;
+	V_regs.LazyFlagArgSrc = srcvalue;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	V_regs.LazyXFlagKind = kLazyFlagsSubL;
+	V_regs.LazyXFlagArgSrc = srcvalue;
+	V_regs.LazyXFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	ArgSetDstValue(result);
+}
+
+LOCALIPROC DoCodeLea(void)
+{
+	/* Lea 0100aaa111mmmrrr */
+	ui5r DstAddr = DecodeDst();
+	ui5r dstreg = V_regs.CurDecOpY.v[0].ArgDat;
+
+	m68k_areg(dstreg) = DstAddr;
+}
+
+LOCALIPROC DoCodePEA(void)
+{
+	/* PEA 0100100001mmmrrr */
+	ui5r DstAddr = DecodeDst();
+
+	m68k_areg(7) -= 4;
+	put_long(m68k_areg(7), DstAddr);
+}
+
+LOCALIPROC DoCodeBsrB(void)
+{
+	m68k_areg(7) -= 4;
+	put_long(m68k_areg(7), m68k_getpc());
+	DoCodeBraB();
+}
+
+LOCALIPROC DoCodeBsrW(void)
+{
+	m68k_areg(7) -= 4;
+	put_long(m68k_areg(7), m68k_getpc() + 2);
+	DoCodeBraW();
+}
+
+#define m68k_logExceptions (dbglog_HAVE && 0)
+
+
+#ifndef WantDumpAJump
+#define WantDumpAJump 0
+#endif
+
+#if WantDumpAJump
+LOCALPROCUSEDONCE DumpAJump(CPTR toaddr)
+{
+	CPTR fromaddr = m68k_getpc();
+	if ((toaddr > fromaddr) || (toaddr < V_regs.pc))
+	{
+		dbglog_writeHex(fromaddr);
+		dbglog_writeCStr(",");
+		dbglog_writeHex(toaddr);
+		dbglog_writeReturn();
+	}
+}
+#endif
+
+LOCALPROC my_reg_call m68k_setpc(CPTR newpc)
+{
+#if WantDumpAJump
+	DumpAJump(newpc);
+#endif
+
+#if 0
+	if (newpc == 0xBD50 /* 401AB4 */) {
+		/* Debugger(); */
+		/* Exception(5); */ /* try and get macsbug */
+	}
+#endif
+
+	V_pc_p = V_regs.pc_pLo + (newpc - V_regs.pc);
+	if (my_cond_rare(V_pc_p >= V_pc_pHi)
+		|| my_cond_rare(V_pc_p < V_regs.pc_pLo))
+	{
+		Recalc_PC_Block();
+	}
+}
+
+LOCALIPROC DoCodeJsr(void)
+{
+	/* Jsr 0100111010mmmrrr */
+	ui5r DstAddr = DecodeDst();
+
+	m68k_areg(7) -= 4;
+	put_long(m68k_areg(7), m68k_getpc());
+	m68k_setpc(DstAddr);
+}
+
+LOCALIPROC DoCodeLinkA6(void)
+{
+	CPTR stackp = m68k_areg(7);
+	stackp -= 4;
+	put_long(stackp, m68k_areg(6));
+	m68k_areg(6) = stackp;
+	m68k_areg(7) = stackp + nextiSWord();
+}
+
+LOCALIPROC DoCodeUnlkA6(void)
+{
+	ui5r src = m68k_areg(6);
+	m68k_areg(6) = get_long(src);
+	m68k_areg(7) = src + 4;
+}
+
+LOCALIPROC DoCodeRts(void)
+{
+	/* Rts 0100111001110101 */
+	ui5r NewPC = get_long(m68k_areg(7));
+	m68k_areg(7) += 4;
+	m68k_setpc(NewPC);
+}
+
+LOCALIPROC DoCodeJmp(void)
+{
+	/* JMP 0100111011mmmrrr */
+	ui5r DstAddr = DecodeDst();
+
+	m68k_setpc(DstAddr);
+}
+
+LOCALIPROC DoCodeClr(void)
+{
+	/* Clr 01000010ssmmmrrr */
+
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = 0;
+
+	HaveSetUpFlags();
+
+	DecodeSetDstValue(0);
+}
+
+LOCALIPROC DoCodeAddA(void)
+{
+	/* ADDA 1101dddm11mmmrrr */
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+
+	ArgSetDstValue(dstvalue + V_regs.SrcVal);
+}
+
+LOCALIPROC DoCodeSubA(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+
+	ArgSetDstValue(dstvalue - V_regs.SrcVal);
+}
+
+LOCALIPROC DoCodeCmpA(void)
+{
+	ui5r dstvalue = DecodeGetSrcGetDstValue();
+
+	V_regs.LazyFlagKind = kLazyFlagsCmpL;
+	V_regs.LazyFlagArgSrc = V_regs.SrcVal;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+}
+
+LOCALFUNC ui4rr m68k_getCR(void)
+{
+	NeedDefaultLazyAllFlags();
+
+	return (XFLG << 4) | (NFLG << 3) | (ZFLG << 2)
+		| (VFLG << 1) | CFLG;
+}
+
+LOCALPROC my_reg_call m68k_setCR(ui4rr newcr)
+{
+	XFLG = (newcr >> 4) & 1;
+	NFLG = (newcr >> 3) & 1;
+	ZFLG = (newcr >> 2) & 1;
+	VFLG = (newcr >> 1) & 1;
+	CFLG = newcr & 1;
+
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+}
+
+
+LOCALFUNC ui4rr m68k_getSR(void)
+{
+	return m68k_getCR()
+			| (V_regs.t1 << 15)
+#if Use68020
+			| (V_regs.t0 << 14)
+#endif
+			| (V_regs.s << 13)
+#if Use68020
+			| (V_regs.m << 12)
+#endif
+			| (V_regs.intmask << 8);
+}
+
+LOCALPROC NeedToGetOut(void)
+{
+	if (V_MaxCyclesToGo <= 0) {
+		/*
+			already have gotten out, and exception processing has
+			caused another exception, such as because a bad
+			stack pointer pointing to a memory mapped device.
+		*/
+	} else {
+		V_regs.MoreCyclesToGo += V_MaxCyclesToGo;
+			/* not counting the current instruction */
+		V_MaxCyclesToGo = 0;
+	}
+}
+
+LOCALPROC SetExternalInterruptPending(void)
+{
+	V_regs.ExternalInterruptPending = trueblnr;
+	NeedToGetOut();
+}
+
+LOCALPROC my_reg_call m68k_setSR(ui4rr newsr)
+{
+	CPTR *pnewstk;
+	CPTR *poldstk = (V_regs.s != 0) ? (
+#if Use68020
+		(V_regs.m != 0) ? &V_regs.msp :
+#endif
+		&V_regs.isp) : &V_regs.usp;
+	ui5r oldintmask = V_regs.intmask;
+
+	V_regs.t1 = (newsr >> 15) & 1;
+#if Use68020
+	V_regs.t0 = (newsr >> 14) & 1;
+	if (V_regs.t0 != 0) {
+		ReportAbnormalID(0x0105, "t0 flag set in m68k_setSR");
+	}
+#endif
+	V_regs.s = (newsr >> 13) & 1;
+#if Use68020
+	V_regs.m = (newsr >> 12) & 1;
+	if (V_regs.m != 0) {
+		ReportAbnormalID(0x0106, "m flag set in m68k_setSR");
+	}
+#endif
+	V_regs.intmask = (newsr >> 8) & 7;
+
+	pnewstk = (V_regs.s != 0) ? (
+#if Use68020
+		(V_regs.m != 0) ? &V_regs.msp :
+#endif
+		&V_regs.isp) : &V_regs.usp;
+
+	if (poldstk != pnewstk) {
+		*poldstk = m68k_areg(7);
+		m68k_areg(7) = *pnewstk;
+	}
+
+	if (V_regs.intmask != oldintmask) {
+		SetExternalInterruptPending();
+	}
+
+	if (V_regs.t1 != 0) {
+		NeedToGetOut();
+	} else {
+		/* V_regs.TracePending = falseblnr; */
+	}
+
+	m68k_setCR(newsr);
+}
+
+LOCALPROC my_reg_call ExceptionTo(CPTR newpc
+#if Use68020
+	, int nr
+#endif
+	)
+{
+	ui4rr saveSR = m68k_getSR();
+
+	if (0 == V_regs.s) {
+		V_regs.usp = m68k_areg(7);
+		m68k_areg(7) =
+#if Use68020
+			(V_regs.m != 0) ? V_regs.msp :
+#endif
+			V_regs.isp;
+		V_regs.s = 1;
+	}
+#if Use68020
+	switch (nr) {
+		case 5: /* Zero Divide */
+		case 6: /* CHK, CHK2 */
+		case 7: /* cpTRAPcc, TRAPCcc, TRAPv */
+		case 9: /* Trace */
+			m68k_areg(7) -= 4;
+			put_long(m68k_areg(7), m68k_getpc());
+			m68k_areg(7) -= 2;
+			put_word(m68k_areg(7), 0x2000 + nr * 4);
+			break;
+		default:
+			m68k_areg(7) -= 2;
+			put_word(m68k_areg(7), nr * 4);
+			break;
+	}
+	/* if V_regs.m should make throw away stack frame */
+#endif
+	m68k_areg(7) -= 4;
+	put_long(m68k_areg(7), m68k_getpc());
+	m68k_areg(7) -= 2;
+	put_word(m68k_areg(7), saveSR);
+	m68k_setpc(newpc);
+	V_regs.t1 = 0;
+#if Use68020
+	V_regs.t0 = 0;
+	V_regs.m = 0;
+#endif
+	V_regs.TracePending = falseblnr;
+}
+
+LOCALPROC my_reg_call Exception(int nr)
+{
+	ExceptionTo(get_long(4 * nr
+#if Use68020
+		+ V_regs.vbr
+#endif
+		)
+#if Use68020
+		, nr
+#endif
+		);
+}
+
+
+LOCALIPROC DoCodeA(void)
+{
+	BackupPC();
+	Exception(0xA);
+}
+
+LOCALFUNC ui4rr nextiword_nm(void)
+/* NOT sign extended */
+{
+	return nextiword();
+}
+
+LOCALIPROC DoCodeMOVEMRmML(void)
+{
+	/* MOVEM reg to mem 01001000111100rrr */
+	si4b z;
+	ui5r regmask = nextiword_nm();
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+	ui5r p = *dstp;
+
+#if Use68020
+	{
+		int n = 0;
+
+		for (z = 0; z < 16; ++z) {
+			if ((regmask & (1 << z)) != 0) {
+				n++;
+			}
+		}
+		*dstp = p - n * 4;
+	}
+#endif
+	for (z = 16; --z >= 0; ) {
+		if ((regmask & (1 << (15 - z))) != 0) {
+#if WantCloserCyc
+			V_MaxCyclesToGo -= (8 * kCycleScale + 2 * WrAvgXtraCyc);
+#endif
+			p -= 4;
+			put_long(p, V_regs.regs[z]);
+		}
+	}
+#if ! Use68020
+	*dstp = p;
+#endif
+}
+
+LOCALIPROC DoCodeMOVEMApRL(void)
+{
+	/* MOVEM mem to reg 01001100111011rrr */
+	si4b z;
+	ui5r regmask = nextiword_nm();
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+	ui5r p = *dstp;
+
+	for (z = 0; z < 16; ++z) {
+		if ((regmask & (1 << z)) != 0) {
+#if WantCloserCyc
+			V_MaxCyclesToGo -= (8 * kCycleScale + 2 * RdAvgXtraCyc);
+#endif
+			V_regs.regs[z] = get_long(p);
+			p += 4;
+		}
+	}
+	*dstp = p;
+}
+
+LOCALPROC my_reg_call SetCCRforAddX(ui5r dstvalue, ui5r srcvalue,
+	ui5r result)
+{
+	ZFLG &= Bool2Bit(result == 0);
+
+	{
+		flagtype flgs = Bool2Bit(ui5r_MSBisSet(srcvalue));
+		flagtype flgo = Bool2Bit(ui5r_MSBisSet(dstvalue));
+		flagtype flgsando = flgs & flgo;
+		flagtype flgsoro = flgs | flgo;
+		flagtype flgn = Bool2Bit(ui5r_MSBisSet(result));
+
+		NFLG = flgn;
+		flgn ^= 1;
+		VFLG = ((flgn | flgsoro) ^ 1) | (flgn & flgsando);
+		XFLG = CFLG = flgsando | (flgn & flgsoro);
+	}
+
+	ArgSetDstValue(result);
+}
+
+LOCALIPROC DoCodeAddXB(void)
+{
+	NeedDefaultLazyAllFlags();
+
+	{
+		ui5r dstvalue = DecodeGetSrcSetDstValue();
+		ui5r srcvalue = V_regs.SrcVal;
+		ui5r result = ui5r_FromSByte(XFLG + dstvalue + srcvalue);
+
+		SetCCRforAddX(dstvalue, srcvalue, result);
+	}
+}
+
+LOCALIPROC DoCodeAddXW(void)
+{
+	if ((kLazyFlagsDefault != V_regs.LazyFlagKind)
+		|| (kLazyFlagsDefault != V_regs.LazyXFlagKind))
+	{
+		NeedDefaultLazyAllFlags();
+	}
+
+	{
+		ui5r dstvalue = DecodeGetSrcSetDstValue();
+		ui5r srcvalue = V_regs.SrcVal;
+		ui5r result = ui5r_FromSWord(XFLG + dstvalue + srcvalue);
+
+		SetCCRforAddX(dstvalue, srcvalue, result);
+	}
+}
+
+LOCALIPROC DoCodeAddXL(void)
+{
+	if (kLazyFlagsAddL == V_regs.LazyFlagKind) {
+		ui5r src = V_regs.LazyFlagArgSrc;
+		ui5r dst = V_regs.LazyFlagArgDst;
+		ui5r result = ui5r_FromULong(dst + src);
+
+		ZFLG = Bool2Bit(result == 0);
+		XFLG = Bool2Bit(result < src);
+
+		V_regs.LazyFlagKind = kLazyFlagsDefault;
+		V_regs.LazyXFlagKind = kLazyFlagsDefault;
+	} else
+	if ((kLazyFlagsDefault == V_regs.LazyFlagKind)
+		&& (kLazyFlagsDefault == V_regs.LazyXFlagKind))
+	{
+		/* ok */
+	} else
+	{
+		NeedDefaultLazyAllFlags();
+	}
+
+	{
+		ui5r dstvalue = DecodeGetSrcSetDstValue();
+		ui5r srcvalue = V_regs.SrcVal;
+		ui5r result = ui5r_FromSLong(XFLG + dstvalue + srcvalue);
+
+		SetCCRforAddX(dstvalue, srcvalue, result);
+	}
+}
+
+LOCALPROC my_reg_call SetCCRforSubX(ui5r dstvalue, ui5r srcvalue,
+	ui5r result)
+{
+	ZFLG &= Bool2Bit(result == 0);
+
+	{
+		flagtype flgs = Bool2Bit(ui5r_MSBisSet(srcvalue));
+		flagtype flgo = Bool2Bit(ui5r_MSBisSet(dstvalue)) ^ 1;
+		flagtype flgsando = flgs & flgo;
+		flagtype flgsoro = flgs | flgo;
+		flagtype flgn = Bool2Bit(ui5r_MSBisSet(result));
+
+		NFLG = flgn;
+		VFLG = ((flgn | flgsoro) ^ 1) | (flgn & flgsando);
+		XFLG = CFLG = flgsando | (flgn & flgsoro);
+	}
+
+	ArgSetDstValue(result);
+}
+
+LOCALIPROC DoCodeSubXB(void)
+{
+	NeedDefaultLazyAllFlags();
+
+	{
+		ui5r dstvalue = DecodeGetSrcSetDstValue();
+		ui5r srcvalue = V_regs.SrcVal;
+		ui5r result = ui5r_FromSByte(dstvalue - srcvalue - XFLG);
+
+		SetCCRforSubX(dstvalue, srcvalue, result);
+	}
+}
+
+LOCALIPROC DoCodeSubXW(void)
+{
+	if ((kLazyFlagsDefault != V_regs.LazyFlagKind)
+		|| (kLazyFlagsDefault != V_regs.LazyXFlagKind))
+	{
+		NeedDefaultLazyAllFlags();
+	}
+
+	{
+		ui5r dstvalue = DecodeGetSrcSetDstValue();
+		ui5r srcvalue = V_regs.SrcVal;
+		ui5r result = ui5r_FromSWord(dstvalue - srcvalue - XFLG);
+
+		SetCCRforSubX(dstvalue, srcvalue, result);
+	}
+}
+
+LOCALIPROC DoCodeSubXL(void)
+{
+	if (kLazyFlagsSubL == V_regs.LazyFlagKind) {
+		ui5r src = V_regs.LazyFlagArgSrc;
+		ui5r dst = V_regs.LazyFlagArgDst;
+		ui5r result = ui5r_FromSLong(dst - src);
+
+		ZFLG = Bool2Bit(result == 0);
+		XFLG = Bool2Bit(((ui5b)dst) < ((ui5b)src));
+
+		V_regs.LazyFlagKind = kLazyFlagsDefault;
+		V_regs.LazyXFlagKind = kLazyFlagsDefault;
+	} else
+	if ((kLazyFlagsDefault == V_regs.LazyFlagKind)
+		&& (kLazyFlagsDefault == V_regs.LazyXFlagKind))
+	{
+		/* ok */
+	} else
+	{
+		NeedDefaultLazyAllFlags();
+	}
+
+	{
+		ui5r dstvalue = DecodeGetSrcSetDstValue();
+		ui5r srcvalue = V_regs.SrcVal;
+		ui5r result = ui5r_FromSLong(dstvalue - srcvalue - XFLG);
+
+		SetCCRforSubX(dstvalue, srcvalue, result);
+	}
+}
+
+LOCALPROC my_reg_call DoCodeNullShift(ui5r dstvalue)
+{
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	ArgSetDstValue(dstvalue);
+}
+
+LOCALPROC DoCodeOverAsl(ui5r dstvalue)
+{
+	XFLG = CFLG = 0;
+	VFLG = Bool2Bit(0 != dstvalue);
+	ZFLG = 1;
+	NFLG = 0;
+
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+	ArgSetDstValue(0);
+}
+
+LOCALPROC my_reg_call DoCodeMaxAsr(ui5r dstvalue)
+{
+	XFLG = CFLG = dstvalue & 1;
+	VFLG = Bool2Bit(0 != dstvalue);
+	ZFLG = 1;
+	NFLG = 0;
+
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+	ArgSetDstValue(0);
+}
+
+LOCALIPROC DoCodeAslB(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else {
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+		if (cnt >= 8) {
+			if (cnt == 8) {
+				DoCodeMaxAsr(dstvalue);
+			} else {
+				DoCodeOverAsl(dstvalue);
+			}
+		} else {
+			ui5r result = ui5r_FromSByte(dstvalue << cnt);
+
+			V_regs.LazyFlagKind = kLazyFlagsAslB;
+			V_regs.LazyFlagArgSrc = cnt;
+			V_regs.LazyFlagArgDst = dstvalue;
+
+			V_regs.LazyXFlagKind = kLazyFlagsAslB;
+			V_regs.LazyXFlagArgSrc = cnt;
+			V_regs.LazyXFlagArgDst = dstvalue;
+
+			HaveSetUpFlags();
+
+			ArgSetDstValue(result);
+		}
+	}
+}
+
+LOCALIPROC DoCodeAslW(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else {
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+		if (cnt >= 16) {
+			if (cnt == 16) {
+				DoCodeMaxAsr(dstvalue);
+			} else {
+				DoCodeOverAsl(dstvalue);
+			}
+		} else {
+			ui5r result = ui5r_FromSWord(dstvalue << cnt);
+
+			V_regs.LazyFlagKind = kLazyFlagsAslW;
+			V_regs.LazyFlagArgSrc = cnt;
+			V_regs.LazyFlagArgDst = dstvalue;
+
+			V_regs.LazyXFlagKind = kLazyFlagsAslW;
+			V_regs.LazyXFlagArgSrc = cnt;
+			V_regs.LazyXFlagArgDst = dstvalue;
+
+			HaveSetUpFlags();
+
+			ArgSetDstValue(result);
+		}
+	}
+}
+
+LOCALIPROC DoCodeAslL(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else {
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+		if (cnt >= 32) {
+			if (cnt == 32) {
+				DoCodeMaxAsr(dstvalue);
+			} else {
+				DoCodeOverAsl(dstvalue);
+			}
+		} else {
+			ui5r result = ui5r_FromSLong(dstvalue << cnt);
+
+			V_regs.LazyFlagKind = kLazyFlagsAslL;
+			V_regs.LazyFlagArgSrc = cnt;
+			V_regs.LazyFlagArgDst = dstvalue;
+
+			V_regs.LazyXFlagKind = kLazyFlagsAslL;
+			V_regs.LazyXFlagArgSrc = cnt;
+			V_regs.LazyXFlagArgDst = dstvalue;
+
+			HaveSetUpFlags();
+
+			ArgSetDstValue(result);
+		}
+	}
+}
+
+LOCALPROC DoCodeOverShift(void)
+{
+	XFLG = CFLG = 0;
+	ZFLG = 1;
+	NFLG = 0;
+	VFLG = 0;
+
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+	ArgSetDstValue(0);
+}
+
+LOCALPROC DoCodeOverShiftN(void)
+{
+	NFLG = 1;
+	VFLG = 0;
+	CFLG = 1;
+	XFLG = CFLG;
+	ZFLG = 0;
+
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+	ArgSetDstValue(~ 0);
+}
+
+LOCALPROC DoCodeOverAShift(ui5r dstvalue)
+{
+	if (ui5r_MSBisSet(dstvalue)) {
+		DoCodeOverShiftN();
+	} else {
+		DoCodeOverShift();
+	}
+}
+
+LOCALIPROC DoCodeAsrB(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else {
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+		if (cnt >= 8) {
+			DoCodeOverAShift(dstvalue);
+		} else {
+			ui5r result = Ui5rASR(dstvalue, cnt);
+
+			V_regs.LazyFlagKind = kLazyFlagsAsrB;
+			V_regs.LazyFlagArgSrc = cnt;
+			V_regs.LazyFlagArgDst = dstvalue;
+
+			V_regs.LazyXFlagKind = kLazyFlagsAsrB;
+			V_regs.LazyXFlagArgSrc = cnt;
+			V_regs.LazyXFlagArgDst = dstvalue;
+
+			HaveSetUpFlags();
+
+			ArgSetDstValue(result);
+		}
+	}
+}
+
+LOCALIPROC DoCodeAsrW(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else {
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+		if (cnt >= 16) {
+			DoCodeOverAShift(dstvalue);
+		} else {
+			ui5r result = Ui5rASR(dstvalue, cnt);
+
+			V_regs.LazyFlagKind = kLazyFlagsAsrW;
+			V_regs.LazyFlagArgSrc = cnt;
+			V_regs.LazyFlagArgDst = dstvalue;
+
+			V_regs.LazyXFlagKind = kLazyFlagsAsrW;
+			V_regs.LazyXFlagArgSrc = cnt;
+			V_regs.LazyXFlagArgDst = dstvalue;
+
+			HaveSetUpFlags();
+
+			ArgSetDstValue(result);
+		}
+	}
+}
+
+LOCALIPROC DoCodeAsrL(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else {
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+		if (cnt >= 32) {
+			DoCodeOverAShift(dstvalue);
+		} else {
+			ui5r result = Ui5rASR(dstvalue, cnt);
+
+			V_regs.LazyFlagKind = kLazyFlagsAsrL;
+			V_regs.LazyFlagArgSrc = cnt;
+			V_regs.LazyFlagArgDst = dstvalue;
+
+			V_regs.LazyXFlagKind = kLazyFlagsAsrL;
+			V_regs.LazyXFlagArgSrc = cnt;
+			V_regs.LazyXFlagArgDst = dstvalue;
+
+			HaveSetUpFlags();
+
+			ArgSetDstValue(result);
+		}
+	}
+}
+
+LOCALPROC my_reg_call DoCodeMaxLslShift(ui5r dstvalue)
+{
+	XFLG = CFLG = dstvalue & 1;
+	ZFLG = 1;
+	NFLG = 0;
+	VFLG = 0;
+
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+	ArgSetDstValue(0);
+}
+
+LOCALIPROC DoCodeLslB(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else {
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+		if (cnt >= 8) {
+			if (cnt == 8) {
+				DoCodeMaxLslShift(dstvalue);
+			} else {
+				DoCodeOverShift();
+			}
+		} else {
+			CFLG = (dstvalue >> (8 - cnt)) & 1;
+			dstvalue = dstvalue << cnt;
+			dstvalue = ui5r_FromSByte(dstvalue);
+
+			ZFLG = Bool2Bit(dstvalue == 0);
+			NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+			VFLG = 0;
+			XFLG = CFLG;
+			V_regs.LazyXFlagKind = kLazyFlagsDefault;
+			V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+			ArgSetDstValue(dstvalue);
+		}
+	}
+}
+
+LOCALIPROC DoCodeLslW(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else {
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+		if (cnt >= 16) {
+			if (cnt == 16) {
+				DoCodeMaxLslShift(dstvalue);
+			} else {
+				DoCodeOverShift();
+			}
+		} else {
+			CFLG = (dstvalue >> (16 - cnt)) & 1;
+			dstvalue = dstvalue << cnt;
+			dstvalue = ui5r_FromSWord(dstvalue);
+
+			ZFLG = Bool2Bit(dstvalue == 0);
+			NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+			VFLG = 0;
+			XFLG = CFLG;
+			V_regs.LazyXFlagKind = kLazyFlagsDefault;
+			V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+			ArgSetDstValue(dstvalue);
+		}
+	}
+}
+
+LOCALIPROC DoCodeLslL(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else {
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+		if (cnt >= 32) {
+			if (cnt == 32) {
+				DoCodeMaxLslShift(dstvalue);
+			} else {
+				DoCodeOverShift();
+			}
+		} else {
+			CFLG = (dstvalue >> (32 - cnt)) & 1;
+			dstvalue = dstvalue << cnt;
+			dstvalue = ui5r_FromSLong(dstvalue);
+
+			ZFLG = Bool2Bit(dstvalue == 0);
+			NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+			VFLG = 0;
+			XFLG = CFLG;
+			V_regs.LazyXFlagKind = kLazyFlagsDefault;
+			V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+			ArgSetDstValue(dstvalue);
+		}
+	}
+}
+
+LOCALIPROC DoCodeLsrB(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+#if WantCloserCyc
+	V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else if (cnt > 32) {
+		DoCodeOverShift();
+	} else {
+		dstvalue = ui5r_FromUByte(dstvalue);
+		dstvalue = dstvalue >> (cnt - 1);
+		CFLG = XFLG = (dstvalue & 1);
+		dstvalue = dstvalue >> 1;
+		ZFLG = Bool2Bit(dstvalue == 0);
+		NFLG = 0 /* Bool2Bit(ui5r_MSBisSet(dstvalue)) */;
+			/* if cnt != 0, always false */
+		VFLG = 0;
+		V_regs.LazyXFlagKind = kLazyFlagsDefault;
+		V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+		ArgSetDstValue(dstvalue);
+	}
+}
+
+LOCALIPROC DoCodeLsrW(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+#if WantCloserCyc
+	V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else if (cnt > 32) {
+		DoCodeOverShift();
+	} else {
+		dstvalue = ui5r_FromUWord(dstvalue);
+		dstvalue = dstvalue >> (cnt - 1);
+		CFLG = XFLG = (dstvalue & 1);
+		dstvalue = dstvalue >> 1;
+		ZFLG = Bool2Bit(dstvalue == 0);
+		NFLG = 0 /* Bool2Bit(ui5r_MSBisSet(dstvalue)) */;
+			/* if cnt != 0, always false */
+		VFLG = 0;
+		V_regs.LazyXFlagKind = kLazyFlagsDefault;
+		V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+		ArgSetDstValue(dstvalue);
+	}
+}
+
+LOCALIPROC DoCodeLsrL(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+#if WantCloserCyc
+	V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else if (cnt > 32) {
+		DoCodeOverShift();
+	} else {
+		dstvalue = ui5r_FromULong(dstvalue);
+		dstvalue = dstvalue >> (cnt - 1);
+		CFLG = XFLG = (dstvalue & 1);
+		dstvalue = dstvalue >> 1;
+		ZFLG = Bool2Bit(dstvalue == 0);
+		NFLG = 0 /* Bool2Bit(ui5r_MSBisSet(dstvalue)) */;
+			/* if cnt != 0, always false */
+		VFLG = 0;
+		V_regs.LazyXFlagKind = kLazyFlagsDefault;
+		V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+		ArgSetDstValue(dstvalue);
+	}
+}
+
+LOCALFUNC ui5r DecodeGetSrcSetDstValueDfltFlags_nm(void)
+{
+	NeedDefaultLazyAllFlags();
+
+	return DecodeGetSrcSetDstValue();
+}
+
+LOCALPROC my_reg_call DoCodeNullXShift(ui5r dstvalue)
+{
+	CFLG = XFLG;
+
+	ZFLG = Bool2Bit(dstvalue == 0);
+	NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+	VFLG = 0;
+
+	ArgSetDstValue(dstvalue);
+}
+
+LOCALIPROC DoCodeRxlB(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+	if (0 == cnt) {
+		DoCodeNullXShift(dstvalue);
+	} else {
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+		for (; cnt; --cnt) {
+			CFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+			dstvalue = (dstvalue << 1) | XFLG;
+			dstvalue = ui5r_FromSByte(dstvalue);
+			XFLG = CFLG;
+		}
+
+		ZFLG = Bool2Bit(dstvalue == 0);
+		NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+		VFLG = 0;
+
+		ArgSetDstValue(dstvalue);
+	}
+}
+
+LOCALIPROC DoCodeRxlW(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+	if (0 == cnt) {
+		DoCodeNullXShift(dstvalue);
+	} else {
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+		for (; cnt; --cnt) {
+			CFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+			dstvalue = (dstvalue << 1) | XFLG;
+			dstvalue = ui5r_FromSWord(dstvalue);
+			XFLG = CFLG;
+		}
+
+		ZFLG = Bool2Bit(dstvalue == 0);
+		NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+		VFLG = 0;
+
+		ArgSetDstValue(dstvalue);
+	}
+}
+
+LOCALIPROC DoCodeRxlL(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+	if (0 == cnt) {
+		DoCodeNullXShift(dstvalue);
+	} else {
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+		for (; cnt; --cnt) {
+			CFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+			dstvalue = (dstvalue << 1) | XFLG;
+			dstvalue = ui5r_FromSLong(dstvalue);
+			XFLG = CFLG;
+		}
+
+		ZFLG = Bool2Bit(dstvalue == 0);
+		NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+		VFLG = 0;
+
+		ArgSetDstValue(dstvalue);
+	}
+}
+
+LOCALIPROC DoCodeRxrB(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+	if (0 == cnt) {
+		DoCodeNullXShift(dstvalue);
+	} else {
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+		dstvalue = ui5r_FromUByte(dstvalue);
+		for (; cnt; --cnt) {
+			CFLG = dstvalue & 1;
+			dstvalue = (dstvalue >> 1) | (((ui5r)XFLG) << 7);
+			XFLG = CFLG;
+		}
+		dstvalue = ui5r_FromSByte(dstvalue);
+
+		ZFLG = Bool2Bit(dstvalue == 0);
+		NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+		VFLG = 0;
+
+		ArgSetDstValue(dstvalue);
+	}
+}
+
+LOCALIPROC DoCodeRxrW(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+	if (0 == cnt) {
+		DoCodeNullXShift(dstvalue);
+	} else {
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+		dstvalue = ui5r_FromUWord(dstvalue);
+		for (; cnt; --cnt) {
+			CFLG = dstvalue & 1;
+			dstvalue = (dstvalue >> 1) | (((ui5r)XFLG) << 15);
+			XFLG = CFLG;
+		}
+		dstvalue = ui5r_FromSWord(dstvalue);
+
+		ZFLG = Bool2Bit(dstvalue == 0);
+		NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+		VFLG = 0;
+
+		ArgSetDstValue(dstvalue);
+	}
+}
+
+LOCALIPROC DoCodeRxrL(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+	if (0 == cnt) {
+		DoCodeNullXShift(dstvalue);
+	} else {
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+		dstvalue = ui5r_FromULong(dstvalue);
+		for (; cnt; --cnt) {
+			CFLG = dstvalue & 1;
+			dstvalue = (dstvalue >> 1) | (((ui5r)XFLG) << 31);
+			XFLG = CFLG;
+		}
+		dstvalue = ui5r_FromSLong(dstvalue);
+
+		ZFLG = Bool2Bit(dstvalue == 0);
+		NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+		VFLG = 0;
+
+		ArgSetDstValue(dstvalue);
+	}
+}
+
+LOCALIPROC DoCodeRolB(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+#if WantCloserCyc
+	V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else {
+		cnt &= 7;
+		if (0 != cnt) {
+			ui3b dst = (ui3b)dstvalue;
+
+			dst = (dst >> (8 - cnt))
+					| ((dst & ((1 << (8 - cnt)) - 1))
+						<< cnt);
+
+			dstvalue = (ui5r)(si5r)(si3b)dst;
+		}
+		ZFLG = Bool2Bit(dstvalue == 0);
+		NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+		VFLG = 0;
+		CFLG = (dstvalue & 1);
+		V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+		ArgSetDstValue(dstvalue);
+	}
+}
+
+LOCALIPROC DoCodeRolW(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+#if WantCloserCyc
+	V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else {
+		cnt &= 15;
+		if (0 != cnt) {
+			ui4b dst = (ui4b)dstvalue;
+
+			dst = (dst >> (16 - cnt))
+					| ((dst & ((1 << (16 - cnt)) - 1))
+						<< cnt);
+
+			dstvalue = (ui5r)(si5r)(si4b)dst;
+		}
+		ZFLG = Bool2Bit(dstvalue == 0);
+		NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+		VFLG = 0;
+		CFLG = (dstvalue & 1);
+		V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+		ArgSetDstValue(dstvalue);
+	}
+}
+
+LOCALIPROC DoCodeRolL(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+#if WantCloserCyc
+	V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else {
+		cnt &= 31;
+		if (0 != cnt) {
+			ui5b dst = (ui5b)dstvalue;
+
+			dst = (dst >> (32 - cnt))
+					| ((dst & ((1 << (32 - cnt)) - 1))
+						<< cnt);
+
+			dstvalue = (ui5r)(si5r)(si5b)dst;
+		}
+		ZFLG = Bool2Bit(dstvalue == 0);
+		NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+		VFLG = 0;
+		CFLG = (dstvalue & 1);
+		V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+		ArgSetDstValue(dstvalue);
+	}
+}
+
+LOCALIPROC DoCodeRorB(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+#if WantCloserCyc
+	V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else {
+		cnt &= 7;
+		if (0 != cnt) {
+			ui3b dst = (ui3b)dstvalue;
+
+			dst = (dst >> cnt)
+					| ((dst & ((1 << cnt) - 1))
+						<< (8 - cnt));
+
+			dstvalue = (ui5r)(si5r)(si3b)dst;
+		}
+		ZFLG = Bool2Bit(dstvalue == 0);
+		NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+		VFLG = 0;
+		CFLG = NFLG;
+
+		V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+		ArgSetDstValue(dstvalue);
+	}
+}
+
+LOCALIPROC DoCodeRorW(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+#if WantCloserCyc
+	V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else {
+		cnt &= 15;
+		if (0 != cnt) {
+			ui4b dst = (ui4b)dstvalue;
+
+			dst = (dst >> cnt)
+					| ((dst & ((1 << cnt) - 1))
+						<< (16 - cnt));
+
+			dstvalue = (ui5r)(si5r)(si4b)dst;
+		}
+		ZFLG = Bool2Bit(dstvalue == 0);
+		NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+		VFLG = 0;
+		CFLG = NFLG;
+
+		V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+		ArgSetDstValue(dstvalue);
+	}
+}
+
+LOCALIPROC DoCodeRorL(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+	ui5r cnt = V_regs.SrcVal & 63;
+
+#if WantCloserCyc
+	V_MaxCyclesToGo -= (cnt * 2 * kCycleScale);
+#endif
+
+	if (0 == cnt) {
+		DoCodeNullShift(dstvalue);
+	} else {
+		cnt &= 31;
+		if (0 != cnt) {
+			ui5b dst = (ui5b)dstvalue;
+
+			dst = (dst >> cnt)
+					| ((dst & ((1 << cnt) - 1))
+						<< (32 - cnt));
+
+			dstvalue = (ui5r)(si5r)(si5b)dst;
+		}
+		ZFLG = Bool2Bit(dstvalue == 0);
+		NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+		VFLG = 0;
+		CFLG = NFLG;
+
+		V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+		ArgSetDstValue(dstvalue);
+	}
+}
+
+
+#if UseLazyZ
+LOCALPROC WillSetZFLG(void)
+{
+	if (kLazyFlagsZSet == V_regs.LazyFlagKind) {
+		/* ok */
+	} else if (kLazyFlagsDefault == V_regs.LazyFlagKind) {
+		/* also ok */
+	} else {
+		V_regs.LazyFlagZSavedKind = V_regs.LazyFlagKind;
+		V_regs.LazyFlagKind = kLazyFlagsZSet;
+	}
+}
+#else
+#define WillSetZFLG NeedDefaultLazyAllFlags
+#endif
+
+LOCALINLINEFUNC ui5r DecodeGetSrcGetDstValueSetZ(void)
+{
+	WillSetZFLG();
+
+	return DecodeGetSrcSetDstValue();
+}
+
+LOCALIPROC DoCodeBTstB(void)
+{
+	ui5r dstvalue = DecodeGetSrcGetDstValueSetZ();
+	ui5r srcvalue = V_regs.SrcVal & 7;
+
+	ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1;
+}
+
+LOCALIPROC DoCodeBTstL(void)
+{
+	ui5r dstvalue = DecodeGetSrcGetDstValueSetZ();
+	ui5r srcvalue = V_regs.SrcVal & 31;
+
+	ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1;
+}
+
+LOCALINLINEFUNC ui5r DecodeGetSrcSetDstValueSetZ(void)
+{
+	WillSetZFLG();
+
+	return DecodeGetSrcSetDstValue();
+}
+
+LOCALIPROC DoCodeBChgB(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValueSetZ();
+	ui5r srcvalue = V_regs.SrcVal & 7;
+
+	ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1;
+
+	dstvalue ^= (1 << srcvalue);
+	ArgSetDstValue(dstvalue);
+}
+
+LOCALIPROC DoCodeBChgL(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValueSetZ();
+	ui5r srcvalue = V_regs.SrcVal & 31;
+
+	ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1;
+
+	dstvalue ^= (1 << srcvalue);
+	ArgSetDstValue(dstvalue);
+}
+
+LOCALIPROC DoCodeBClrB(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValueSetZ();
+	ui5r srcvalue = V_regs.SrcVal & 7;
+
+	ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1;
+
+	dstvalue &= ~ (1 << srcvalue);
+	ArgSetDstValue(dstvalue);
+}
+
+LOCALIPROC DoCodeBClrL(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValueSetZ();
+	ui5r srcvalue = V_regs.SrcVal & 31;
+
+	ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1;
+
+	dstvalue &= ~ (1 << srcvalue);
+	ArgSetDstValue(dstvalue);
+}
+
+LOCALIPROC DoCodeBSetB(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValueSetZ();
+	ui5r srcvalue = V_regs.SrcVal & 7;
+
+	ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1;
+
+	dstvalue |= (1 << srcvalue);
+	ArgSetDstValue(dstvalue);
+}
+
+LOCALIPROC DoCodeBSetL(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValueSetZ();
+	ui5r srcvalue = V_regs.SrcVal & 31;
+
+	ZFLG = ((dstvalue >> srcvalue) ^ 1) & 1;
+
+	dstvalue |= (1 << srcvalue);
+	ArgSetDstValue(dstvalue);
+}
+
+LOCALIPROC DoCodeAnd(void)
+{
+	/* DoBinOpAnd(DecodeI_xxxxxxxxssmmmrrr()); */
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+
+	dstvalue &= V_regs.SrcVal;
+		/*
+			don't need to extend, since excess high
+			bits all the same as desired high bit.
+		*/
+
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	ArgSetDstValue(dstvalue);
+}
+
+LOCALIPROC DoCodeOr(void)
+{
+	/* DoBinOr(DecodeI_xxxxxxxxssmmmrrr()); */
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+
+	dstvalue |= V_regs.SrcVal;
+		/*
+			don't need to extend, since excess high
+			bits all the same as desired high bit.
+		*/
+
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	ArgSetDstValue(dstvalue);
+}
+
+LOCALIPROC DoCodeEor(void)
+{
+	/* Eor 1011ddd1ssmmmrrr */
+	/* DoBinOpEor(DecodeDEa_xxxxdddxssmmmrrr()); */
+	ui5r dstvalue = DecodeGetSrcSetDstValue();
+
+	dstvalue ^= V_regs.SrcVal;
+		/*
+			don't need to extend, since excess high
+			bits all the same as desired high bit.
+		*/
+
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	ArgSetDstValue(dstvalue);
+}
+
+LOCALIPROC DoCodeNot(void)
+{
+	/* Not 01000110ssmmmrrr */
+	ui5r dstvalue = DecodeGetSetDstValue();
+
+	dstvalue = ~ dstvalue;
+
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	ArgSetDstValue(dstvalue);
+}
+
+LOCALPROC DoCodeScc_t(void)
+{
+#if WantCloserCyc
+	if (kAMdRegB == V_regs.CurDecOpY.v[1].AMd) {
+		V_MaxCyclesToGo -= (2 * kCycleScale);
+	}
+#endif
+	DecodeSetDstValue(0xff);
+}
+
+LOCALPROC DoCodeScc_f(void)
+{
+	DecodeSetDstValue(0);
+}
+
+LOCALIPROC DoCodeScc(void)
+{
+	/* Scc 0101cccc11mmmrrr */
+	cctrue(DoCodeScc_t, DoCodeScc_f);
+}
+
+LOCALIPROC DoCodeEXTL(void)
+{
+	/* EXT.L */
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+	ui5r dstvalue = ui5r_FromSWord(*dstp);
+
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	*dstp = dstvalue;
+}
+
+LOCALIPROC DoCodeEXTW(void)
+{
+	/* EXT.W */
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+	ui5r dstvalue = ui5r_FromSByte(*dstp);
+
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+#if LittleEndianUnaligned
+	*(ui4b *)dstp = dstvalue;
+#else
+	*dstp = (*dstp & ~ 0xffff) | (dstvalue & 0xffff);
+#endif
+}
+
+LOCALIPROC DoCodeNegB(void)
+{
+	ui5r dstvalue = DecodeGetSetDstValue();
+	ui5r result = ui5r_FromSByte(0 - dstvalue);
+
+	V_regs.LazyFlagKind = kLazyFlagsNegB;
+	V_regs.LazyFlagArgDst = dstvalue;
+	V_regs.LazyXFlagKind = kLazyFlagsNegB;
+	V_regs.LazyXFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	ArgSetDstValue(result);
+}
+
+LOCALIPROC DoCodeNegW(void)
+{
+	ui5r dstvalue = DecodeGetSetDstValue();
+	ui5r result = ui5r_FromSWord(0 - dstvalue);
+
+	V_regs.LazyFlagKind = kLazyFlagsNegW;
+	V_regs.LazyFlagArgDst = dstvalue;
+	V_regs.LazyXFlagKind = kLazyFlagsNegW;
+	V_regs.LazyXFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	ArgSetDstValue(result);
+}
+
+LOCALIPROC DoCodeNegL(void)
+{
+	ui5r dstvalue = DecodeGetSetDstValue();
+	ui5r result = ui5r_FromSLong(0 - dstvalue);
+
+	V_regs.LazyFlagKind = kLazyFlagsNegL;
+	V_regs.LazyFlagArgDst = dstvalue;
+	V_regs.LazyXFlagKind = kLazyFlagsNegL;
+	V_regs.LazyXFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	ArgSetDstValue(result);
+}
+
+LOCALPROC my_reg_call SetCCRforNegX(ui5r dstvalue, ui5r result)
+{
+	ZFLG &= Bool2Bit(result == 0);
+
+	{
+		flagtype flgs = Bool2Bit(ui5r_MSBisSet(dstvalue));
+		flagtype flgn = Bool2Bit(ui5r_MSBisSet(result));
+
+		NFLG = flgn;
+		VFLG = flgs & flgn;
+		XFLG = CFLG = flgs | flgn;
+	}
+
+	ArgSetDstValue(result);
+}
+
+LOCALIPROC DoCodeNegXB(void)
+{
+	NeedDefaultLazyAllFlags();
+
+	{
+		ui5r dstvalue = DecodeGetSetDstValue();
+		ui5r result = ui5r_FromSByte(0 - (XFLG + dstvalue));
+
+		SetCCRforNegX(dstvalue, result);
+	}
+}
+
+LOCALIPROC DoCodeNegXW(void)
+{
+	if ((kLazyFlagsDefault != V_regs.LazyFlagKind)
+		|| (kLazyFlagsDefault != V_regs.LazyXFlagKind))
+	{
+		NeedDefaultLazyAllFlags();
+	}
+
+	{
+		ui5r dstvalue = DecodeGetSetDstValue();
+		ui5r result = ui5r_FromSWord(0 - (XFLG + dstvalue));
+
+		SetCCRforNegX(dstvalue, result);
+	}
+}
+
+LOCALIPROC DoCodeNegXL(void)
+{
+	if (kLazyFlagsNegL == V_regs.LazyFlagKind) {
+		NeedDefaultLazyFlagsNegL();
+	} else
+	if ((kLazyFlagsDefault == V_regs.LazyFlagKind)
+		&& (kLazyFlagsDefault == V_regs.LazyXFlagKind))
+	{
+		/* ok */
+	} else
+	{
+		NeedDefaultLazyAllFlags();
+	}
+
+	{
+		ui5r dstvalue = DecodeGetSetDstValue();
+		ui5r result = ui5r_FromSLong(0 - (XFLG + dstvalue));
+
+		SetCCRforNegX(dstvalue, result);
+	}
+}
+
+LOCALIPROC DoCodeMulU(void)
+{
+	/* MulU 1100ddd011mmmrrr */
+	ui5r srcvalue = DecodeGetSrcValue();
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+	ui5r dstvalue = *dstp;
+
+	dstvalue = ui5r_FromSLong(ui5r_FromUWord(dstvalue)
+		* ui5r_FromUWord(srcvalue));
+#if WantCloserCyc
+	{
+		ui5r v = srcvalue;
+
+		while (v != 0) {
+			if ((v & 1) != 0) {
+				V_MaxCyclesToGo -= (2 * kCycleScale);
+			}
+			v >>= 1;
+		}
+	}
+#endif
+
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	*dstp = dstvalue;
+}
+
+LOCALIPROC DoCodeMulS(void)
+{
+	/* MulS 1100ddd111mmmrrr */
+	ui5r srcvalue = DecodeGetSrcValue();
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+	ui5r dstvalue = *dstp;
+
+	dstvalue = ui5r_FromSLong((si5b)(si4b)dstvalue
+		* (si5b)(si4b)srcvalue);
+#if WantCloserCyc
+	{
+		ui5r v = (srcvalue << 1);
+
+		while (v != 0) {
+			if ((v & 1) != ((v >> 1) & 1)) {
+				V_MaxCyclesToGo -= (2 * kCycleScale);
+			}
+			v >>= 1;
+		}
+	}
+#endif
+
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	*dstp = dstvalue;
+}
+
+LOCALIPROC DoCodeDivU(void)
+{
+	/* DivU 1000ddd011mmmrrr */
+	ui5r srcvalue = DecodeGetSrcValue();
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+	ui5r dstvalue = *dstp;
+
+	if (srcvalue == 0) {
+#if WantCloserCyc
+		V_MaxCyclesToGo -=
+			(38 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
+#endif
+		Exception(5);
+#if m68k_logExceptions
+		dbglog_WriteNote("*** zero devide exception");
+#endif
+	} else {
+		ui5b newv = (ui5b)dstvalue / (ui5b)(ui4b)srcvalue;
+		ui5b rem = (ui5b)dstvalue % (ui5b)(ui4b)srcvalue;
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (133 * kCycleScale);
+#endif
+		if (newv > 0xffff) {
+			NeedDefaultLazyAllFlags();
+
+			VFLG = NFLG = 1;
+			CFLG = 0;
+		} else {
+			VFLG = CFLG = 0;
+			ZFLG = Bool2Bit(((si4b)(newv)) == 0);
+			NFLG = Bool2Bit(((si4b)(newv)) < 0);
+
+			V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+			newv = (newv & 0xffff) | ((ui5b)rem << 16);
+			dstvalue = newv;
+		}
+	}
+
+	*dstp = dstvalue;
+}
+
+LOCALIPROC DoCodeDivS(void)
+{
+	/* DivS 1000ddd111mmmrrr */
+	ui5r srcvalue = DecodeGetSrcValue();
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+	ui5r dstvalue = *dstp;
+
+	if (srcvalue == 0) {
+#if WantCloserCyc
+		V_MaxCyclesToGo -=
+			(38 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
+#endif
+		Exception(5);
+#if m68k_logExceptions
+		dbglog_WriteNote("*** zero devide exception");
+#endif
+	} else {
+		si5b newv = (si5b)dstvalue / (si5b)(si4b)srcvalue;
+		ui4b rem = (si5b)dstvalue % (si5b)(si4b)srcvalue;
+#if WantCloserCyc
+		V_MaxCyclesToGo -= (150 * kCycleScale);
+#endif
+		if (((newv & 0xffff8000) != 0) &&
+			((newv & 0xffff8000) != 0xffff8000))
+		{
+			NeedDefaultLazyAllFlags();
+
+			VFLG = NFLG = 1;
+			CFLG = 0;
+		} else {
+			if (((si4b)rem < 0) != ((si5b)dstvalue < 0)) {
+				rem = - rem;
+			}
+			VFLG = CFLG = 0;
+			ZFLG = Bool2Bit(((si4b)(newv)) == 0);
+			NFLG = Bool2Bit(((si4b)(newv)) < 0);
+
+			V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+			newv = (newv & 0xffff) | ((ui5b)rem << 16);
+			dstvalue = newv;
+		}
+	}
+
+	*dstp = dstvalue;
+}
+
+LOCALIPROC DoCodeExg(void)
+{
+	/* Exg dd 1100ddd101000rrr, opsize = 4 */
+	/* Exg aa 1100ddd101001rrr, opsize = 4 */
+	/* Exg da 1100ddd110001rrr, opsize = 4 */
+
+	ui5r srcreg = V_regs.CurDecOpY.v[0].ArgDat;
+	ui5r *srcp = &V_regs.regs[srcreg];
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+	ui5r srcvalue = *srcp;
+
+	*srcp = *dstp;
+	*dstp = srcvalue;
+}
+
+LOCALIPROC DoCodeMoveEaCR(void)
+{
+	/* 0100010011mmmrrr */
+	m68k_setCR(DecodeGetDstValue());
+}
+
+LOCALPROC DoPrivilegeViolation(void)
+{
+#if WantCloserCyc
+	V_MaxCyclesToGo += GetDcoCycles(V_regs.CurDecOp);
+	V_MaxCyclesToGo -=
+		(34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
+#endif
+	BackupPC();
+	Exception(8);
+#if m68k_logExceptions
+	dbglog_WriteNote("*** Privilege Violation exception");
+#endif
+}
+
+LOCALIPROC DoCodeMoveSREa(void)
+{
+	/* Move from SR 0100000011mmmrrr */
+#if Use68020
+	if (0 == V_regs.s) {
+		DoPrivilegeViolation();
+	} else
+#endif
+	{
+		DecodeSetDstValue(m68k_getSR());
+	}
+}
+
+LOCALIPROC DoCodeMoveEaSR(void)
+{
+	/* 0100011011mmmrrr */
+	if (0 == V_regs.s) {
+		DoPrivilegeViolation();
+	} else {
+		m68k_setSR(DecodeGetDstValue());
+	}
+}
+
+LOCALIPROC DoCodeOrISR(void)
+{
+	if (0 == V_regs.s) {
+		DoPrivilegeViolation();
+	} else {
+		V_regs.SrcVal = nextiword_nm();
+
+		m68k_setSR(m68k_getSR() | V_regs.SrcVal);
+	}
+}
+
+LOCALIPROC DoCodeAndISR(void)
+{
+	if (0 == V_regs.s) {
+		DoPrivilegeViolation();
+	} else {
+		V_regs.SrcVal = nextiword_nm();
+
+		m68k_setSR(m68k_getSR() & V_regs.SrcVal);
+	}
+}
+
+LOCALIPROC DoCodeEorISR(void)
+{
+	if (0 == V_regs.s) {
+		DoPrivilegeViolation();
+	} else {
+		V_regs.SrcVal = nextiword_nm();
+
+		m68k_setSR(m68k_getSR() ^ V_regs.SrcVal);
+	}
+}
+
+LOCALIPROC DoCodeOrICCR(void)
+{
+	V_regs.SrcVal = nextiword_nm();
+
+	m68k_setCR(m68k_getCR() | V_regs.SrcVal);
+}
+
+LOCALIPROC DoCodeAndICCR(void)
+{
+	V_regs.SrcVal = nextiword_nm();
+
+	m68k_setCR(m68k_getCR() & V_regs.SrcVal);
+}
+
+LOCALIPROC DoCodeEorICCR(void)
+{
+	V_regs.SrcVal = nextiword_nm();
+
+	m68k_setCR(m68k_getCR() ^ V_regs.SrcVal);
+}
+
+LOCALIPROC DoCodeMOVEMApRW(void)
+{
+	/* MOVEM mem to reg 01001100110011rrr */
+	si4b z;
+	ui5r regmask = nextiword_nm();
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+	ui5r p = *dstp;
+
+	for (z = 0; z < 16; ++z) {
+		if ((regmask & (1 << z)) != 0) {
+#if WantCloserCyc
+			V_MaxCyclesToGo -= (4 * kCycleScale + RdAvgXtraCyc);
+#endif
+			V_regs.regs[z] = get_word(p);
+			p += 2;
+		}
+	}
+	*dstp = p;
+}
+
+LOCALIPROC DoCodeMOVEMRmMW(void)
+{
+	/* MOVEM reg to mem 01001000110100rrr */
+	si4b z;
+	ui5r regmask = nextiword_nm();
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+	ui5r p = *dstp;
+
+#if Use68020
+	{
+		int n = 0;
+
+		for (z = 0; z < 16; ++z) {
+			if ((regmask & (1 << z)) != 0) {
+				n++;
+			}
+		}
+		*dstp = p - n * 2;
+	}
+#endif
+	for (z = 16; --z >= 0; ) {
+		if ((regmask & (1 << (15 - z))) != 0) {
+#if WantCloserCyc
+			V_MaxCyclesToGo -= (4 * kCycleScale + WrAvgXtraCyc);
+#endif
+			p -= 2;
+			put_word(p, V_regs.regs[z]);
+		}
+	}
+#if ! Use68020
+	*dstp = p;
+#endif
+}
+
+LOCALIPROC DoCodeMOVEMrmW(void)
+{
+	/* MOVEM reg to mem 010010001ssmmmrrr */
+	si4b z;
+	ui5r regmask = nextiword_nm();
+	ui5r p = DecodeDst();
+
+	for (z = 0; z < 16; ++z) {
+		if ((regmask & (1 << z)) != 0) {
+#if WantCloserCyc
+			V_MaxCyclesToGo -=
+				(4 * kCycleScale + WrAvgXtraCyc);
+#endif
+			put_word(p, V_regs.regs[z]);
+			p += 2;
+		}
+	}
+}
+
+LOCALIPROC DoCodeMOVEMrmL(void)
+{
+	/* MOVEM reg to mem 010010001ssmmmrrr */
+	si4b z;
+	ui5r regmask = nextiword_nm();
+	ui5r p = DecodeDst();
+
+	for (z = 0; z < 16; ++z) {
+		if ((regmask & (1 << z)) != 0) {
+#if WantCloserCyc
+			V_MaxCyclesToGo -=
+				(8 * kCycleScale + 2 * WrAvgXtraCyc);
+#endif
+			put_long(p, V_regs.regs[z]);
+			p += 4;
+		}
+	}
+}
+
+LOCALIPROC DoCodeMOVEMmrW(void)
+{
+	/* MOVEM mem to reg 0100110011smmmrrr */
+	si4b z;
+	ui5r regmask = nextiword_nm();
+	ui5r p = DecodeDst();
+
+	for (z = 0; z < 16; ++z) {
+		if ((regmask & (1 << z)) != 0) {
+#if WantCloserCyc
+			V_MaxCyclesToGo -=
+				(4 * kCycleScale + RdAvgXtraCyc);
+#endif
+			V_regs.regs[z] = get_word(p);
+			p += 2;
+		}
+	}
+}
+
+LOCALIPROC DoCodeMOVEMmrL(void)
+{
+	/* MOVEM mem to reg 0100110011smmmrrr */
+	si4b z;
+	ui5r regmask = nextiword_nm();
+	ui5r p = DecodeDst();
+
+	for (z = 0; z < 16; ++z) {
+		if ((regmask & (1 << z)) != 0) {
+#if WantCloserCyc
+			V_MaxCyclesToGo -=
+				(8 * kCycleScale + 2 * RdAvgXtraCyc);
+#endif
+			V_regs.regs[z] = get_long(p);
+			p += 4;
+		}
+	}
+}
+
+LOCALIPROC DoCodeAbcd(void)
+{
+	/* ABCD r 1100ddd100000rrr */
+	/* ABCD m 1100ddd100001rrr */
+
+	ui5r dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm();
+	ui5r srcvalue = V_regs.SrcVal;
+
+	{
+		/* if (V_regs.opsize != 1) a bug */
+		int flgs = ui5r_MSBisSet(srcvalue);
+		int flgo = ui5r_MSBisSet(dstvalue);
+		ui4b newv_lo =
+			(srcvalue & 0xF) + (dstvalue & 0xF) + XFLG;
+		ui4b newv_hi = (srcvalue & 0xF0) + (dstvalue & 0xF0);
+		ui4b newv;
+
+		if (newv_lo > 9) {
+			newv_lo += 6;
+		}
+		newv = newv_hi + newv_lo;
+		CFLG = XFLG = Bool2Bit((newv & 0x1F0) > 0x90);
+		if (CFLG != 0) {
+			newv += 0x60;
+		}
+		dstvalue = ui5r_FromSByte(newv);
+		if (dstvalue != 0) {
+			ZFLG = 0;
+		}
+		NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+		VFLG = Bool2Bit((flgs != flgo) && ((NFLG != 0) != flgo));
+		/*
+			but according to my reference book,
+			VFLG is Undefined for ABCD
+		*/
+	}
+
+	ArgSetDstValue(dstvalue);
+}
+
+LOCALIPROC DoCodeSbcd(void)
+{
+	ui5r dstvalue = DecodeGetSrcSetDstValueDfltFlags_nm();
+	ui5r srcvalue = V_regs.SrcVal;
+
+	{
+		int flgs = ui5r_MSBisSet(srcvalue);
+		int flgo = ui5r_MSBisSet(dstvalue);
+		ui4b newv_lo =
+			(dstvalue & 0xF) - (srcvalue & 0xF) - XFLG;
+		ui4b newv_hi = (dstvalue & 0xF0) - (srcvalue & 0xF0);
+		ui4b newv;
+
+		if (newv_lo > 9) {
+			newv_lo -= 6;
+			newv_hi -= 0x10;
+		}
+		newv = newv_hi + (newv_lo & 0xF);
+		CFLG = XFLG = Bool2Bit((newv_hi & 0x1F0) > 0x90);
+		if (CFLG != 0) {
+			newv -= 0x60;
+		}
+		dstvalue = ui5r_FromSByte(newv);
+		if (dstvalue != 0) {
+			ZFLG = 0;
+		}
+		NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+		VFLG = Bool2Bit((flgs != flgo) && ((NFLG != 0) != flgo));
+		/*
+			but according to my reference book,
+			VFLG is Undefined for SBCD
+		*/
+	}
+
+	ArgSetDstValue(dstvalue);
+}
+
+LOCALIPROC DoCodeNbcd(void)
+{
+	/* Nbcd 0100100000mmmrrr */
+	ui5r dstvalue = DecodeGetSetDstValue();
+
+	NeedDefaultLazyAllFlags();
+
+	{
+		ui4b newv_lo = - (dstvalue & 0xF) - XFLG;
+		ui4b newv_hi = - (dstvalue & 0xF0);
+		ui4b newv;
+
+		if (newv_lo > 9) {
+			newv_lo -= 6;
+			newv_hi -= 0x10;
+		}
+		newv = newv_hi + (newv_lo & 0xF);
+		CFLG = XFLG = Bool2Bit((newv_hi & 0x1F0) > 0x90);
+		if (CFLG != 0) {
+			newv -= 0x60;
+		}
+
+		dstvalue = ui5r_FromSByte(newv);
+		NFLG = Bool2Bit(ui5r_MSBisSet(dstvalue));
+		if (dstvalue != 0) {
+			ZFLG = 0;
+		}
+	}
+
+	ArgSetDstValue(dstvalue);
+}
+
+LOCALIPROC DoCodeRte(void)
+{
+	/* Rte 0100111001110011 */
+	if (0 == V_regs.s) {
+		DoPrivilegeViolation();
+	} else {
+		ui5r NewPC;
+		CPTR stackp = m68k_areg(7);
+		ui5r NewSR = get_word(stackp);
+		stackp += 2;
+		NewPC = get_long(stackp);
+		stackp += 4;
+
+#if Use68020
+		{
+			ui4b format = get_word(stackp);
+			stackp += 2;
+
+			switch ((format >> 12) & 0x0F) {
+				case 0:
+					/* ReportAbnormal("rte stack frame format 0"); */
+					break;
+				case 1:
+					ReportAbnormalID(0x0107,
+						"rte stack frame format 1");
+					NewPC = m68k_getpc() - 2;
+						/* rerun instruction */
+					break;
+				case 2:
+					ReportAbnormalID(0x0108,
+						"rte stack frame format 2");
+					stackp += 4;
+					break;
+				case 9:
+					ReportAbnormalID(0x0109,
+						"rte stack frame format 9");
+					stackp += 12;
+					break;
+				case 10:
+					ReportAbnormalID(0x010A,
+						"rte stack frame format 10");
+					stackp += 24;
+					break;
+				case 11:
+					ReportAbnormalID(0x010B,
+						"rte stack frame format 11");
+					stackp += 84;
+					break;
+				default:
+					ReportAbnormalID(0x010C,
+						"unknown rte stack frame format");
+					Exception(14);
+					return;
+					break;
+			}
+		}
+#endif
+		m68k_areg(7) = stackp;
+		m68k_setSR(NewSR);
+		m68k_setpc(NewPC);
+	}
+}
+
+LOCALIPROC DoCodeNop(void)
+{
+	/* Nop 0100111001110001 */
+}
+
+LOCALIPROC DoCodeMoveP0(void)
+{
+	/* MoveP 0000ddd1mm001aaa */
+	ui5r srcreg = V_regs.CurDecOpY.v[0].ArgDat;
+	ui5r *srcp = &V_regs.regs[srcreg];
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+
+	ui5r Displacement = nextiword_nm();
+		/* shouldn't this sign extend ? */
+	CPTR memp = *srcp + Displacement;
+
+	ui4b val = ((get_byte(memp) & 0x00FF) << 8)
+		| (get_byte(memp + 2) & 0x00FF);
+
+	*dstp =
+		(*dstp & ~ 0xffff) | (val & 0xffff);
+
+#if 0
+	if ((Displacement & 0x00008000) != 0) {
+		/* **** for testing only **** */
+		BackupPC();
+		op_illg();
+	}
+#endif
+}
+
+LOCALIPROC DoCodeMoveP1(void)
+{
+	/* MoveP 0000ddd1mm001aaa */
+	ui5r srcreg = V_regs.CurDecOpY.v[0].ArgDat;
+	ui5r *srcp = &V_regs.regs[srcreg];
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+
+	ui5r Displacement = nextiword_nm();
+		/* shouldn't this sign extend ? */
+	CPTR memp = *srcp + Displacement;
+
+	ui5b val = ((get_byte(memp) & 0x00FF) << 24)
+		| ((get_byte(memp + 2) & 0x00FF) << 16)
+		| ((get_byte(memp + 4) & 0x00FF) << 8)
+		| (get_byte(memp + 6) & 0x00FF);
+
+	*dstp = val;
+}
+
+LOCALIPROC DoCodeMoveP2(void)
+{
+	/* MoveP 0000ddd1mm001aaa */
+	ui5r srcreg = V_regs.CurDecOpY.v[0].ArgDat;
+	ui5r *srcp = &V_regs.regs[srcreg];
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+
+	ui5r Displacement = nextiword_nm();
+		/* shouldn't this sign extend ? */
+	CPTR memp = *srcp + Displacement;
+
+	si4b val = *dstp;
+
+	put_byte(memp, val >> 8);
+	put_byte(memp + 2, val);
+}
+
+LOCALIPROC DoCodeMoveP3(void)
+{
+	/* MoveP 0000ddd1mm001aaa */
+	ui5r srcreg = V_regs.CurDecOpY.v[0].ArgDat;
+	ui5r *srcp = &V_regs.regs[srcreg];
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+
+	ui5r Displacement = nextiword_nm();
+		/* shouldn't this sign extend ? */
+	CPTR memp = *srcp + Displacement;
+
+	si5b val = *dstp;
+
+	put_byte(memp, val >> 24);
+	put_byte(memp + 2, val >> 16);
+	put_byte(memp + 4, val >> 8);
+	put_byte(memp + 6, val);
+}
+
+LOCALPROC op_illg(void)
+{
+	BackupPC();
+	Exception(4);
+#if m68k_logExceptions
+	dbglog_WriteNote("*** illegal instruction exception");
+#endif
+}
+
+LOCALIPROC DoCodeChk(void)
+{
+	ui5r dstvalue = DecodeGetSrcGetDstValue();
+	ui5r srcvalue = V_regs.SrcVal;
+
+	if (ui5r_MSBisSet(srcvalue)) {
+		NeedDefaultLazyAllFlags();
+
+#if WantCloserCyc
+		V_MaxCyclesToGo -=
+			(30 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
+#endif
+		NFLG = 1;
+		Exception(6);
+	} else if (((si5r)srcvalue) > ((si5r)dstvalue)) {
+		NeedDefaultLazyAllFlags();
+
+#if WantCloserCyc
+		V_MaxCyclesToGo -=
+			(30 * kCycleScale + 3 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
+#endif
+		NFLG = 0;
+		Exception(6);
+	}
+}
+
+LOCALIPROC DoCodeTrap(void)
+{
+	/* Trap 010011100100vvvv */
+	Exception(V_regs.CurDecOpY.v[1].ArgDat);
+}
+
+LOCALIPROC DoCodeTrapV(void)
+{
+	/* TrapV 0100111001110110 */
+	NeedDefaultLazyAllFlags();
+
+	if (VFLG != 0) {
+#if WantCloserCyc
+		V_MaxCyclesToGo += GetDcoCycles(V_regs.CurDecOp);
+		V_MaxCyclesToGo -=
+			(34 * kCycleScale + 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
+#endif
+		Exception(7);
+	}
+}
+
+LOCALIPROC DoCodeRtr(void)
+{
+	/* Rtr 0100111001110111 */
+	ui5r NewPC;
+	CPTR stackp = m68k_areg(7);
+	ui5r NewCR = get_word(stackp);
+	stackp += 2;
+	NewPC = get_long(stackp);
+	stackp += 4;
+	m68k_areg(7) = stackp;
+	m68k_setCR(NewCR);
+	m68k_setpc(NewPC);
+}
+
+LOCALIPROC DoCodeLink(void)
+{
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+	CPTR stackp = m68k_areg(7);
+
+	stackp -= 4;
+	m68k_areg(7) = stackp; /* only matters if dstreg == 7 + 8 */
+	put_long(stackp, *dstp);
+	*dstp = stackp;
+	m68k_areg(7) += ui5r_FromSWord(nextiword_nm());
+}
+
+LOCALIPROC DoCodeUnlk(void)
+{
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+
+	if (dstreg != 7 + 8) {
+		ui5r src = *dstp;
+		*dstp = get_long(src);
+		m68k_areg(7) = src + 4;
+	} else {
+		/* wouldn't expect this to happen */
+		m68k_areg(7) = get_long(m68k_areg(7)) + 4;
+	}
+}
+
+LOCALIPROC DoCodeMoveRUSP(void)
+{
+	/* MOVE USP 0100111001100aaa */
+	if (0 == V_regs.s) {
+		DoPrivilegeViolation();
+	} else {
+		ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+		ui5r *dstp = &V_regs.regs[dstreg];
+
+		V_regs.usp = *dstp;
+	}
+}
+
+LOCALIPROC DoCodeMoveUSPR(void)
+{
+	/* MOVE USP 0100111001101aaa */
+	if (0 == V_regs.s) {
+		DoPrivilegeViolation();
+	} else {
+		ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+		ui5r *dstp = &V_regs.regs[dstreg];
+
+		*dstp = V_regs.usp;
+	}
+}
+
+LOCALIPROC DoCodeTas(void)
+{
+	/* Tas 0100101011mmmrrr */
+	ui5r dstvalue = DecodeGetSetDstValue();
+
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	dstvalue |= 0x80;
+
+	ArgSetDstValue(dstvalue);
+}
+
+LOCALIPROC DoCodeFdefault(void)
+{
+	BackupPC();
+	Exception(0xB);
+}
+
+LOCALPROC m68k_setstopped(void)
+{
+	/* not implemented. doesn't seemed to be used on Mac Plus */
+	Exception(4); /* fake an illegal instruction */
+#if m68k_logExceptions
+	dbglog_WriteNote("*** set stopped");
+#endif
+}
+
+LOCALIPROC DoCodeStop(void)
+{
+	/* Stop 0100111001110010 */
+	if (0 == V_regs.s) {
+		DoPrivilegeViolation();
+	} else {
+		m68k_setSR(nextiword_nm());
+		m68k_setstopped();
+	}
+}
+
+FORWARDPROC local_customreset(void);
+
+LOCALIPROC DoCodeReset(void)
+{
+	/* Reset 0100111001100000 */
+	if (0 == V_regs.s) {
+		DoPrivilegeViolation();
+	} else {
+		local_customreset();
+	}
+}
+
+#if Use68020
+LOCALIPROC DoCodeCallMorRtm(void)
+{
+	/* CALLM or RTM 0000011011mmmrrr */
+	ReportAbnormalID(0x010D, "CALLM or RTM instruction");
+}
+#endif
+
+#if Use68020
+LOCALIPROC DoCodeMoveCCREa(void)
+{
+	/* Move from CCR 0100001011mmmrrr */
+	DecodeSetDstValue(m68k_getCR());
+}
+#endif
+
+#if Use68020
+LOCALIPROC DoCodeBraL(void)
+{
+	/* Bra 0110ccccnnnnnnnn */
+	si5r offset = ((si5b)(ui5b)nextilong()) - 4;
+	ui3p s = V_pc_p + offset;
+
+	V_pc_p = s;
+
+#if USE_PCLIMIT
+	if (my_cond_rare(s >= V_pc_pHi)
+		|| my_cond_rare(s < V_regs.pc_pLo))
+	{
+		Recalc_PC_Block();
+	}
+#endif
+}
+#endif
+
+#if Use68020
+LOCALPROC SkipiLong(void)
+{
+	V_pc_p += 4;
+
+#if USE_PCLIMIT
+	if (my_cond_rare(V_pc_p >= V_pc_pHi)) {
+		Recalc_PC_Block();
+	}
+#endif
+}
+#endif
+
+#if Use68020
+LOCALIPROC DoCodeBccL(void)
+{
+	/* Bcc 0110ccccnnnnnnnn */
+	cctrue(DoCodeBraL, SkipiLong);
+}
+#endif
+
+#if Use68020
+LOCALIPROC DoCodeBsrL(void)
+{
+	si5r offset = ((si5b)(ui5b)nextilong()) - 4;
+	ui3p s = V_pc_p + offset;
+
+	m68k_areg(7) -= 4;
+	put_long(m68k_areg(7), m68k_getpc());
+	V_pc_p = s;
+
+#if USE_PCLIMIT
+	if (my_cond_rare(s >= V_pc_pHi)
+		|| my_cond_rare(s < V_regs.pc_pLo))
+	{
+		Recalc_PC_Block();
+	}
+#endif
+
+	/* ReportAbnormal("long branch in DoCode6"); */
+	/* Used by various Apps */
+}
+#endif
+
+#if Use68020
+LOCALIPROC DoCodeEXTBL(void)
+{
+	/* EXTB.L */
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+	ui5r dstvalue = ui5r_FromSByte(*dstp);
+
+	V_regs.LazyFlagKind = kLazyFlagsTstL;
+	V_regs.LazyFlagArgDst = dstvalue;
+
+	HaveSetUpFlags();
+
+	*dstp = dstvalue;
+}
+#endif
+
+#if Use68020
+LOCALPROC DoCHK2orCMP2(void)
+{
+	/* CHK2 or CMP2 00000ss011mmmrrr */
+	ui5r regv;
+	ui5r lower;
+	ui5r upper;
+	ui5r extra = nextiword_nm();
+	ui5r DstAddr = DecodeDst();
+	ui5r srcreg = (extra >> 12) & 0x0F;
+	ui5r *srcp = &V_regs.regs[srcreg];
+
+	/* ReportAbnormal("CHK2 or CMP2 instruction"); */
+	switch (V_regs.CurDecOpY.v[0].ArgDat) {
+		case 1:
+			if ((extra & 0x8000) == 0) {
+				regv = ui5r_FromSByte(*srcp);
+			} else {
+				regv = ui5r_FromSLong(*srcp);
+			}
+			lower = get_byte(DstAddr);
+			upper = get_byte(DstAddr + 1);
+			break;
+		case 2:
+			if ((extra & 0x8000) == 0) {
+				regv = ui5r_FromSWord(*srcp);
+			} else {
+				regv = ui5r_FromSLong(*srcp);
+			}
+			lower = get_word(DstAddr);
+			upper = get_word(DstAddr + 2);
+			break;
+		default:
+#if ExtraAbnormalReports
+			if (4 != V_regs.CurDecOpY.v[0].ArgDat) {
+				ReportAbnormalID(0x010E,
+					"illegal opsize in CHK2 or CMP2");
+			}
+#endif
+			if ((extra & 0x8000) == 0) {
+				regv = ui5r_FromSLong(*srcp);
+			} else {
+				regv = ui5r_FromSLong(*srcp);
+			}
+			lower = get_long(DstAddr);
+			upper = get_long(DstAddr + 4);
+			break;
+	}
+
+	NeedDefaultLazyAllFlags();
+
+	ZFLG = Bool2Bit((upper == regv) || (lower == regv));
+	CFLG = Bool2Bit((((si5r)lower) <= ((si5r)upper))
+			? (((si5r)regv) < ((si5r)lower)
+				|| ((si5r)regv) > ((si5r)upper))
+			: (((si5r)regv) > ((si5r)upper)
+				|| ((si5r)regv) < ((si5r)lower)));
+
+	if ((extra & 0x800) && (CFLG != 0)) {
+		Exception(6);
+	}
+}
+#endif
+
+#if Use68020
+LOCALPROC DoCAS(void)
+{
+	/* CAS 00001ss011mmmrrr */
+	ui5r srcvalue;
+	ui5r dstvalue;
+
+	ui4b src = nextiword_nm();
+	int ru = (src >> 6) & 7;
+	int rc = src & 7;
+
+	ReportAbnormalID(0x010F, "CAS instruction");
+	switch (V_regs.CurDecOpY.v[0].ArgDat) {
+		case 1:
+			srcvalue = ui5r_FromSByte(V_regs.regs[rc]);
+			break;
+		case 2:
+			srcvalue = ui5r_FromSWord(V_regs.regs[rc]);
+			break;
+		default:
+#if ExtraAbnormalReports
+			if (4 != V_regs.CurDecOpY.v[0].ArgDat) {
+				ReportAbnormalID(0x0110, "illegal opsize in DoCAS");
+			}
+#endif
+			srcvalue = ui5r_FromSLong(V_regs.regs[rc]);
+			break;
+	}
+	dstvalue = DecodeGetSetDstValue();
+
+	{
+		int flgs = ((si5b)srcvalue) < 0;
+		int flgo = ((si5b)dstvalue) < 0;
+		ui5r newv = dstvalue - srcvalue;
+		if (V_regs.CurDecOpY.v[0].ArgDat == 1) {
+			newv = ui5r_FromSByte(newv);
+		} else if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
+			newv = ui5r_FromSWord(newv);
+		} else {
+			newv = ui5r_FromSLong(newv);
+		}
+		ZFLG = Bool2Bit(((si5b)newv) == 0);
+		NFLG = Bool2Bit(((si5b)newv) < 0);
+		VFLG = Bool2Bit((flgs != flgo) && ((NFLG != 0) != flgo));
+		CFLG = Bool2Bit(
+			(flgs && ! flgo) || ((NFLG != 0) && ((! flgo) || flgs)));
+
+		V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+		if (ZFLG != 0) {
+			ArgSetDstValue(m68k_dreg(ru));
+		} else {
+			V_regs.ArgAddr.rga = &V_regs.regs[rc];
+
+			if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
+				*V_regs.ArgAddr.rga =
+					(*V_regs.ArgAddr.rga & ~ 0xffff)
+						| ((dstvalue) & 0xffff);
+			} else if (V_regs.CurDecOpY.v[0].ArgDat < 2) {
+				*V_regs.ArgAddr.rga =
+					(*V_regs.ArgAddr.rga & ~ 0xff)
+						| ((dstvalue) & 0xff);
+			} else {
+				*V_regs.ArgAddr.rga = dstvalue;
+			}
+		}
+	}
+}
+#endif
+
+#if Use68020
+LOCALPROC DoCAS2(void)
+{
+	/* CAS2 00001ss011111100 */
+	ui5b extra = nextilong();
+	int dc2 = extra & 7;
+	int du2 = (extra >> 6) & 7;
+	int dc1 = (extra >> 16) & 7;
+	int du1 = (extra >> 22) & 7;
+	CPTR rn1 = V_regs.regs[(extra >> 28) & 0x0F];
+	CPTR rn2 = V_regs.regs[(extra >> 12) & 0x0F];
+	si5b src = m68k_dreg(dc1);
+	si5r dst1;
+	si5r dst2;
+
+	ReportAbnormalID(0x0111, "DoCAS2 instruction");
+	if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
+		dst1 = get_word(rn1);
+		dst2 = get_word(rn2);
+		src = (si5b)(si4b)src;
+	} else {
+		dst1 = get_long(rn1);
+		dst2 = get_long(rn2);
+	}
+	{
+		int flgs = src < 0;
+		int flgo = dst1 < 0;
+		si5b newv = dst1 - src;
+		if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
+			newv = (ui4b)newv;
+		}
+		ZFLG = Bool2Bit(newv == 0);
+		NFLG = Bool2Bit(newv < 0);
+		VFLG = Bool2Bit((flgs != flgo) && ((NFLG != 0) != flgo));
+		CFLG = Bool2Bit(
+			(flgs && ! flgo) || ((NFLG != 0) && ((! flgo) || flgs)));
+
+		V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+		if (ZFLG != 0) {
+			src = m68k_dreg(dc2);
+			if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
+				src = (si5b)(si4b)src;
+			}
+			flgs = src < 0;
+			flgo = dst2 < 0;
+			newv = dst2 - src;
+			if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
+				newv = (ui4b)newv;
+			}
+			ZFLG = Bool2Bit(newv == 0);
+			NFLG = Bool2Bit(newv < 0);
+			VFLG = Bool2Bit((flgs != flgo) && ((NFLG != 0) != flgo));
+			CFLG = Bool2Bit((flgs && ! flgo)
+				|| ((NFLG != 0) && ((! flgo) || flgs)));
+
+			V_regs.LazyFlagKind = kLazyFlagsDefault;
+			if (ZFLG != 0) {
+				if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
+					put_word(rn1, m68k_dreg(du1));
+					put_word(rn2, m68k_dreg(du2));
+				} else {
+					put_word(rn1, m68k_dreg(du1));
+					put_word(rn2, m68k_dreg(du2));
+				}
+			}
+		}
+	}
+	if (ZFLG == 0) {
+		if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
+			m68k_dreg(du1) =
+				(m68k_dreg(du1) & ~ 0xffff) | ((ui5b)dst1 & 0xffff);
+			m68k_dreg(du2) =
+				(m68k_dreg(du2) & ~ 0xffff) | ((ui5b)dst2 & 0xffff);
+		} else {
+			m68k_dreg(du1) = dst1;
+			m68k_dreg(du2) = dst2;
+		}
+	}
+}
+#endif
+
+#if Use68020
+LOCALPROC DoMOVES(void)
+{
+	/* MoveS 00001110ssmmmrrr */
+	ReportAbnormalID(0x0112, "MoveS instruction");
+	if (0 == V_regs.s) {
+		DoPrivilegeViolation();
+	} else {
+		ui4b extra = nextiword_nm();
+		if (extra & 0x0800) {
+			ui5b src = V_regs.regs[(extra >> 12) & 0x0F];
+			DecodeSetDstValue(src);
+		} else {
+			ui5r srcvalue = DecodeGetDstValue();
+			ui5b rr = (extra >> 12) & 7;
+			if (extra & 0x8000) {
+				m68k_areg(rr) = srcvalue;
+			} else {
+				V_regs.ArgAddr.rga = &V_regs.regs[rr];
+
+				if (V_regs.CurDecOpY.v[0].ArgDat == 2) {
+					*V_regs.ArgAddr.rga =
+						(*V_regs.ArgAddr.rga & ~ 0xffff)
+							| ((srcvalue) & 0xffff);
+				} else if (V_regs.CurDecOpY.v[0].ArgDat < 2) {
+					*V_regs.ArgAddr.rga =
+						(*V_regs.ArgAddr.rga & ~ 0xff)
+							| ((srcvalue) & 0xff);
+				} else {
+					*V_regs.ArgAddr.rga = srcvalue;
+				}
+			}
+		}
+	}
+}
+#endif
+
+#define ui5b_lo(x) ((x) & 0x0000FFFF)
+#define ui5b_hi(x) (((x) >> 16) & 0x0000FFFF)
+
+#if Use68020
+struct ui6r0 {
+	ui5b hi;
+	ui5b lo;
+};
+typedef struct ui6r0 ui6r0;
+#endif
+
+#if Use68020
+LOCALPROC Ui6r_Negate(ui6r0 *v)
+{
+	v->hi = ~ v->hi;
+	v->lo = - v->lo;
+	if (v->lo == 0) {
+		v->hi++;
+	}
+}
+#endif
+
+#if Use68020
+LOCALFUNC blnr my_reg_call Ui6r_IsZero(ui6r0 *v)
+{
+	return (v->hi == 0) && (v->lo == 0);
+}
+#endif
+
+#if Use68020
+LOCALFUNC blnr my_reg_call Ui6r_IsNeg(ui6r0 *v)
+{
+	return ((si5b)v->hi) < 0;
+}
+#endif
+
+#if Use68020
+LOCALPROC mul_unsigned(ui5b src1, ui5b src2, ui6r0 *dst)
+{
+	ui5b src1_lo = ui5b_lo(src1);
+	ui5b src2_lo = ui5b_lo(src2);
+	ui5b src1_hi = ui5b_hi(src1);
+	ui5b src2_hi = ui5b_hi(src2);
+
+	ui5b r0 = src1_lo * src2_lo;
+	ui5b r1 = src1_hi * src2_lo;
+	ui5b r2 = src1_lo * src2_hi;
+	ui5b r3 = src1_hi * src2_hi;
+
+	ui5b ra1 = ui5b_hi(r0) + ui5b_lo(r1) + ui5b_lo(r2);
+
+	dst->lo = (ui5b_lo(ra1) << 16) | ui5b_lo(r0);
+	dst->hi = ui5b_hi(ra1) + ui5b_hi(r1) + ui5b_hi(r2) + r3;
+}
+#endif
+
+#if Use68020
+LOCALFUNC blnr div_unsigned(ui6r0 *src, ui5b div,
+	ui5b *quot, ui5b *rem)
+{
+	int i;
+	ui5b q = 0;
+	ui5b cbit = 0;
+	ui5b src_hi = src->hi;
+	ui5b src_lo = src->lo;
+
+	if (div <= src_hi) {
+		return trueblnr;
+	}
+	for (i = 0 ; i < 32 ; i++) {
+		cbit = src_hi & 0x80000000ul;
+		src_hi <<= 1;
+		if (src_lo & 0x80000000ul) {
+			src_hi++;
+		}
+		src_lo <<= 1;
+		q = q << 1;
+		if (cbit || div <= src_hi) {
+			q |= 1;
+			src_hi -= div;
+		}
+	}
+	*quot = q;
+	*rem = src_hi;
+	return falseblnr;
+}
+#endif
+
+#if Use68020
+LOCALIPROC DoCodeMulL(void)
+{
+	/* MULU 0100110000mmmrrr 0rrr0s0000000rrr */
+	/* MULS 0100110000mmmrrr 0rrr1s0000000rrr */
+	ui6r0 dst;
+	ui4b extra = nextiword();
+	ui5b r2 = (extra >> 12) & 7;
+	ui5b dstvalue = m68k_dreg(r2);
+	ui5r srcvalue = DecodeGetDstValue();
+
+	if (extra & 0x800) {
+		/* MULS.L - signed */
+
+		si5b src1 = (si5b)srcvalue;
+		si5b src2 = (si5b)dstvalue;
+		blnr s1 = src1 < 0;
+		blnr s2 = src2 < 0;
+		blnr sr = s1 != s2;
+
+		/* ReportAbnormal("MULS.L"); */
+		/* used by Sys 7.5.5 boot extensions */
+		if (s1) {
+			src1 = - src1;
+		}
+		if (s2) {
+			src2 = - src2;
+		}
+		mul_unsigned((ui5b)src1, (ui5b)src2, &dst);
+		if (sr) {
+			Ui6r_Negate(&dst);
+		}
+		VFLG = CFLG = 0;
+		ZFLG = Bool2Bit(Ui6r_IsZero(&dst));
+		NFLG = Bool2Bit(Ui6r_IsNeg(&dst));
+
+		V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+		if (extra & 0x400) {
+			m68k_dreg(extra & 7) = dst.hi;
+		} else {
+			if ((dst.lo & 0x80000000) != 0) {
+				if ((dst.hi & 0xffffffff) != 0xffffffff) {
+					VFLG = 1;
+				}
+			} else {
+				if (dst.hi != 0) {
+					VFLG = 1;
+				}
+			}
+		}
+	} else {
+		/* MULU.L - unsigned */
+
+		/* ReportAbnormal("MULU.U"); */
+		/* Used by various Apps */
+
+		mul_unsigned(srcvalue, dstvalue, &dst);
+
+		VFLG = CFLG = 0;
+		ZFLG = Bool2Bit(Ui6r_IsZero(&dst));
+		NFLG = Bool2Bit(Ui6r_IsNeg(&dst));
+
+		V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+		if (extra & 0x400) {
+			m68k_dreg(extra & 7) = dst.hi;
+		} else {
+			if (dst.hi != 0) {
+				VFLG = 1;
+			}
+		}
+	}
+	m68k_dreg(r2) = dst.lo;
+}
+#endif
+
+#if Use68020
+LOCALIPROC DoCodeDivL(void)
+{
+	/* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */
+	/* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */
+	/* ReportAbnormal("DIVS/DIVU long"); */
+	ui6r0 v2;
+	ui5b quot;
+	ui5b rem;
+	ui4b extra = nextiword();
+	ui5b rDr = extra & 7;
+	ui5b rDq = (extra >> 12) & 7;
+	ui5r src = (ui5b)(si5b)DecodeGetDstValue();
+
+	if (src == 0) {
+		Exception(5);
+#if m68k_logExceptions
+		dbglog_WriteNote("*** zero devide exception");
+#endif
+		return;
+	}
+	if (0 != (extra & 0x0800)) {
+		/* signed variant */
+		blnr sr;
+		blnr s2;
+		blnr s1 = ((si5b)src < 0);
+
+		v2.lo = (si5b)m68k_dreg(rDq);
+		if (extra & 0x0400) {
+			v2.hi = (si5b)m68k_dreg(rDr);
+		} else {
+			v2.hi = ((si5b)v2.lo) < 0 ? -1 : 0;
+		}
+		s2 = Ui6r_IsNeg(&v2);
+		sr = (s1 != s2);
+		if (s2) {
+			Ui6r_Negate(&v2);
+		}
+		if (s1) {
+			src = - src;
+		}
+		if (div_unsigned(&v2, src, &quot, &rem)
+			|| (sr ? quot > 0x80000000 : quot > 0x7fffffff))
+		{
+			NeedDefaultLazyAllFlags();
+
+			VFLG = NFLG = 1;
+			CFLG = 0;
+		} else {
+			if (sr) {
+				quot = - quot;
+			}
+			if (((si5b)rem < 0) != s2) {
+				rem = - rem;
+			}
+			VFLG = CFLG = 0;
+			ZFLG = Bool2Bit(((si5b)quot) == 0);
+			NFLG = Bool2Bit(((si5b)quot) < 0);
+
+			V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+			m68k_dreg(rDr) = rem;
+			m68k_dreg(rDq) = quot;
+		}
+	} else {
+		/* unsigned */
+
+		v2.lo = (ui5b)m68k_dreg(rDq);
+		if (extra & 0x400) {
+			v2.hi = (ui5b)m68k_dreg(rDr);
+		} else {
+			v2.hi = 0;
+		}
+		if (div_unsigned(&v2, src, &quot, &rem)) {
+			NeedDefaultLazyAllFlags();
+
+			VFLG = NFLG = 1;
+			CFLG = 0;
+		} else {
+			VFLG = CFLG = 0;
+			ZFLG = Bool2Bit(((si5b)quot) == 0);
+			NFLG = Bool2Bit(((si5b)quot) < 0);
+
+			V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+			m68k_dreg(rDr) = rem;
+			m68k_dreg(rDq) = quot;
+		}
+	}
+}
+#endif
+
+#if Use68020
+LOCALIPROC DoMoveToControl(void)
+{
+	if (0 == V_regs.s) {
+		DoPrivilegeViolation();
+	} else {
+		ui4b src = nextiword_nm();
+		int regno = (src >> 12) & 0x0F;
+		ui5b v = V_regs.regs[regno];
+
+		switch (src & 0x0FFF) {
+			case 0x0000:
+				V_regs.sfc = v & 7;
+				/* ReportAbnormal("DoMoveToControl: sfc"); */
+				/* happens on entering macsbug */
+				break;
+			case 0x0001:
+				V_regs.dfc = v & 7;
+				/* ReportAbnormal("DoMoveToControl: dfc"); */
+				break;
+			case 0x0002:
+				V_regs.cacr = v & 0x3;
+				/* ReportAbnormal("DoMoveToControl: cacr"); */
+				/* used by Sys 7.5.5 boot */
+				break;
+			case 0x0800:
+				V_regs.usp = v;
+				ReportAbnormalID(0x0113, "DoMoveToControl: usp");
+				break;
+			case 0x0801:
+				V_regs.vbr = v;
+				/* ReportAbnormal("DoMoveToControl: vbr"); */
+				/* happens on entering macsbug */
+				break;
+			case 0x0802:
+				V_regs.caar = v &0xfc;
+				/* ReportAbnormal("DoMoveToControl: caar"); */
+				/* happens on entering macsbug */
+				break;
+			case 0x0803:
+				V_regs.msp = v;
+				if (V_regs.m == 1) {
+					m68k_areg(7) = V_regs.msp;
+				}
+				/* ReportAbnormal("DoMoveToControl: msp"); */
+				/* happens on entering macsbug */
+				break;
+			case 0x0804:
+				V_regs.isp = v;
+				if (V_regs.m == 0) {
+					m68k_areg(7) = V_regs.isp;
+				}
+				ReportAbnormalID(0x0114, "DoMoveToControl: isp");
+				break;
+			default:
+				op_illg();
+				ReportAbnormalID(0x0115,
+					"DoMoveToControl: unknown reg");
+				break;
+		}
+	}
+}
+#endif
+
+#if Use68020
+LOCALIPROC DoMoveFromControl(void)
+{
+	if (0 == V_regs.s) {
+		DoPrivilegeViolation();
+	} else {
+		ui5b v;
+		ui4b src = nextiword_nm();
+		int regno = (src >> 12) & 0x0F;
+
+		switch (src & 0x0FFF) {
+			case 0x0000:
+				v = V_regs.sfc;
+				/* ReportAbnormal("DoMoveFromControl: sfc"); */
+				/* happens on entering macsbug */
+				break;
+			case 0x0001:
+				v = V_regs.dfc;
+				/* ReportAbnormal("DoMoveFromControl: dfc"); */
+				/* happens on entering macsbug */
+				break;
+			case 0x0002:
+				v = V_regs.cacr;
+				/* ReportAbnormal("DoMoveFromControl: cacr"); */
+				/* used by Sys 7.5.5 boot */
+				break;
+			case 0x0800:
+				v = V_regs.usp;
+				ReportAbnormalID(0x0116, "DoMoveFromControl: usp");
+				break;
+			case 0x0801:
+				v = V_regs.vbr;
+				/* ReportAbnormal("DoMoveFromControl: vbr"); */
+				/* happens on entering macsbug */
+				break;
+			case 0x0802:
+				v = V_regs.caar;
+				/* ReportAbnormal("DoMoveFromControl: caar"); */
+				/* happens on entering macsbug */
+				break;
+			case 0x0803:
+				v = (V_regs.m == 1)
+					? m68k_areg(7)
+					: V_regs.msp;
+				/* ReportAbnormal("DoMoveFromControl: msp"); */
+				/* happens on entering macsbug */
+				break;
+			case 0x0804:
+				v = (V_regs.m == 0)
+					? m68k_areg(7)
+					: V_regs.isp;
+				ReportAbnormalID(0x0117, "DoMoveFromControl: isp");
+				break;
+			default:
+				v = 0;
+				ReportAbnormalID(0x0118,
+					"DoMoveFromControl: unknown reg");
+				op_illg();
+				break;
+		}
+		V_regs.regs[regno] = v;
+	}
+}
+#endif
+
+#if Use68020
+LOCALIPROC DoCodeBkpt(void)
+{
+	/* BKPT 0100100001001rrr */
+	ReportAbnormalID(0x0119, "BKPT instruction");
+	op_illg();
+}
+#endif
+
+#if Use68020
+LOCALIPROC DoCodeRtd(void)
+{
+	/* Rtd 0100111001110100 */
+	ui5r NewPC = get_long(m68k_areg(7));
+	si5b offs = nextiSWord();
+	/* ReportAbnormal("RTD"); */
+	/* used by Sys 7.5.5 boot */
+	m68k_areg(7) += (4 + offs);
+	m68k_setpc(NewPC);
+}
+#endif
+
+#if Use68020
+LOCALIPROC DoCodeLinkL(void)
+{
+	/* Link.L 0100100000001rrr */
+
+	ui5r dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui5r *dstp = &V_regs.regs[dstreg];
+	CPTR stackp = m68k_areg(7);
+
+	ReportAbnormalID(0x011A, "Link.L");
+
+	stackp -= 4;
+	m68k_areg(7) = stackp; /* only matters if dstreg == 7 + 8 */
+	put_long(stackp, *dstp);
+	*dstp = stackp;
+	m68k_areg(7) += (si5b)nextilong();
+}
+#endif
+
+#if Use68020
+LOCALPROC DoCodeTRAPcc_t(void)
+{
+	ReportAbnormalID(0x011B, "TRAPcc trapping");
+	Exception(7);
+	/* pc pushed onto stack wrong */
+}
+#endif
+
+#if Use68020
+LOCALPROC DoCodeTRAPcc_f(void)
+{
+}
+#endif
+
+#if Use68020
+LOCALIPROC DoCodeTRAPcc(void)
+{
+	/* TRAPcc 0101cccc11111sss */
+	/* ReportAbnormal("TRAPcc"); */
+	switch (V_regs.CurDecOpY.v[1].ArgDat) {
+		case 2:
+			ReportAbnormalID(0x011C, "TRAPcc word data");
+			SkipiWord();
+			break;
+		case 3:
+			ReportAbnormalID(0x011D, "TRAPcc long data");
+			SkipiLong();
+			break;
+		case 4:
+			/* ReportAbnormal("TRAPcc no data"); */
+			/* no optional data */
+			break;
+		default:
+			ReportAbnormalID(0x011E, "TRAPcc illegal format");
+			op_illg();
+			break;
+	}
+	cctrue(DoCodeTRAPcc_t, DoCodeTRAPcc_f);
+}
+#endif
+
+#if Use68020
+LOCALIPROC DoCodePack(void)
+{
+	ui5r offs = nextiSWord();
+	ui5r val = DecodeGetSrcValue();
+
+	ReportAbnormalID(0x011F, "PACK");
+
+	val += offs;
+	val = ((val >> 4) & 0xf0) | (val & 0xf);
+
+	DecodeSetDstValue(val);
+}
+#endif
+
+#if Use68020
+LOCALIPROC DoCodeUnpk(void)
+{
+	ui5r offs = nextiSWord();
+	ui5r val = DecodeGetSrcValue();
+
+	ReportAbnormalID(0x0120, "UNPK");
+
+	val = (((val & 0xF0) << 4) | (val & 0x0F)) + offs;
+
+	DecodeSetDstValue(val);
+}
+#endif
+
+#if Use68020
+LOCALIPROC DoBitField(void)
+{
+	ui5b tmp;
+	ui5b newtmp;
+	CPTR dsta;
+	ui5b bf0;
+	ui3b bf1;
+	ui5b dstreg = V_regs.CurDecOpY.v[1].ArgDat;
+	ui4b extra = nextiword();
+	ui5b offset = ((extra & 0x0800) != 0)
+		? m68k_dreg((extra >> 6) & 7)
+		: ((extra >> 6) & 0x1f);
+	ui5b width = ((extra & 0x0020) != 0)
+		? m68k_dreg(extra & 7)
+		: extra;
+	ui3b bfa[5];
+	ui5b offwid;
+
+	/* ReportAbnormal("Bit Field operator"); */
+	/* width = ((width - 1) & 0x1f) + 1; */ /* 0 -> 32 */
+	width &= 0x001F; /* except width == 0 really means 32 */
+	if (V_regs.CurDecOpY.v[0].AMd == 0) {
+		bf0 = m68k_dreg(dstreg);
+		offset &= 0x1f;
+		tmp = bf0;
+		if (0 != offset) {
+			tmp = (tmp << offset) | (tmp >> (32 - offset));
+		}
+	} else {
+		/*
+			V_regs.ArgKind == AKMemory,
+			otherwise illegal and don't get here
+		*/
+		dsta = DecodeDst();
+		dsta += Ui5rASR(offset, 3);
+		offset &= 7;
+		offwid = offset + ((width == 0) ? 32 : width);
+
+		/* if (offwid > 0) */ {
+			bf1 = get_byte(dsta);
+			bfa[0] = bf1;
+			tmp = ((ui5b)bf1) << (24 + offset);
+		}
+		if (offwid > 8) {
+			bf1 = get_byte(dsta + 1);
+			bfa[1] = bf1;
+			tmp |= ((ui5b)bf1) << (16 + offset);
+		}
+		if (offwid > 16) {
+			bf1 = get_byte(dsta + 2);
+			bfa[2] = bf1;
+			tmp |= ((ui5r)bf1) << (8 + offset);
+		}
+		if (offwid > 24) {
+			bf1 = get_byte(dsta + 3);
+			bfa[3] = bf1;
+			tmp |= ((ui5r)bf1) << (offset);
+		}
+		if (offwid > 32) {
+			bf1 = get_byte(dsta + 4);
+			bfa[4] = bf1;
+			tmp |= ((ui5r)bf1) >> (8 - offset);
+		}
+	}
+
+	NFLG = Bool2Bit(((si5b)tmp) < 0);
+	if (width != 0) {
+		tmp >>= (32 - width);
+	}
+	ZFLG = tmp == 0;
+	VFLG = 0;
+	CFLG = 0;
+
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+
+	newtmp = tmp;
+
+	switch (V_regs.CurDecOpY.v[0].ArgDat) {
+		case 0: /* BFTST */
+			/* do nothing */
+			break;
+		case 1: /* BFEXTU */
+			m68k_dreg((extra >> 12) & 7) = tmp;
+			break;
+		case 2: /* BFCHG */
+			newtmp = ~ newtmp;
+			if (width != 0) {
+				newtmp &= ((1 << width) - 1);
+			}
+			break;
+		case 3: /* BFEXTS */
+			if (NFLG != 0) {
+				m68k_dreg((extra >> 12) & 7) = tmp
+					| ((width == 0) ? 0 : (-1 << width));
+			} else {
+				m68k_dreg((extra >> 12) & 7) = tmp;
+			}
+			break;
+		case 4: /* BFCLR */
+			newtmp = 0;
+			break;
+		case 5: /* BFFFO */
+			{
+				ui5b mask = 1 << ((width == 0) ? 31 : (width - 1));
+				ui5r i = offset;
+
+				while ((0 != mask) && (0 == (tmp & mask))) {
+					mask >>= 1;
+					i++;
+				}
+				m68k_dreg((extra >> 12) & 7) = i;
+			}
+			break;
+		case 6: /* BFSET */
+			newtmp = (width == 0) ? ~ 0 : ((1 << width) - 1);
+			break;
+		case 7: /* BFINS */
+			newtmp = m68k_dreg((extra >> 12) & 7);
+			if (width != 0) {
+				newtmp &= ((1 << width) - 1);
+			}
+			break;
+	}
+
+	if (newtmp != tmp) {
+
+		if (width != 0) {
+			newtmp <<= (32 - width);
+		}
+
+		if (V_regs.CurDecOpY.v[0].AMd == 0) {
+			ui5b mask = ~ 0;
+
+			if (width != 0) {
+				mask <<= (32 - width);
+			}
+
+			if (0 != offset) {
+				newtmp = (newtmp >> offset) | (newtmp << (32 - offset));
+				mask = (mask >> offset) | (mask << (32 - offset));
+			}
+
+			bf0 = (bf0 & ~ mask) | (newtmp);
+			m68k_dreg(dstreg) = bf0;
+		} else {
+
+			/* if (offwid > 0) */ {
+				ui3b mask = ~ (0xFF >> offset);
+
+				bf1 = newtmp >> (24 + offset);
+				if (offwid < 8) {
+					mask |= (0xFF >> offwid);
+				}
+				if (mask != 0) {
+					bf1 |= bfa[0] & mask;
+				}
+				put_byte(dsta + 0, bf1);
+			}
+			if (offwid > 8) {
+				bf1 = newtmp >> (16 + offset);
+				if (offwid < 16) {
+					bf1 |= (bfa[1] & (0xFF >> (offwid - 8)));
+				}
+				put_byte(dsta + 1, bf1);
+			}
+			if (offwid > 16) {
+				bf1 = newtmp >> (8 + offset);
+				if (offwid < 24) {
+					bf1 |= (bfa[2] & (0xFF >> (offwid - 16)));
+				}
+				put_byte(dsta + 2, bf1);
+			}
+			if (offwid > 24) {
+				bf1 = newtmp >> (offset);
+				if (offwid < 32) {
+					bf1 |= (bfa[3] & (0xFF >> (offwid - 24)));
+				}
+				put_byte(dsta + 3, bf1);
+			}
+			if (offwid > 32) {
+				bf1 = newtmp << (8 - offset);
+				bf1 |= (bfa[4] & (0xFF >> (offwid - 32)));
+				put_byte(dsta + 4, bf1);
+			}
+		}
+	}
+}
+#endif
+
+#if EmMMU | EmFPU
+LOCALFUNC blnr DecodeModeRegister(ui5b sz)
+{
+	blnr IsOk;
+	ui4r Dat = V_regs.CurDecOpY.v[0].ArgDat;
+	ui4r themode = (Dat >> 3) & 7;
+	ui4r thereg = Dat & 7;
+
+	switch (themode) {
+		case 0 :
+			V_regs.ArgKind = AKRegister;
+			V_regs.ArgAddr.rga = &V_regs.regs[thereg];
+			IsOk = trueblnr;
+			break;
+		case 1 :
+			V_regs.ArgKind = AKRegister;
+			V_regs.ArgAddr.rga = &V_regs.regs[thereg + 8];
+			IsOk = trueblnr;
+			break;
+		case 2 :
+			V_regs.ArgKind = AKMemory;
+			V_regs.ArgAddr.mem = m68k_areg(thereg);
+			IsOk = trueblnr;
+			break;
+		case 3 :
+			V_regs.ArgKind = AKMemory;
+			V_regs.ArgAddr.mem = m68k_areg(thereg);
+			if ((thereg == 7) && (sz == 1)) {
+				m68k_areg(thereg) += 2;
+			} else {
+				m68k_areg(thereg) += sz;
+			}
+			IsOk = trueblnr;
+			break;
+		case 4 :
+			V_regs.ArgKind = AKMemory;
+			if ((thereg == 7) && (sz == 1)) {
+				m68k_areg(thereg) -= 2;
+			} else {
+				m68k_areg(thereg) -= sz;
+			}
+			V_regs.ArgAddr.mem = m68k_areg(thereg);
+			IsOk = trueblnr;
+			break;
+		case 5 :
+			V_regs.ArgKind = AKMemory;
+			V_regs.ArgAddr.mem = m68k_areg(thereg)
+				+ nextiSWord();
+			IsOk = trueblnr;
+			break;
+		case 6 :
+			V_regs.ArgKind = AKMemory;
+			V_regs.ArgAddr.mem = get_disp_ea(m68k_areg(thereg));
+			IsOk = trueblnr;
+			break;
+		case 7 :
+			switch (thereg) {
+				case 0 :
+					V_regs.ArgKind = AKMemory;
+					V_regs.ArgAddr.mem = nextiSWord();
+					IsOk = trueblnr;
+					break;
+				case 1 :
+					V_regs.ArgKind = AKMemory;
+					V_regs.ArgAddr.mem = nextilong();
+					IsOk = trueblnr;
+					break;
+				case 2 :
+					V_regs.ArgKind = AKMemory;
+					V_regs.ArgAddr.mem = m68k_getpc();
+					V_regs.ArgAddr.mem += nextiSWord();
+					IsOk = trueblnr;
+					break;
+				case 3 :
+					V_regs.ArgKind = AKMemory;
+					V_regs.ArgAddr.mem = get_disp_ea(m68k_getpc());
+					IsOk = trueblnr;
+					break;
+				case 4 :
+					V_regs.ArgKind = AKMemory;
+					V_regs.ArgAddr.mem = m68k_getpc();
+					if (sz == 1) {
+						++V_regs.ArgAddr.mem;
+					}
+					m68k_setpc(V_regs.ArgAddr.mem + sz);
+					IsOk = trueblnr;
+					break;
+				default:
+					IsOk = falseblnr;
+					break;
+			}
+			break;
+		default:
+			IsOk = falseblnr;
+			break;
+	}
+
+	return IsOk;
+}
+#endif
+
+#if EmMMU | EmFPU
+LOCALFUNC ui5r GetArgValueL(void)
+{
+	ui5r v;
+
+	if (AKMemory == V_regs.ArgKind) {
+		v = get_long(V_regs.ArgAddr.mem);
+	} else {
+		/* must be AKRegister */
+		v = ui5r_FromSLong(*V_regs.ArgAddr.rga);
+	}
+
+	return v;
+}
+#endif
+
+#if EmMMU | EmFPU
+LOCALFUNC ui5r GetArgValueW(void)
+{
+	ui5r v;
+
+	if (AKMemory == V_regs.ArgKind) {
+		v = get_word(V_regs.ArgAddr.mem);
+	} else {
+		/* must be AKRegister */
+		v = ui5r_FromSWord(*V_regs.ArgAddr.rga);
+	}
+
+	return v;
+}
+#endif
+
+#if EmMMU | EmFPU
+LOCALFUNC ui5r GetArgValueB(void)
+{
+	ui5r v;
+
+	if (AKMemory == V_regs.ArgKind) {
+		v = get_byte(V_regs.ArgAddr.mem);
+	} else {
+		/* must be AKRegister */
+		v = ui5r_FromSByte(*V_regs.ArgAddr.rga);
+	}
+
+	return v;
+}
+#endif
+
+#if EmMMU | EmFPU
+LOCALPROC SetArgValueL(ui5r v)
+{
+	if (AKMemory == V_regs.ArgKind) {
+		put_long(V_regs.ArgAddr.mem, v);
+	} else {
+		/* must be AKRegister */
+		*V_regs.ArgAddr.rga = v;
+	}
+}
+#endif
+
+#if EmMMU | EmFPU
+LOCALPROC SetArgValueW(ui5r v)
+{
+	if (AKMemory == V_regs.ArgKind) {
+		put_word(V_regs.ArgAddr.mem, v);
+	} else {
+		/* must be AKRegister */
+		*V_regs.ArgAddr.rga =
+			(*V_regs.ArgAddr.rga & ~ 0xffff) | ((v) & 0xffff);
+	}
+}
+#endif
+
+#if EmMMU | EmFPU
+LOCALPROC SetArgValueB(ui5r v)
+{
+	if (AKMemory == V_regs.ArgKind) {
+		put_byte(V_regs.ArgAddr.mem, v);
+	} else {
+		/* must be AKRegister */
+		*V_regs.ArgAddr.rga =
+			(*V_regs.ArgAddr.rga & ~ 0xff) | ((v) & 0xff);
+	}
+}
+#endif
+
+
+#if EmMMU
+LOCALIPROC DoCodeMMU(void)
+{
+	/*
+		Emulate enough of MMU for System 7.5.5 universal
+		to boot on Mac Plus 68020. There is one
+		spurious "PMOVE TC, (A0)".
+		And implement a few more PMOVE operations seen
+		when running Disk Copy 6.3.3 and MacsBug.
+	*/
+	ui4r opcode = ((ui4r)(V_regs.CurDecOpY.v[0].AMd) << 8)
+		| V_regs.CurDecOpY.v[0].ArgDat;
+	if (opcode == 0xF010) {
+		ui4b ew = (int)nextiword_nm();
+		if (ew == 0x4200) {
+			/* PMOVE TC, (A0) */
+			/* fprintf(stderr, "0xF010 0x4200\n"); */
+			if (DecodeModeRegister(4)) {
+				SetArgValueL(0);
+				return;
+			}
+		} else if ((ew == 0x4E00) || (ew == 0x4A00)) {
+			/* PMOVE CRP, (A0) and PMOVE SRP, (A0) */
+			/* fprintf(stderr, "0xF010 %x\n", ew); */
+			if (DecodeModeRegister(4)) {
+				SetArgValueL(0x7FFF0001);
+				V_regs.ArgAddr.mem += 4;
+				SetArgValueL(0);
+				return;
+			}
+		} else if (ew == 0x6200) {
+			/* PMOVE MMUSR, (A0) */
+			/* fprintf(stderr, "0xF010 %x\n", ew); */
+			if (DecodeModeRegister(2)) {
+				SetArgValueW(0);
+				return;
+			}
+		}
+		/* fprintf(stderr, "extensions %x\n", ew); */
+		BackupPC();
+	}
+	/* fprintf(stderr, "opcode %x\n", (int)opcode); */
+	ReportAbnormalID(0x0121, "MMU op");
+	DoCodeFdefault();
+}
+#endif
+
+#if EmFPU
+
+#include "FPMATHEM.h"
+#include "FPCPEMDV.h"
+
+#endif
+
+#if HaveGlbReg
+LOCALPROC Em_Swap(void)
+{
+#ifdef r_pc_p
+	{
+		ui3p t = g_pc_p;
+		g_pc_p = regs.pc_p;
+		regs.pc_p = t;
+	}
+#endif
+#ifdef r_MaxCyclesToGo
+	{
+		si5rr t = g_MaxCyclesToGo;
+		g_MaxCyclesToGo = regs.MaxCyclesToGo;
+		regs.MaxCyclesToGo = t;
+	}
+#endif
+#ifdef r_pc_pHi
+	{
+		ui3p t = g_pc_pHi;
+		g_pc_pHi = regs.pc_pHi;
+		regs.pc_pHi = t;
+	}
+#endif
+#ifdef r_regs
+	{
+		struct regstruct *t = g_regs;
+		g_regs = regs.save_regs;
+		regs.save_regs = t;
+	}
+#endif
+}
+#endif
+
+#if HaveGlbReg
+#define Em_Enter Em_Swap
+#else
+#define Em_Enter()
+#endif
+
+#if HaveGlbReg
+#define Em_Exit Em_Swap
+#else
+#define Em_Exit()
+#endif
+
+#if HaveGlbReg
+LOCALFUNC blnr LocalMemAccessNtfy(ATTep pT)
+{
+	blnr v;
+
+	Em_Exit();
+	v = MemAccessNtfy(pT);
+	Em_Enter();
+
+	return v;
+}
+#else
+#define LocalMemAccessNtfy MemAccessNtfy
+#endif
+
+#if HaveGlbReg
+LOCALFUNC ui5b LocalMMDV_Access(ATTep p, ui5b Data,
+	blnr WriteMem, blnr ByteSize, CPTR addr)
+{
+	ui5b v;
+
+	Em_Exit();
+	v = MMDV_Access(p, Data, WriteMem, ByteSize, addr);
+	Em_Enter();
+
+	return v;
+}
+#else
+#define LocalMMDV_Access MMDV_Access
+#endif
+
+LOCALPROC local_customreset(void)
+{
+	Em_Exit();
+	customreset();
+	Em_Enter();
+}
+
+LOCALFUNC ATTep LocalFindATTel(CPTR addr)
+{
+	ATTep prev;
+	ATTep p;
+
+	p = V_regs.HeadATTel;
+	if ((addr & p->cmpmask) != p->cmpvalu) {
+		do {
+			prev = p;
+			p = p->Next;
+		} while ((addr & p->cmpmask) != p->cmpvalu);
+
+		{
+			ATTep next = p->Next;
+
+			if (nullpr == next) {
+				/* don't move the end guard */
+			} else {
+				/* move to first */
+				prev->Next = next;
+				p->Next = V_regs.HeadATTel;
+				V_regs.HeadATTel = p;
+			}
+		}
+	}
+
+	return p;
+}
+
+LOCALPROC SetUpMATC(
+	MATCp CurMATC,
+	ATTep p)
+{
+	CurMATC->cmpmask = p->cmpmask;
+	CurMATC->usemask = p->usemask;
+	CurMATC->cmpvalu = p->cmpvalu;
+	CurMATC->usebase = p->usebase;
+}
+
+LOCALFUNC ui5r my_reg_call get_byte_ext(CPTR addr)
+{
+	ATTep p;
+	ui3p m;
+	ui5r AccFlags;
+	ui5r Data;
+
+Label_Retry:
+	p = LocalFindATTel(addr);
+	AccFlags = p->Access;
+
+	if (0 != (AccFlags & kATTA_readreadymask)) {
+		SetUpMATC(&V_regs.MATCrdB, p);
+		m = p->usebase + (addr & p->usemask);
+
+		Data = *m;
+	} else if (0 != (AccFlags & kATTA_mmdvmask)) {
+		Data = LocalMMDV_Access(p, 0, falseblnr, trueblnr, addr);
+	} else if (0 != (AccFlags & kATTA_ntfymask)) {
+		if (LocalMemAccessNtfy(p)) {
+			goto Label_Retry;
+		} else {
+			Data = 0; /* fail */
+		}
+	} else {
+		Data = 0; /* fail */
+	}
+
+	return ui5r_FromSByte(Data);
+}
+
+LOCALPROC my_reg_call put_byte_ext(CPTR addr, ui5r b)
+{
+	ATTep p;
+	ui3p m;
+	ui5r AccFlags;
+
+Label_Retry:
+	p = LocalFindATTel(addr);
+	AccFlags = p->Access;
+
+	if (0 != (AccFlags & kATTA_writereadymask)) {
+		SetUpMATC(&V_regs.MATCwrB, p);
+		m = p->usebase + (addr & p->usemask);
+		*m = b;
+	} else if (0 != (AccFlags & kATTA_mmdvmask)) {
+		(void) LocalMMDV_Access(p, b & 0x00FF,
+			trueblnr, trueblnr, addr);
+	} else if (0 != (AccFlags & kATTA_ntfymask)) {
+		if (LocalMemAccessNtfy(p)) {
+			goto Label_Retry;
+		} else {
+			/* fail */
+		}
+	} else {
+		/* fail */
+	}
+}
+
+LOCALFUNC ui5r my_reg_call get_word_ext(CPTR addr)
+{
+	ui5r Data;
+
+	if (0 != (addr & 0x01)) {
+		ui5r hi = get_byte(addr);
+		ui5r lo = get_byte(addr + 1);
+		Data = ((hi << 8) & 0x0000FF00)
+			| (lo & 0x000000FF);
+	} else {
+		ATTep p;
+		ui3p m;
+		ui5r AccFlags;
+
+Label_Retry:
+		p = LocalFindATTel(addr);
+		AccFlags = p->Access;
+
+		if (0 != (AccFlags & kATTA_readreadymask)) {
+			SetUpMATC(&V_regs.MATCrdW, p);
+			V_regs.MATCrdW.cmpmask |= 0x01;
+			m = p->usebase + (addr & p->usemask);
+			Data = do_get_mem_word(m);
+		} else if (0 != (AccFlags & kATTA_mmdvmask)) {
+			Data = LocalMMDV_Access(p, 0, falseblnr, falseblnr, addr);
+		} else if (0 != (AccFlags & kATTA_ntfymask)) {
+			if (LocalMemAccessNtfy(p)) {
+				goto Label_Retry;
+			} else {
+				Data = 0; /* fail */
+			}
+		} else {
+			Data = 0; /* fail */
+		}
+	}
+
+	return ui5r_FromSWord(Data);
+}
+
+LOCALPROC my_reg_call put_word_ext(CPTR addr, ui5r w)
+{
+	if (0 != (addr & 0x01)) {
+		put_byte(addr, w >> 8);
+		put_byte(addr + 1, w);
+	} else {
+		ATTep p;
+		ui3p m;
+		ui5r AccFlags;
+
+Label_Retry:
+		p = LocalFindATTel(addr);
+		AccFlags = p->Access;
+
+		if (0 != (AccFlags & kATTA_writereadymask)) {
+			SetUpMATC(&V_regs.MATCwrW, p);
+			V_regs.MATCwrW.cmpmask |= 0x01;
+			m = p->usebase + (addr & p->usemask);
+			do_put_mem_word(m, w);
+		} else if (0 != (AccFlags & kATTA_mmdvmask)) {
+			(void) LocalMMDV_Access(p, w & 0x0000FFFF,
+				trueblnr, falseblnr, addr);
+		} else if (0 != (AccFlags & kATTA_ntfymask)) {
+			if (LocalMemAccessNtfy(p)) {
+				goto Label_Retry;
+			} else {
+				/* fail */
+			}
+		} else {
+			/* fail */
+		}
+	}
+}
+
+LOCALFUNC ui5r my_reg_call get_long_misaligned_ext(CPTR addr)
+{
+	ui5r hi = get_word(addr);
+	ui5r lo = get_word(addr + 2);
+	ui5r Data = ((hi << 16) & 0xFFFF0000)
+		| (lo & 0x0000FFFF);
+
+	return ui5r_FromSLong(Data);
+}
+
+LOCALPROC my_reg_call put_long_misaligned_ext(CPTR addr, ui5r l)
+{
+	put_word(addr, l >> 16);
+	put_word(addr + 2, l);
+}
+
+#if FasterAlignedL
+LOCALFUNC ui5r my_reg_call get_long_ext(CPTR addr)
+{
+	ui5r Data;
+
+	if (0 != (addr & 0x03)) {
+		ui5r hi = get_word(addr);
+		ui5r lo = get_word(addr + 2);
+		Data = ((hi << 16) & 0xFFFF0000)
+			| (lo & 0x0000FFFF);
+	} else {
+		ATTep p;
+		ui3p m;
+		ui5r AccFlags;
+
+Label_Retry:
+		p = LocalFindATTel(addr);
+		AccFlags = p->Access;
+
+		if (0 != (AccFlags & kATTA_readreadymask)) {
+			SetUpMATC(&V_regs.MATCrdL, p);
+			V_regs.MATCrdL.cmpmask |= 0x03;
+			m = p->usebase + (addr & p->usemask);
+			Data = do_get_mem_long(m);
+		} else if (0 != (AccFlags & kATTA_mmdvmask)) {
+			ui5r hi = LocalMMDV_Access(p, 0,
+				falseblnr, falseblnr, addr);
+			ui5r lo = LocalMMDV_Access(p, 0,
+				falseblnr, falseblnr, addr + 2);
+			Data = ((hi << 16) & 0xFFFF0000)
+				| (lo & 0x0000FFFF);
+		} else if (0 != (AccFlags & kATTA_ntfymask)) {
+			if (LocalMemAccessNtfy(p)) {
+				goto Label_Retry;
+			} else {
+				Data = 0; /* fail */
+			}
+		} else {
+			Data = 0; /* fail */
+		}
+	}
+
+	return ui5r_FromSLong(Data);
+}
+#endif
+
+#if FasterAlignedL
+LOCALPROC my_reg_call put_long_ext(CPTR addr, ui5r l)
+{
+	if (0 != (addr & 0x03)) {
+		put_word(addr, l >> 16);
+		put_word(addr + 2, l);
+	} else {
+		ATTep p;
+		ui3p m;
+		ui5r AccFlags;
+
+Label_Retry:
+		p = LocalFindATTel(addr);
+		AccFlags = p->Access;
+
+		if (0 != (AccFlags & kATTA_writereadymask)) {
+			SetUpMATC(&V_regs.MATCwrL, p);
+			V_regs.MATCwrL.cmpmask |= 0x03;
+			m = p->usebase + (addr & p->usemask);
+			do_put_mem_long(m, l);
+		} else if (0 != (AccFlags & kATTA_mmdvmask)) {
+			(void) LocalMMDV_Access(p, (l >> 16) & 0x0000FFFF,
+				trueblnr, falseblnr, addr);
+			(void) LocalMMDV_Access(p, l & 0x0000FFFF,
+				trueblnr, falseblnr, addr + 2);
+		} else if (0 != (AccFlags & kATTA_ntfymask)) {
+			if (LocalMemAccessNtfy(p)) {
+				goto Label_Retry;
+			} else {
+				/* fail */
+			}
+		} else {
+			/* fail */
+		}
+	}
+}
+#endif
+
+LOCALPROC Recalc_PC_Block(void)
+{
+	ATTep p;
+	CPTR curpc = m68k_getpc();
+
+Label_Retry:
+	p = LocalFindATTel(curpc);
+	if (my_cond_rare(0 == (p->Access & kATTA_readreadymask))) {
+		if (0 != (p->Access & kATTA_ntfymask)) {
+			if (LocalMemAccessNtfy(p)) {
+				goto Label_Retry;
+			}
+		}
+		/* in trouble if get here */
+#if ExtraAbnormalReports
+		ReportAbnormalID(0x0122, "Recalc_PC_Block fails");
+			/* happens on Restart */
+#endif
+
+		V_regs.pc_pLo = V_regs.fakeword;
+		V_pc_p = V_regs.pc_pLo;
+		V_pc_pHi = V_regs.pc_pLo + 2;
+		V_regs.pc = curpc;
+	} else {
+		ui5r m2 = p->usemask & ~ p->cmpmask;
+		m2 = m2 & ~ (m2 + 1);
+
+		V_pc_p = p->usebase + (curpc & p->usemask);
+		V_regs.pc_pLo = V_pc_p - (curpc & m2);
+		V_pc_pHi = V_regs.pc_pLo + m2 + 1;
+		V_regs.pc = curpc - (V_pc_p - V_regs.pc_pLo);
+	}
+}
+
+LOCALFUNC ui5r my_reg_call Recalc_PC_BlockReturnUi5r(ui5r v)
+{
+	/*
+		Used to prevent compiler from saving
+		register on the stack in calling
+		functions, when Recalc_PC_Block isn't being called.
+	*/
+	Recalc_PC_Block();
+
+	return v;
+}
+
+LOCALFUNC ui5r nextilong_ext(void)
+{
+	ui5r r;
+
+	V_pc_p -= 4;
+
+	{
+		ui5r hi = nextiword();
+		ui5r lo = nextiword();
+		r = ((hi << 16) & 0xFFFF0000)
+			| (lo & 0x0000FFFF);
+	}
+
+	return r;
+}
+
+LOCALPROC DoCheckExternalInterruptPending(void)
+{
+	ui3r level = *V_regs.fIPL;
+	if ((level > V_regs.intmask) || (level == 7)) {
+#if WantCloserCyc
+		V_MaxCyclesToGo -=
+			(44 * kCycleScale + 5 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
+#endif
+		Exception(24 + level);
+		V_regs.intmask = level;
+	}
+}
+
+LOCALPROC do_trace(void)
+{
+	V_regs.TracePending = trueblnr;
+	NeedToGetOut();
+}
+
+GLOBALPROC m68k_go_nCycles(ui5b n)
+{
+	Em_Enter();
+	V_MaxCyclesToGo += (n + V_regs.ResidualCycles);
+	while (V_MaxCyclesToGo > 0) {
+
+#if 0
+		if (V_regs.ResetPending) {
+			m68k_DoReset();
+		}
+#endif
+		if (V_regs.TracePending) {
+#if WantCloserCyc
+			V_MaxCyclesToGo -= (34 * kCycleScale
+				+ 4 * RdAvgXtraCyc + 3 * WrAvgXtraCyc);
+#endif
+			Exception(9);
+		}
+		if (V_regs.ExternalInterruptPending) {
+			V_regs.ExternalInterruptPending = falseblnr;
+			DoCheckExternalInterruptPending();
+		}
+		if (V_regs.t1 != 0) {
+			do_trace();
+		}
+		m68k_go_MaxCycles();
+		V_MaxCyclesToGo += V_regs.MoreCyclesToGo;
+		V_regs.MoreCyclesToGo = 0;
+	}
+
+	V_regs.ResidualCycles = V_MaxCyclesToGo;
+	V_MaxCyclesToGo = 0;
+	Em_Exit();
+}
+
+GLOBALFUNC si5r GetCyclesRemaining(void)
+{
+	si5r v;
+
+	Em_Enter();
+	v = V_regs.MoreCyclesToGo + V_MaxCyclesToGo;
+	Em_Exit();
+
+	return v;
+}
+
+GLOBALPROC SetCyclesRemaining(si5r n)
+{
+	Em_Enter();
+
+	if (V_MaxCyclesToGo >= n) {
+		V_regs.MoreCyclesToGo = 0;
+		V_MaxCyclesToGo = n;
+	} else {
+		V_regs.MoreCyclesToGo = n - V_MaxCyclesToGo;
+	}
+
+	Em_Exit();
+}
+
+GLOBALFUNC ATTep FindATTel(CPTR addr)
+{
+	ATTep v;
+
+	Em_Enter();
+	v = LocalFindATTel(addr);
+	Em_Exit();
+
+	return v;
+}
+
+GLOBALFUNC ui3r get_vm_byte(CPTR addr)
+{
+	ui3r v;
+
+	Em_Enter();
+	v = (ui3b) get_byte(addr);
+	Em_Exit();
+
+	return v;
+}
+
+GLOBALFUNC ui4r get_vm_word(CPTR addr)
+{
+	ui4r v;
+
+	Em_Enter();
+	v = (ui4b) get_word(addr);
+	Em_Exit();
+
+	return v;
+}
+
+GLOBALFUNC ui5r get_vm_long(CPTR addr)
+{
+	ui5r v;
+
+	Em_Enter();
+	v = (ui5b) get_long(addr);
+	Em_Exit();
+
+	return v;
+}
+
+GLOBALPROC put_vm_byte(CPTR addr, ui3r b)
+{
+	Em_Enter();
+	put_byte(addr, ui5r_FromSByte(b));
+	Em_Exit();
+}
+
+GLOBALPROC put_vm_word(CPTR addr, ui4r w)
+{
+	Em_Enter();
+	put_word(addr, ui5r_FromSWord(w));
+	Em_Exit();
+}
+
+GLOBALPROC put_vm_long(CPTR addr, ui5r l)
+{
+	Em_Enter();
+	put_long(addr, ui5r_FromSLong(l));
+	Em_Exit();
+}
+
+GLOBALPROC SetHeadATTel(ATTep p)
+{
+	Em_Enter();
+
+	V_regs.MATCrdB.cmpmask = 0;
+	V_regs.MATCrdB.cmpvalu = 0xFFFFFFFF;
+	V_regs.MATCwrB.cmpmask = 0;
+	V_regs.MATCwrB.cmpvalu = 0xFFFFFFFF;
+	V_regs.MATCrdW.cmpmask = 0;
+	V_regs.MATCrdW.cmpvalu = 0xFFFFFFFF;
+	V_regs.MATCwrW.cmpmask = 0;
+	V_regs.MATCwrW.cmpvalu = 0xFFFFFFFF;
+#if FasterAlignedL
+	V_regs.MATCrdL.cmpmask = 0;
+	V_regs.MATCrdL.cmpvalu = 0xFFFFFFFF;
+	V_regs.MATCwrL.cmpmask = 0;
+	V_regs.MATCwrL.cmpvalu = 0xFFFFFFFF;
+#endif
+	/* force Recalc_PC_Block soon */
+		V_regs.pc = m68k_getpc();
+		V_regs.pc_pLo = V_pc_p;
+		V_pc_pHi = V_regs.pc_pLo + 2;
+	V_regs.HeadATTel = p;
+
+	Em_Exit();
+}
+
+GLOBALPROC DiskInsertedPsuedoException(CPTR newpc, ui5b data)
+{
+	Em_Enter();
+	ExceptionTo(newpc
+#if Use68020
+		, 0
+#endif
+		);
+	m68k_areg(7) -= 4;
+	put_long(m68k_areg(7), data);
+	Em_Exit();
+}
+
+GLOBALPROC m68k_IPLchangeNtfy(void)
+{
+	Em_Enter();
+	{
+		ui3r level = *V_regs.fIPL;
+
+		if ((level > V_regs.intmask) || (level == 7)) {
+			SetExternalInterruptPending();
+		}
+	}
+	Em_Exit();
+}
+
+#if WantDumpTable
+LOCALPROC InitDumpTable(void)
+{
+	si5b i;
+
+	for (i = 0; i < kNumIKinds; ++i) {
+		DumpTable[i] = 0;
+	}
+}
+
+LOCALPROC DumpATable(ui5b *p, ui5b n)
+{
+	si5b i;
+
+	for (i = 0; i < n; ++i) {
+		dbglog_writeNum(p[i]);
+		dbglog_writeReturn();
+	}
+}
+
+EXPORTPROC DoDumpTable(void);
+GLOBALPROC DoDumpTable(void)
+{
+	DumpATable(DumpTable, kNumIKinds);
+}
+#endif
+
+GLOBALPROC m68k_reset(void)
+{
+	Em_Enter();
+
+#if WantDumpTable
+	InitDumpTable();
+#endif
+	V_MaxCyclesToGo = 0;
+	V_regs.MoreCyclesToGo = 0;
+	V_regs.ResidualCycles = 0;
+	V_pc_p = (ui3p)nullpr;
+	V_pc_pHi = (ui3p)nullpr;
+	V_regs.pc_pLo = (ui3p)nullpr;
+
+	do_put_mem_word(V_regs.fakeword, 0x4AFC);
+		/* illegal instruction opcode */
+
+#if 0
+	V_regs.ResetPending = trueblnr;
+	NeedToGetOut();
+#else
+/* Sets the MC68000 reset jump vector... */
+	m68k_setpc(get_long(0x00000004));
+
+/* Sets the initial stack vector... */
+	m68k_areg(7) = get_long(0x00000000);
+
+	V_regs.s = 1;
+#if Use68020
+	V_regs.m = 0;
+	V_regs.t0 = 0;
+#endif
+	V_regs.t1 = 0;
+	ZFLG = CFLG = NFLG = VFLG = 0;
+
+	V_regs.LazyFlagKind = kLazyFlagsDefault;
+	V_regs.LazyXFlagKind = kLazyFlagsDefault;
+
+	V_regs.ExternalInterruptPending = falseblnr;
+	V_regs.TracePending = falseblnr;
+	V_regs.intmask = 7;
+
+#if Use68020
+	V_regs.sfc = 0;
+	V_regs.dfc = 0;
+	V_regs.vbr = 0;
+	V_regs.cacr = 0;
+	V_regs.caar = 0;
+#endif
+#endif
+
+	Em_Exit();
+}
+
+#if SmallGlobals
+GLOBALPROC MINEM68K_ReserveAlloc(void)
+{
+	ReserveAllocOneBlock((ui3p *)&regs.disp_table,
+		disp_table_sz * 8, 6, falseblnr);
+}
+#endif
+
+GLOBALPROC MINEM68K_Init(
+	ui3b *fIPL)
+{
+	regs.fIPL = fIPL;
+#ifdef r_regs
+	regs.save_regs = &regs;
+#endif
+
+	M68KITAB_setup(regs.disp_table);
+}
--- /dev/null
+++ b/src/MINEM68K.h
@@ -1,0 +1,53 @@
+/*
+	MINEM68K.h
+
+	Copyright (C) 2004 Bernd Schmidt, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef MINEM68K_H
+#error "header already included"
+#else
+#define MINEM68K_H
+#endif
+
+EXPORTPROC MINEM68K_Init(
+	ui3b *fIPL);
+#if SmallGlobals
+EXPORTPROC MINEM68K_ReserveAlloc(void);
+#endif
+
+EXPORTPROC m68k_IPLchangeNtfy(void);
+EXPORTPROC DiskInsertedPsuedoException(CPTR newpc, ui5b data);
+EXPORTPROC m68k_reset(void);
+
+EXPORTFUNC si5r GetCyclesRemaining(void);
+EXPORTPROC SetCyclesRemaining(si5r n);
+
+EXPORTPROC m68k_go_nCycles(ui5b n);
+
+/*
+	general purpose access of address space
+	of emulated computer. (memory and
+	memory mapped hardware.)
+*/
+
+EXPORTFUNC ui3r get_vm_byte(CPTR addr);
+EXPORTFUNC ui4r get_vm_word(CPTR addr);
+EXPORTFUNC ui5r get_vm_long(CPTR addr);
+
+EXPORTPROC put_vm_byte(CPTR addr, ui3r b);
+EXPORTPROC put_vm_word(CPTR addr, ui4r w);
+EXPORTPROC put_vm_long(CPTR addr, ui5r l);
+
+EXPORTPROC SetHeadATTel(ATTep p);
+EXPORTFUNC ATTep FindATTel(CPTR addr);
--- /dev/null
+++ b/src/MOUSEMDV.c
@@ -1,0 +1,129 @@
+/*
+	MOUSEMDV.c
+
+	Copyright (C) 2006 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	MOUSe EMulated DeVice
+
+	Emulation of the mouse in the Mac Plus.
+
+	This code descended from "Mouse-MacOS.c" in Richard F. Bannister's
+	Macintosh port of vMac, by Philip Cummins.
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+#include "MYOSGLUE.h"
+#include "ENDIANAC.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+#include "SCCEMDEV.h"
+#include "MINEM68K.h"
+#endif
+
+#include "MOUSEMDV.h"
+
+GLOBALPROC Mouse_Update(void)
+{
+#if HaveMasterMyEvtQLock
+	if (0 != MasterMyEvtQLock) {
+		--MasterMyEvtQLock;
+	}
+#endif
+
+	/*
+		Check mouse position first. After mouse button or key event,
+		can't process another mouse position until following tick,
+		otherwise button or key will be in wrong place.
+	*/
+
+	/*
+		if start doing this too soon after boot,
+		will mess up memory check
+	*/
+	if (Mouse_Enabled()) {
+		MyEvtQEl *p;
+
+		if (
+#if HaveMasterMyEvtQLock
+			(0 == MasterMyEvtQLock) &&
+#endif
+			(nullpr != (p = MyEvtQOutP())))
+		{
+#if EmClassicKbrd
+#if EnableMouseMotion
+			if (MyEvtQElKindMouseDelta == p->kind) {
+
+				if ((p->u.pos.h != 0) || (p->u.pos.v != 0)) {
+					put_ram_word(0x0828,
+						get_ram_word(0x0828) + p->u.pos.v);
+					put_ram_word(0x082A,
+						get_ram_word(0x082A) + p->u.pos.h);
+					put_ram_byte(0x08CE, get_ram_byte(0x08CF));
+						/* Tell MacOS to redraw the Mouse */
+				}
+				MyEvtQOutDone();
+			} else
+#endif
+#endif
+			if (MyEvtQElKindMousePos == p->kind) {
+				ui5r NewMouse = (p->u.pos.v << 16) | p->u.pos.h;
+
+				if (get_ram_long(0x0828) != NewMouse) {
+					put_ram_long(0x0828, NewMouse);
+						/* Set Mouse Position */
+					put_ram_long(0x082C, NewMouse);
+#if EmClassicKbrd
+					put_ram_byte(0x08CE, get_ram_byte(0x08CF));
+						/* Tell MacOS to redraw the Mouse */
+#else
+					put_ram_long(0x0830, NewMouse);
+					put_ram_byte(0x08CE, 0xFF);
+						/* Tell MacOS to redraw the Mouse */
+#endif
+				}
+				MyEvtQOutDone();
+			}
+		}
+	}
+
+#if EmClassicKbrd
+	{
+		MyEvtQEl *p;
+
+		if (
+#if HaveMasterMyEvtQLock
+			(0 == MasterMyEvtQLock) &&
+#endif
+			(nullpr != (p = MyEvtQOutP())))
+		{
+			if (MyEvtQElKindMouseButton == p->kind) {
+				MouseBtnUp = p->u.press.down ? 0 : 1;
+				MyEvtQOutDone();
+				MasterMyEvtQLock = 4;
+			}
+		}
+	}
+#endif
+}
+
+GLOBALPROC Mouse_EndTickNotify(void)
+{
+	if (Mouse_Enabled()) {
+		/* tell platform specific code where the mouse went */
+		CurMouseV = get_ram_word(0x082C);
+		CurMouseH = get_ram_word(0x082E);
+	}
+}
--- /dev/null
+++ b/src/MOUSEMDV.h
@@ -1,0 +1,24 @@
+/*
+	MOUSEMDV.h
+
+	Copyright (C) 2003 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef MOUSEMDV_H
+#error "header already included"
+#else
+#define MOUSEMDV_H
+#endif
+
+EXPORTPROC Mouse_Update(void);
+EXPORTPROC Mouse_EndTickNotify(void);
--- /dev/null
+++ b/src/MYOSGLUE.h
@@ -1,0 +1,441 @@
+/*
+	MYOSGLUE.h
+
+	Copyright (C) 2006 Philip Cummins, Richard F. Bannister,
+		Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	MY Operating System GLUE.
+
+	header file for operating system dependent code.
+	the same header is used for all platforms.
+
+	This code is descended from Richard F. Bannister's Macintosh
+	port of vMac, by Philip Cummins.
+*/
+
+#ifdef MYOSGLUE_H
+#ifndef AllFiles
+#error "header already included"
+#endif
+#else
+#define MYOSGLUE_H
+#endif
+
+
+#if WantAbnormalReports
+EXPORTOSGLUPROC WarnMsgAbnormalID(ui4r id);
+#endif
+
+#if dbglog_HAVE
+EXPORTOSGLUPROC dbglog_writeCStr(char *s);
+EXPORTOSGLUPROC dbglog_writeReturn(void);
+EXPORTOSGLUPROC dbglog_writeHex(ui5r x);
+EXPORTOSGLUPROC dbglog_writeNum(ui5r x);
+EXPORTOSGLUPROC dbglog_writeMacChar(ui3r x);
+EXPORTOSGLUPROC dbglog_writeln(char *s);
+EXPORTOSGLUPROC dbglog_writelnNum(char *s, simr v);
+#endif
+
+EXPORTOSGLUPROC ReserveAllocOneBlock(ui3p *p, uimr n, ui3r align,
+	blnr FillOnes);
+
+EXPORTOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount);
+
+
+EXPORTVAR(ui3p, ROM)
+
+/*
+	error codes returned by Mini vMac extensions
+	(passed back to the emulated 68k code).
+*/
+
+#define tMacErr ui4r
+
+#define mnvm_noErr      ((tMacErr) 0x0000)
+	/* (ui4b)    0 - No Error */
+#define mnvm_miscErr    ((tMacErr) 0xFFFF)
+	/* (ui4b) -  1 - Should probably replace these */
+#define mnvm_controlErr ((tMacErr) 0xFFEF)
+	/* (ui4b) - 17 - I/O System Errors */
+#define mnvm_statusErr  ((tMacErr) 0xFFEE)
+	/* (ui4b) - 18 - Driver can't respond to Status call */
+#define mnvm_closErr    ((tMacErr) 0xFFE8)
+	/* (ui4b) - 24 - I/O System Errors */
+#define mnvm_eofErr     ((tMacErr) 0xFFD9)
+	/* (ui4b) - 39 - End of file */
+#define mnvm_tmfoErr    ((tMacErr) 0xFFD6)
+	/* (ui4b) - 42 - too many files open */
+#define mnvm_fnfErr     ((tMacErr) 0xFFD5)
+	/* (ui4b) - 43 - File not found */
+#define mnvm_wPrErr     ((tMacErr) 0xFFD4)
+	/* (ui4b) - 44 - diskette is write protected */
+#define mnvm_vLckdErr   ((tMacErr) 0xFFD2)
+	/* (ui4b) - 46 - volume is locked */
+#define mnvm_dupFNErr   ((tMacErr) 0xFFD0)
+	/* (ui4b) - 48 - duplicate filename */
+#define mnvm_opWrErr    ((tMacErr) 0xFFCF)
+	/* (ui4b) - 49 - file already open with with write permission */
+#define mnvm_paramErr   ((tMacErr) 0xFFCE)
+	/* (ui4b) - 50 - error in parameter list */
+#define mnvm_permErr    ((tMacErr) 0xFFCA)
+	/* (ui4b) - 54 - permissions error (on file open) */
+#define mnvm_nsDrvErr   ((tMacErr) 0xFFC8)
+	/* (ui4b) - 56 - No Such Drive */
+#define mnvm_wrPermErr  ((tMacErr) 0xFFC3)
+	/* (ui4b) - 61 - write permissions error */
+#define mnvm_offLinErr  ((tMacErr) 0xFFBF)
+	/* (ui4b) - 65 - off-line drive */
+#define mnvm_dirNFErr  ((tMacErr) 0xFF88)
+	/* (ui4b) - 120 - directory not found */
+#define mnvm_afpAccessDenied  ((tMacErr) 0xEC78)
+	/* (ui4b) - 5000 - Insufficient access privileges for operation */
+
+#if IncludePbufs
+
+#define tPbuf ui4r
+
+#define NotAPbuf ((tPbuf)0xFFFF)
+
+EXPORTOSGLUFUNC tMacErr CheckPbuf(tPbuf Pbuf_No);
+EXPORTOSGLUFUNC tMacErr PbufGetSize(tPbuf Pbuf_No, ui5r *Count);
+
+EXPORTOSGLUFUNC tMacErr PbufNew(ui5b count, tPbuf *r);
+EXPORTOSGLUPROC PbufDispose(tPbuf i);
+EXPORTOSGLUPROC PbufTransfer(ui3p Buffer,
+	tPbuf i, ui5r offset, ui5r count, blnr IsWrite);
+
+#endif
+
+#define tDrive ui4r
+
+EXPORTVAR(ui5b, vSonyWritableMask)
+EXPORTVAR(ui5b, vSonyInsertedMask)
+
+#define vSonyIsInserted(Drive_No) \
+	((vSonyInsertedMask & ((ui5b)1 << (Drive_No))) != 0)
+
+EXPORTOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer,
+	tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count,
+	ui5r *Sony_ActCount);
+EXPORTOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No);
+EXPORTOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count);
+
+EXPORTOSGLUFUNC blnr AnyDiskInserted(void);
+EXPORTOSGLUPROC DiskRevokeWritable(tDrive Drive_No);
+
+#if IncludeSonyRawMode
+EXPORTVAR(blnr, vSonyRawMode)
+#endif
+
+#if IncludeSonyNew
+EXPORTVAR(blnr, vSonyNewDiskWanted)
+EXPORTVAR(ui5b, vSonyNewDiskSize)
+EXPORTOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No);
+#endif
+
+#if IncludeSonyNameNew
+EXPORTVAR(tPbuf, vSonyNewDiskName)
+#endif
+
+#if IncludeSonyGetName
+EXPORTOSGLUFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r);
+#endif
+
+#if IncludeHostTextClipExchange
+EXPORTOSGLUFUNC tMacErr HTCEexport(tPbuf i);
+EXPORTOSGLUFUNC tMacErr HTCEimport(tPbuf *r);
+#endif
+
+EXPORTVAR(ui5b, OnTrueTime)
+
+EXPORTVAR(ui5b, CurMacDateInSeconds)
+#if AutoLocation
+EXPORTVAR(ui5b, CurMacLatitude)
+EXPORTVAR(ui5b, CurMacLongitude)
+#endif
+#if AutoTimeZone
+EXPORTVAR(ui5b, CurMacDelta)
+	/* (dlsDelta << 24) | (gmtDelta & 0x00FFFFFF) */
+#endif
+
+
+#define vMacScreenNumPixels \
+	((long)vMacScreenHeight * (long)vMacScreenWidth)
+#define vMacScreenNumBits (vMacScreenNumPixels << vMacScreenDepth)
+#define vMacScreenNumBytes (vMacScreenNumBits / 8)
+#define vMacScreenBitWidth ((long)vMacScreenWidth << vMacScreenDepth)
+#define vMacScreenByteWidth (vMacScreenBitWidth / 8)
+
+#define vMacScreenMonoNumBytes (vMacScreenNumPixels / 8)
+#define vMacScreenMonoByteWidth ((long)vMacScreenWidth / 8)
+
+#if 0 != vMacScreenDepth
+EXPORTVAR(blnr, UseColorMode)
+EXPORTVAR(blnr, ColorModeWorks)
+#endif
+
+#if 0 != vMacScreenDepth
+EXPORTVAR(blnr, ColorMappingChanged)
+#endif
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+#define CLUT_size (1 << (1 << vMacScreenDepth))
+
+EXPORTVAR(ui4r, CLUT_reds[CLUT_size])
+EXPORTVAR(ui4r, CLUT_greens[CLUT_size])
+EXPORTVAR(ui4r, CLUT_blues[CLUT_size])
+#endif
+
+EXPORTVAR(blnr, EmVideoDisable)
+EXPORTVAR(si3b, EmLagTime)
+
+EXPORTOSGLUPROC Screen_OutputFrame(ui3p screencurrentbuff);
+EXPORTOSGLUPROC DoneWithDrawingForTick(void);
+
+EXPORTVAR(blnr, ForceMacOff)
+
+EXPORTVAR(blnr, WantMacInterrupt)
+
+EXPORTVAR(blnr, WantMacReset)
+
+EXPORTOSGLUFUNC blnr ExtraTimeNotOver(void);
+
+EXPORTVAR(ui3b, SpeedValue)
+
+#if EnableAutoSlow
+EXPORTVAR(blnr, WantNotAutoSlow)
+#endif
+
+/* where emulated machine thinks mouse is */
+EXPORTVAR(ui4b, CurMouseV)
+EXPORTVAR(ui4b, CurMouseH)
+
+#if EnableAutoSlow
+EXPORTVAR(ui5r, QuietTime)
+EXPORTVAR(ui5r, QuietSubTicks)
+
+#define QuietEnds() \
+{ \
+	QuietTime = 0; \
+	QuietSubTicks = 0; \
+}
+#else
+#define QuietEnds()
+#endif
+
+#if 3 == kLn2SoundSampSz
+#define trSoundSamp ui3r
+#define tbSoundSamp ui3b
+#define tpSoundSamp ui3p
+#define kCenterSound 0x80
+#elif 4 == kLn2SoundSampSz
+#define trSoundSamp ui4r
+#define tbSoundSamp ui4b
+#define tpSoundSamp ui4p
+#define kCenterSound 0x8000
+#else
+#error "unsupported kLn2SoundSampSz"
+#endif
+
+#if MySoundEnabled
+
+EXPORTOSGLUFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL);
+EXPORTOSGLUPROC MySound_EndWrite(ui4r actL);
+
+/* 370 samples per tick = 22,254.54 per second */
+#endif
+
+#if EmLocalTalk
+
+#define LT_TxBfMxSz 1024
+EXPORTVAR(ui3p, LT_TxBuffer)
+EXPORTVAR(ui4r, LT_TxBuffSz)
+
+EXPORTOSGLUPROC LT_TransmitPacket(void);
+
+EXPORTVAR(ui3p, LT_RxBuffer)
+EXPORTVAR(ui5r, LT_RxBuffSz)
+
+EXPORTOSGLUPROC LT_ReceivePacket(void);
+
+#endif
+
+EXPORTOSGLUPROC WaitForNextTick(void);
+
+#define MyEvtQElKindKey 0
+#define MyEvtQElKindMouseButton 1
+#define MyEvtQElKindMousePos 2
+#define MyEvtQElKindMouseDelta 3
+
+struct MyEvtQEl {
+	/* expected size : 8 bytes */
+	ui3b kind;
+	ui3b pad[3];
+	union {
+		struct {
+			ui3b down;
+			ui3b key;
+		} press;
+		struct {
+			ui4b h;
+			ui4b v;
+		} pos;
+	} u;
+};
+typedef struct MyEvtQEl MyEvtQEl;
+
+EXPORTOSGLUFUNC MyEvtQEl * MyEvtQOutP(void);
+EXPORTOSGLUPROC MyEvtQOutDone(void);
+
+#define MKC_A 0x00
+#define MKC_B 0x0B
+#define MKC_C 0x08
+#define MKC_D 0x02
+#define MKC_E 0x0E
+#define MKC_F 0x03
+#define MKC_G 0x05
+#define MKC_H 0x04
+#define MKC_I 0x22
+#define MKC_J 0x26
+#define MKC_K 0x28
+#define MKC_L 0x25
+#define MKC_M 0x2E
+#define MKC_N 0x2D
+#define MKC_O 0x1F
+#define MKC_P 0x23
+#define MKC_Q 0x0C
+#define MKC_R 0x0F
+#define MKC_S 0x01
+#define MKC_T 0x11
+#define MKC_U 0x20
+#define MKC_V 0x09
+#define MKC_W 0x0D
+#define MKC_X 0x07
+#define MKC_Y 0x10
+#define MKC_Z 0x06
+
+#define MKC_1 0x12
+#define MKC_2 0x13
+#define MKC_3 0x14
+#define MKC_4 0x15
+#define MKC_5 0x17
+#define MKC_6 0x16
+#define MKC_7 0x1A
+#define MKC_8 0x1C
+#define MKC_9 0x19
+#define MKC_0 0x1D
+
+#define MKC_Command 0x37
+#define MKC_Shift 0x38
+#define MKC_CapsLock 0x39
+#define MKC_Option 0x3A
+
+#define MKC_Space 0x31
+#define MKC_Return 0x24
+#define MKC_BackSpace 0x33
+#define MKC_Tab 0x30
+
+#define MKC_Left /* 0x46 */ 0x7B
+#define MKC_Right /* 0x42 */ 0x7C
+#define MKC_Down /* 0x48 */ 0x7D
+#define MKC_Up /* 0x4D */ 0x7E
+
+#define MKC_Minus 0x1B
+#define MKC_Equal 0x18
+#define MKC_BackSlash 0x2A
+#define MKC_Comma 0x2B
+#define MKC_Period 0x2F
+#define MKC_Slash 0x2C
+#define MKC_SemiColon 0x29
+#define MKC_SingleQuote 0x27
+#define MKC_LeftBracket 0x21
+#define MKC_RightBracket 0x1E
+#define MKC_Grave 0x32
+#define MKC_Clear 0x47
+#define MKC_KPEqual 0x51
+#define MKC_KPDevide 0x4B
+#define MKC_KPMultiply 0x43
+#define MKC_KPSubtract 0x4E
+#define MKC_KPAdd 0x45
+#define MKC_Enter 0x4C
+
+#define MKC_KP1 0x53
+#define MKC_KP2 0x54
+#define MKC_KP3 0x55
+#define MKC_KP4 0x56
+#define MKC_KP5 0x57
+#define MKC_KP6 0x58
+#define MKC_KP7 0x59
+#define MKC_KP8 0x5B
+#define MKC_KP9 0x5C
+#define MKC_KP0 0x52
+#define MKC_Decimal 0x41
+
+/* these aren't on the Mac Plus keyboard */
+
+#define MKC_Control 0x3B
+#define MKC_Escape 0x35
+#define MKC_F1 0x7a
+#define MKC_F2 0x78
+#define MKC_F3 0x63
+#define MKC_F4 0x76
+#define MKC_F5 0x60
+#define MKC_F6 0x61
+#define MKC_F7 0x62
+#define MKC_F8 0x64
+#define MKC_F9 0x65
+#define MKC_F10 0x6d
+#define MKC_F11 0x67
+#define MKC_F12 0x6f
+
+#define MKC_Home 0x73
+#define MKC_End 0x77
+#define MKC_PageUp 0x74
+#define MKC_PageDown 0x79
+#define MKC_Help 0x72 /* = Insert */
+#define MKC_ForwardDel 0x75
+#define MKC_Print 0x69
+#define MKC_ScrollLock 0x6B
+#define MKC_Pause 0x71
+
+#define MKC_AngleBracket 0x0A /* found on german keyboard */
+
+/*
+	Additional codes found in Apple headers
+
+	#define MKC_RightShift 0x3C
+	#define MKC_RightOption 0x3D
+	#define MKC_RightControl 0x3E
+	#define MKC_Function 0x3F
+
+	#define MKC_VolumeUp 0x48
+	#define MKC_VolumeDown 0x49
+	#define MKC_Mute 0x4A
+
+	#define MKC_F16 0x6A
+	#define MKC_F17 0x40
+	#define MKC_F18 0x4F
+	#define MKC_F19 0x50
+	#define MKC_F20 0x5A
+
+	#define MKC_F13 MKC_Print
+	#define MKC_F14 MKC_ScrollLock
+	#define MKC_F15 MKC_Pause
+*/
+
+/* not Apple key codes, only for Mini vMac */
+
+#define MKC_CM 0x80
+#define MKC_None 0xFF
--- /dev/null
+++ b/src/OSGLUCCO.m
@@ -1,0 +1,4993 @@
+/*
+	OSGLUCCO.m
+
+	Copyright (C) 2012 Paul C. Pratt, SDL by Sam Lantinga and others
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Operating System GLUe for mac os CoCOa
+
+	All operating system dependent code for the
+	Mac OS Cocoa should go here.
+
+	Originally derived from Cocoa port of SDL Library
+	by Sam Lantinga (but little trace of that remains).
+*/
+
+#include "CNFGRAPI.h"
+#include "SYSDEPNS.h"
+#include "ENDIANAC.h"
+
+#include "MYOSGLUE.h"
+
+#include "STRCONST.h"
+
+/* --- adapting to API/ABI version differences --- */
+
+
+#ifndef MAC_OS_X_VERSION_10_5
+#define MAC_OS_X_VERSION_10_5 1050
+#endif
+
+#ifndef MAC_OS_X_VERSION_10_6
+#define MAC_OS_X_VERSION_10_6 1060
+#endif
+
+
+#ifndef WantGraphicsSwitching
+#define WantGraphicsSwitching 0
+#endif
+
+#if MAC_OS_X_VERSION_10_5 > MAC_OS_X_VERSION_MAX_ALLOWED
+
+typedef unsigned long NSUInteger;
+typedef long NSInteger;
+
+typedef struct __CFError * CFErrorRef;
+
+#if WantGraphicsSwitching
+#define NSOpenGLPFAAllowOfflineRenderers \
+	(NSOpenGLPixelFormatAttribute)96
+#endif
+
+#endif
+
+#if MAC_OS_X_VERSION_10_6 > MAC_OS_X_VERSION_MAX_ALLOWED
+
+@protocol NSWindowDelegate <NSObject> @end
+@protocol NSApplicationDelegate <NSObject> @end
+
+#endif
+
+
+LOCALVAR CFBundleRef AppServBunRef;
+
+LOCALVAR blnr DidApplicationServicesBun = falseblnr;
+
+LOCALFUNC blnr HaveApplicationServicesBun(void)
+{
+	if (! DidApplicationServicesBun) {
+		AppServBunRef = CFBundleGetBundleWithIdentifier(
+			CFSTR("com.apple.ApplicationServices"));
+		DidApplicationServicesBun = trueblnr;
+	}
+	return (AppServBunRef != NULL);
+}
+
+#if MayFullScreen
+
+LOCALVAR CFBundleRef HIToolboxBunRef;
+
+LOCALVAR blnr DidHIToolboxBunRef = falseblnr;
+
+LOCALFUNC blnr HaveHIToolboxBunRef(void)
+{
+	if (! DidHIToolboxBunRef) {
+		HIToolboxBunRef = CFBundleGetBundleWithIdentifier(
+			CFSTR("com.apple.HIToolbox"));
+		DidHIToolboxBunRef = trueblnr;
+	}
+	return (HIToolboxBunRef != NULL);
+}
+
+#endif
+
+
+#if MayFullScreen
+
+/* SetSystemUIModeProcPtr API always not available */
+
+typedef UInt32                          MySystemUIMode;
+typedef OptionBits                      MySystemUIOptions;
+
+enum {
+	MykUIModeNormal                 = 0,
+	MykUIModeAllHidden              = 3
+};
+
+enum {
+	MykUIOptionAutoShowMenuBar      = 1 << 0,
+	MykUIOptionDisableAppleMenu     = 1 << 2,
+	MykUIOptionDisableProcessSwitch = 1 << 3,
+	MykUIOptionDisableForceQuit     = 1 << 4,
+	MykUIOptionDisableSessionTerminate = 1 << 5,
+	MykUIOptionDisableHide          = 1 << 6
+};
+
+typedef OSStatus (*SetSystemUIModeProcPtr)
+	(MySystemUIMode inMode, MySystemUIOptions inOptions);
+LOCALVAR SetSystemUIModeProcPtr MySetSystemUIMode = NULL;
+LOCALVAR blnr DidSetSystemUIMode = falseblnr;
+
+LOCALFUNC blnr HaveMySetSystemUIMode(void)
+{
+	if (! DidSetSystemUIMode) {
+		if (HaveHIToolboxBunRef()) {
+			MySetSystemUIMode =
+				(SetSystemUIModeProcPtr)
+				CFBundleGetFunctionPointerForName(
+					HIToolboxBunRef, CFSTR("SetSystemUIMode"));
+		}
+		DidSetSystemUIMode = trueblnr;
+	}
+	return (MySetSystemUIMode != NULL);
+}
+
+#endif
+
+
+typedef Boolean (*CFURLCopyResourcePropertyForKeyProcPtr) (
+	CFURLRef    url,
+	CFStringRef key,
+	void        *propertyValueTypeRefPtr,
+	CFErrorRef  *error
+	);
+LOCALVAR CFURLCopyResourcePropertyForKeyProcPtr
+	MyCFURLCopyResourcePropertyForKey = NULL;
+LOCALVAR blnr DidCFURLCopyResourcePropertyForKey = falseblnr;
+
+LOCALFUNC blnr HaveMyCFURLCopyResourcePropertyForKey(void)
+{
+	if (! DidCFURLCopyResourcePropertyForKey) {
+		if (HaveApplicationServicesBun()) {
+			MyCFURLCopyResourcePropertyForKey =
+				(CFURLCopyResourcePropertyForKeyProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AppServBunRef,
+					CFSTR("CFURLCopyResourcePropertyForKey"));
+		}
+		DidCFURLCopyResourcePropertyForKey = trueblnr;
+	}
+	return (MyCFURLCopyResourcePropertyForKey != NULL);
+}
+
+
+LOCALVAR const CFStringRef *MykCFURLIsAliasFileKey
+	= NULL;
+LOCALVAR blnr DidkCFURLIsAliasFileKey = falseblnr;
+
+LOCALFUNC blnr HaveMykCFURLIsAliasFileKey(void)
+{
+	if (! DidkCFURLIsAliasFileKey) {
+		if (HaveApplicationServicesBun()) {
+			MykCFURLIsAliasFileKey =
+				(const CFStringRef *)
+				CFBundleGetDataPointerForName(
+					AppServBunRef, CFSTR("kCFURLIsAliasFileKey"));
+		}
+		DidkCFURLIsAliasFileKey = trueblnr;
+	}
+	return (MykCFURLIsAliasFileKey != NULL);
+}
+
+
+LOCALVAR const CFStringRef *MykCFURLIsSymbolicLinkKey
+	= NULL;
+LOCALVAR blnr DidkCFURLIsSymbolicLinkKey = falseblnr;
+
+LOCALFUNC blnr HaveMykCFURLIsSymbolicLinkKey(void)
+{
+	if (! DidkCFURLIsSymbolicLinkKey) {
+		if (HaveApplicationServicesBun()) {
+			MykCFURLIsSymbolicLinkKey =
+				(const CFStringRef *)
+				CFBundleGetDataPointerForName(
+					AppServBunRef, CFSTR("kCFURLIsSymbolicLinkKey"));
+		}
+		DidkCFURLIsSymbolicLinkKey = trueblnr;
+	}
+	return (MykCFURLIsSymbolicLinkKey != NULL);
+}
+
+
+typedef CFDataRef (*CFURLCreateBookmarkDataFromFileProcPtr) (
+	CFAllocatorRef allocator, CFURLRef fileURL, CFErrorRef *errorRef);
+LOCALVAR CFURLCreateBookmarkDataFromFileProcPtr
+	MyCFURLCreateBookmarkDataFromFile = NULL;
+LOCALVAR blnr DidCFURLCreateBookmarkDataFromFile = falseblnr;
+
+LOCALFUNC blnr HaveMyCFURLCreateBookmarkDataFromFile(void)
+{
+	if (! DidCFURLCreateBookmarkDataFromFile) {
+		if (HaveApplicationServicesBun()) {
+			MyCFURLCreateBookmarkDataFromFile =
+				(CFURLCreateBookmarkDataFromFileProcPtr)
+				CFBundleGetFunctionPointerForName(AppServBunRef,
+					CFSTR("CFURLCreateBookmarkDataFromFile"));
+		}
+		DidCFURLCreateBookmarkDataFromFile = trueblnr;
+	}
+	return (MyCFURLCreateBookmarkDataFromFile != NULL);
+}
+
+
+typedef CFOptionFlags MyCFURLBookmarkResolutionOptions;
+
+typedef CFURLRef (*CFURLCreateByResolvingBookmarkDataProcPtr) (
+	CFAllocatorRef allocator, CFDataRef bookmark,
+	MyCFURLBookmarkResolutionOptions options, CFURLRef relativeToURL,
+	CFArrayRef resourcePropertiesToInclude,
+	Boolean* isStale, CFErrorRef* error);
+LOCALVAR CFURLCreateByResolvingBookmarkDataProcPtr
+	MyCFURLCreateByResolvingBookmarkData = NULL;
+LOCALVAR blnr DidCFURLCreateByResolvingBookmarkData = falseblnr;
+
+LOCALFUNC blnr HaveMyCFURLCreateByResolvingBookmarkData(void)
+{
+	if (! DidCFURLCreateByResolvingBookmarkData) {
+		if (HaveApplicationServicesBun()) {
+			MyCFURLCreateByResolvingBookmarkData =
+				(CFURLCreateByResolvingBookmarkDataProcPtr)
+				CFBundleGetFunctionPointerForName(AppServBunRef,
+					CFSTR("CFURLCreateByResolvingBookmarkData"));
+		}
+		DidCFURLCreateByResolvingBookmarkData = trueblnr;
+	}
+	return (MyCFURLCreateByResolvingBookmarkData != NULL);
+}
+
+
+typedef boolean_t (*CGCursorIsVisibleProcPtr)(void);
+
+LOCALVAR CGCursorIsVisibleProcPtr MyCGCursorIsVisible = NULL;
+LOCALVAR blnr DidCGCursorIsVisible = falseblnr;
+
+LOCALFUNC blnr HaveMyCGCursorIsVisible(void)
+{
+	if (! DidCGCursorIsVisible) {
+		if (HaveApplicationServicesBun()) {
+			MyCGCursorIsVisible =
+				(CGCursorIsVisibleProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AppServBunRef, CFSTR("CGCursorIsVisible"));
+		}
+		DidCGCursorIsVisible = trueblnr;
+	}
+	return (MyCGCursorIsVisible != NULL);
+}
+
+
+/* --- some simple utilities --- */
+
+GLOBALOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount)
+{
+	(void) memcpy((char *)destPtr, (char *)srcPtr, byteCount);
+}
+
+/* --- control mode and internationalization --- */
+
+#define NeedCell2UnicodeMap 1
+
+#include "INTLCHAR.h"
+
+/* --- sending debugging info to file --- */
+
+LOCALVAR NSString *myAppName = nil;
+LOCALVAR NSString *MyDataPath = nil;
+
+#if dbglog_HAVE
+
+#define dbglog_ToStdErr 0
+
+#if ! dbglog_ToStdErr
+LOCALVAR FILE *dbglog_File = NULL;
+#endif
+
+LOCALFUNC blnr dbglog_open0(void)
+{
+#if dbglog_ToStdErr
+	return trueblnr;
+#else
+	NSString *myLogPath = [MyDataPath
+		stringByAppendingPathComponent: @"dbglog.txt"];
+	const char *path = [myLogPath fileSystemRepresentation];
+
+	dbglog_File = fopen(path, "w");
+	return (NULL != dbglog_File);
+#endif
+}
+
+LOCALPROC dbglog_write0(char *s, uimr L)
+{
+#if dbglog_ToStdErr
+	(void) fwrite(s, 1, L, stderr);
+#else
+	if (NULL != dbglog_File) {
+		(void) fwrite(s, 1, L, dbglog_File);
+	}
+#endif
+}
+
+LOCALPROC dbglog_close0(void)
+{
+#if ! dbglog_ToStdErr
+	if (NULL != dbglog_File) {
+		fclose(dbglog_File);
+		dbglog_File = NULL;
+	}
+#endif
+}
+
+#endif
+
+/* --- information about the environment --- */
+
+#define WantColorTransValid 1
+
+#include "COMOSGLU.h"
+
+#define WantKeyboard_RemapMac 1
+
+#include "PBUFSTDC.h"
+
+#include "CONTROLM.h"
+
+/* --- text translation --- */
+
+LOCALPROC UniCharStrFromSubstCStr(int *L, unichar *x, char *s)
+{
+	int i;
+	int L0;
+	ui3b ps[ClStrMaxLength];
+
+	ClStrFromSubstCStr(&L0, ps, s);
+
+	for (i = 0; i < L0; ++i) {
+		x[i] = Cell2UnicodeMap[ps[i]];
+	}
+
+	*L = L0;
+}
+
+LOCALFUNC NSString * NSStringCreateFromSubstCStr(char *s)
+{
+	int L;
+	unichar x[ClStrMaxLength];
+
+	UniCharStrFromSubstCStr(&L, x, s);
+
+	return [NSString stringWithCharacters:x length:L];
+}
+
+#if IncludeSonyNameNew
+LOCALFUNC blnr MacRomanFileNameToNSString(tPbuf i,
+	NSString **r)
+{
+	ui3p p;
+	void *Buffer = PbufDat[i];
+	ui5b L = PbufSize[i];
+
+	p = (ui3p)malloc(L /* + 1 */);
+	if (p != NULL) {
+		NSData *d;
+		ui3b *p0 = (ui3b *)Buffer;
+		ui3b *p1 = (ui3b *)p;
+
+		if (L > 0) {
+			ui5b j = L;
+
+			do {
+				ui3b x = *p0++;
+				if (x < 32) {
+					x = '-';
+				} else if (x >= 128) {
+				} else {
+					switch (x) {
+						case '/':
+						case '<':
+						case '>':
+						case '|':
+						case ':':
+							x = '-';
+						default:
+							break;
+					}
+				}
+				*p1++ = x;
+			} while (--j > 0);
+
+			if ('.' == p[0]) {
+				p[0] = '-';
+			}
+		}
+
+#if 0
+		*p1 = 0;
+		*r = [NSString stringWithCString:(char *)p
+			encoding:NSMacOSRomanStringEncoding];
+			/* only as of OS X 10.4 */
+		free(p);
+#endif
+
+		d = [[NSData alloc] initWithBytesNoCopy:p length:L];
+
+		*r = [[[NSString alloc]
+			initWithData:d encoding:NSMacOSRomanStringEncoding]
+			autorelease];
+
+		[d release];
+
+		return trueblnr;
+	}
+
+	return falseblnr;
+}
+#endif
+
+#if IncludeSonyGetName || IncludeHostTextClipExchange
+LOCALFUNC tMacErr NSStringToRomanPbuf(NSString *string, tPbuf *r)
+{
+	tMacErr v = mnvm_miscErr;
+	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+#if 0
+	const char *s = [s0
+		cStringUsingEncoding: NSMacOSRomanStringEncoding];
+	ui5r L = strlen(s);
+		/* only as of OS X 10.4 */
+#endif
+#if 0
+	NSData *d0 = [string dataUsingEncoding: NSMacOSRomanStringEncoding];
+#endif
+	NSData *d0 = [string dataUsingEncoding: NSMacOSRomanStringEncoding
+		allowLossyConversion: YES];
+	const void *s = [d0 bytes];
+	NSUInteger L = [d0 length];
+
+	if (NULL == s) {
+		v = mnvm_miscErr;
+	} else {
+		ui3p p = (ui3p)malloc(L);
+
+		if (NULL == p) {
+			v = mnvm_miscErr;
+		} else {
+			/* memcpy((char *)p, s, L); */
+			ui3b *p0 = (ui3b *)s;
+			ui3b *p1 = (ui3b *)p;
+			int i;
+
+			for (i = L; --i >= 0; ) {
+				ui3b v = *p0++;
+				if (10 == v) {
+					v = 13;
+				}
+				*p1++ = v;
+			}
+
+			v = PbufNewFromPtr(p, L, r);
+		}
+	}
+
+	[pool release];
+
+	return v;
+}
+#endif
+
+/* --- drives --- */
+
+LOCALFUNC blnr FindNamedChildPath(NSString *parentPath,
+	char *ChildName, NSString **childPath)
+{
+	blnr v = falseblnr;
+
+#if 0
+	NSString *ss = [NSString stringWithCString:s
+		encoding:NSASCIIStringEncoding];
+		/* only as of OS X 10.4 */
+#endif
+#if 0
+	NSData *d = [NSData dataWithBytes: ChildName
+		length: strlen(ChildName)];
+	NSString *ss = [[[NSString alloc]
+		initWithData:d encoding:NSASCIIStringEncoding]
+		autorelease];
+#endif
+	NSString *ss = NSStringCreateFromSubstCStr(ChildName);
+	if (nil != ss) {
+		NSString *r = [parentPath stringByAppendingPathComponent: ss];
+		if (nil != r) {
+			*childPath = r;
+			v = trueblnr;
+		}
+	}
+
+	return v;
+}
+
+LOCALFUNC NSString *MyResolveAlias(NSString *filePath,
+	Boolean *targetIsFolder)
+{
+	NSString *resolvedPath = nil;
+	CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
+		(CFStringRef)filePath, kCFURLPOSIXPathStyle, NO);
+
+
+	if (url != NULL) {
+		if (HaveMyCFURLCopyResourcePropertyForKey()
+			&& HaveMykCFURLIsAliasFileKey()
+			&& HaveMykCFURLIsSymbolicLinkKey()
+			&& HaveMyCFURLCreateBookmarkDataFromFile()
+			&& HaveMyCFURLCreateByResolvingBookmarkData())
+		{
+			BOOL isDir;
+			Boolean isStale;
+			CFBooleanRef is_alias_file = NULL;
+			CFBooleanRef is_symbolic_link = NULL;
+			CFDataRef bookmark = NULL;
+			CFURLRef resolvedurl = NULL;
+
+			if (MyCFURLCopyResourcePropertyForKey(url,
+				*MykCFURLIsAliasFileKey, &is_alias_file, NULL))
+			if (CFBooleanGetValue(is_alias_file))
+			if (MyCFURLCopyResourcePropertyForKey(url,
+				*MykCFURLIsSymbolicLinkKey, &is_symbolic_link, NULL))
+			if (! CFBooleanGetValue(is_symbolic_link))
+			if (NULL != (bookmark = MyCFURLCreateBookmarkDataFromFile(
+				kCFAllocatorDefault, url, NULL)))
+			if (NULL != (resolvedurl =
+				MyCFURLCreateByResolvingBookmarkData(
+					kCFAllocatorDefault,
+					bookmark,
+					0 /* MyCFURLBookmarkResolutionOptions options */,
+					NULL /* relativeToURL */,
+					NULL /* resourcePropertiesToInclude */,
+					&isStale,
+					NULL /* error */)))
+			if (nil != (resolvedPath =
+				(NSString *)CFURLCopyFileSystemPath(
+					resolvedurl, kCFURLPOSIXPathStyle)))
+			{
+				if ([[NSFileManager defaultManager]
+					fileExistsAtPath: resolvedPath isDirectory: &isDir])
+				{
+					*targetIsFolder = isDir;
+				} else
+				{
+					*targetIsFolder = FALSE;
+				}
+
+				[resolvedPath autorelease];
+			}
+
+			if (NULL != resolvedurl) {
+				CFRelease(resolvedurl);
+			}
+			if (NULL != bookmark) {
+				CFRelease(bookmark);
+			}
+			if (NULL != is_alias_file) {
+				CFRelease(is_alias_file);
+			}
+			if (NULL != is_symbolic_link) {
+				CFRelease(is_symbolic_link);
+			}
+		} else {
+			FSRef fsRef;
+			Boolean wasAliased;
+
+			if (CFURLGetFSRef(url, &fsRef)) {
+				/*
+					FSResolveAliasFile deprecated in 10.8
+				*/
+
+				if ((FSResolveAliasFile(&fsRef,
+					TRUE /*resolveAliasChains*/,
+					targetIsFolder, &wasAliased) == noErr)
+					&& wasAliased)
+				{
+					CFURLRef resolvedurl =
+						CFURLCreateFromFSRef(kCFAllocatorDefault,
+							&fsRef);
+					if (resolvedurl != NULL) {
+						resolvedPath =
+							(NSString *)CFURLCopyFileSystemPath(
+								resolvedurl, kCFURLPOSIXPathStyle);
+						[resolvedPath autorelease];
+						CFRelease(resolvedurl);
+					}
+				}
+			}
+		}
+
+		CFRelease(url);
+	}
+
+	return resolvedPath;
+}
+
+LOCALFUNC blnr FindNamedChildDirPath(NSString *parentPath,
+	char *ChildName, NSString **childPath)
+{
+	NSString *r;
+	BOOL isDir;
+	Boolean isDirectory;
+	blnr v = falseblnr;
+
+	if (FindNamedChildPath(parentPath, ChildName, &r))
+	if ([[NSFileManager defaultManager]
+		fileExistsAtPath:r isDirectory: &isDir])
+	{
+		if (isDir) {
+			*childPath = r;
+			v = trueblnr;
+		} else {
+			NSString *RslvPath = MyResolveAlias(r, &isDirectory);
+			if (nil != RslvPath) {
+				if (isDirectory) {
+					*childPath = RslvPath;
+					v = trueblnr;
+				}
+			}
+		}
+	}
+
+	return v;
+}
+
+LOCALFUNC blnr FindNamedChildFilePath(NSString *parentPath,
+	char *ChildName, NSString **childPath)
+{
+	NSString *r;
+	BOOL isDir;
+	Boolean isDirectory;
+	blnr v = falseblnr;
+
+	if (FindNamedChildPath(parentPath, ChildName, &r))
+	if ([[NSFileManager defaultManager]
+		fileExistsAtPath:r isDirectory: &isDir])
+	{
+		if (! isDir) {
+			NSString *RslvPath = MyResolveAlias(r, &isDirectory);
+			if (nil != RslvPath) {
+				if (! isDirectory) {
+					*childPath = RslvPath;
+					v = trueblnr;
+				}
+			} else {
+				*childPath = r;
+				v = trueblnr;
+			}
+		}
+	}
+
+	return v;
+}
+
+
+#define NotAfileRef NULL
+
+LOCALVAR FILE *Drives[NumDrives]; /* open disk image files */
+#if IncludeSonyGetName || IncludeSonyNew
+LOCALVAR NSString *DriveNames[NumDrives];
+#endif
+
+LOCALPROC InitDrives(void)
+{
+	/*
+		This isn't really needed, Drives[i] and DriveNames[i]
+		need not have valid values when not vSonyIsInserted[i].
+	*/
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		Drives[i] = NotAfileRef;
+#if IncludeSonyGetName || IncludeSonyNew
+		DriveNames[i] = nil;
+#endif
+	}
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer,
+	tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count,
+	ui5r *Sony_ActCount)
+{
+	tMacErr err = mnvm_miscErr;
+	FILE *refnum = Drives[Drive_No];
+	ui5r NewSony_Count = 0;
+
+	if (0 == fseek(refnum, Sony_Start, SEEK_SET)) {
+		if (IsWrite) {
+			NewSony_Count = fwrite(Buffer, 1, Sony_Count, refnum);
+		} else {
+			NewSony_Count = fread(Buffer, 1, Sony_Count, refnum);
+		}
+
+		if (NewSony_Count == Sony_Count) {
+			err = mnvm_noErr;
+		}
+	}
+
+	if (nullpr != Sony_ActCount) {
+		*Sony_ActCount = NewSony_Count;
+	}
+
+	return err; /*& figure out what really to return &*/
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count)
+{
+	tMacErr err = mnvm_miscErr;
+	FILE *refnum = Drives[Drive_No];
+	long v;
+
+	if (0 == fseek(refnum, 0, SEEK_END)) {
+		v = ftell(refnum);
+		if (v >= 0) {
+			*Sony_Count = v;
+			err = mnvm_noErr;
+		}
+	}
+
+	return err; /*& figure out what really to return &*/
+}
+
+#ifndef HaveAdvisoryLocks
+#define HaveAdvisoryLocks 1
+#endif
+
+/*
+	What is the difference between fcntl(fd, F_SETLK ...
+	and flock(fd ... ?
+*/
+
+#if HaveAdvisoryLocks
+LOCALFUNC blnr MyLockFile(FILE *refnum)
+{
+	blnr IsOk = falseblnr;
+
+#if 0
+	struct flock fl;
+	int fd = fileno(refnum);
+
+	fl.l_start = 0; /* starting offset */
+	fl.l_len = 0; /* len = 0 means until end of file */
+	/* fl.pid_t l_pid; */ /* lock owner, don't need to set */
+	fl.l_type = F_WRLCK; /* lock type: read/write, etc. */
+	fl.l_whence = SEEK_SET; /* type of l_start */
+	if (-1 == fcntl(fd, F_SETLK, &fl)) {
+		MacMsg(kStrImageInUseTitle, kStrImageInUseMessage,
+			falseblnr);
+	} else {
+		IsOk = trueblnr;
+	}
+#else
+	int fd = fileno(refnum);
+
+	if (-1 == flock(fd, LOCK_EX | LOCK_NB)) {
+		if (EWOULDBLOCK == errno) {
+			/* already locked */
+			MacMsg(kStrImageInUseTitle, kStrImageInUseMessage,
+				falseblnr);
+		} else
+		{
+			/*
+				Failed for other reasons, such as unsupported
+				for this volume.
+				Don't prevent opening.
+			*/
+			IsOk = trueblnr;
+		}
+	} else {
+		IsOk = trueblnr;
+	}
+#endif
+
+	return IsOk;
+}
+#endif
+
+#if HaveAdvisoryLocks
+LOCALPROC MyUnlockFile(FILE *refnum)
+{
+#if 0
+	struct flock fl;
+	int fd = fileno(refnum);
+
+	fl.l_start = 0; /* starting offset */
+	fl.l_len = 0; /* len = 0 means until end of file */
+	/* fl.pid_t l_pid; */ /* lock owner, don't need to set */
+	fl.l_type = F_UNLCK;     /* lock type: read/write, etc. */
+	fl.l_whence = SEEK_SET;   /* type of l_start */
+	if (-1 == fcntl(fd, F_SETLK, &fl)) {
+		/* an error occurred */
+	}
+#else
+	int fd = fileno(refnum);
+
+	if (-1 == flock(fd, LOCK_UN)) {
+	}
+#endif
+}
+#endif
+
+LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, blnr deleteit)
+{
+	FILE *refnum = Drives[Drive_No];
+
+	DiskEjectedNotify(Drive_No);
+
+#if HaveAdvisoryLocks
+	MyUnlockFile(refnum);
+#endif
+
+	fclose(refnum);
+	Drives[Drive_No] = NotAfileRef; /* not really needed */
+
+#if IncludeSonyGetName || IncludeSonyNew
+	{
+		NSString *filePath = DriveNames[Drive_No];
+		if (NULL != filePath) {
+			if (deleteit) {
+				NSAutoreleasePool *pool =
+					[[NSAutoreleasePool alloc] init];
+				const char *s = [filePath fileSystemRepresentation];
+				remove(s);
+				[pool release];
+			}
+			[filePath release];
+			DriveNames[Drive_No] = NULL; /* not really needed */
+		}
+	}
+#endif
+
+	return mnvm_noErr;
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
+{
+	return vSonyEject0(Drive_No, falseblnr);
+}
+
+#if IncludeSonyNew
+GLOBALOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No)
+{
+	return vSonyEject0(Drive_No, trueblnr);
+}
+#endif
+
+LOCALPROC UnInitDrives(void)
+{
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		if (vSonyIsInserted(i)) {
+			(void) vSonyEject(i);
+		}
+	}
+}
+
+#if IncludeSonyGetName
+GLOBALOSGLUFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r)
+{
+	tMacErr v = mnvm_miscErr;
+	NSString *filePath = DriveNames[Drive_No];
+	if (NULL != filePath) {
+		NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+		NSString *s0 = [filePath lastPathComponent];
+		v = NSStringToRomanPbuf(s0, r);
+
+		[pool release];
+	}
+
+	return v;
+}
+#endif
+
+LOCALFUNC blnr Sony_Insert0(FILE *refnum, blnr locked,
+	NSString *filePath)
+{
+	tDrive Drive_No;
+	blnr IsOk = falseblnr;
+
+	if (! FirstFreeDisk(&Drive_No)) {
+		MacMsg(kStrTooManyImagesTitle, kStrTooManyImagesMessage,
+			falseblnr);
+	} else {
+		/* printf("Sony_Insert0 %d\n", (int)Drive_No); */
+
+#if HaveAdvisoryLocks
+		if (locked || MyLockFile(refnum))
+#endif
+		{
+			Drives[Drive_No] = refnum;
+			DiskInsertNotify(Drive_No, locked);
+
+#if IncludeSonyGetName || IncludeSonyNew
+			DriveNames[Drive_No] = [filePath retain];
+#endif
+
+			IsOk = trueblnr;
+		}
+	}
+
+	if (! IsOk) {
+		fclose(refnum);
+	}
+
+	return IsOk;
+}
+
+LOCALFUNC blnr Sony_Insert1(NSString *filePath, blnr silentfail)
+{
+	/* const char *drivepath = [filePath UTF8String]; */
+	const char *drivepath = [filePath fileSystemRepresentation];
+	blnr locked = falseblnr;
+	/* printf("Sony_Insert1 %s\n", drivepath); */
+	FILE *refnum = fopen(drivepath, "rb+");
+	if (NULL == refnum) {
+		locked = trueblnr;
+		refnum = fopen(drivepath, "rb");
+	}
+	if (NULL == refnum) {
+		if (! silentfail) {
+			MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
+		}
+	} else {
+		return Sony_Insert0(refnum, locked, filePath);
+	}
+	return falseblnr;
+}
+
+LOCALFUNC blnr Sony_Insert2(char *s)
+{
+	NSString *sPath;
+
+	if (! FindNamedChildFilePath(MyDataPath, s, &sPath)) {
+		return falseblnr;
+	} else {
+		return Sony_Insert1(sPath, trueblnr);
+	}
+}
+
+LOCALFUNC tMacErr LoadMacRomPath(NSString *RomPath)
+{
+	FILE *ROM_File;
+	int File_Size;
+	tMacErr err = mnvm_fnfErr;
+	const char *path = [RomPath fileSystemRepresentation];
+
+	ROM_File = fopen(path, "rb");
+	if (NULL != ROM_File) {
+		File_Size = fread(ROM, 1, kROM_Size, ROM_File);
+		if (kROM_Size != File_Size) {
+			if (feof(ROM_File)) {
+				MacMsgOverride(kStrShortROMTitle,
+					kStrShortROMMessage);
+				err = mnvm_eofErr;
+			} else {
+				MacMsgOverride(kStrNoReadROMTitle,
+					kStrNoReadROMMessage);
+				err = mnvm_miscErr;
+			}
+		} else {
+			err = ROM_IsValid();
+		}
+		fclose(ROM_File);
+	}
+
+	return err;
+}
+
+LOCALFUNC blnr Sony_Insert1a(NSString *filePath)
+{
+	blnr v;
+
+	if (! ROM_loaded) {
+		v = (mnvm_noErr == LoadMacRomPath(filePath));
+	} else {
+		v = Sony_Insert1(filePath, falseblnr);
+	}
+
+	return v;
+}
+
+LOCALPROC Sony_ResolveInsert(NSString *filePath)
+{
+	Boolean isDirectory;
+	NSString *RslvPath = MyResolveAlias(filePath, &isDirectory);
+	if (nil != RslvPath) {
+		if (! isDirectory) {
+			(void) Sony_Insert1a(RslvPath);
+		}
+	} else {
+		(void) Sony_Insert1a(filePath);
+	}
+}
+
+LOCALFUNC blnr Sony_InsertIth(int i)
+{
+	blnr v;
+
+	if ((i > 9) || ! FirstFreeDisk(nullpr)) {
+		v = falseblnr;
+	} else {
+		char s[] = "disk?.dsk";
+
+		s[4] = '0' + i;
+
+		v = Sony_Insert2(s);
+	}
+
+	return v;
+}
+
+LOCALFUNC blnr LoadInitialImages(void)
+{
+	if (! AnyDiskInserted()) {
+		int i;
+
+		for (i = 1; Sony_InsertIth(i); ++i) {
+			/* stop on first error (including file not found) */
+		}
+	}
+
+	return trueblnr;
+}
+
+#if IncludeSonyNew
+LOCALFUNC blnr WriteZero(FILE *refnum, ui5b L)
+{
+#define ZeroBufferSize 2048
+	ui5b i;
+	ui3b buffer[ZeroBufferSize];
+
+	memset(&buffer, 0, ZeroBufferSize);
+
+	while (L > 0) {
+		i = (L > ZeroBufferSize) ? ZeroBufferSize : L;
+		if (fwrite(buffer, 1, i, refnum) != i) {
+			return falseblnr;
+		}
+		L -= i;
+	}
+	return trueblnr;
+}
+#endif
+
+#if IncludeSonyNew
+LOCALPROC MakeNewDisk0(ui5b L, NSString *sPath)
+{
+	blnr IsOk = falseblnr;
+	const char *drivepath = [sPath fileSystemRepresentation];
+	FILE *refnum = fopen(drivepath, "wb+");
+	if (NULL == refnum) {
+		MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
+	} else {
+		if (WriteZero(refnum, L)) {
+			IsOk = Sony_Insert0(refnum, falseblnr, sPath);
+			refnum = NULL;
+		}
+		if (refnum != NULL) {
+			fclose(refnum);
+		}
+		if (! IsOk) {
+			(void) remove(drivepath);
+		}
+	}
+}
+#endif
+
+/* --- ROM --- */
+
+LOCALFUNC tMacErr LoadMacRomFrom(NSString *parentPath)
+{
+	NSString *RomPath;
+	tMacErr err = mnvm_fnfErr;
+
+	if (FindNamedChildFilePath(parentPath, RomFileName, &RomPath)) {
+		err = LoadMacRomPath(RomPath);
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr LoadMacRomFromAppDir(void)
+{
+	return LoadMacRomFrom(MyDataPath);
+}
+
+LOCALFUNC tMacErr LoadMacRomFromPrefDir(void)
+{
+	NSString *PrefsPath;
+	NSString *GryphelPath;
+	NSString *RomsPath;
+	tMacErr err = mnvm_fnfErr;
+	NSArray *paths = NSSearchPathForDirectoriesInDomains(
+		NSLibraryDirectory, NSUserDomainMask, YES);
+	if ((nil != paths) && ([paths count] > 0))
+	{
+		NSString *LibPath = [paths objectAtIndex:0];
+		if (FindNamedChildDirPath(LibPath, "Preferences", &PrefsPath))
+		if (FindNamedChildDirPath(PrefsPath, "Gryphel", &GryphelPath))
+		if (FindNamedChildDirPath(GryphelPath, "mnvm_rom", &RomsPath))
+		{
+			err = LoadMacRomFrom(RomsPath);
+		}
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr LoadMacRomFromGlobalDir(void)
+{
+	NSString *GryphelPath;
+	NSString *RomsPath;
+	tMacErr err = mnvm_fnfErr;
+	NSArray *paths = NSSearchPathForDirectoriesInDomains(
+		NSApplicationSupportDirectory, NSLocalDomainMask, NO);
+	if ((nil != paths) && ([paths count] > 0))
+	{
+		NSString *LibPath = [paths objectAtIndex:0];
+		if (FindNamedChildDirPath(LibPath, "Gryphel", &GryphelPath))
+		if (FindNamedChildDirPath(GryphelPath, "mnvm_rom", &RomsPath))
+		{
+			err = LoadMacRomFrom(RomsPath);
+		}
+	}
+
+	return err;
+}
+
+LOCALFUNC blnr LoadMacRom(void)
+{
+	tMacErr err;
+
+	if (mnvm_fnfErr == (err = LoadMacRomFromAppDir()))
+	if (mnvm_fnfErr == (err = LoadMacRomFromPrefDir()))
+	if (mnvm_fnfErr == (err = LoadMacRomFromGlobalDir()))
+	{
+	}
+
+	return trueblnr; /* keep launching Mini vMac, regardless */
+}
+
+
+#if IncludeHostTextClipExchange
+GLOBALOSGLUFUNC tMacErr HTCEexport(tPbuf i)
+{
+	void *Buffer;
+	ui5r L;
+	tMacErr err = mnvm_miscErr;
+
+	PbufKillToPtr(&Buffer, &L, i);
+
+	if (L > 0) {
+		int j;
+		ui3b *p = (ui3b *)Buffer;
+
+		for (j = L; --j >= 0; ) {
+			ui3b v = *p;
+			if (13 == v) {
+				*p = 10;
+			}
+			++p;
+		}
+	}
+
+	{
+		NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+		NSData *d = [[NSData alloc]
+			initWithBytesNoCopy: Buffer length: L];
+		/* NSData *d = [NSData dataWithBytes: Buffer length: L]; */
+		NSString *ss = [[[NSString alloc]
+			initWithData:d encoding:NSMacOSRomanStringEncoding]
+			autorelease];
+		NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
+		NSArray *newTypes =
+			[NSArray arrayWithObject: NSStringPboardType];
+
+		(void) [pasteboard declareTypes: newTypes owner: nil];
+		if ([pasteboard setString: ss forType: NSStringPboardType]) {
+			err = mnvm_noErr;
+		}
+
+		[d release];
+
+		[pool release];
+	}
+
+	return err;
+}
+#endif
+
+#if IncludeHostTextClipExchange
+GLOBALOSGLUFUNC tMacErr HTCEimport(tPbuf *r)
+{
+	tMacErr err = mnvm_miscErr;
+	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+	NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
+	NSArray *supportedTypes = [NSArray
+		arrayWithObject: NSStringPboardType];
+	NSString *available = [pasteboard
+		availableTypeFromArray: supportedTypes];
+
+	if (nil != available) {
+		NSString *string = [pasteboard
+			stringForType: NSStringPboardType];
+		if (nil != string) {
+			err = NSStringToRomanPbuf(string, r);
+		}
+	}
+
+	[pool release];
+
+	return err;
+}
+#endif
+
+
+#if EmLocalTalk
+
+#include "BPFILTER.h"
+
+#endif
+
+
+#define UseCGContextDrawImage 0
+
+LOCALVAR NSWindow *MyWindow = nil;
+LOCALVAR NSView *MyNSview = nil;
+#if UseCGContextDrawImage
+LOCALVAR NSGraphicsContext *MyNSgfxContext = nil;
+LOCALVAR CGContextRef MyCGcontext = nil;
+LOCALVAR void *MyPixels = NULL;
+LOCALVAR ui4b MyPitch;
+LOCALVAR ui3b MyBytesPerPixel;
+#endif
+
+LOCALVAR NSOpenGLContext *MyNSOpnGLCntxt = nil;
+LOCALVAR short GLhOffset;
+LOCALVAR short GLvOffset;
+	/* OpenGL coordinates of upper left point of drawing area */
+
+
+LOCALPROC MyHideCursor(void)
+{
+	[NSCursor hide];
+}
+
+LOCALPROC MyShowCursor(void)
+{
+	if (nil != MyWindow) {
+		[MyWindow invalidateCursorRectsForView:
+			MyNSview];
+	}
+#if 0
+	[cursor->nscursor performSelectorOnMainThread: @selector(set)
+		withObject: nil waitUntilDone: NO];
+#endif
+#if 0
+	[[NSCursor arrowCursor] set];
+#endif
+	[NSCursor unhide];
+}
+
+#if EnableMoveMouse
+LOCALFUNC CGPoint QZ_PrivateSDLToCG(NSPoint *p)
+{
+	CGPoint cgp;
+
+	*p = [MyNSview convertPoint: *p toView: nil];
+	p->y = [MyNSview frame].size.height - p->y;
+	*p = [MyWindow convertBaseToScreen: *p];
+
+	cgp.x = p->x;
+	cgp.y = CGDisplayPixelsHigh(kCGDirectMainDisplay)
+		- p->y;
+
+	return cgp;
+}
+#endif
+
+LOCALPROC QZ_GetMouseLocation(NSPoint *p)
+{
+	/* incorrect while window is being dragged */
+
+	*p = [NSEvent mouseLocation]; /* global coordinates */
+	if (nil != MyWindow) {
+		*p = [MyWindow convertScreenToBase: *p];
+	}
+	*p = [MyNSview convertPoint: *p fromView: nil];
+	p->y = [MyNSview frame].size.height - p->y;
+}
+
+/* --- keyboard --- */
+
+LOCALVAR NSUInteger MyCurrentMods = 0;
+
+/*
+	Apple documentation says:
+	"The lower 16 bits of the modifier flags are reserved
+	for device-dependent bits."
+
+	observed to be:
+*/
+#define My_NSLShiftKeyMask   0x0002
+#define My_NSRShiftKeyMask   0x0004
+#define My_NSLControlKeyMask 0x0001
+#define My_NSRControlKeyMask 0x2000
+#define My_NSLCommandKeyMask 0x0008
+#define My_NSRCommandKeyMask 0x0010
+#define My_NSLOptionKeyMask  0x0020
+#define My_NSROptionKeyMask  0x0040
+/*
+	Avoid using the above unless it is
+	really needed.
+*/
+
+LOCALPROC MyUpdateKeyboardModifiers(NSUInteger newMods)
+{
+	NSUInteger changeMask = MyCurrentMods ^ newMods;
+
+	if (0 != changeMask) {
+		if (0 != (changeMask & NSAlphaShiftKeyMask)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_CapsLock,
+				0 != (newMods & NSAlphaShiftKeyMask));
+		}
+
+#if MKC_formac_RShift == MKC_formac_Shift
+		if (0 != (changeMask & NSShiftKeyMask)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_Shift,
+				0 != (newMods & NSShiftKeyMask));
+		}
+#else
+		if (0 != (changeMask & My_NSLShiftKeyMask)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_Shift,
+				0 != (newMods & My_NSLShiftKeyMask));
+		}
+		if (0 != (changeMask & My_NSRShiftKeyMask)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_RShift,
+				0 != (newMods & My_NSRShiftKeyMask));
+		}
+#endif
+
+#if MKC_formac_RControl == MKC_formac_Control
+		if (0 != (changeMask & NSControlKeyMask)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_Control,
+				0 != (newMods & NSControlKeyMask));
+		}
+#else
+		if (0 != (changeMask & My_NSLControlKeyMask)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_Control,
+				0 != (newMods & My_NSLControlKeyMask));
+		}
+		if (0 != (changeMask & My_NSRControlKeyMask)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_RControl,
+				0 != (newMods & My_NSRControlKeyMask));
+		}
+#endif
+
+#if MKC_formac_RCommand == MKC_formac_Command
+		if (0 != (changeMask & NSCommandKeyMask)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_Command,
+				0 != (newMods & NSCommandKeyMask));
+		}
+#else
+		if (0 != (changeMask & My_NSLCommandKeyMask)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_Command,
+				0 != (newMods & My_NSLCommandKeyMask));
+		}
+		if (0 != (changeMask & My_NSRCommandKeyMask)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_RCommand,
+				0 != (newMods & My_NSRCommandKeyMask));
+		}
+#endif
+
+#if MKC_formac_ROption == MKC_formac_Option
+		if (0 != (changeMask & NSAlternateKeyMask)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_Option,
+				0 != (newMods & NSAlternateKeyMask));
+		}
+#else
+		if (0 != (changeMask & My_NSLOptionKeyMask)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_Option,
+				0 != (newMods & My_NSLOptionKeyMask));
+		}
+		if (0 != (changeMask & My_NSROptionKeyMask)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_ROption,
+				0 != (newMods & My_NSROptionKeyMask));
+		}
+#endif
+
+		MyCurrentMods = newMods;
+	}
+}
+
+/* --- mouse --- */
+
+/* cursor hiding */
+
+LOCALVAR blnr WantCursorHidden = falseblnr;
+
+#if MayFullScreen
+LOCALVAR short hOffset;
+	/* number of pixels to left of drawing area in window */
+LOCALVAR short vOffset;
+	/* number of pixels above drawing area in window */
+#endif
+
+#if MayFullScreen
+LOCALVAR blnr GrabMachine = falseblnr;
+#endif
+
+#if VarFullScreen
+LOCALVAR blnr UseFullScreen = (0 != WantInitFullScreen);
+#endif
+
+#if EnableMagnify
+LOCALVAR blnr UseMagnify = (0 != WantInitMagnify);
+#endif
+
+LOCALVAR blnr gBackgroundFlag = falseblnr;
+LOCALVAR blnr CurSpeedStopped = trueblnr;
+
+#if EnableMagnify
+#define MaxScale MyWindowScale
+#else
+#define MaxScale 1
+#endif
+
+LOCALVAR blnr HaveCursorHidden = falseblnr;
+
+LOCALPROC ForceShowCursor(void)
+{
+	if (HaveCursorHidden) {
+		HaveCursorHidden = falseblnr;
+		MyShowCursor();
+	}
+}
+
+/* cursor moving */
+
+#if EnableMoveMouse
+LOCALFUNC blnr MyMoveMouse(si4b h, si4b v)
+{
+	NSPoint p;
+	CGPoint cgp;
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		h -= ViewHStart;
+		v -= ViewVStart;
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+		h *= MyWindowScale;
+		v *= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		h += hOffset;
+		v += vOffset;
+	}
+#endif
+
+	p = NSMakePoint(h, v);
+	cgp = QZ_PrivateSDLToCG(&p);
+
+	/*
+		this is the magic call that fixes cursor "freezing"
+		after warp
+	*/
+	CGAssociateMouseAndMouseCursorPosition(0);
+	CGWarpMouseCursorPosition(cgp);
+	CGAssociateMouseAndMouseCursorPosition(1);
+
+#if 0
+	if (noErr != CGSetLocalEventsSuppressionInterval(0.0)) {
+		/* don't use MacMsg which can call MyMoveMouse */
+	}
+	if (noErr != CGWarpMouseCursorPosition(cgp)) {
+		/* don't use MacMsg which can call MyMoveMouse */
+	}
+#endif
+
+	return trueblnr;
+}
+#endif
+
+#if EnableFSMouseMotion
+LOCALPROC AdjustMouseMotionGrab(void)
+{
+#if MayFullScreen
+	if (GrabMachine) {
+		/*
+			if magnification changes, need to reset,
+			even if HaveMouseMotion already true
+		*/
+		if (MyMoveMouse(ViewHStart + (ViewHSize / 2),
+			ViewVStart + (ViewVSize / 2)))
+		{
+			SavedMouseH = ViewHStart + (ViewHSize / 2);
+			SavedMouseV = ViewVStart + (ViewVSize / 2);
+			HaveMouseMotion = trueblnr;
+		}
+	} else
+#endif
+	{
+		if (HaveMouseMotion) {
+			(void) MyMoveMouse(CurMouseH, CurMouseV);
+			HaveMouseMotion = falseblnr;
+		}
+	}
+}
+#endif
+
+#if EnableFSMouseMotion
+LOCALPROC MyMouseConstrain(void)
+{
+	si4b shiftdh;
+	si4b shiftdv;
+
+	if (SavedMouseH < ViewHStart + (ViewHSize / 4)) {
+		shiftdh = ViewHSize / 2;
+	} else if (SavedMouseH > ViewHStart + ViewHSize - (ViewHSize / 4)) {
+		shiftdh = - ViewHSize / 2;
+	} else {
+		shiftdh = 0;
+	}
+	if (SavedMouseV < ViewVStart + (ViewVSize / 4)) {
+		shiftdv = ViewVSize / 2;
+	} else if (SavedMouseV > ViewVStart + ViewVSize - (ViewVSize / 4)) {
+		shiftdv = - ViewVSize / 2;
+	} else {
+		shiftdv = 0;
+	}
+	if ((shiftdh != 0) || (shiftdv != 0)) {
+		SavedMouseH += shiftdh;
+		SavedMouseV += shiftdv;
+		if (! MyMoveMouse(SavedMouseH, SavedMouseV)) {
+			HaveMouseMotion = falseblnr;
+		}
+	}
+}
+#endif
+
+/* cursor state */
+
+LOCALPROC MousePositionNotify(int NewMousePosh, int NewMousePosv)
+{
+	blnr ShouldHaveCursorHidden = trueblnr;
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		NewMousePosh -= hOffset;
+		NewMousePosv -= vOffset;
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+		NewMousePosh /= MyWindowScale;
+		NewMousePosv /= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		NewMousePosh += ViewHStart;
+		NewMousePosv += ViewVStart;
+	}
+#endif
+
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		MyMousePositionSetDelta(NewMousePosh - SavedMouseH,
+			NewMousePosv - SavedMouseV);
+		SavedMouseH = NewMousePosh;
+		SavedMouseV = NewMousePosv;
+	} else
+#endif
+	{
+		if (NewMousePosh < 0) {
+			NewMousePosh = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePosh >= vMacScreenWidth) {
+			NewMousePosh = vMacScreenWidth - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+		if (NewMousePosv < 0) {
+			NewMousePosv = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePosv >= vMacScreenHeight) {
+			NewMousePosv = vMacScreenHeight - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+
+#if VarFullScreen
+		if (UseFullScreen)
+#endif
+#if MayFullScreen
+		{
+			ShouldHaveCursorHidden = trueblnr;
+		}
+#endif
+
+		/* if (ShouldHaveCursorHidden || CurMouseButton) */
+		/*
+			for a game like arkanoid, would like mouse to still
+			move even when outside window in one direction
+		*/
+		MyMousePositionSet(NewMousePosh, NewMousePosv);
+	}
+
+	WantCursorHidden = ShouldHaveCursorHidden;
+}
+
+LOCALPROC CheckMouseState(void)
+{
+	/*
+		incorrect while window is being dragged
+		so only call when needed.
+	*/
+	NSPoint p;
+
+	QZ_GetMouseLocation(&p);
+	MousePositionNotify((int) p.x, (int) p.y);
+}
+
+LOCALVAR blnr gTrueBackgroundFlag = falseblnr;
+
+
+LOCALVAR ui3p ScalingBuff = nullpr;
+
+LOCALVAR ui3p CLUT_final;
+
+#define CLUT_finalsz1 (256 * 8)
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+
+#define CLUT_finalClrSz (256 << (5 - vMacScreenDepth))
+
+#define CLUT_finalsz ((CLUT_finalClrSz > CLUT_finalsz1) \
+	? CLUT_finalClrSz : CLUT_finalsz1)
+
+#else
+#define CLUT_finalsz CLUT_finalsz1
+#endif
+
+
+#define ScrnMapr_DoMap UpdateBWLuminanceCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 3
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+
+#define ScrnMapr_DoMap UpdateMappedColorCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#endif
+
+#if vMacScreenDepth >= 4
+
+#define ScrnTrns_DoTrans UpdateTransColorCopy
+#define ScrnTrns_Src GetCurDrawBuff()
+#define ScrnTrns_Dst ScalingBuff
+#define ScrnTrns_SrcDepth vMacScreenDepth
+#define ScrnTrns_DstDepth 5
+#define ScrnTrns_DstZLo 1
+
+#include "SCRNTRNS.h"
+
+#endif
+
+LOCALPROC UpdateLuminanceCopy(si4b top, si4b left,
+	si4b bottom, si4b right)
+{
+	int i;
+
+#if 0 != vMacScreenDepth
+	if (UseColorMode) {
+
+#if vMacScreenDepth < 4
+
+		if (! ColorTransValid) {
+			int j;
+			int k;
+			ui5p p4;
+
+			p4 = (ui5p)CLUT_final;
+			for (i = 0; i < 256; ++i) {
+				for (k = 1 << (3 - vMacScreenDepth); --k >= 0; ) {
+					j = (i >> (k << vMacScreenDepth)) & (CLUT_size - 1);
+					*p4++ = (((long)CLUT_reds[j] & 0xFF00) << 16)
+						| (((long)CLUT_greens[j] & 0xFF00) << 8)
+						| ((long)CLUT_blues[j] & 0xFF00);
+				}
+			}
+			ColorTransValid = trueblnr;
+		}
+
+		UpdateMappedColorCopy(top, left, bottom, right);
+
+#else
+		UpdateTransColorCopy(top, left, bottom, right);
+#endif
+
+	} else
+#endif
+	{
+		if (! ColorTransValid) {
+			int k;
+			ui3p p4 = (ui3p)CLUT_final;
+
+			for (i = 0; i < 256; ++i) {
+				for (k = 8; --k >= 0; ) {
+					*p4++ = ((i >> k) & 0x01) - 1;
+				}
+			}
+			ColorTransValid = trueblnr;
+		}
+
+		UpdateBWLuminanceCopy(top, left, bottom, right);
+	}
+}
+
+LOCALPROC MyDrawWithOpenGL(ui4r top, ui4r left, ui4r bottom, ui4r right)
+{
+	if (nil == MyNSOpnGLCntxt) {
+		/* oops */
+	} else {
+		si4b top2;
+		si4b left2;
+
+#if VarFullScreen
+		if (UseFullScreen)
+#endif
+#if MayFullScreen
+		{
+			if (top < ViewVStart) {
+				top = ViewVStart;
+			}
+			if (left < ViewHStart) {
+				left = ViewHStart;
+			}
+			if (bottom > ViewVStart + ViewVSize) {
+				bottom = ViewVStart + ViewVSize;
+			}
+			if (right > ViewHStart + ViewHSize) {
+				right = ViewHStart + ViewHSize;
+			}
+
+			if ((top >= bottom) || (left >= right)) {
+				goto label_exit;
+			}
+		}
+#endif
+
+		top2 = top;
+		left2 = left;
+
+#if VarFullScreen
+		if (UseFullScreen)
+#endif
+#if MayFullScreen
+		{
+			left2 -= ViewHStart;
+			top2 -= ViewVStart;
+		}
+#endif
+
+#if EnableMagnify
+		if (UseMagnify) {
+			top2 *= MyWindowScale;
+			left2 *= MyWindowScale;
+		}
+#endif
+
+		[MyNSOpnGLCntxt makeCurrentContext];
+
+		UpdateLuminanceCopy(top, left, bottom, right);
+		glRasterPos2i(GLhOffset + left2, GLvOffset - top2);
+#if 0 != vMacScreenDepth
+		if (UseColorMode) {
+			glDrawPixels(right - left,
+				bottom - top,
+				GL_RGBA,
+				GL_UNSIGNED_INT_8_8_8_8,
+				ScalingBuff + (left + top * vMacScreenWidth) * 4
+				);
+		} else
+#endif
+		{
+			glDrawPixels(right - left,
+				bottom - top,
+				GL_LUMINANCE,
+				GL_UNSIGNED_BYTE,
+				ScalingBuff + (left + top * vMacScreenWidth)
+				);
+		}
+
+#if 0 /* a very quick and dirty check of where drawing */
+		glDrawPixels(right - left,
+			1,
+			GL_RED,
+			GL_UNSIGNED_BYTE,
+			ScalingBuff + (left + top * vMacScreenWidth)
+			);
+
+		glDrawPixels(1,
+			bottom - top,
+			GL_RED,
+			GL_UNSIGNED_BYTE,
+			ScalingBuff + (left + top * vMacScreenWidth)
+			);
+#endif
+
+		glFlush();
+	}
+
+#if MayFullScreen
+label_exit:
+	;
+#endif
+}
+
+#if UseCGContextDrawImage
+LOCALPROC SDL_UpdateRect(si5b x, si5b y, ui5b w, ui5b h)
+{
+	if ([MyWindow isMiniaturized]) {
+
+		/* Do nothing if miniaturized */
+
+	} else {
+		NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
+		if (ctx != MyNSgfxContext) {
+			/* uhoh, you might be rendering from another thread... */
+			[NSGraphicsContext
+				setCurrentContext: MyNSgfxContext];
+			ctx = MyNSgfxContext;
+		}
+		CGContextRef cgc = (CGContextRef) [ctx graphicsPort];
+		CGContextFlush(MyCGcontext);
+		CGImageRef image = CGBitmapContextCreateImage(
+			MyCGcontext);
+		CGRect rectangle = CGRectMake(0, 0,
+			[MyNSview frame].size.width,
+			[MyNSview frame].size.height);
+
+		CGContextDrawImage(cgc, rectangle, image);
+		CGImageRelease(image);
+		CGContextFlush(cgc);
+	}
+}
+#endif
+
+/* --- time, date, location --- */
+
+#define dbglog_TimeStuff (0 && dbglog_HAVE)
+
+LOCALVAR ui5b TrueEmulatedTime = 0;
+
+LOCALVAR NSTimeInterval LatestTime;
+LOCALVAR NSTimeInterval NextTickChangeTime;
+
+#define MyTickDuration (1.0 / 60.14742)
+
+LOCALVAR ui5b NewMacDateInSeconds;
+
+LOCALVAR blnr EmulationWasInterrupted = falseblnr;
+
+LOCALPROC UpdateTrueEmulatedTime(void)
+{
+	NSTimeInterval TimeDiff;
+
+	LatestTime = [NSDate timeIntervalSinceReferenceDate];
+	TimeDiff = LatestTime - NextTickChangeTime;
+
+	if (TimeDiff >= 0.0) {
+		if (TimeDiff > 16 * MyTickDuration) {
+			/* emulation interrupted, forget it */
+			++TrueEmulatedTime;
+			NextTickChangeTime = LatestTime + MyTickDuration;
+
+			EmulationWasInterrupted = trueblnr;
+#if dbglog_TimeStuff
+			dbglog_writelnNum("emulation interrupted",
+				TrueEmulatedTime);
+#endif
+		} else {
+			do {
+#if 0 && dbglog_TimeStuff
+				dbglog_writeln("got next tick");
+#endif
+				++TrueEmulatedTime;
+				TimeDiff -= MyTickDuration;
+				NextTickChangeTime += MyTickDuration;
+			} while (TimeDiff >= 0.0);
+		}
+	} else if (TimeDiff < (-16 * MyTickDuration)) {
+		/* clock set back, reset */
+#if dbglog_TimeStuff
+		dbglog_writeln("clock set back");
+#endif
+
+		NextTickChangeTime = LatestTime + MyTickDuration;
+	}
+}
+
+
+LOCALVAR ui5b MyDateDelta;
+
+LOCALFUNC blnr CheckDateTime(void)
+{
+	NewMacDateInSeconds = ((ui5b)LatestTime) + MyDateDelta;
+	if (CurMacDateInSeconds != NewMacDateInSeconds) {
+		CurMacDateInSeconds = NewMacDateInSeconds;
+		return trueblnr;
+	} else {
+		return falseblnr;
+	}
+}
+
+LOCALPROC StartUpTimeAdjust(void)
+{
+	LatestTime = [NSDate timeIntervalSinceReferenceDate];
+	NextTickChangeTime = LatestTime;
+}
+
+LOCALFUNC blnr InitLocationDat(void)
+{
+	NSTimeZone *MyZone = [NSTimeZone localTimeZone];
+	ui5b TzOffSet = (ui5b)[MyZone secondsFromGMT];
+#if AutoTimeZone
+	BOOL isdst = [MyZone isDaylightSavingTime];
+#endif
+
+	MyDateDelta = TzOffSet - 1233815296;
+	LatestTime = [NSDate timeIntervalSinceReferenceDate];
+	NewMacDateInSeconds = ((ui5b)LatestTime) + MyDateDelta;
+	CurMacDateInSeconds = NewMacDateInSeconds;
+#if AutoTimeZone
+	CurMacDelta = (TzOffSet & 0x00FFFFFF)
+		| ((isdst ? 0x80 : 0) << 24);
+#endif
+
+	return trueblnr;
+}
+
+/* --- sound --- */
+
+#if MySoundEnabled
+
+#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */
+#define kSoundBuffers (1 << kLn2SoundBuffers)
+#define kSoundBuffMask (kSoundBuffers - 1)
+
+#define DesiredMinFilledSoundBuffs 3
+	/*
+		if too big then sound lags behind emulation.
+		if too small then sound will have pauses.
+	*/
+
+#define kLnOneBuffLen 9
+#define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen)
+#define kOneBuffLen (1UL << kLnOneBuffLen)
+#define kAllBuffLen (1UL << kLnAllBuffLen)
+#define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3)
+#define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3)
+#define kOneBuffSz (1UL << kLnOneBuffSz)
+#define kAllBuffSz (1UL << kLnAllBuffSz)
+#define kOneBuffMask (kOneBuffLen - 1)
+#define kAllBuffMask (kAllBuffLen - 1)
+#define dbhBufferSize (kAllBuffSz + kOneBuffSz)
+
+#define dbglog_SoundStuff (0 && dbglog_HAVE)
+#define dbglog_SoundBuffStats (0 && dbglog_HAVE)
+
+LOCALVAR tpSoundSamp TheSoundBuffer = nullpr;
+static volatile ui4b ThePlayOffset;
+static volatile ui4b TheFillOffset;
+static volatile ui4b MinFilledSoundBuffs;
+#if dbglog_SoundBuffStats
+LOCALVAR ui4b MaxFilledSoundBuffs;
+#endif
+LOCALVAR ui4b TheWriteOffset;
+
+LOCALPROC MySound_Start0(void)
+{
+	/* Reset variables */
+	ThePlayOffset = 0;
+	TheFillOffset = 0;
+	TheWriteOffset = 0;
+	MinFilledSoundBuffs = kSoundBuffers + 1;
+#if dbglog_SoundBuffStats
+	MaxFilledSoundBuffs = 0;
+#endif
+}
+
+GLOBALOSGLUFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL)
+{
+	ui4b ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset);
+	ui4b WriteBuffContig =
+		kOneBuffLen - (TheWriteOffset & kOneBuffMask);
+
+	if (WriteBuffContig < n) {
+		n = WriteBuffContig;
+	}
+	if (ToFillLen < n) {
+		/* overwrite previous buffer */
+#if dbglog_SoundStuff
+		dbglog_writeln("sound buffer over flow");
+#endif
+		TheWriteOffset -= kOneBuffLen;
+	}
+
+	*actL = n;
+	return TheSoundBuffer + (TheWriteOffset & kAllBuffMask);
+}
+
+#if 4 == kLn2SoundSampSz
+LOCALPROC ConvertSoundBlockToNative(tpSoundSamp p)
+{
+	int i;
+
+	for (i = kOneBuffLen; --i >= 0; ) {
+		*p++ -= 0x8000;
+	}
+}
+#else
+#define ConvertSoundBlockToNative(p)
+#endif
+
+LOCALPROC MySound_WroteABlock(void)
+{
+#if (4 == kLn2SoundSampSz)
+	ui4b PrevWriteOffset = TheWriteOffset - kOneBuffLen;
+	tpSoundSamp p = TheSoundBuffer + (PrevWriteOffset & kAllBuffMask);
+#endif
+
+#if dbglog_SoundStuff
+	dbglog_writeln("enter MySound_WroteABlock");
+#endif
+
+	ConvertSoundBlockToNative(p);
+
+	TheFillOffset = TheWriteOffset;
+
+#if dbglog_SoundBuffStats
+	{
+		ui4b ToPlayLen = TheFillOffset
+			- ThePlayOffset;
+		ui4b ToPlayBuffs = ToPlayLen >> kLnOneBuffLen;
+
+		if (ToPlayBuffs > MaxFilledSoundBuffs) {
+			MaxFilledSoundBuffs = ToPlayBuffs;
+		}
+	}
+#endif
+}
+
+LOCALFUNC blnr MySound_EndWrite0(ui4r actL)
+{
+	blnr v;
+
+	TheWriteOffset += actL;
+
+	if (0 != (TheWriteOffset & kOneBuffMask)) {
+		v = falseblnr;
+	} else {
+		/* just finished a block */
+
+		MySound_WroteABlock();
+
+		v = trueblnr;
+	}
+
+	return v;
+}
+
+LOCALPROC MySound_SecondNotify0(void)
+{
+	if (MinFilledSoundBuffs <= kSoundBuffers) {
+		if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) {
+#if dbglog_SoundStuff
+			dbglog_writeln("MinFilledSoundBuffs too high");
+#endif
+			NextTickChangeTime += MyTickDuration;
+		} else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) {
+#if dbglog_SoundStuff
+			dbglog_writeln("MinFilledSoundBuffs too low");
+#endif
+			++TrueEmulatedTime;
+		}
+#if dbglog_SoundBuffStats
+		dbglog_writelnNum("MinFilledSoundBuffs",
+			MinFilledSoundBuffs);
+		dbglog_writelnNum("MaxFilledSoundBuffs",
+			MaxFilledSoundBuffs);
+		MaxFilledSoundBuffs = 0;
+#endif
+		MinFilledSoundBuffs = kSoundBuffers + 1;
+	}
+}
+
+typedef ui4r trSoundTemp;
+
+#define kCenterTempSound 0x8000
+
+#define AudioStepVal 0x0040
+
+#if 3 == kLn2SoundSampSz
+#define ConvertTempSoundSampleFromNative(v) ((v) << 8)
+#elif 4 == kLn2SoundSampSz
+#define ConvertTempSoundSampleFromNative(v) ((v) + kCenterSound)
+#else
+#error "unsupported kLn2SoundSampSz"
+#endif
+
+#if 3 == kLn2SoundSampSz
+#define ConvertTempSoundSampleToNative(v) ((v) >> 8)
+#elif 4 == kLn2SoundSampSz
+#define ConvertTempSoundSampleToNative(v) ((v) - kCenterSound)
+#else
+#error "unsupported kLn2SoundSampSz"
+#endif
+
+LOCALPROC SoundRampTo(trSoundTemp *last_val, trSoundTemp dst_val,
+	tpSoundSamp *stream, int *len)
+{
+	trSoundTemp diff;
+	tpSoundSamp p = *stream;
+	int n = *len;
+	trSoundTemp v1 = *last_val;
+
+	while ((v1 != dst_val) && (0 != n)) {
+		if (v1 > dst_val) {
+			diff = v1 - dst_val;
+			if (diff > AudioStepVal) {
+				v1 -= AudioStepVal;
+			} else {
+				v1 = dst_val;
+			}
+		} else {
+			diff = dst_val - v1;
+			if (diff > AudioStepVal) {
+				v1 += AudioStepVal;
+			} else {
+				v1 = dst_val;
+			}
+		}
+
+		--n;
+		*p++ = ConvertTempSoundSampleToNative(v1);
+	}
+
+	*stream = p;
+	*len = n;
+	*last_val = v1;
+}
+
+struct MySoundR {
+	tpSoundSamp fTheSoundBuffer;
+	volatile ui4b (*fPlayOffset);
+	volatile ui4b (*fFillOffset);
+	volatile ui4b (*fMinFilledSoundBuffs);
+
+	volatile trSoundTemp lastv;
+
+	blnr enabled;
+	blnr wantplaying;
+	blnr HaveStartedPlaying;
+
+	AudioUnit outputAudioUnit;
+};
+typedef struct MySoundR MySoundR;
+
+LOCALPROC my_audio_callback(void *udata, void *stream, int len)
+{
+	ui4b ToPlayLen;
+	ui4b FilledSoundBuffs;
+	int i;
+	MySoundR *datp = (MySoundR *)udata;
+	tpSoundSamp CurSoundBuffer = datp->fTheSoundBuffer;
+	ui4b CurPlayOffset = *datp->fPlayOffset;
+	trSoundTemp v0 = datp->lastv;
+	trSoundTemp v1 = v0;
+	tpSoundSamp dst = (tpSoundSamp)stream;
+
+#if kLn2SoundSampSz > 3
+	len >>= (kLn2SoundSampSz - 3);
+#endif
+
+#if dbglog_SoundStuff
+	dbglog_writeln("Enter my_audio_callback");
+	dbglog_writelnNum("len", len);
+#endif
+
+label_retry:
+	ToPlayLen = *datp->fFillOffset - CurPlayOffset;
+	FilledSoundBuffs = ToPlayLen >> kLnOneBuffLen;
+
+	if (! datp->wantplaying) {
+#if dbglog_SoundStuff
+		dbglog_writeln("playing end transistion");
+#endif
+
+		SoundRampTo(&v1, kCenterTempSound, &dst, &len);
+
+		ToPlayLen = 0;
+	} else if (! datp->HaveStartedPlaying) {
+#if dbglog_SoundStuff
+		dbglog_writeln("playing start block");
+#endif
+
+		if ((ToPlayLen >> kLnOneBuffLen) < 8) {
+			ToPlayLen = 0;
+		} else {
+			tpSoundSamp p = datp->fTheSoundBuffer
+				+ (CurPlayOffset & kAllBuffMask);
+			trSoundTemp v2 = ConvertTempSoundSampleFromNative(*p);
+
+#if dbglog_SoundStuff
+			dbglog_writeln("have enough samples to start");
+#endif
+
+			SoundRampTo(&v1, v2, &dst, &len);
+
+			if (v1 == v2) {
+#if dbglog_SoundStuff
+				dbglog_writeln("finished start transition");
+#endif
+
+				datp->HaveStartedPlaying = trueblnr;
+			}
+		}
+	}
+
+	if (0 == len) {
+		/* done */
+
+		if (FilledSoundBuffs < *datp->fMinFilledSoundBuffs) {
+			*datp->fMinFilledSoundBuffs = FilledSoundBuffs;
+		}
+	} else if (0 == ToPlayLen) {
+
+#if dbglog_SoundStuff
+		dbglog_writeln("under run");
+#endif
+
+		for (i = 0; i < len; ++i) {
+			*dst++ = ConvertTempSoundSampleToNative(v1);
+		}
+		*datp->fMinFilledSoundBuffs = 0;
+	} else {
+		ui4b PlayBuffContig = kAllBuffLen
+			- (CurPlayOffset & kAllBuffMask);
+		tpSoundSamp p = CurSoundBuffer
+			+ (CurPlayOffset & kAllBuffMask);
+
+		if (ToPlayLen > PlayBuffContig) {
+			ToPlayLen = PlayBuffContig;
+		}
+		if (ToPlayLen > len) {
+			ToPlayLen = len;
+		}
+
+		for (i = 0; i < ToPlayLen; ++i) {
+			*dst++ = *p++;
+		}
+		v1 = ConvertTempSoundSampleFromNative(p[-1]);
+
+		CurPlayOffset += ToPlayLen;
+		len -= ToPlayLen;
+
+		*datp->fPlayOffset = CurPlayOffset;
+
+		goto label_retry;
+	}
+
+	datp->lastv = v1;
+}
+
+LOCALFUNC OSStatus audioCallback(
+	void                       *inRefCon,
+	AudioUnitRenderActionFlags *ioActionFlags,
+	const AudioTimeStamp       *inTimeStamp,
+	UInt32                     inBusNumber,
+	UInt32                     inNumberFrames,
+	AudioBufferList            *ioData)
+{
+	AudioBuffer *abuf;
+	UInt32 i;
+	UInt32 n = ioData->mNumberBuffers;
+
+#if dbglog_SoundStuff
+	dbglog_writeln("Enter audioCallback");
+	dbglog_writelnNum("mNumberBuffers", n);
+#endif
+
+	for (i = 0; i < n; i++) {
+		abuf = &ioData->mBuffers[i];
+		my_audio_callback(inRefCon,
+			abuf->mData, abuf->mDataByteSize);
+	}
+
+	return 0;
+}
+
+LOCALVAR MySoundR cur_audio;
+
+LOCALPROC ZapAudioVars(void)
+{
+	memset(&cur_audio, 0, sizeof(MySoundR));
+}
+
+LOCALPROC MySound_Stop(void)
+{
+#if dbglog_SoundStuff
+	dbglog_writeln("enter MySound_Stop");
+#endif
+
+	if (cur_audio.wantplaying) {
+		OSStatus result;
+		ui4r retry_limit = 50; /* half of a second */
+
+		cur_audio.wantplaying = falseblnr;
+
+label_retry:
+		if (kCenterTempSound == cur_audio.lastv) {
+#if dbglog_SoundStuff
+			dbglog_writeln("reached kCenterTempSound");
+#endif
+
+			/* done */
+		} else if (0 == --retry_limit) {
+#if dbglog_SoundStuff
+			dbglog_writeln("retry limit reached");
+#endif
+			/* done */
+		} else
+		{
+			/*
+				give time back, particularly important
+				if got here on a suspend event.
+			*/
+			struct timespec rqt;
+			struct timespec rmt;
+
+#if dbglog_SoundStuff
+			dbglog_writeln("busy, so sleep");
+#endif
+
+			rqt.tv_sec = 0;
+			rqt.tv_nsec = 10000000;
+			(void) nanosleep(&rqt, &rmt);
+
+			goto label_retry;
+		}
+
+		if (noErr != (result = AudioOutputUnitStop(
+			cur_audio.outputAudioUnit)))
+		{
+#if dbglog_HAVE
+			dbglog_writeln("AudioOutputUnitStop fails");
+#endif
+		}
+	}
+
+#if dbglog_SoundStuff
+	dbglog_writeln("leave MySound_Stop");
+#endif
+}
+
+LOCALPROC MySound_Start(void)
+{
+	OSStatus result;
+
+	if ((! cur_audio.wantplaying) && cur_audio.enabled) {
+#if dbglog_SoundStuff
+		dbglog_writeln("enter MySound_Start");
+#endif
+
+		MySound_Start0();
+		cur_audio.lastv = kCenterTempSound;
+		cur_audio.HaveStartedPlaying = falseblnr;
+		cur_audio.wantplaying = trueblnr;
+
+		if (noErr != (result = AudioOutputUnitStart(
+			cur_audio.outputAudioUnit)))
+		{
+#if dbglog_HAVE
+			dbglog_writeln("AudioOutputUnitStart fails");
+#endif
+			cur_audio.wantplaying = falseblnr;
+		}
+
+#if dbglog_SoundStuff
+		dbglog_writeln("leave MySound_Start");
+#endif
+	}
+}
+
+LOCALPROC MySound_UnInit(void)
+{
+	if (cur_audio.enabled) {
+		OSStatus result;
+		struct AURenderCallbackStruct callback;
+
+		cur_audio.enabled = falseblnr;
+
+		/* Remove the input callback */
+		callback.inputProc = 0;
+		callback.inputProcRefCon = 0;
+
+		if (noErr != (result = AudioUnitSetProperty(
+			cur_audio.outputAudioUnit,
+			kAudioUnitProperty_SetRenderCallback,
+			kAudioUnitScope_Input,
+			0,
+			&callback,
+			sizeof(callback))))
+		{
+#if dbglog_HAVE
+			dbglog_writeln("AudioUnitSetProperty fails"
+				"(kAudioUnitProperty_SetRenderCallback)");
+#endif
+		}
+
+		if (noErr != (result = CloseComponent(
+			cur_audio.outputAudioUnit)))
+		{
+#if dbglog_HAVE
+			dbglog_writeln("CloseComponent fails in MySound_UnInit");
+#endif
+		}
+	}
+}
+
+#define SOUND_SAMPLERATE 22255 /* = round(7833600 * 2 / 704) */
+
+LOCALFUNC blnr MySound_Init(void)
+{
+	OSStatus result = noErr;
+	Component comp;
+	ComponentDescription desc;
+	struct AURenderCallbackStruct callback;
+	AudioStreamBasicDescription requestedDesc;
+
+	cur_audio.fTheSoundBuffer = TheSoundBuffer;
+	cur_audio.fPlayOffset = &ThePlayOffset;
+	cur_audio.fFillOffset = &TheFillOffset;
+	cur_audio.fMinFilledSoundBuffs = &MinFilledSoundBuffs;
+	cur_audio.wantplaying = falseblnr;
+
+	desc.componentType = kAudioUnitType_Output;
+	desc.componentSubType = kAudioUnitSubType_DefaultOutput;
+	desc.componentManufacturer = kAudioUnitManufacturer_Apple;
+	desc.componentFlags = 0;
+	desc.componentFlagsMask = 0;
+
+
+	requestedDesc.mFormatID = kAudioFormatLinearPCM;
+	requestedDesc.mFormatFlags = kLinearPCMFormatFlagIsPacked
+#if 3 != kLn2SoundSampSz
+		| kLinearPCMFormatFlagIsSignedInteger
+#endif
+		;
+	requestedDesc.mChannelsPerFrame = 1;
+	requestedDesc.mSampleRate = SOUND_SAMPLERATE;
+
+	requestedDesc.mBitsPerChannel = (1 << kLn2SoundSampSz);
+#if 0
+	requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
+#endif
+#if 0
+	requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
+#endif
+
+	requestedDesc.mFramesPerPacket = 1;
+	requestedDesc.mBytesPerFrame = (requestedDesc.mBitsPerChannel
+		* requestedDesc.mChannelsPerFrame) >> 3;
+	requestedDesc.mBytesPerPacket = requestedDesc.mBytesPerFrame
+		* requestedDesc.mFramesPerPacket;
+
+
+	callback.inputProc = audioCallback;
+	callback.inputProcRefCon = &cur_audio;
+
+	if (NULL == (comp = FindNextComponent(NULL, &desc)))
+	{
+#if dbglog_HAVE
+		dbglog_writeln("Failed to start CoreAudio: "
+			"FindNextComponent returned NULL");
+#endif
+	} else
+
+	if (noErr != (result = OpenAComponent(
+		comp, &cur_audio.outputAudioUnit)))
+	{
+#if dbglog_HAVE
+		dbglog_writeln("Failed to start CoreAudio: OpenAComponent");
+#endif
+	} else
+
+	if (noErr != (result = AudioUnitInitialize(
+		cur_audio.outputAudioUnit)))
+	{
+#if dbglog_HAVE
+		dbglog_writeln(
+			"Failed to start CoreAudio: AudioUnitInitialize");
+#endif
+	} else
+
+	if (noErr != (result = AudioUnitSetProperty(
+		cur_audio.outputAudioUnit,
+		kAudioUnitProperty_StreamFormat,
+		kAudioUnitScope_Input,
+		0,
+		&requestedDesc,
+		sizeof(requestedDesc))))
+	{
+#if dbglog_HAVE
+		dbglog_writeln("Failed to start CoreAudio: "
+			"AudioUnitSetProperty(kAudioUnitProperty_StreamFormat)");
+#endif
+	} else
+
+	if (noErr != (result = AudioUnitSetProperty(
+		cur_audio.outputAudioUnit,
+		kAudioUnitProperty_SetRenderCallback,
+		kAudioUnitScope_Input,
+		0,
+		&callback,
+		sizeof(callback))))
+	{
+#if dbglog_HAVE
+		dbglog_writeln("Failed to start CoreAudio: "
+			"AudioUnitSetProperty(kAudioUnitProperty_SetInputCallback)"
+			);
+#endif
+	} else
+
+	{
+		cur_audio.enabled = trueblnr;
+
+		MySound_Start();
+			/*
+				This should be taken care of by LeaveSpeedStopped,
+				but since takes a while to get going properly,
+				start early.
+			*/
+	}
+
+	return trueblnr; /* keep going, even if no sound */
+}
+
+GLOBALOSGLUPROC MySound_EndWrite(ui4r actL)
+{
+	if (MySound_EndWrite0(actL)) {
+	}
+}
+
+LOCALPROC MySound_SecondNotify(void)
+{
+	if (cur_audio.enabled) {
+		MySound_SecondNotify0();
+	}
+}
+
+#endif
+
+LOCALPROC FinishSubMenu(NSMenu *theMenu, NSMenu *parentMenu,
+	NSString *sTitle)
+{
+	NSMenuItem *menuItem = [[NSMenuItem alloc]
+		initWithTitle: sTitle
+		action: nil
+		keyEquivalent: @""];
+
+	[menuItem setSubmenu: theMenu];
+	[parentMenu addItem: menuItem];
+	[menuItem release];
+}
+
+LOCALFUNC NSMenu *setApplicationMenu(NSMenu *mainMenu)
+{
+	NSMenuItem *menuItem;
+	NSString *sAppName = NSStringCreateFromSubstCStr("^p");
+		/* doesn't matter though, OS X replaces this */
+	NSString *sAbout =
+		NSStringCreateFromSubstCStr(kStrMenuItemAbout);
+	NSString *sHide =
+		NSStringCreateFromSubstCStr(kStrAppMenuItemHide);
+	NSString *sHideOthers =
+		NSStringCreateFromSubstCStr(kStrAppMenuItemHideOthers);
+	NSString *sShowAll =
+		NSStringCreateFromSubstCStr(kStrAppMenuItemShowAll);
+	NSString *sQuit =
+		NSStringCreateFromSubstCStr(kStrAppMenuItemQuit);
+
+	NSMenu *appleMenu = [[NSMenu alloc] initWithTitle: sAppName];
+
+	/* Add menu items */
+	menuItem = [appleMenu addItemWithTitle: sAbout
+		action: @selector(performApplicationAbout:)
+		keyEquivalent: @"a"];
+	[menuItem setKeyEquivalentModifierMask: NSControlKeyMask];
+
+	[appleMenu addItem:[NSMenuItem separatorItem]];
+
+	[appleMenu addItemWithTitle: sHide
+		action: @selector(hide:) keyEquivalent: @""];
+
+	[appleMenu
+		addItemWithTitle: sHideOthers
+		action: @selector(hideOtherApplications:)
+		keyEquivalent: @""];
+
+	[appleMenu addItemWithTitle: sShowAll
+		action: @selector(unhideAllApplications:)
+		keyEquivalent: @""];
+
+	[appleMenu addItem: [NSMenuItem separatorItem]];
+
+	menuItem = [appleMenu addItemWithTitle: sQuit
+		action: @selector(terminate:) keyEquivalent: @"q"];
+	[menuItem setKeyEquivalentModifierMask: NSControlKeyMask];
+
+	FinishSubMenu(appleMenu, mainMenu, sAppName);
+
+	[appleMenu release];
+
+	return appleMenu;
+}
+
+/* Create File menu */
+LOCALPROC setupFileMenu(NSMenu *mainMenu)
+{
+	NSMenu *fileMenu;
+	NSMenuItem *menuItem;
+	NSString *sFile =
+		NSStringCreateFromSubstCStr(kStrMenuFile);
+	NSString *sOpen =
+		NSStringCreateFromSubstCStr(kStrMenuItemOpen ";ll");
+
+	fileMenu = [[NSMenu alloc] initWithTitle: sFile];
+
+	menuItem = [fileMenu
+		addItemWithTitle: sOpen
+		action: @selector(performFileOpen:)
+		keyEquivalent: @"o"];
+	[menuItem setKeyEquivalentModifierMask: NSControlKeyMask];
+
+	FinishSubMenu(fileMenu, mainMenu, sFile);
+
+	[fileMenu release];
+}
+
+/* Create Special menu */
+LOCALPROC setupSpecialMenu(NSMenu *mainMenu)
+{
+	NSMenu *specialMenu;
+	NSString *sSpecial =
+		NSStringCreateFromSubstCStr(kStrMenuSpecial);
+	NSString *sMore =
+		NSStringCreateFromSubstCStr(kStrMenuItemMore ";ll");
+
+	specialMenu = [[NSMenu alloc] initWithTitle: sSpecial];
+
+	[specialMenu
+		addItemWithTitle: sMore
+		action: @selector(performSpecialMoreCommands:)
+		keyEquivalent: @""];
+
+	FinishSubMenu(specialMenu, mainMenu, sSpecial);
+
+	[specialMenu release];
+}
+
+LOCALPROC MyMenuSetup(void)
+{
+	NSMenu *mainMenu = [[NSMenu alloc] init];
+	NSMenu *appleMenu = setApplicationMenu(mainMenu);
+
+	setupFileMenu(mainMenu);
+	setupSpecialMenu(mainMenu);
+
+	[NSApp setMainMenu: mainMenu];
+
+	/*
+		Tell the application object that this is now
+		the application menu, if this unsupported
+		call actually exists. Doesn't seem to
+		be needed anyway, at least in OS X 10.7
+	*/
+	if([NSApp respondsToSelector:@selector(setAppleMenu:)]) {
+		/* [NSApp setAppleMenu: appleMenu]; */
+		[NSApp performSelector: @selector(setAppleMenu:)
+			withObject:appleMenu];
+	}
+
+	[mainMenu release];
+}
+
+
+
+/* --- video out --- */
+
+
+#if ! UseCGContextDrawImage
+LOCALPROC HaveChangedScreenBuff(ui4r top, ui4r left,
+	ui4r bottom, ui4r right)
+{
+	if ([MyNSview lockFocusIfCanDraw]) {
+		MyDrawWithOpenGL(top, left, bottom, right);
+		[MyNSview unlockFocus];
+	}
+}
+#else
+LOCALPROC HaveChangedScreenBuff(ui4r top, ui4r left,
+	ui4r bottom, ui4r right)
+{
+	int i;
+	int j;
+	ui3b *the_data = (ui3b *)GetCurDrawBuff();
+	ui3b *p;
+	ui5b color;
+	ui5b black_color = 0;
+		/* SDL_MapRGB(cur_video.format, 0, 0, 0) */
+	ui5b white_color = 0;
+		/* SDL_MapRGB(cur_video.format, 255, 255, 255) */
+
+	switch (MyBytesPerPixel) {
+		case 2: /* (1)-5-5-5 RGB */
+#if 0
+			rmask = 0x7C00;
+			gmask = 0x03E0;
+			bmask = 0x001F;
+#endif
+			break;
+		case 4:
+#if LittleEndianUnaligned
+#if 0
+			rmask = 0x0000FF00;
+			gmask = 0x00FF0000;
+			bmask = 0xFF000000;
+#endif
+			black_color = 0x000000FF;
+			white_color = 0xFFFFFFFF;
+#else
+#if 0
+			rmask = 0x00FF0000;
+			gmask = 0x0000FF00;
+			bmask = 0x000000FF;
+#endif
+			black_color = 0xFF000000;
+			white_color = 0xFFFFFFFF;
+#endif
+			break;
+	}
+
+#if EnableMagnify
+	if (UseMagnify) {
+		for (i = top * MyWindowScale; i < bottom * MyWindowScale; ++i) {
+			for (j = left * MyWindowScale;
+				j < right * MyWindowScale; ++j)
+			{
+				p = the_data + (((i / MyWindowScale) * vMacScreenWidth
+					+ (j / MyWindowScale)) / 8);
+				if (0 != (*p & (1 << ((~ (j / MyWindowScale)) & 0x7))))
+				{
+					color = black_color;
+				} else {
+					color = white_color;
+				}
+				switch (MyBytesPerPixel) {
+					case 2: { /* Probably 15-bpp or 16-bpp */
+						ui4b *bufp;
+
+						bufp = (ui4b *)MyPixels
+							+ i * MyPitch / 2 + j;
+						*bufp = color;
+					}
+					break;
+
+					case 4: { /* Probably 32-bpp */
+						ui5b *bufp;
+
+						bufp = (ui5b *)MyPixels
+							+ i * MyPitch / 4 + j;
+						*bufp = color;
+					}
+					break;
+				}
+			}
+		}
+	} else
+#endif
+	{
+		for (i = top; i < bottom; ++i) {
+			for (j = left; j < right; ++j) {
+				p = the_data + ((i * vMacScreenWidth + j) / 8);
+				if (0 != (*p & (1 << ((~ j) & 0x7)))) {
+					color = black_color;
+				} else {
+					color = white_color;
+				}
+				switch (MyBytesPerPixel) {
+					case 2: { /* Probably 15-bpp or 16-bpp */
+						ui4b *bufp;
+
+						bufp = (ui4b *)MyPixels
+							+ i * MyPitch / 2 + j;
+						*bufp = color;
+					}
+					break;
+					case 4: { /* Probably 32-bpp */
+						ui5b *bufp;
+
+						bufp = (ui5b *)MyPixels
+							+ i * MyPitch / 4 + j;
+						*bufp = color;
+					}
+					break;
+				}
+			}
+		}
+	}
+
+#if EnableMagnify
+	if (UseMagnify) {
+		SDL_UpdateRect(left * MyWindowScale,
+			top * MyWindowScale,
+			(right - left) * MyWindowScale,
+			(bottom - top) * MyWindowScale);
+	} else
+#endif
+	{
+		SDL_UpdateRect(left, top,
+			right - left, bottom - top);
+	}
+}
+#endif
+
+LOCALPROC MyDrawChangesAndClear(void)
+{
+	if (ScreenChangedBottom > ScreenChangedTop) {
+		HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft,
+			ScreenChangedBottom, ScreenChangedRight);
+		ScreenClearChanges();
+	}
+}
+
+GLOBALOSGLUPROC DoneWithDrawingForTick(void)
+{
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		AutoScrollScreen();
+	}
+#endif
+	MyDrawChangesAndClear();
+}
+
+/* --- keyboard input --- */
+
+LOCALPROC DisableKeyRepeat(void)
+{
+}
+
+LOCALPROC RestoreKeyRepeat(void)
+{
+}
+
+LOCALPROC ReconnectKeyCodes3(void)
+{
+}
+
+LOCALPROC DisconnectKeyCodes3(void)
+{
+	DisconnectKeyCodes2();
+	MyMouseButtonSet(falseblnr);
+}
+
+/* --- basic dialogs --- */
+
+LOCALPROC CheckSavedMacMsg(void)
+{
+	/* called only on quit, if error saved but not yet reported */
+
+	if (nullpr != SavedBriefMsg) {
+		NSString *briefMsg0 =
+			NSStringCreateFromSubstCStr(SavedBriefMsg);
+		NSString *longMsg0 =
+			NSStringCreateFromSubstCStr(SavedLongMsg);
+		NSString *quitMsg0 =
+			NSStringCreateFromSubstCStr(kStrCmdQuit);
+
+		(void) NSRunAlertPanel(briefMsg0, @"%@", quitMsg0, nil, nil,
+			longMsg0);
+
+		SavedBriefMsg = nullpr;
+	}
+}
+
+/* --- hide/show menubar --- */
+
+enum {
+	MyNSApplicationPresentationDefault                    = 0,
+	MyNSApplicationPresentationAutoHideDock               = (1 <<  0),
+	MyNSApplicationPresentationHideDock                   = (1 <<  1),
+	MyNSApplicationPresentationAutoHideMenuBar            = (1 <<  2),
+	MyNSApplicationPresentationHideMenuBar                = (1 <<  3),
+	MyNSApplicationPresentationDisableAppleMenu           = (1 <<  4),
+	MyNSApplicationPresentationDisableProcessSwitching    = (1 <<  5),
+	MyNSApplicationPresentationDisableForceQuit           = (1 <<  6),
+	MyNSApplicationPresentationDisableSessionTermination  = (1 <<  7),
+	MyNSApplicationPresentationDisableHideApplication     = (1 <<  8),
+	MyNSApplicationPresentationDisableMenuBarTransparency = (1 <<  9),
+	MyNSApplicationPresentationFullScreen                 = (1 << 10),
+	MyNSApplicationPresentationAutoHideToolbar            = (1 << 11)
+};
+typedef NSUInteger MyNSApplicationPresentationOptions;
+
+@interface MyNSApplication : NSObject
+- (void)setPresentationOptions:
+	(MyNSApplicationPresentationOptions)newOptions;
+@end
+
+
+#if MayFullScreen
+LOCALPROC My_HideMenuBar(void)
+{
+	if ([NSApp respondsToSelector:@selector(setPresentationOptions:)]) {
+		[((MyNSApplication *)NSApp) setPresentationOptions:
+			MyNSApplicationPresentationHideDock
+			| MyNSApplicationPresentationHideMenuBar
+#if GrabKeysFullScreen
+			| MyNSApplicationPresentationDisableProcessSwitching
+#if GrabKeysMaxFullScreen /* dangerous !! */
+			| MyNSApplicationPresentationDisableForceQuit
+			| MyNSApplicationPresentationDisableSessionTermination
+#endif
+#endif
+			];
+	} else
+	if (HaveMySetSystemUIMode()) {
+		(void) MySetSystemUIMode(MykUIModeAllHidden,
+			MykUIOptionDisableAppleMenu
+#if GrabKeysFullScreen
+			| MykUIOptionDisableProcessSwitch
+#if GrabKeysMaxFullScreen /* dangerous !! */
+			| MykUIOptionDisableForceQuit
+			| MykUIOptionDisableSessionTerminate
+#endif
+#endif
+			);
+	} else
+	{
+	}
+}
+#endif
+
+#if MayFullScreen
+LOCALPROC My_ShowMenuBar(void)
+{
+	if ([NSApp respondsToSelector:@selector(setPresentationOptions:)]) {
+		[((MyNSApplication *)NSApp) setPresentationOptions:
+			MyNSApplicationPresentationDefault];
+	} else
+	if (HaveMySetSystemUIMode()) {
+		(void) MySetSystemUIMode(MykUIModeNormal,
+			0);
+	} else
+	{
+	}
+}
+#endif
+
+/* --- event handling for main window --- */
+
+LOCALPROC MyBeginDialog(void)
+{
+	DisconnectKeyCodes3();
+	ForceShowCursor();
+}
+
+LOCALPROC MyEndDialog(void)
+{
+	[MyWindow makeKeyWindow];
+	EmulationWasInterrupted = trueblnr;
+}
+
+LOCALPROC InsertADisk0(void)
+{
+	NSOpenPanel *panel = [NSOpenPanel openPanel];
+
+	[panel setAllowsMultipleSelection: YES];
+
+	MyBeginDialog();
+
+	if (NSOKButton == [panel runModal]) {
+		int i;
+		NSArray *a = [panel URLs];
+		int n = [a count];
+
+		for (i = 0; i < n; ++i) {
+			NSURL *fileURL = [a objectAtIndex: i];
+			NSString* filePath = [fileURL path];
+			(void) Sony_Insert1a(filePath);
+		}
+	}
+
+	MyEndDialog();
+}
+
+/* --- main window creation and disposal --- */
+
+LOCALFUNC blnr Screen_Init(void)
+{
+#if 0
+	if (noErr != Gestalt(gestaltSystemVersion,
+		&cur_video.system_version))
+	{
+		cur_video.system_version = 0;
+	}
+#endif
+
+#if 0
+#define MyCGMainDisplayID CGMainDisplayID
+	CGDirectDisplayID CurMainDisplayID = MyCGMainDisplayID();
+
+	cur_video.width = (ui5b) CGDisplayPixelsWide(CurMainDisplayID);
+	cur_video.height = (ui5b) CGDisplayPixelsHigh(CurMainDisplayID);
+#endif
+
+	InitKeyCodes();
+
+	return trueblnr;
+}
+
+#if MayFullScreen
+LOCALPROC AdjustMachineGrab(void)
+{
+#if EnableFSMouseMotion
+	AdjustMouseMotionGrab();
+#endif
+}
+#endif
+
+#if MayFullScreen
+LOCALPROC UngrabMachine(void)
+{
+	GrabMachine = falseblnr;
+	AdjustMachineGrab();
+}
+#endif
+
+LOCALPROC MyAdjustGLforSize(int h, int v)
+{
+	[MyNSOpnGLCntxt makeCurrentContext];
+
+	glClearColor (0.0, 0.0, 0.0, 1.0);
+
+#if 1
+	glViewport(0, 0, h, v);
+	glMatrixMode(GL_PROJECTION);
+	glLoadIdentity();
+	glOrtho(0, h, 0, v, -1.0, 1.0);
+	glMatrixMode(GL_MODELVIEW);
+#endif
+
+	glColor3f(0.0, 0.0, 0.0);
+#if EnableMagnify
+	if (UseMagnify) {
+		glPixelZoom(MyWindowScale, - MyWindowScale);
+	} else
+#endif
+	{
+		glPixelZoom(1, -1);
+	}
+	glPixelStorei(GL_UNPACK_ROW_LENGTH, vMacScreenWidth);
+
+	glClear(GL_COLOR_BUFFER_BIT);
+
+	[NSOpenGLContext clearCurrentContext];
+
+	ScreenChangedAll();
+}
+
+LOCALVAR blnr WantScreensChangedCheck = falseblnr;
+
+LOCALPROC MyUpdateOpenGLContext(void)
+{
+	if (nil != MyNSOpnGLCntxt) {
+		[MyNSOpnGLCntxt makeCurrentContext];
+		[MyNSOpnGLCntxt update];
+	}
+}
+
+LOCALPROC CloseMyOpenGLContext(void)
+{
+	if (nil != MyNSOpnGLCntxt) {
+
+		[NSOpenGLContext clearCurrentContext];
+		/*
+			Only because MyDrawWithOpenGL doesn't
+			bother to do this. No one
+			uses the current context
+			without settting it first.
+		*/
+	}
+}
+
+LOCALFUNC blnr GetOpnGLCntxt(void)
+{
+	blnr v = falseblnr;
+
+	if (nil == MyNSOpnGLCntxt) {
+		NSRect NewWinRect = [MyNSview frame];
+		NSOpenGLPixelFormat *fmt;
+
+#if WantGraphicsSwitching
+		{
+			NSOpenGLPixelFormatAttribute attr0[] = {
+				NSOpenGLPFAAllowOfflineRenderers,
+				0};
+
+			fmt =
+				[[NSOpenGLPixelFormat alloc] initWithAttributes:attr0];
+		}
+		if (nil != fmt) {
+			/* ok */
+		} else
+#endif
+		{
+			NSOpenGLPixelFormatAttribute attr[] = {
+				0};
+
+			fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
+			if (nil == fmt) {
+#if dbglog_HAVE
+				dbglog_writeln("Could not create fmt");
+#endif
+				goto label_exit;
+			}
+		}
+
+		MyNSOpnGLCntxt = [[NSOpenGLContext alloc]
+			initWithFormat:fmt shareContext:nil];
+
+		[fmt release];
+
+		if (nil == MyNSOpnGLCntxt) {
+#if dbglog_HAVE
+			dbglog_writeln("Could not create MyNSOpnGLCntxt");
+#endif
+			goto label_exit;
+		}
+
+		/* fprintf(stderr, "%s\n", "Got OpenGL context"); */
+
+		[MyNSOpnGLCntxt setView: MyNSview];
+		[MyNSOpnGLCntxt update];
+
+		MyAdjustGLforSize(NewWinRect.size.width,
+			NewWinRect.size.height);
+
+#if 0 != vMacScreenDepth
+		ColorModeWorks = trueblnr;
+#endif
+	}
+	v = trueblnr;
+
+label_exit:
+	return v;
+}
+
+typedef NSUInteger (*modifierFlagsProcPtr)
+	(id self, SEL cmd);
+
+/* Subclass of NSWindow to fix genie effect and support resize events */
+@interface MyClassWindow : NSWindow
+@end
+
+@implementation MyClassWindow
+
+#if MayFullScreen
+- (BOOL)canBecomeKeyWindow
+{
+	return
+#if VarFullScreen
+		(! UseFullScreen) ? [super canBecomeKeyWindow] :
+#endif
+		YES;
+}
+#endif
+
+#if MayFullScreen
+- (BOOL)canBecomeMainWindow
+{
+	return
+#if VarFullScreen
+		(! UseFullScreen) ? [super canBecomeMainWindow] :
+#endif
+		YES;
+}
+#endif
+
+#if MayFullScreen
+- (NSRect)constrainFrameRect:(NSRect)frameRect
+	toScreen:(NSScreen *)screen
+{
+#if VarFullScreen
+	if (! UseFullScreen) {
+		return [super constrainFrameRect:frameRect toScreen:screen];
+	} else
+#endif
+	{
+		return frameRect;
+	}
+}
+#endif
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+{
+	/* NSPasteboard *pboard = [sender draggingPasteboard]; */
+	NSDragOperation sourceDragMask =
+		[sender draggingSourceOperationMask];
+	NSDragOperation v = NSDragOperationNone;
+
+	if (0 != (sourceDragMask & NSDragOperationGeneric)) {
+		return NSDragOperationGeneric;
+	}
+
+	return v;
+}
+
+- (void)draggingExited:(id <NSDraggingInfo>)sender
+{
+	/* remove hilighting */
+}
+
+- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
+{
+	return YES;
+}
+
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
+{
+	BOOL v = NO;
+	NSPasteboard *pboard = [sender draggingPasteboard];
+	/*
+		NSDragOperation sourceDragMask =
+			[sender draggingSourceOperationMask];
+	*/
+
+	if ([[pboard types] containsObject:NSFilenamesPboardType]) {
+		int i;
+		NSArray *file_names =
+			[pboard propertyListForType: NSFilenamesPboardType];
+		int n = [file_names count];
+
+		for (i = 0; i < n; ++i) {
+			NSString *filePath = [file_names objectAtIndex:i];
+			Sony_ResolveInsert(filePath);
+		}
+		v = YES;
+	} else if ([[pboard types] containsObject: NSURLPboardType]) {
+		NSURL *fileURL = [NSURL URLFromPasteboard: pboard];
+		NSString* filePath = [fileURL path];
+		Sony_ResolveInsert(filePath);
+		v = YES;
+	}
+
+	if (v && gTrueBackgroundFlag) {
+		{
+			SEL sel = @selector(modifierFlags);
+
+			if ([NSEvent respondsToSelector:sel]) {
+				modifierFlagsProcPtr imp = (modifierFlagsProcPtr)
+					[NSEvent methodForSelector:sel];
+
+				MyUpdateKeyboardModifiers(imp([NSEvent class], sel));
+			}
+		}
+
+		[NSApp activateIgnoringOtherApps: YES];
+	}
+
+	return v;
+}
+
+- (void) concludeDragOperation:(id <NSDraggingInfo>)the_sender
+{
+}
+
+@end
+
+@interface MyClassWindowDelegate : NSObject <NSWindowDelegate>
+@end
+
+@implementation MyClassWindowDelegate
+
+- (BOOL)windowShouldClose:(id)sender
+{
+	RequestMacOff = trueblnr;
+	return NO;
+}
+
+- (void)windowDidBecomeKey:(NSNotification *)aNotification
+{
+	gTrueBackgroundFlag = falseblnr;
+}
+
+- (void)windowDidResignKey:(NSNotification *)aNotification
+{
+	gTrueBackgroundFlag = trueblnr;
+}
+
+@end
+
+@interface MyClassView : NSView
+@end
+
+@implementation MyClassView
+
+- (void)resetCursorRects
+{
+	[self addCursorRect: [self visibleRect]
+		cursor: [NSCursor arrowCursor]];
+}
+
+- (BOOL)isOpaque
+{
+	return YES;
+}
+
+- (void)drawRect:(NSRect)dirtyRect
+{
+	/*
+		Called upon makeKeyAndOrderFront. Create our
+		OpenGL context here, because can't do so
+		before makeKeyAndOrderFront.
+		And if create after then our content won't
+		be drawn initially, resulting in flicker.
+	*/
+	if (GetOpnGLCntxt()) {
+		MyDrawWithOpenGL(0, 0, vMacScreenHeight, vMacScreenWidth);
+	}
+}
+
+@end
+
+#if UseCGContextDrawImage
+/* absent in 10.3.9.  */
+CG_EXTERN CGImageRef CGBitmapContextCreateImage(CGContextRef);
+#endif
+
+
+LOCALVAR MyClassWindowDelegate *MyWinDelegate = nil;
+
+LOCALPROC CloseMainWindow(void)
+{
+	if (nil != MyWinDelegate) {
+		[MyWinDelegate release];
+		MyWinDelegate = nil;
+	}
+
+	if (nil != MyWindow) {
+		[MyWindow close];
+		MyWindow = nil;
+	}
+
+	if (nil != MyNSview) {
+		[MyNSview release];
+		MyNSview = nil;
+	}
+
+#if UseCGContextDrawImage
+	if (nil != MyCGcontext) {
+		CGContextFlush(MyCGcontext);
+		CGContextRelease(MyCGcontext);
+		MyCGcontext = nil;
+	}
+
+	if (NULL != MyPixels) {
+		free(MyPixels);
+		MyPixels = NULL;
+	}
+#endif
+
+	if (nil != MyNSOpnGLCntxt) {
+		[MyNSOpnGLCntxt release];
+		MyNSOpnGLCntxt = nil;
+	}
+}
+
+LOCALPROC QZ_SetCaption(void)
+{
+#if 0
+	NSString *string =
+		[[NSString alloc] initWithUTF8String: kStrAppName];
+#endif
+	[MyWindow setTitle: myAppName /* string */];
+#if 0
+	[string release];
+#endif
+}
+
+enum {
+	kMagStateNormal,
+#if EnableMagnify
+	kMagStateMagnifgy,
+#endif
+	kNumMagStates
+};
+
+#define kMagStateAuto kNumMagStates
+
+#if MayNotFullScreen
+LOCALVAR int CurWinIndx;
+LOCALVAR blnr HavePositionWins[kNumMagStates];
+LOCALVAR NSPoint WinPositionWins[kNumMagStates];
+#endif
+
+LOCALVAR NSRect SavedScrnBounds;
+
+LOCALFUNC blnr CreateMainWindow(void)
+{
+#if UseCGContextDrawImage
+	CGColorSpaceRef cgColorspace;
+#endif
+	unsigned int style;
+	NSRect MainScrnBounds;
+	NSRect AllScrnBounds;
+	NSRect NewWinRect;
+	NSPoint botleftPos;
+	int NewWindowHeight = vMacScreenHeight;
+	int NewWindowWidth = vMacScreenWidth;
+	blnr v = falseblnr;
+
+#if VarFullScreen
+	if (UseFullScreen) {
+		My_HideMenuBar();
+	} else {
+		My_ShowMenuBar();
+	}
+#else
+#if MayFullScreen
+	My_HideMenuBar();
+#endif
+#endif
+
+	MainScrnBounds = [[NSScreen mainScreen] frame];
+	SavedScrnBounds = MainScrnBounds;
+	{
+		int i;
+		NSArray *screens = [NSScreen screens];
+		int n = [screens count];
+
+		AllScrnBounds = MainScrnBounds;
+		for (i = 0; i < n; ++i) {
+			AllScrnBounds = NSUnionRect(AllScrnBounds,
+				[[screens objectAtIndex:i] frame]);
+		}
+	}
+
+#if EnableMagnify
+	if (UseMagnify) {
+		NewWindowHeight *= MyWindowScale;
+		NewWindowWidth *= MyWindowScale;
+	}
+#endif
+
+	botleftPos.x = MainScrnBounds.origin.x
+		+ floor((MainScrnBounds.size.width
+			- NewWindowWidth) / 2);
+	botleftPos.y = MainScrnBounds.origin.y
+		+ floor((MainScrnBounds.size.height
+			- NewWindowHeight) / 2);
+	if (botleftPos.x < MainScrnBounds.origin.x) {
+		botleftPos.x = MainScrnBounds.origin.x;
+	}
+	if (botleftPos.y < MainScrnBounds.origin.y) {
+		botleftPos.y = MainScrnBounds.origin.y;
+	}
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		ViewHSize = MainScrnBounds.size.width;
+		ViewVSize = MainScrnBounds.size.height;
+#if EnableMagnify
+		if (UseMagnify) {
+			ViewHSize /= MyWindowScale;
+			ViewVSize /= MyWindowScale;
+		}
+#endif
+		if (ViewHSize >= vMacScreenWidth) {
+			ViewHStart = 0;
+			ViewHSize = vMacScreenWidth;
+		} else {
+			ViewHSize &= ~ 1;
+		}
+		if (ViewVSize >= vMacScreenHeight) {
+			ViewVStart = 0;
+			ViewVSize = vMacScreenHeight;
+		} else {
+			ViewVSize &= ~ 1;
+		}
+	}
+#endif
+
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		NewWinRect = AllScrnBounds;
+
+		GLhOffset = botleftPos.x - AllScrnBounds.origin.x;
+		GLvOffset = (botleftPos.y - AllScrnBounds.origin.y)
+			+ ((NewWindowHeight < MainScrnBounds.size.height)
+				? NewWindowHeight : MainScrnBounds.size.height);
+
+		hOffset = GLhOffset;
+		vOffset = AllScrnBounds.size.height - GLvOffset;
+
+		style = NSBorderlessWindowMask;
+	}
+#endif
+#if VarFullScreen
+	else
+#endif
+#if MayNotFullScreen
+	{
+		int WinIndx;
+
+#if EnableMagnify
+		if (UseMagnify) {
+			WinIndx = kMagStateMagnifgy;
+		} else
+#endif
+		{
+			WinIndx = kMagStateNormal;
+		}
+
+		if (! HavePositionWins[WinIndx]) {
+			WinPositionWins[WinIndx].x = botleftPos.x;
+			WinPositionWins[WinIndx].y = botleftPos.y;
+			HavePositionWins[WinIndx] = trueblnr;
+			NewWinRect = NSMakeRect(botleftPos.x, botleftPos.y,
+				NewWindowWidth, NewWindowHeight);
+		} else {
+			NewWinRect = NSMakeRect(WinPositionWins[WinIndx].x,
+				WinPositionWins[WinIndx].y,
+				NewWindowWidth, NewWindowHeight);
+		}
+
+		GLhOffset = 0;
+		GLvOffset = NewWindowHeight;
+
+		style = NSTitledWindowMask
+			| NSMiniaturizableWindowMask | NSClosableWindowMask;
+
+		CurWinIndx = WinIndx;
+	}
+#endif
+
+	/* Manually create a window, avoids having a nib file resource */
+	MyWindow = [[MyClassWindow alloc]
+		initWithContentRect: NewWinRect
+		styleMask: style
+		backing: NSBackingStoreBuffered
+		defer: YES];
+
+	if (nil == MyWindow) {
+#if dbglog_HAVE
+		dbglog_writeln("Could not create the Cocoa window");
+#endif
+		goto label_exit;
+	}
+
+	/* [MyWindow setReleasedWhenClosed: YES]; */
+		/*
+			no need to set current_video as it's the
+			default for NSWindows
+		*/
+	QZ_SetCaption();
+	[MyWindow setAcceptsMouseMovedEvents: YES];
+	[MyWindow setViewsNeedDisplay: NO];
+
+	[MyWindow registerForDraggedTypes:
+		[NSArray arrayWithObjects:
+			NSURLPboardType, NSFilenamesPboardType, nil]];
+
+	MyWinDelegate = [[MyClassWindowDelegate alloc] init];
+	if (nil == MyWinDelegate) {
+#if dbglog_HAVE
+		dbglog_writeln("Could not create MyNSview");
+#endif
+		goto label_exit;
+	}
+	[MyWindow setDelegate: MyWinDelegate];
+
+	MyNSview = [[MyClassView alloc] init];
+	if (nil == MyNSview) {
+#if dbglog_HAVE
+		dbglog_writeln("Could not create MyNSview");
+#endif
+		goto label_exit;
+	}
+	[MyWindow setContentView: MyNSview];
+
+	[MyWindow makeKeyAndOrderFront: nil];
+
+	/* just in case drawRect didn't get called */
+	if (! GetOpnGLCntxt()) {
+#if dbglog_HAVE
+		dbglog_writeln("Could not GetOpnGLCntxt");
+#endif
+		goto label_exit;
+	}
+
+#if UseCGContextDrawImage
+	MyPitch = 4 * NewWindowWidth;
+	MyPixels = malloc(NewWindowHeight * MyPitch);
+
+	cgColorspace = CGColorSpaceCreateDeviceRGB();
+	MyCGcontext = CGBitmapContextCreate(MyPixels,
+		NewWindowWidth, NewWindowHeight,
+		8, MyPitch, cgColorspace,
+		kCGImageAlphaNoneSkipFirst);
+	CGColorSpaceRelease(cgColorspace);
+
+	MyNSgfxContext = [NSGraphicsContext
+		graphicsContextWithWindow: MyWindow];
+	[NSGraphicsContext setCurrentContext: MyNSgfxContext];
+
+	MyBytesPerPixel = 4;
+#endif
+
+	v = trueblnr;
+
+label_exit:
+
+	return v;
+}
+
+#if EnableRecreateW
+LOCALPROC ZapMyWState(void)
+{
+	MyWindow = nil;
+	MyNSview = nil;
+	MyWinDelegate = nil;
+#if UseCGContextDrawImage
+	MyNSgfxContext = nil;
+	MyCGcontext = nil;
+	MyPixels = NULL;
+#endif
+	MyNSOpnGLCntxt = nil;
+}
+#endif
+
+#if EnableRecreateW
+struct MyWState {
+#if MayFullScreen
+	ui4r f_ViewHSize;
+	ui4r f_ViewVSize;
+	ui4r f_ViewHStart;
+	ui4r f_ViewVStart;
+	short f_hOffset;
+	short f_vOffset;
+#endif
+#if VarFullScreen
+	blnr f_UseFullScreen;
+#endif
+#if EnableMagnify
+	blnr f_UseMagnify;
+#endif
+#if MayNotFullScreen
+	int f_CurWinIndx;
+#endif
+	NSWindow *f_MyWindow;
+	NSView *f_MyNSview;
+	MyClassWindowDelegate *f_MyWinDelegate;
+#if UseCGContextDrawImage
+	NSGraphicsContext *f_MyNSgfxContext;
+	CGContextRef f_MyCGcontext;
+	void *f_MyPixels;
+	ui4b f_MyPitch;
+	ui3b f_MyBytesPerPixel;
+#endif
+	NSOpenGLContext *f_MyNSOpnGLCntxt;
+	short f_GLhOffset;
+	short f_GLvOffset;
+};
+typedef struct MyWState MyWState;
+#endif
+
+#if EnableRecreateW
+LOCALPROC GetMyWState(MyWState *r)
+{
+#if MayFullScreen
+	r->f_ViewHSize = ViewHSize;
+	r->f_ViewVSize = ViewVSize;
+	r->f_ViewHStart = ViewHStart;
+	r->f_ViewVStart = ViewVStart;
+	r->f_hOffset = hOffset;
+	r->f_vOffset = vOffset;
+#endif
+#if VarFullScreen
+	r->f_UseFullScreen = UseFullScreen;
+#endif
+#if EnableMagnify
+	r->f_UseMagnify = UseMagnify;
+#endif
+#if MayNotFullScreen
+	r->f_CurWinIndx = CurWinIndx;
+#endif
+	r->f_MyWindow = MyWindow;
+	r->f_MyNSview = MyNSview;
+	r->f_MyWinDelegate = MyWinDelegate;
+#if UseCGContextDrawImage
+	r->f_MyNSgfxContext = MyNSgfxContext;
+	r->f_MyCGcontext = MyCGcontext;
+	r->f_MyPixels = MyPixels;
+	r->f_MyPitch = MyPitch;
+	r->f_MyBytesPerPixel = MyBytesPerPixel;
+#endif
+	r->f_MyNSOpnGLCntxt = MyNSOpnGLCntxt;
+	r->f_GLhOffset = GLhOffset;
+	r->f_GLvOffset = GLvOffset;
+}
+#endif
+
+#if EnableRecreateW
+LOCALPROC SetMyWState(MyWState *r)
+{
+#if MayFullScreen
+	ViewHSize = r->f_ViewHSize;
+	ViewVSize = r->f_ViewVSize;
+	ViewHStart = r->f_ViewHStart;
+	ViewVStart = r->f_ViewVStart;
+	hOffset = r->f_hOffset;
+	vOffset = r->f_vOffset;
+#endif
+#if VarFullScreen
+	UseFullScreen = r->f_UseFullScreen;
+#endif
+#if EnableMagnify
+	UseMagnify = r->f_UseMagnify;
+#endif
+#if MayNotFullScreen
+	CurWinIndx = r->f_CurWinIndx;
+#endif
+	MyWindow = r->f_MyWindow;
+	MyNSview = r->f_MyNSview;
+	MyWinDelegate = r->f_MyWinDelegate;
+#if UseCGContextDrawImage
+	MyNSgfxContext = r->f_MyNSgfxContext;
+	MyCGcontext = r->f_MyCGcontext;
+	MyPixels = r->f_MyPixels;
+	MyPitch = r->f_MyPitch;
+	MyBytesPerPixel = r->f_MyBytesPerPixel;
+#endif
+	MyNSOpnGLCntxt = r->f_MyNSOpnGLCntxt;
+	GLhOffset = r->f_GLhOffset;
+	GLvOffset = r->f_GLvOffset;
+}
+#endif
+
+#if EnableRecreateW
+LOCALPROC ReCreateMainWindow(void)
+{
+	MyWState old_state;
+	MyWState new_state;
+	blnr HadCursorHidden = HaveCursorHidden;
+
+#if VarFullScreen
+	if (! UseFullScreen)
+#endif
+#if MayNotFullScreen
+	{
+		/* save old position */
+		NSRect r =
+			[NSWindow contentRectForFrameRect: [MyWindow frame]
+				styleMask: [MyWindow styleMask]];
+		WinPositionWins[CurWinIndx] = r.origin;
+	}
+#endif
+
+#if MayFullScreen
+	if (GrabMachine) {
+		GrabMachine = falseblnr;
+		UngrabMachine();
+	}
+#endif
+
+	CloseMyOpenGLContext();
+
+	GetMyWState(&old_state);
+
+	ZapMyWState();
+
+#if EnableMagnify
+	UseMagnify = WantMagnify;
+#endif
+#if VarFullScreen
+	UseFullScreen = WantFullScreen;
+#endif
+
+	if (! CreateMainWindow()) {
+		CloseMainWindow();
+		SetMyWState(&old_state);
+
+#if VarFullScreen
+		if (UseFullScreen) {
+			My_HideMenuBar();
+		} else {
+			My_ShowMenuBar();
+		}
+#endif
+
+		/* avoid retry */
+#if VarFullScreen
+		WantFullScreen = UseFullScreen;
+#endif
+#if EnableMagnify
+		WantMagnify = UseMagnify;
+#endif
+
+	} else {
+		GetMyWState(&new_state);
+		SetMyWState(&old_state);
+		CloseMainWindow();
+		SetMyWState(&new_state);
+
+		if (HadCursorHidden) {
+			(void) MyMoveMouse(CurMouseH, CurMouseV);
+		}
+	}
+}
+#endif
+
+#if VarFullScreen && EnableMagnify
+enum {
+	kWinStateWindowed,
+#if EnableMagnify
+	kWinStateFullScreen,
+#endif
+	kNumWinStates
+};
+#endif
+
+#if VarFullScreen && EnableMagnify
+LOCALVAR int WinMagStates[kNumWinStates];
+#endif
+
+LOCALPROC ZapWinStateVars(void)
+{
+#if MayNotFullScreen
+	{
+		int i;
+
+		for (i = 0; i < kNumMagStates; ++i) {
+			HavePositionWins[i] = falseblnr;
+		}
+	}
+#endif
+#if VarFullScreen && EnableMagnify
+	{
+		int i;
+
+		for (i = 0; i < kNumWinStates; ++i) {
+			WinMagStates[i] = kMagStateAuto;
+		}
+	}
+#endif
+}
+
+#if VarFullScreen
+LOCALPROC ToggleWantFullScreen(void)
+{
+	WantFullScreen = ! WantFullScreen;
+
+#if EnableMagnify
+	{
+		int OldWinState =
+			UseFullScreen ? kWinStateFullScreen : kWinStateWindowed;
+		int OldMagState =
+			UseMagnify ? kMagStateMagnifgy : kMagStateNormal;
+		int NewWinState =
+			WantFullScreen ? kWinStateFullScreen : kWinStateWindowed;
+		int NewMagState = WinMagStates[NewWinState];
+
+		WinMagStates[OldWinState] = OldMagState;
+		if (kMagStateAuto != NewMagState) {
+			WantMagnify = (kMagStateMagnifgy == NewMagState);
+		} else {
+			WantMagnify = falseblnr;
+			if (WantFullScreen) {
+				NSRect MainScrnBounds = [[NSScreen mainScreen] frame];
+
+				if ((MainScrnBounds.size.width
+						>= vMacScreenWidth * MyWindowScale)
+					&& (MainScrnBounds.size.height
+						>= vMacScreenHeight * MyWindowScale)
+					)
+				{
+					WantMagnify = trueblnr;
+				}
+			}
+		}
+	}
+#endif
+}
+#endif
+
+/* --- SavedTasks --- */
+
+LOCALPROC LeaveBackground(void)
+{
+	ReconnectKeyCodes3();
+	DisableKeyRepeat();
+	EmulationWasInterrupted = trueblnr;
+}
+
+LOCALPROC EnterBackground(void)
+{
+	RestoreKeyRepeat();
+	DisconnectKeyCodes3();
+
+	ForceShowCursor();
+}
+
+LOCALPROC LeaveSpeedStopped(void)
+{
+#if MySoundEnabled
+	MySound_Start();
+#endif
+
+	StartUpTimeAdjust();
+}
+
+LOCALPROC EnterSpeedStopped(void)
+{
+#if MySoundEnabled
+	MySound_Stop();
+#endif
+}
+
+#if IncludeSonyNew && ! SaveDialogEnable
+LOCALFUNC blnr FindOrMakeNamedChildDirPath(NSString *parentPath,
+	char *ChildName, NSString **childPath)
+{
+	NSString *r;
+	BOOL isDir;
+	Boolean isDirectory;
+	NSFileManager *fm = [NSFileManager defaultManager];
+	blnr v = falseblnr;
+
+	if (FindNamedChildPath(parentPath, ChildName, &r)) {
+		if ([fm fileExistsAtPath:r isDirectory: &isDir])
+		{
+			if (isDir) {
+				*childPath = r;
+				v = trueblnr;
+			} else {
+				NSString *RslvPath = MyResolveAlias(r, &isDirectory);
+				if (nil != RslvPath) {
+					if (isDirectory) {
+						*childPath = RslvPath;
+						v = trueblnr;
+					}
+				}
+			}
+		} else {
+			if ([fm respondsToSelector:@selector(
+createDirectoryAtPath:withIntermediateDirectories:attributes:error:
+				)])
+			{
+				if ([fm
+					createDirectoryAtPath:r
+					withIntermediateDirectories:NO
+					attributes:nil
+					error:nil])
+				{
+					*childPath = r;
+					v = trueblnr;
+				}
+			} else
+			if ([fm respondsToSelector:
+				@selector(createDirectoryAtPath:attributes:)])
+			{
+				if ([fm
+					createDirectoryAtPath:r
+					attributes:nil])
+				{
+					*childPath = r;
+					v = trueblnr;
+				}
+			} else
+			{
+				/* fail */
+			}
+		}
+	}
+
+	return v;
+}
+#endif
+
+@interface MyNSSavePanel : NSObject
+- (NSInteger)runModalForDirectory:(NSString *)path
+	file:(NSString *)filename;
+- (void)setNameFieldStringValue:(NSString *)value;
+@end
+
+#if IncludeSonyNew
+LOCALPROC MakeNewDisk(ui5b L, NSString *drivename)
+{
+#if SaveDialogEnable
+	NSInteger result = NSCancelButton;
+	NSSavePanel *panel = [NSSavePanel savePanel];
+
+	MyBeginDialog();
+
+	if ([panel respondsToSelector:@selector(setNameFieldStringValue:)])
+	{
+#if 0
+		[panel setNameFieldStringValue: drivename];
+			/* available as of OS X 10.6 */
+#endif
+#if 0
+		[panel performSelector:@selector(setNameFieldStringValue:)
+			withObject: drivename];
+#endif
+		[((MyNSSavePanel *)panel)
+			setNameFieldStringValue: drivename];
+
+		result = [panel runModal];
+	} else
+	if ([panel
+		respondsToSelector: @selector(runModalForDirectory:file:)])
+	{
+#if 0
+		result = [panel runModalForDirectory: nil file: drivename];
+			/*
+				compiler warns deprecated. To avoid warning, and
+				to still work if removed from SDK, use NSInvocation.
+			*/
+#endif
+#if 0
+		NSString *sDirName = nil;
+		SEL sel = @selector(runModalForDirectory:file:);
+		NSInvocation* invoc =
+			[NSInvocation invocationWithMethodSignature:
+				[panel methodSignatureForSelector: sel]];
+		[invoc setTarget:panel];
+		[invoc setSelector:sel];
+		[invoc setArgument:&sDirName atIndex:2];
+		[invoc setArgument:&drivename atIndex:3];
+		[invoc invoke];
+		[invoc getReturnValue: &result];
+#endif
+		/* an easier way ? seems to work */
+		result = [((MyNSSavePanel *)panel)
+			runModalForDirectory: nil file: drivename];
+	} else
+	{
+		/* fail */
+	}
+
+	MyEndDialog();
+
+	if (NSOKButton == result) {
+		NSString* filePath = [[panel URL] path];
+		MakeNewDisk0(L, filePath);
+	}
+#else /* SaveDialogEnable */
+	NSString *sPath;
+
+	if (FindOrMakeNamedChildDirPath(MyDataPath, "out", &sPath)) {
+		NSString *filePath =
+			[sPath stringByAppendingPathComponent: drivename];
+		MakeNewDisk0(L, filePath);
+	}
+#endif /* SaveDialogEnable */
+}
+#endif
+
+#if IncludeSonyNew
+LOCALPROC MakeNewDiskAtDefault(ui5b L)
+{
+	MakeNewDisk(L, @"untitled.dsk");
+}
+#endif
+
+LOCALPROC CheckForSavedTasks(void)
+{
+	if (MyEvtQNeedRecover) {
+		MyEvtQNeedRecover = falseblnr;
+
+		/* attempt cleanup, MyEvtQNeedRecover may get set again */
+		MyEvtQTryRecoverFromFull();
+	}
+
+	if (RequestMacOff) {
+		RequestMacOff = falseblnr;
+		if (AnyDiskInserted()) {
+			MacMsgOverride(kStrQuitWarningTitle,
+				kStrQuitWarningMessage);
+		} else {
+			ForceMacOff = trueblnr;
+		}
+	}
+
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (gTrueBackgroundFlag != gBackgroundFlag) {
+		gBackgroundFlag = gTrueBackgroundFlag;
+		if (gTrueBackgroundFlag) {
+			EnterBackground();
+		} else {
+			LeaveBackground();
+		}
+	}
+
+	if (EmulationWasInterrupted) {
+		EmulationWasInterrupted = falseblnr;
+
+		if (! gTrueBackgroundFlag) {
+			CheckMouseState();
+		}
+	}
+
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		MyMouseConstrain();
+	}
+#endif
+
+#if VarFullScreen
+	if (gTrueBackgroundFlag && WantFullScreen) {
+		ToggleWantFullScreen();
+	}
+#endif
+
+	if (WantScreensChangedCheck) {
+		WantScreensChangedCheck = falseblnr;
+
+		MyUpdateOpenGLContext();
+
+#if VarFullScreen
+		/*
+			triggered on enter full screen for some
+			reason in OS X 10.11. so check against
+			saved rect.
+		*/
+		if ((WantFullScreen)
+			&& (! NSEqualRects(SavedScrnBounds,
+				[[NSScreen mainScreen] frame])))
+		{
+			ToggleWantFullScreen();
+		}
+#endif
+	}
+
+	if (CurSpeedStopped != (SpeedStopped ||
+		(gBackgroundFlag && ! RunInBackground
+#if EnableAutoSlow && 0
+			&& (QuietSubTicks >= 4092)
+#endif
+		)))
+	{
+		CurSpeedStopped = ! CurSpeedStopped;
+		if (CurSpeedStopped) {
+			EnterSpeedStopped();
+		} else {
+			LeaveSpeedStopped();
+		}
+	}
+
+	if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
+		MacMsgDisplayOn();
+	}
+
+#if EnableRecreateW
+	if (0
+#if EnableMagnify
+		|| (UseMagnify != WantMagnify)
+#endif
+#if VarFullScreen
+		|| (UseFullScreen != WantFullScreen)
+#endif
+		)
+	{
+		ReCreateMainWindow();
+	}
+#endif
+
+#if MayFullScreen
+	if (GrabMachine != (
+#if VarFullScreen
+		UseFullScreen &&
+#endif
+		! (gTrueBackgroundFlag || CurSpeedStopped)))
+	{
+		GrabMachine = ! GrabMachine;
+		AdjustMachineGrab();
+	}
+#endif
+
+#if IncludeSonyNew
+	if (vSonyNewDiskWanted) {
+#if IncludeSonyNameNew
+		if (vSonyNewDiskName != NotAPbuf) {
+			NSString *sNewDiskName;
+			if (MacRomanFileNameToNSString(vSonyNewDiskName,
+				&sNewDiskName))
+			{
+				MakeNewDisk(vSonyNewDiskSize, sNewDiskName);
+			}
+			PbufDispose(vSonyNewDiskName);
+			vSonyNewDiskName = NotAPbuf;
+		} else
+#endif
+		{
+			MakeNewDiskAtDefault(vSonyNewDiskSize);
+		}
+		vSonyNewDiskWanted = falseblnr;
+			/* must be done after may have gotten disk */
+	}
+#endif
+
+	if (NeedWholeScreenDraw) {
+		NeedWholeScreenDraw = falseblnr;
+		ScreenChangedAll();
+	}
+
+	if (! gTrueBackgroundFlag) {
+		if (RequestInsertDisk) {
+			RequestInsertDisk = falseblnr;
+			InsertADisk0();
+		}
+	}
+
+#if NeedRequestIthDisk
+	if (0 != RequestIthDisk) {
+		Sony_InsertIth(RequestIthDisk);
+		RequestIthDisk = 0;
+	}
+#endif
+
+	if (HaveCursorHidden != (
+#if MayNotFullScreen
+		(WantCursorHidden
+#if VarFullScreen
+			|| UseFullScreen
+#endif
+		) &&
+#endif
+		! (gTrueBackgroundFlag || CurSpeedStopped)))
+	{
+		HaveCursorHidden = ! HaveCursorHidden;
+		if (HaveCursorHidden) {
+			MyHideCursor();
+		} else {
+			MyShowCursor();
+		}
+	}
+
+#if 1
+	/*
+		Check if actual cursor visibility is what it should be.
+		If move mouse to dock then cursor is made visible, but then
+		if move directly to our window, cursor is not hidden again.
+	*/
+	if (HaveMyCGCursorIsVisible()) {
+		/* but only in OS X 10.3 and later */
+		/* deprecated in cocoa, but no alternative (?) */
+		if (MyCGCursorIsVisible()) {
+			if (HaveCursorHidden) {
+				MyHideCursor();
+				if (MyCGCursorIsVisible()) {
+					/*
+						didn't work, attempt undo so that
+						hide cursor count won't get large
+					*/
+					MyShowCursor();
+				}
+			}
+		} else {
+			if (! HaveCursorHidden) {
+				MyShowCursor();
+				/*
+					don't check if worked, assume can't decrement
+					hide cursor count below 0
+				*/
+			}
+		}
+	}
+#endif
+}
+
+/* --- main program flow --- */
+
+GLOBALOSGLUFUNC blnr ExtraTimeNotOver(void)
+{
+	UpdateTrueEmulatedTime();
+	return TrueEmulatedTime == OnTrueTime;
+}
+
+LOCALPROC ProcessEventModifiers(NSEvent *event)
+{
+	NSUInteger newMods = [event modifierFlags];
+
+	MyUpdateKeyboardModifiers(newMods);
+}
+
+LOCALPROC ProcessEventLocation(NSEvent *event)
+{
+	NSPoint p = [event locationInWindow];
+	NSWindow *w = [event window];
+
+	if (w != MyWindow) {
+		if (nil != w) {
+			p = [w convertBaseToScreen: p];
+		}
+		p = [MyWindow convertScreenToBase: p];
+	}
+	p = [MyNSview convertPoint: p fromView: nil];
+	p.y = [MyNSview frame].size.height - p.y;
+	MousePositionNotify((int) p.x, (int) p.y);
+}
+
+LOCALPROC ProcessKeyEvent(blnr down, NSEvent *event)
+{
+	ui3r scancode = [event keyCode];
+
+	ProcessEventModifiers(event);
+	Keyboard_UpdateKeyMap2(Keyboard_RemapMac(scancode), down);
+}
+
+LOCALPROC ProcessOneSystemEvent(NSEvent *event)
+{
+	switch ([event type]) {
+		case NSLeftMouseDown:
+		case NSRightMouseDown:
+		case NSOtherMouseDown:
+			/*
+				int button = QZ_OtherMouseButtonToSDL(
+					[event buttonNumber]);
+			*/
+			ProcessEventLocation(event);
+			ProcessEventModifiers(event);
+			if (([event window] == MyWindow)
+				&& (! gTrueBackgroundFlag)
+#if MayNotFullScreen
+				&& (WantCursorHidden
+#if VarFullScreen
+				|| UseFullScreen
+#endif
+				)
+#endif
+				)
+			{
+				MyMouseButtonSet(trueblnr);
+			} else {
+				/* doesn't belong to us */
+				[NSApp sendEvent: event];
+			}
+			break;
+
+		case NSLeftMouseUp:
+		case NSRightMouseUp:
+		case NSOtherMouseUp:
+			/*
+				int button = QZ_OtherMouseButtonToSDL(
+					[event buttonNumber]);
+			*/
+			ProcessEventLocation(event);
+			ProcessEventModifiers(event);
+			if (! MyMouseButtonState) {
+				/* doesn't belong to us */
+				[NSApp sendEvent: event];
+			} else {
+				MyMouseButtonSet(falseblnr);
+			}
+			break;
+
+		case NSMouseMoved:
+			{
+				ProcessEventLocation(event);
+				ProcessEventModifiers(event);
+			}
+			break;
+		case NSLeftMouseDragged:
+		case NSRightMouseDragged:
+		case NSOtherMouseDragged:
+			if (! MyMouseButtonState) {
+				/* doesn't belong to us ? */
+				[NSApp sendEvent: event];
+			} else {
+				ProcessEventLocation(event);
+				ProcessEventModifiers(event);
+			}
+			break;
+		case NSKeyUp:
+			ProcessKeyEvent(falseblnr, event);
+			break;
+		case NSKeyDown:
+			ProcessKeyEvent(trueblnr, event);
+			break;
+		case NSFlagsChanged:
+			ProcessEventModifiers(event);
+			break;
+		/* case NSScrollWheel: */
+		/* case NSSystemDefined: */
+		/* case NSAppKitDefined: */
+		/* case NSApplicationDefined: */
+		/* case NSPeriodic: */
+		/* case NSCursorUpdate: */
+		default:
+			[NSApp sendEvent: event];
+	}
+}
+
+GLOBALOSGLUPROC WaitForNextTick(void)
+{
+	NSDate *TheUntil;
+	int i;
+	NSEvent *event;
+	NSAutoreleasePool *pool;
+
+	pool = [[NSAutoreleasePool alloc] init];
+
+	NSDate *TheDistantFuture = [NSDate distantFuture];
+	NSDate *TheDistantPast = [NSDate distantPast];
+#if 0
+	NSDate *TheNextTick = [NSDate
+		dateWithTimeIntervalSinceReferenceDate: NextTickChangeTime];
+#endif
+
+	TheUntil = TheDistantPast;
+
+label_retry:
+
+	i = 32;
+	while ((--i >= 0) && (nil != (event =
+		[NSApp nextEventMatchingMask: NSAnyEventMask
+			untilDate: TheUntil
+			inMode: NSDefaultRunLoopMode
+			dequeue: YES])))
+	{
+		ProcessOneSystemEvent(event);
+		TheUntil = TheDistantPast;
+	}
+
+	CheckForSavedTasks();
+
+	if (ForceMacOff) {
+		goto label_exit;
+	}
+
+	if (CurSpeedStopped) {
+		DoneWithDrawingForTick();
+		TheUntil = TheDistantFuture;
+		goto label_retry;
+	}
+
+	if (ExtraTimeNotOver()) {
+#if 1
+#if 0 && EnableAutoSlow
+		if ((QuietSubTicks >= 16384)
+			&& (QuietTime >= 34)
+			&& ! WantNotAutoSlow)
+		{
+			TheUntil = [NSDate
+				dateWithTimeIntervalSinceReferenceDate:
+					(NextTickChangeTime + 0.50)];
+		} else
+#endif
+		{
+			NSTimeInterval inTimeout =
+				NextTickChangeTime - LatestTime;
+			if (inTimeout > 0.0) {
+				struct timespec rqt;
+				struct timespec rmt;
+
+				rqt.tv_sec = 0;
+				rqt.tv_nsec = inTimeout * 1000000000.0;
+				(void) nanosleep(&rqt, &rmt);
+			}
+			TheUntil = TheDistantPast;
+		}
+#else
+		/*
+			This has higher overhead.
+		*/
+		TheUntil = TheNextTick;
+#endif
+		goto label_retry;
+	}
+
+#if 0
+	if (! gTrueBackgroundFlag) {
+		CheckMouseState();
+	}
+#endif
+
+	if (CheckDateTime()) {
+#if MySoundEnabled
+		MySound_SecondNotify();
+#endif
+#if EnableDemoMsg
+		DemoModeSecondNotify();
+#endif
+	}
+
+	OnTrueTime = TrueEmulatedTime;
+
+#if dbglog_TimeStuff
+	dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime);
+#endif
+
+label_exit:
+	[pool release];
+}
+
+typedef Boolean (*SecTranslocateIsTranslocatedURL_t)(
+	CFURLRef path, bool *isTranslocated, CFErrorRef * error);
+typedef CFURLRef (*SecTranslocateCreateOriginalPathForURL_t)(
+	CFURLRef translocatedPath, CFErrorRef * error);
+
+LOCALFUNC blnr setupWorkingDirectory(void)
+{
+	NSString *myAppDir;
+	NSString *contentsPath;
+	NSString *dataPath;
+	NSBundle *myBundle = [NSBundle mainBundle];
+	NSString *myAppPath = [myBundle bundlePath];
+
+#if WantUnTranslocate
+	{
+		bool isTranslocated;
+		void *sec_handle = NULL;
+		SecTranslocateIsTranslocatedURL_t
+			mySecTranslocateIsTranslocatedURL = NULL;
+		CFURLRef url = NULL;
+		SecTranslocateCreateOriginalPathForURL_t
+			mySecTranslocateCreateOriginalPathForURL = NULL;
+		CFURLRef untranslocatedURL = NULL;
+		NSString *realAppPath = NULL;
+
+		if (NULL == (sec_handle = dlopen(
+			"/System/Library/Frameworks/Security.framework/Security",
+			RTLD_LAZY)))
+		{
+			/* fail */
+		} else
+		if (NULL == (mySecTranslocateIsTranslocatedURL =
+			dlsym(sec_handle, "SecTranslocateIsTranslocatedURL")))
+		{
+			/* fail */
+		} else
+		if (NULL == (url =
+			CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
+				(CFStringRef)myAppPath, kCFURLPOSIXPathStyle, NO)))
+		{
+			/* fail */
+		} else
+		if (! mySecTranslocateIsTranslocatedURL(url, &isTranslocated,
+			NULL))
+		{
+			/* fail */
+		} else
+		if (! isTranslocated) {
+			/* done */
+		} else
+		if (NULL == (mySecTranslocateCreateOriginalPathForURL =
+			dlsym(sec_handle,
+				"SecTranslocateCreateOriginalPathForURL")))
+		{
+			/* fail */
+		} else
+		if (NULL == (untranslocatedURL =
+			mySecTranslocateCreateOriginalPathForURL(url, NULL)))
+		{
+			/* fail */
+		} else
+		if (NULL == (realAppPath =
+			(NSString *)CFURLCopyFileSystemPath(
+				untranslocatedURL, kCFURLPOSIXPathStyle)))
+		{
+			/* fail */
+		} else
+		{
+			myAppPath = realAppPath;
+		}
+
+		if (NULL != realAppPath) {
+			[realAppPath autorelease];
+		}
+		if (NULL != untranslocatedURL) {
+			CFRelease(untranslocatedURL);
+		}
+		if (NULL != url) {
+			CFRelease(url);
+		}
+		if (NULL != sec_handle) {
+			if (0 != dlclose(sec_handle)) {
+				/* dbglog_writeln("dlclose  failed"); */
+			}
+		}
+	}
+#endif /* WantUnTranslocate */
+
+	myAppDir = [myAppPath stringByDeletingLastPathComponent];
+	myAppName = [[[myAppPath lastPathComponent]
+		stringByDeletingPathExtension] retain];
+
+	MyDataPath = myAppDir;
+	if (FindNamedChildDirPath(myAppPath, "Contents", &contentsPath))
+	if (FindNamedChildDirPath(contentsPath, "mnvm_dat", &dataPath))
+	{
+		MyDataPath = dataPath;
+	}
+	[MyDataPath retain];
+
+	return trueblnr;
+}
+
+@interface MyClassApplicationDelegate : NSObject <NSApplicationDelegate>
+@end
+
+@implementation MyClassApplicationDelegate
+
+- (BOOL)application:(NSApplication *)theApplication
+	openFile:(NSString *)filename
+{
+	(void) Sony_Insert1a(filename);
+
+	return TRUE;
+}
+
+- (void) applicationDidFinishLaunching: (NSNotification *) note
+{
+	[NSApp stop: nil]; /* stop immediately */
+
+	{
+		/*
+			doesn't actually stop until an event, so make one.
+			(As suggested by Michiel de Hoon in
+			http://www.cocoabuilder.com/ post.)
+		*/
+		NSEvent* event = [NSEvent
+			otherEventWithType: NSApplicationDefined
+			location: NSMakePoint(0, 0)
+			modifierFlags: 0
+			timestamp: 0.0
+			windowNumber: 0
+			context: nil
+			subtype: 0
+			data1: 0
+			data2: 0];
+		[NSApp postEvent: event atStart: true];
+	}
+}
+
+- (void)applicationDidChangeScreenParameters:
+	(NSNotification *)aNotification
+{
+	WantScreensChangedCheck = trueblnr;
+}
+
+- (IBAction)performSpecialMoreCommands:(id)sender
+{
+	DoMoreCommandsMsg();
+}
+
+- (IBAction)performFileOpen:(id)sender
+{
+	RequestInsertDisk = trueblnr;
+}
+
+- (IBAction)performApplicationAbout:(id)sender
+{
+	DoAboutMsg();
+}
+
+@end
+
+LOCALVAR MyClassApplicationDelegate *MyApplicationDelegate = nil;
+
+LOCALFUNC blnr InitCocoaStuff(void)
+{
+	NSApplication *MyNSApp = [NSApplication sharedApplication];
+		/*
+			in Xcode 6.2, MyNSApp isn't the same as NSApp,
+			breaks NSApp setDelegate
+		*/
+
+	MyMenuSetup();
+
+	MyApplicationDelegate = [[MyClassApplicationDelegate alloc] init];
+	[MyNSApp setDelegate: MyApplicationDelegate];
+
+#if 0
+	[MyNSApp finishLaunching];
+#endif
+		/*
+			If use finishLaunching, after
+			Hide Mini vMac command, activating from
+			Dock doesn't bring our window forward.
+			Using "run" instead fixes this.
+			As suggested by Hugues De Keyzer in
+			http://forums.libsdl.org/ post.
+			SDL 2.0 doesn't use this
+			technique. Was another solution found?
+		*/
+
+	[MyNSApp run];
+		/*
+			our applicationDidFinishLaunching forces
+			immediate halt.
+		*/
+
+	return trueblnr;
+}
+
+LOCALPROC UnInitCocoaStuff(void)
+{
+	if (nil != MyApplicationDelegate) {
+		[MyApplicationDelegate release];
+	}
+	if (nil != myAppName) {
+		[myAppName release];
+	}
+	if (nil != MyDataPath) {
+		[MyDataPath release];
+	}
+}
+
+/* --- platform independent code can be thought of as going here --- */
+
+#include "PROGMAIN.h"
+
+LOCALPROC ZapOSGLUVars(void)
+{
+	InitDrives();
+	ZapWinStateVars();
+#if MySoundEnabled
+	ZapAudioVars();
+#endif
+}
+
+LOCALPROC ReserveAllocAll(void)
+{
+#if dbglog_HAVE
+	dbglog_ReserveAlloc();
+#endif
+	ReserveAllocOneBlock(&ROM, kROM_Size, 5, falseblnr);
+
+	ReserveAllocOneBlock(&screencomparebuff,
+		vMacScreenNumBytes, 5, trueblnr);
+#if UseControlKeys
+	ReserveAllocOneBlock(&CntrlDisplayBuff,
+		vMacScreenNumBytes, 5, falseblnr);
+#endif
+
+	ReserveAllocOneBlock(&ScalingBuff, vMacScreenNumPixels
+#if 0 != vMacScreenDepth
+		* 4
+#endif
+		, 5, falseblnr);
+	ReserveAllocOneBlock(&CLUT_final, CLUT_finalsz, 5, falseblnr);
+
+#if MySoundEnabled
+	ReserveAllocOneBlock((ui3p *)&TheSoundBuffer,
+		dbhBufferSize, 5, falseblnr);
+#endif
+
+	EmulationReserveAlloc();
+}
+
+LOCALFUNC blnr AllocMyMemory(void)
+{
+#if 0 /* for testing start up error reporting */
+	MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr);
+	return falseblnr;
+#else
+	uimr n;
+	blnr IsOk = falseblnr;
+
+	ReserveAllocOffset = 0;
+	ReserveAllocBigBlock = nullpr;
+	ReserveAllocAll();
+	n = ReserveAllocOffset;
+	ReserveAllocBigBlock = (ui3p)calloc(1, n);
+	if (NULL == ReserveAllocBigBlock) {
+		MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr);
+	} else {
+		ReserveAllocOffset = 0;
+		ReserveAllocAll();
+		if (n != ReserveAllocOffset) {
+			/* oops, program error */
+		} else {
+			IsOk = trueblnr;
+		}
+	}
+
+	return IsOk;
+#endif
+}
+
+LOCALPROC UnallocMyMemory(void)
+{
+	if (nullpr != ReserveAllocBigBlock) {
+		free((char *) ReserveAllocBigBlock);
+	}
+}
+
+LOCALFUNC blnr InitOSGLU(void)
+{
+	blnr IsOk = falseblnr;
+	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+	if (AllocMyMemory())
+	if (setupWorkingDirectory())
+#if dbglog_HAVE
+	if (dbglog_open())
+#endif
+#if MySoundEnabled
+	if (MySound_Init())
+		/* takes a while to stabilize, do as soon as possible */
+#endif
+	if (LoadMacRom())
+	if (LoadInitialImages())
+	if (InitCocoaStuff())
+		/*
+			Can get openFile call backs here
+			for initial files.
+			So must load ROM, disk1.dsk, etc first.
+		*/
+#if UseActvCode
+	if (ActvCodeInit())
+#endif
+#if EmLocalTalk
+	if (InitLocalTalk())
+#endif
+	if (InitLocationDat())
+	if (Screen_Init())
+	if (CreateMainWindow())
+	if (WaitForRom())
+	{
+		IsOk = trueblnr;
+	}
+
+	[pool release];
+
+	return IsOk;
+}
+
+#if dbglog_HAVE && 0
+IMPORTPROC DumpRTC(void);
+#endif
+
+LOCALPROC UnInitOSGLU(void)
+{
+	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+#if dbglog_HAVE && 0
+	DumpRTC();
+#endif
+
+	if (MacMsgDisplayed) {
+		MacMsgDisplayOff();
+	}
+
+	RestoreKeyRepeat();
+#if MayFullScreen
+	UngrabMachine();
+#endif
+#if MySoundEnabled
+	MySound_Stop();
+#endif
+#if MySoundEnabled
+	MySound_UnInit();
+#endif
+#if IncludePbufs
+	UnInitPbufs();
+#endif
+	UnInitDrives();
+
+	ForceShowCursor();
+
+#if dbglog_HAVE
+	dbglog_close();
+#endif
+
+	CheckSavedMacMsg();
+
+	CloseMyOpenGLContext();
+	CloseMainWindow();
+
+#if MayFullScreen
+	My_ShowMenuBar();
+#endif
+
+	UnInitCocoaStuff();
+
+	UnallocMyMemory();
+
+	[pool release];
+}
+
+int main(int argc, char **argv)
+{
+	ZapOSGLUVars();
+
+	if (InitOSGLU()) {
+		ProgramMain();
+	}
+	UnInitOSGLU();
+
+	return 0;
+}
--- /dev/null
+++ b/src/OSGLUGTK.c
@@ -1,0 +1,1764 @@
+/*
+	OSGLUGTK.c
+
+	Copyright (C) 2009 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Operating System GLUe for GTK
+
+	All operating system dependent code for the
+	GIMP Toolkit should go here.
+*/
+
+#include "CNFGRAPI.h"
+#include "SYSDEPNS.h"
+#include "ENDIANAC.h"
+
+#include "MYOSGLUE.h"
+
+#include "STRCONST.h"
+
+#include "COMOSGLU.h"
+
+/* --- some simple utilities --- */
+
+GLOBALOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount)
+{
+	(void) memcpy((char *)destPtr, (char *)srcPtr, byteCount);
+}
+
+/* --- control mode and internationalization --- */
+
+#define NeedCell2PlainAsciiMap 1
+
+#include "INTLCHAR.h"
+
+#include "CONTROLM.h"
+
+/* --- sending debugging info to file --- */
+
+#if dbglog_HAVE
+
+#define dbglog_ToStdErr 0
+
+#if ! dbglog_ToStdErr
+LOCALVAR FILE *dbglog_File = NULL;
+#endif
+
+LOCALFUNC blnr dbglog_open0(void)
+{
+#if dbglog_ToStdErr
+	return trueblnr;
+#else
+	dbglog_File = fopen("dbglog.txt", "w");
+	return (NULL != dbglog_File);
+#endif
+}
+
+LOCALPROC dbglog_write0(char *s, uimr L)
+{
+#if dbglog_ToStdErr
+	(void) fwrite(s, 1, L, stderr);
+#else
+	if (dbglog_File != NULL) {
+		(void) fwrite(s, 1, L, dbglog_File);
+	}
+#endif
+}
+
+LOCALPROC dbglog_close0(void)
+{
+#if ! dbglog_ToStdErr
+	if (dbglog_File != NULL) {
+		fclose(dbglog_File);
+		dbglog_File = NULL;
+	}
+#endif
+}
+
+#endif
+
+/* --- debug settings and utilities --- */
+
+#define MyDbgEvents (dbglog_HAVE && 1)
+
+#if ! dbglog_HAVE
+#define WriteExtraErr(s)
+#else
+LOCALPROC WriteExtraErr(char *s)
+{
+	dbglog_writeCStr("*** error: ");
+	dbglog_writeCStr(s);
+	dbglog_writeReturn();
+}
+#endif
+
+/* --- text translation --- */
+
+LOCALPROC NativeStrFromCStr(char *r, char *s, blnr AddEllipsis)
+{
+	ui3b ps[ClStrMaxLength];
+	int i;
+	int L;
+
+	ClStrFromSubstCStr(&L, ps, s);
+
+	for (i = 0; i < L; ++i) {
+		r[i] = Cell2PlainAsciiMap[ps[i]];
+	}
+
+	if (AddEllipsis) {
+		r[L] = '.';
+		++L;
+		r[L] = '.';
+		++L;
+		r[L] = '.';
+		++L;
+	}
+
+	r[L] = 0;
+}
+
+/* --- drives --- */
+
+#define NotAfileRef NULL
+
+LOCALVAR FILE *Drives[NumDrives]; /* open disk image files */
+
+LOCALPROC InitDrives(void)
+{
+	/*
+		This isn't really needed, Drives[i] and DriveNames[i]
+		need not have valid values when not vSonyIsInserted[i].
+	*/
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		Drives[i] = NotAfileRef;
+	}
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer,
+	tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count,
+	ui5r *Sony_ActCount)
+{
+	ui5r NewSony_Count = Sony_Count;
+
+	fseek(Drives[Drive_No], Sony_Start, SEEK_SET);
+
+	if (IsWrite) {
+		fwrite(Buffer, 1, NewSony_Count, Drives[Drive_No]);
+	} else {
+		fread(Buffer, 1, NewSony_Count, Drives[Drive_No]);
+	}
+
+	if (nullpr != Sony_ActCount) {
+		*Sony_ActCount = NewSony_Count;
+	}
+
+	return mnvm_noErr; /*& figure out what really to return &*/
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count)
+{
+	fseek(Drives[Drive_No], 0, SEEK_END);
+	*Sony_Count = ftell(Drives[Drive_No]);
+	return mnvm_noErr; /*& figure out what really to return &*/
+}
+
+LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, blnr deleteit)
+{
+	DiskEjectedNotify(Drive_No);
+
+	fclose(Drives[Drive_No]);
+	Drives[Drive_No] = NotAfileRef; /* not really needed */
+
+
+	return mnvm_noErr;
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
+{
+	return vSonyEject0(Drive_No, falseblnr);
+}
+
+LOCALPROC UnInitDrives(void)
+{
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		if (vSonyIsInserted(i)) {
+			(void) vSonyEject(i);
+		}
+	}
+}
+
+LOCALFUNC blnr Sony_Insert0(FILE *refnum, blnr locked,
+	char *drivepath)
+{
+	tDrive Drive_No;
+
+	if (! FirstFreeDisk(&Drive_No)) {
+		fclose(refnum);
+		MacMsg(kStrTooManyImagesTitle,
+			kStrTooManyImagesMessage, falseblnr);
+		return falseblnr;
+	} else {
+		/* printf("Sony_Insert0 %d\n", (int)Drive_No); */
+		Drives[Drive_No] = refnum;
+		DiskInsertNotify(Drive_No, locked);
+
+		return trueblnr;
+	}
+}
+
+LOCALFUNC blnr Sony_Insert1(char *drivepath, blnr silentfail)
+{
+	blnr locked = falseblnr;
+	/* printf("Sony_Insert1 %s\n", drivepath); */
+	FILE *refnum = fopen(drivepath, "rb+");
+	if (NULL == refnum) {
+		locked = trueblnr;
+		refnum = fopen(drivepath, "rb");
+	}
+	if (NULL == refnum) {
+		if (! silentfail) {
+			MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
+		}
+	} else {
+		return Sony_Insert0(refnum, locked, drivepath);
+	}
+	return falseblnr;
+}
+
+LOCALFUNC tMacErr LoadMacRomFrom(char *path)
+{
+	tMacErr err;
+	FILE *ROM_File;
+	int File_Size;
+
+	ROM_File = fopen(path, "rb");
+	if (NULL == ROM_File) {
+		err = mnvm_fnfErr;
+	} else {
+		File_Size = fread(ROM, 1, kROM_Size, ROM_File);
+		if (kROM_Size != File_Size) {
+			if (feof(ROM_File)) {
+				MacMsgOverride(kStrShortROMTitle,
+					kStrShortROMMessage);
+				err = mnvm_eofErr;
+			} else {
+				MacMsgOverride(kStrNoReadROMTitle,
+					kStrNoReadROMMessage);
+				err = mnvm_miscErr;
+			}
+		} else {
+			err = ROM_IsValid();
+		}
+		fclose(ROM_File);
+	}
+
+	return err;
+}
+
+LOCALFUNC blnr Sony_Insert1a(char *drivepath, blnr silentfail)
+{
+	blnr v;
+
+	if (! ROM_loaded) {
+		v = (mnvm_noErr == LoadMacRomFrom(drivepath));
+	} else {
+		v = Sony_Insert1(drivepath, silentfail);
+	}
+
+	return v;
+}
+
+LOCALFUNC blnr Sony_InsertIth(int i)
+{
+	blnr v;
+
+	if ((i > 9) || ! FirstFreeDisk(nullpr)) {
+		v = falseblnr;
+	} else {
+		char s[] = "disk?.dsk";
+
+		s[4] = '0' + i;
+
+		v = Sony_Insert1(s, trueblnr);
+	}
+
+	return v;
+}
+
+LOCALFUNC blnr LoadInitialImages(void)
+{
+	int i;
+
+	for (i = 1; Sony_InsertIth(i); ++i) {
+		/* stop on first error (including file not found) */
+	}
+
+	return trueblnr;
+}
+
+/* --- ROM --- */
+
+LOCALVAR char *rom_path = NULL;
+
+LOCALFUNC blnr LoadMacRom(void)
+{
+	tMacErr err;
+
+	if ((NULL == rom_path)
+		|| (mnvm_fnfErr == (err = LoadMacRomFrom(rom_path))))
+	if (mnvm_fnfErr == (err = LoadMacRomFrom(RomFileName)))
+	{
+	}
+
+	return trueblnr;
+}
+
+/* --- video out --- */
+
+static GtkWidget *drawing_area;
+
+LOCALVAR blnr gBackgroundFlag = falseblnr;
+LOCALVAR blnr gTrueBackgroundFlag = falseblnr;
+LOCALVAR blnr CurSpeedStopped = trueblnr;
+
+LOCALPROC HaveChangedScreenBuff(si4b top, si4b left,
+	si4b bottom, si4b right)
+{
+	guchar graybuf[vMacScreenWidth * vMacScreenHeight];
+
+	{
+		int i;
+		int j;
+		int k;
+		ui3b *p1 = GetCurDrawBuff()
+			+ (ui5r)vMacScreenWidth / 8 * top;
+		ui3b *p2 = (ui3b *)graybuf + (ui5r)vMacScreenWidth * top;
+		ui5b t0;
+
+		UnusedParam(left);
+		UnusedParam(right);
+		for (i = bottom - top; --i >= 0; ) {
+			for (j = vMacScreenWidth / 8; --j >= 0; ) {
+				t0 = *p1++;
+				for (k = 8; --k >= 0; ) {
+					*p2++ = ((t0 >> k) & 0x01) - 1;
+				}
+			}
+		}
+	}
+
+	gdk_draw_gray_image(drawing_area->window,
+		drawing_area->style->fg_gc[GTK_WIDGET_STATE(drawing_area)],
+		left /* x */,
+		top /* y */,
+		right - left /* width */,
+		bottom - top /* height */,
+		GDK_RGB_DITHER_NONE,
+		graybuf + left + (ui5r)vMacScreenWidth * top,
+		vMacScreenWidth);
+}
+
+LOCALPROC MyDrawChangesAndClear(void)
+{
+	if (ScreenChangedBottom > ScreenChangedTop) {
+		HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft,
+			ScreenChangedBottom, ScreenChangedRight);
+		ScreenClearChanges();
+	}
+}
+
+GLOBALOSGLUPROC DoneWithDrawingForTick(void)
+{
+	MyDrawChangesAndClear();
+}
+
+/* --- mouse --- */
+
+LOCALVAR blnr HaveCursorHidden = falseblnr;
+LOCALVAR blnr WantCursorHidden = falseblnr;
+
+static GdkCursor *blank_cursor;
+static GtkWidget *window = NULL;
+
+LOCALPROC ForceShowCursor(void)
+{
+	if (HaveCursorHidden) {
+		HaveCursorHidden = falseblnr;
+
+		if (window) {
+			gdk_window_set_cursor(window->window, NULL);
+		}
+	}
+}
+
+/* cursor state */
+
+LOCALPROC MousePositionNotify(int NewMousePosh, int NewMousePosv)
+{
+	blnr ShouldHaveCursorHidden = trueblnr;
+
+	{
+		if (NewMousePosh < 0) {
+			NewMousePosh = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePosh >= vMacScreenWidth) {
+			NewMousePosh = vMacScreenWidth - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+		if (NewMousePosv < 0) {
+			NewMousePosv = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePosv >= vMacScreenHeight) {
+			NewMousePosv = vMacScreenHeight - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+
+
+		/* if (ShouldHaveCursorHidden || CurMouseButton) */
+		/*
+			for a game like arkanoid, would like mouse to still
+			move even when outside window in one direction
+		*/
+		MyMousePositionSet(NewMousePosh, NewMousePosv);
+	}
+
+	WantCursorHidden = ShouldHaveCursorHidden;
+}
+
+LOCALPROC CheckMouseState(void)
+{
+#if 0
+	gint x;
+	gint y;
+	gint x0;
+	gint y0;
+
+	gdk_display_get_pointer(gdk_drawable_get_display(window),
+		NULL, &x, &y, NULL);
+	(void) gdk_window_get_origin(window, &x0, &y0);
+	MousePositionNotify(x - x0, y - y0);
+#endif
+	gint x;
+	gint y;
+
+	gtk_widget_get_pointer(drawing_area, &x, &y);
+	/* (void) gdk_window_get_pointer(window, &x, &y, NULL); */
+	MousePositionNotify(x, y);
+}
+
+/* --- keyboard input --- */
+
+#define MaxNumKeycode 256
+#define KeyCodeMask (MaxNumKeycode - 1)
+	/*
+		assume keycodes >= 0 and < MaxNumKeycode, which
+		isn't promised by gtk documentation.
+	*/
+
+
+LOCALVAR ui3b KC2MKC[MaxNumKeycode];
+
+LOCALPROC KC2MKCAssignOne(guint keyval, ui3r key)
+{
+	GdkKeymapKey *keys;
+	gint n_keys;
+	int i;
+
+	if (gdk_keymap_get_entries_for_keyval(NULL,
+		keyval, &keys, &n_keys))
+	{
+		for (i = 0; i < n_keys; i++) {
+			KC2MKC[keys[i].keycode & KeyCodeMask] = key;
+		}
+		g_free(keys);
+	}
+#if 0
+	fprintf(stderr, "%d %d %d\n", (int)ks, key, (int)code);
+#endif
+}
+
+LOCALFUNC blnr KC2MKCInit(void)
+{
+	int i;
+
+	for (i = 0; i < 256; ++i) {
+		KC2MKC[i] = MKC_None;
+	}
+
+#ifdef GDK_KP_Insert
+	KC2MKCAssignOne(GDK_KP_Insert, MKC_KP0);
+#endif
+#ifdef GDK_KP_End
+	KC2MKCAssignOne(GDK_KP_End, MKC_KP1);
+#endif
+#ifdef GDK_KP_Down
+	KC2MKCAssignOne(GDK_KP_Down, MKC_KP2);
+#endif
+#ifdef GDK_KP_Next
+	KC2MKCAssignOne(GDK_KP_Next, MKC_KP3);
+#endif
+#ifdef GDK_KP_Left
+	KC2MKCAssignOne(GDK_KP_Left, MKC_KP4);
+#endif
+#ifdef GDK_KP_Begin
+	KC2MKCAssignOne(GDK_KP_Begin, MKC_KP5);
+#endif
+#ifdef GDK_KP_Right
+	KC2MKCAssignOne(GDK_KP_Right, MKC_KP6);
+#endif
+#ifdef GDK_KP_Home
+	KC2MKCAssignOne(GDK_KP_Home, MKC_KP7);
+#endif
+#ifdef GDK_KP_Up
+	KC2MKCAssignOne(GDK_KP_Up, MKC_KP8);
+#endif
+#ifdef GDK_KP_Prior
+	KC2MKCAssignOne(GDK_KP_Prior, MKC_KP9);
+#endif
+#ifdef GDK_KP_Delete
+	KC2MKCAssignOne(GDK_KP_Delete, MKC_Decimal);
+#endif
+
+	KC2MKCAssignOne(GDK_asciitilde, MKC_formac_Grave);
+	KC2MKCAssignOne(GDK_underscore, MKC_Minus);
+	KC2MKCAssignOne(GDK_plus, MKC_Equal);
+	KC2MKCAssignOne(GDK_braceleft, MKC_LeftBracket);
+	KC2MKCAssignOne(GDK_braceright, MKC_RightBracket);
+	KC2MKCAssignOne(GDK_bar, MKC_formac_BackSlash);
+	KC2MKCAssignOne(GDK_colon, MKC_SemiColon);
+	KC2MKCAssignOne(GDK_quotedbl, MKC_SingleQuote);
+	KC2MKCAssignOne(GDK_less, MKC_Comma);
+	KC2MKCAssignOne(GDK_greater, MKC_Period);
+	KC2MKCAssignOne(GDK_question, MKC_formac_Slash);
+
+	KC2MKCAssignOne(GDK_a, MKC_A);
+	KC2MKCAssignOne(GDK_b, MKC_B);
+	KC2MKCAssignOne(GDK_c, MKC_C);
+	KC2MKCAssignOne(GDK_d, MKC_D);
+	KC2MKCAssignOne(GDK_e, MKC_E);
+	KC2MKCAssignOne(GDK_f, MKC_F);
+	KC2MKCAssignOne(GDK_g, MKC_G);
+	KC2MKCAssignOne(GDK_h, MKC_H);
+	KC2MKCAssignOne(GDK_i, MKC_I);
+	KC2MKCAssignOne(GDK_j, MKC_J);
+	KC2MKCAssignOne(GDK_k, MKC_K);
+	KC2MKCAssignOne(GDK_l, MKC_L);
+	KC2MKCAssignOne(GDK_m, MKC_M);
+	KC2MKCAssignOne(GDK_n, MKC_N);
+	KC2MKCAssignOne(GDK_o, MKC_O);
+	KC2MKCAssignOne(GDK_p, MKC_P);
+	KC2MKCAssignOne(GDK_q, MKC_Q);
+	KC2MKCAssignOne(GDK_r, MKC_R);
+	KC2MKCAssignOne(GDK_s, MKC_S);
+	KC2MKCAssignOne(GDK_t, MKC_T);
+	KC2MKCAssignOne(GDK_u, MKC_U);
+	KC2MKCAssignOne(GDK_v, MKC_V);
+	KC2MKCAssignOne(GDK_w, MKC_W);
+	KC2MKCAssignOne(GDK_x, MKC_X);
+	KC2MKCAssignOne(GDK_y, MKC_Y);
+	KC2MKCAssignOne(GDK_z, MKC_Z);
+
+	/*
+		main mappings
+	*/
+
+	KC2MKCAssignOne(GDK_F1, MKC_formac_F1);
+	KC2MKCAssignOne(GDK_F2, MKC_formac_F2);
+	KC2MKCAssignOne(GDK_F3, MKC_formac_F3);
+	KC2MKCAssignOne(GDK_F4, MKC_formac_F4);
+	KC2MKCAssignOne(GDK_F5, MKC_formac_F5);
+	KC2MKCAssignOne(GDK_F6, MKC_F6);
+	KC2MKCAssignOne(GDK_F7, MKC_F7);
+	KC2MKCAssignOne(GDK_F8, MKC_F8);
+	KC2MKCAssignOne(GDK_F9, MKC_F9);
+	KC2MKCAssignOne(GDK_F10, MKC_F10);
+	KC2MKCAssignOne(GDK_F11, MKC_F11);
+	KC2MKCAssignOne(GDK_F12, MKC_F12);
+
+#ifdef GDK_Delete
+	KC2MKCAssignOne(GDK_Delete, MKC_formac_ForwardDel);
+#endif
+#ifdef GDK_Insert
+	KC2MKCAssignOne(GDK_Insert, MKC_formac_Help);
+#endif
+#ifdef GDK_Help
+	KC2MKCAssignOne(GDK_Help, MKC_formac_Help);
+#endif
+#ifdef GDK_Home
+	KC2MKCAssignOne(GDK_Home, MKC_formac_Home);
+#endif
+#ifdef GDK_End
+	KC2MKCAssignOne(GDK_End, MKC_formac_End);
+#endif
+
+#ifdef GDK_Page_Up
+	KC2MKCAssignOne(GDK_Page_Up, MKC_formac_PageUp);
+#else
+#ifdef GDK_Prior
+	KC2MKCAssignOne(GDK_Prior, MKC_formac_PageUp);
+#endif
+#endif
+
+#ifdef GDK_Page_Down
+	KC2MKCAssignOne(GDK_Page_Down, MKC_formac_PageDown);
+#else
+#ifdef GDK_Next
+	KC2MKCAssignOne(GDK_Next, MKC_formac_PageDown);
+#endif
+#endif
+
+#ifdef GDK_Print
+	KC2MKCAssignOne(GDK_Print, MKC_Print);
+#endif
+#ifdef GDK_Scroll_Lock
+	KC2MKCAssignOne(GDK_Scroll_Lock, MKC_ScrollLock);
+#endif
+#ifdef GDK_Pause
+	KC2MKCAssignOne(GDK_Pause, MKC_Pause);
+#endif
+
+	KC2MKCAssignOne(GDK_KP_Add, MKC_KPAdd);
+	KC2MKCAssignOne(GDK_KP_Subtract, MKC_KPSubtract);
+	KC2MKCAssignOne(GDK_KP_Multiply, MKC_KPMultiply);
+	KC2MKCAssignOne(GDK_KP_Divide, MKC_KPDevide);
+	KC2MKCAssignOne(GDK_KP_Enter, MKC_formac_Enter);
+	KC2MKCAssignOne(GDK_KP_Equal, MKC_KPEqual);
+
+	KC2MKCAssignOne(GDK_KP_0, MKC_KP0);
+	KC2MKCAssignOne(GDK_KP_1, MKC_KP1);
+	KC2MKCAssignOne(GDK_KP_2, MKC_KP2);
+	KC2MKCAssignOne(GDK_KP_3, MKC_KP3);
+	KC2MKCAssignOne(GDK_KP_4, MKC_KP4);
+	KC2MKCAssignOne(GDK_KP_5, MKC_KP5);
+	KC2MKCAssignOne(GDK_KP_6, MKC_KP6);
+	KC2MKCAssignOne(GDK_KP_7, MKC_KP7);
+	KC2MKCAssignOne(GDK_KP_8, MKC_KP8);
+	KC2MKCAssignOne(GDK_KP_9, MKC_KP9);
+	KC2MKCAssignOne(GDK_KP_Decimal, MKC_Decimal);
+
+	KC2MKCAssignOne(GDK_Left, MKC_Left);
+	KC2MKCAssignOne(GDK_Right, MKC_Right);
+	KC2MKCAssignOne(GDK_Up, MKC_Up);
+	KC2MKCAssignOne(GDK_Down, MKC_Down);
+
+	KC2MKCAssignOne(GDK_grave, MKC_formac_Grave);
+	KC2MKCAssignOne(GDK_minus, MKC_Minus);
+	KC2MKCAssignOne(GDK_equal, MKC_Equal);
+	KC2MKCAssignOne(GDK_bracketleft, MKC_LeftBracket);
+	KC2MKCAssignOne(GDK_bracketright, MKC_RightBracket);
+	KC2MKCAssignOne(GDK_backslash, MKC_formac_BackSlash);
+	KC2MKCAssignOne(GDK_semicolon, MKC_SemiColon);
+	KC2MKCAssignOne(GDK_apostrophe, MKC_SingleQuote);
+	KC2MKCAssignOne(GDK_comma, MKC_Comma);
+	KC2MKCAssignOne(GDK_period, MKC_Period);
+	KC2MKCAssignOne(GDK_slash, MKC_formac_Slash);
+
+	KC2MKCAssignOne(GDK_Escape, MKC_formac_Escape);
+
+	KC2MKCAssignOne(GDK_Tab, MKC_Tab);
+	KC2MKCAssignOne(GDK_Return, MKC_Return);
+	KC2MKCAssignOne(GDK_space, MKC_Space);
+	KC2MKCAssignOne(GDK_BackSpace, MKC_BackSpace);
+
+	KC2MKCAssignOne(GDK_Caps_Lock, MKC_formac_CapsLock);
+	KC2MKCAssignOne(GDK_Num_Lock, MKC_Clear);
+
+	KC2MKCAssignOne(GDK_Meta_L, MKC_formac_Command);
+
+	KC2MKCAssignOne(GDK_Meta_R, MKC_formac_RCommand);
+
+	KC2MKCAssignOne(GDK_Mode_switch, MKC_formac_Option);
+	KC2MKCAssignOne(GDK_Menu, MKC_formac_Option);
+	KC2MKCAssignOne(GDK_Super_L, MKC_formac_Option);
+	KC2MKCAssignOne(GDK_Super_R, MKC_formac_ROption);
+	KC2MKCAssignOne(GDK_Hyper_L, MKC_formac_Option);
+	KC2MKCAssignOne(GDK_Hyper_R, MKC_formac_ROption);
+
+	KC2MKCAssignOne(GDK_F13, MKC_formac_Option);
+		/*
+			seen being used in Mandrake Linux 9.2
+			for windows key
+		*/
+
+	KC2MKCAssignOne(GDK_Shift_L, MKC_formac_Shift);
+	KC2MKCAssignOne(GDK_Shift_R, MKC_formac_RShift);
+
+	KC2MKCAssignOne(GDK_Alt_L, MKC_formac_Command);
+
+	KC2MKCAssignOne(GDK_Alt_R, MKC_formac_RCommand);
+
+	KC2MKCAssignOne(GDK_Control_L, MKC_formac_Control);
+
+	KC2MKCAssignOne(GDK_Control_R, MKC_formac_RControl);
+
+	KC2MKCAssignOne(GDK_1, MKC_1);
+	KC2MKCAssignOne(GDK_2, MKC_2);
+	KC2MKCAssignOne(GDK_3, MKC_3);
+	KC2MKCAssignOne(GDK_4, MKC_4);
+	KC2MKCAssignOne(GDK_5, MKC_5);
+	KC2MKCAssignOne(GDK_6, MKC_6);
+	KC2MKCAssignOne(GDK_7, MKC_7);
+	KC2MKCAssignOne(GDK_8, MKC_8);
+	KC2MKCAssignOne(GDK_9, MKC_9);
+	KC2MKCAssignOne(GDK_0, MKC_0);
+
+	KC2MKCAssignOne(GDK_A, MKC_A);
+	KC2MKCAssignOne(GDK_B, MKC_B);
+	KC2MKCAssignOne(GDK_C, MKC_C);
+	KC2MKCAssignOne(GDK_D, MKC_D);
+	KC2MKCAssignOne(GDK_E, MKC_E);
+	KC2MKCAssignOne(GDK_F, MKC_F);
+	KC2MKCAssignOne(GDK_G, MKC_G);
+	KC2MKCAssignOne(GDK_H, MKC_H);
+	KC2MKCAssignOne(GDK_I, MKC_I);
+	KC2MKCAssignOne(GDK_J, MKC_J);
+	KC2MKCAssignOne(GDK_K, MKC_K);
+	KC2MKCAssignOne(GDK_L, MKC_L);
+	KC2MKCAssignOne(GDK_M, MKC_M);
+	KC2MKCAssignOne(GDK_N, MKC_N);
+	KC2MKCAssignOne(GDK_O, MKC_O);
+	KC2MKCAssignOne(GDK_P, MKC_P);
+	KC2MKCAssignOne(GDK_Q, MKC_Q);
+	KC2MKCAssignOne(GDK_R, MKC_R);
+	KC2MKCAssignOne(GDK_S, MKC_S);
+	KC2MKCAssignOne(GDK_T, MKC_T);
+	KC2MKCAssignOne(GDK_U, MKC_U);
+	KC2MKCAssignOne(GDK_V, MKC_V);
+	KC2MKCAssignOne(GDK_W, MKC_W);
+	KC2MKCAssignOne(GDK_X, MKC_X);
+	KC2MKCAssignOne(GDK_Y, MKC_Y);
+	KC2MKCAssignOne(GDK_Z, MKC_Z);
+
+	InitKeyCodes();
+
+	return trueblnr;
+}
+
+LOCALPROC CheckTheCapsLock(void)
+{
+	GdkModifierType mask;
+
+	(void) gdk_window_get_pointer(window->window, NULL, NULL, &mask);
+
+	Keyboard_UpdateKeyMap2(MKC_formac_CapsLock,
+		(mask & GDK_LOCK_MASK) != 0);
+}
+
+LOCALPROC DoKeyCode(guint keycode, blnr down)
+{
+	if (GDK_Caps_Lock == keycode) {
+		CheckTheCapsLock();
+	} else {
+		ui3r key = KC2MKC[keycode & KeyCodeMask];
+
+		if (MKC_None != key) {
+			Keyboard_UpdateKeyMap2(key, down);
+		}
+	}
+}
+
+/* --- time, date, location --- */
+
+LOCALVAR ui5b TrueEmulatedTime = 0;
+
+#include "DATE2SEC.h"
+
+#define TicksPerSecond 1000000
+
+LOCALVAR blnr HaveTimeDelta = falseblnr;
+LOCALVAR ui5b TimeDelta;
+
+LOCALVAR ui5b NewMacDateInSeconds;
+
+LOCALVAR ui5b LastTimeSec;
+LOCALVAR ui5b LastTimeUsec;
+
+LOCALPROC GetCurrentTicks(void)
+{
+	GTimeVal t;
+
+	g_get_current_time(&t);
+	if (! HaveTimeDelta) {
+		time_t Current_Time;
+		struct tm *s;
+
+#if 0
+		GDate *date;
+		date = g_date_new();
+		g_date_set_time_val(date, &t);
+		g_date_free(date);
+#endif
+		(void) time(&Current_Time);
+		s = localtime(&Current_Time);
+		TimeDelta = Date2MacSeconds(s->tm_sec, s->tm_min, s->tm_hour,
+			s->tm_mday, 1 + s->tm_mon, 1900 + s->tm_year) - t.tv_sec;
+#if 0 && AutoTimeZone /* how portable is this ? */
+		CurMacDelta = ((ui5b)(s->tm_gmtoff) & 0x00FFFFFF)
+			| ((s->tm_isdst ? 0x80 : 0) << 24);
+#endif
+		HaveTimeDelta = trueblnr;
+	}
+
+	NewMacDateInSeconds = t.tv_sec + TimeDelta;
+	LastTimeSec = (ui5b)t.tv_sec;
+	LastTimeUsec = (ui5b)t.tv_usec;
+}
+
+#define MyInvTimeStep 16626 /* TicksPerSecond / 60.14742 */
+
+LOCALVAR ui5b NextTimeSec;
+LOCALVAR ui5b NextTimeUsec;
+
+LOCALPROC IncrNextTime(void)
+{
+	NextTimeUsec += MyInvTimeStep;
+	if (NextTimeUsec >= TicksPerSecond) {
+		NextTimeUsec -= TicksPerSecond;
+		NextTimeSec += 1;
+	}
+}
+
+LOCALPROC InitNextTime(void)
+{
+	NextTimeSec = LastTimeSec;
+	NextTimeUsec = LastTimeUsec;
+	IncrNextTime();
+}
+
+LOCALPROC StartUpTimeAdjust(void)
+{
+	GetCurrentTicks();
+	InitNextTime();
+}
+
+LOCALFUNC si5b GetTimeDiff(void)
+{
+	return ((si5b)(LastTimeSec - NextTimeSec)) * TicksPerSecond
+		+ ((si5b)(LastTimeUsec - NextTimeUsec));
+}
+
+LOCALPROC UpdateTrueEmulatedTime(void)
+{
+	si5b TimeDiff;
+
+	GetCurrentTicks();
+
+	TimeDiff = GetTimeDiff();
+	if (TimeDiff >= 0) {
+		if (TimeDiff > 4 * MyInvTimeStep) {
+			/* emulation interrupted, forget it */
+			++TrueEmulatedTime;
+			InitNextTime();
+		} else {
+			do {
+				++TrueEmulatedTime;
+				IncrNextTime();
+				TimeDiff -= TicksPerSecond;
+			} while (TimeDiff >= 0);
+		}
+	} else if (TimeDiff < - 2 * MyInvTimeStep) {
+		/* clock goofed if ever get here, reset */
+		InitNextTime();
+	}
+}
+
+LOCALFUNC blnr CheckDateTime(void)
+{
+	if (CurMacDateInSeconds != NewMacDateInSeconds) {
+		CurMacDateInSeconds = NewMacDateInSeconds;
+		return trueblnr;
+	} else {
+		return falseblnr;
+	}
+}
+
+LOCALFUNC blnr InitLocationDat(void)
+{
+	GetCurrentTicks();
+	CurMacDateInSeconds = NewMacDateInSeconds;
+
+	return trueblnr;
+}
+
+/* --- basic dialogs --- */
+
+LOCALPROC CheckSavedMacMsg(void)
+{
+	if (nullpr != SavedBriefMsg) {
+		char briefMsg0[ClStrMaxLength + 1];
+		char longMsg0[ClStrMaxLength + 1];
+
+		NativeStrFromCStr(briefMsg0, SavedBriefMsg, falseblnr);
+		NativeStrFromCStr(longMsg0, SavedLongMsg, falseblnr);
+
+		fprintf(stderr, "%s\n", briefMsg0);
+		fprintf(stderr, "%s\n", longMsg0);
+
+		SavedBriefMsg = nullpr;
+	}
+}
+
+LOCALVAR blnr CaughtMouse = falseblnr;
+
+/* --- main window creation and disposal --- */
+
+LOCALVAR int my_argc;
+LOCALVAR char **my_argv;
+
+/* Create a new backing pixmap of the appropriate size */
+static gboolean configure_event(GtkWidget *widget,
+	GdkEventConfigure *event)
+{
+	return TRUE;
+}
+
+/* Redraw the screen from the backing pixmap */
+static gboolean expose_event(GtkWidget *widget,
+	GdkEventExpose *event,
+	gpointer user_data)
+{
+	int x0 = event->area.x;
+	int y0 = event->area.y;
+	int x1 = x0 + event->area.width;
+	int y1 = y0 + event->area.height;
+
+#if 0 && MyDbgEvents
+	fprintf(stderr, "- event - Expose\n");
+#endif
+
+	if (x0 < 0) {
+		x0 = 0;
+	}
+	if (x1 > vMacScreenWidth) {
+		x1 = vMacScreenWidth;
+	}
+	if (y0 < 0) {
+		y0 = 0;
+	}
+	if (y1 > vMacScreenHeight) {
+		y1 = vMacScreenHeight;
+	}
+	if ((x0 < x1) && (y0 < y1)) {
+		HaveChangedScreenBuff(y0, x0, y1, x1);
+	}
+
+	return FALSE;
+}
+
+static gboolean button_press_event(GtkWidget *widget,
+	GdkEventButton *event,
+	gpointer user_data)
+{
+	MousePositionNotify(event->x, event->y);
+	MyMouseButtonSet(trueblnr);
+
+	return TRUE;
+}
+
+static gboolean button_release_event(GtkWidget *widget,
+	GdkEventButton *event,
+	gpointer user_data)
+{
+	MousePositionNotify(event->x, event->y);
+	MyMouseButtonSet(falseblnr);
+
+	return TRUE;
+}
+
+static gboolean motion_notify_event(GtkWidget *widget,
+	GdkEventMotion *event,
+	gpointer user_data)
+{
+	int x;
+	int y;
+	GdkModifierType state;
+
+	if (event->is_hint) {
+		gdk_window_get_pointer(event->window, &x, &y, &state);
+	} else {
+		x = event->x;
+		y = event->y;
+		state = event->state;
+	}
+
+	MousePositionNotify(x, y);
+	MyMouseButtonSet((state & GDK_BUTTON1_MASK) != 0);
+
+	return TRUE;
+}
+
+static gboolean enter_notify_event(GtkWidget *widget,
+	GdkEventCrossing *event,
+	gpointer user_data)
+{
+	CaughtMouse = trueblnr;
+
+	MousePositionNotify(event->x, event->y);
+	MyMouseButtonSet((event->state & GDK_BUTTON1_MASK) != 0);
+
+	return TRUE;
+}
+
+static gboolean leave_notify_event(GtkWidget *widget,
+	GdkEventCrossing *event,
+	gpointer user_data)
+{
+	MousePositionNotify(event->x, event->y);
+	MyMouseButtonSet((event->state & GDK_BUTTON1_MASK) != 0);
+
+	CaughtMouse = falseblnr;
+
+	return TRUE;
+}
+
+static gboolean delete_event(GtkWidget *widget,
+	GdkEventMotion *event)
+{
+	RequestMacOff = trueblnr;
+
+	return TRUE;
+}
+
+LOCALPROC ReconnectKeyCodes3(void)
+{
+	CheckTheCapsLock();
+
+#if 0
+	if (WantCmdOptOnReconnect) {
+		WantCmdOptOnReconnect = falseblnr;
+
+		GetTheDownKeys();
+	}
+#endif
+}
+
+LOCALPROC DisconnectKeyCodes3(void)
+{
+	DisconnectKeyCodes2();
+	MyMouseButtonSet(falseblnr);
+}
+
+LOCALVAR blnr ADialogIsUp = falseblnr;
+
+LOCALPROC MyBeginDialog(void)
+{
+	DisconnectKeyCodes3();
+	ADialogIsUp = trueblnr;
+	ForceShowCursor();
+}
+
+LOCALPROC MyEndDialog(void)
+{
+	ADialogIsUp = falseblnr;
+	ReconnectKeyCodes3();
+}
+
+/* --- SavedTasks --- */
+
+LOCALPROC LeaveBackground(void)
+{
+	ReconnectKeyCodes3();
+#if 0
+	DisableKeyRepeat();
+#endif
+}
+
+LOCALPROC EnterBackground(void)
+{
+#if 0
+	RestoreKeyRepeat();
+#endif
+	DisconnectKeyCodes3();
+
+	ForceShowCursor();
+}
+
+LOCALPROC LeaveSpeedStopped(void)
+{
+	StartUpTimeAdjust();
+}
+
+LOCALPROC EnterSpeedStopped(void)
+{
+}
+
+static void InsertADisk0(void)
+{
+	char ts[ClStrMaxLength + 1];
+	GtkWidget *dialog;
+
+	NativeStrFromCStr(ts, kStrMenuItemOpen, falseblnr);
+
+	MyBeginDialog();
+	dialog = gtk_file_chooser_dialog_new(ts,
+		GTK_WINDOW(window),
+		GTK_FILE_CHOOSER_ACTION_OPEN,
+		GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+		GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+		NULL);
+	MyEndDialog();
+
+	if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
+		char *filename;
+
+		filename =
+			gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+		(void) Sony_Insert1a(filename, falseblnr);
+		g_free(filename);
+	}
+
+	gtk_widget_destroy(dialog);
+}
+
+LOCALPROC CheckForSavedTasks(void)
+{
+	if (MyEvtQNeedRecover) {
+		MyEvtQNeedRecover = falseblnr;
+
+		/* attempt cleanup, MyEvtQNeedRecover may get set again */
+		MyEvtQTryRecoverFromFull();
+	}
+
+	if (RequestMacOff) {
+		RequestMacOff = falseblnr;
+		if (AnyDiskInserted()) {
+			MacMsgOverride(kStrQuitWarningTitle,
+				kStrQuitWarningMessage);
+		} else {
+			ForceMacOff = trueblnr;
+		}
+	}
+
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (gTrueBackgroundFlag != gBackgroundFlag) {
+		gBackgroundFlag = gTrueBackgroundFlag;
+		if (gTrueBackgroundFlag) {
+			EnterBackground();
+		} else {
+			LeaveBackground();
+		}
+	}
+
+	if (CurSpeedStopped != (SpeedStopped ||
+		(gBackgroundFlag && ! RunInBackground
+#if EnableAutoSlow && 0
+			&& (QuietSubTicks >= 4092)
+#endif
+		)))
+	{
+		CurSpeedStopped = ! CurSpeedStopped;
+		if (CurSpeedStopped) {
+			EnterSpeedStopped();
+		} else {
+			LeaveSpeedStopped();
+		}
+	}
+
+
+	if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
+		MacMsgDisplayOn();
+	}
+
+	if (NeedWholeScreenDraw) {
+		NeedWholeScreenDraw = falseblnr;
+		ScreenChangedAll();
+	}
+
+	if (HaveCursorHidden != (WantCursorHidden && CaughtMouse
+		&& ! (gTrueBackgroundFlag || ADialogIsUp || CurSpeedStopped)))
+	{
+		HaveCursorHidden = ! HaveCursorHidden;
+		if (HaveCursorHidden) {
+			gdk_window_set_cursor(window->window, blank_cursor);
+		} else {
+			gdk_window_set_cursor(window->window, NULL);
+		}
+	}
+
+	if (gTrueBackgroundFlag || ADialogIsUp) {
+	} else {
+		if (RequestInsertDisk) {
+			RequestInsertDisk = falseblnr;
+			InsertADisk0();
+		}
+	}
+
+#if NeedRequestIthDisk
+	if (0 != RequestIthDisk) {
+		Sony_InsertIth(RequestIthDisk);
+		RequestIthDisk = 0;
+	}
+#endif
+}
+
+/* --- command line parsing --- */
+
+LOCALFUNC blnr ScanCommandLine(void)
+{
+	int i;
+
+	for (i = 1; i < my_argc; ++i) {
+		if ('-' == my_argv[i][0]) {
+#if 0
+			if ((0 == strcmp(my_argv[i], "--display")) ||
+				(0 == strcmp(my_argv[i], "-display")))
+			{
+				++i;
+				if (i < my_argc) {
+					display_name = my_argv[i];
+				}
+			} else
+#endif
+			if ((0 == strcmp(my_argv[i], "--rom")) ||
+				(0 == strcmp(my_argv[i], "-r")))
+			{
+				++i;
+				if (i < my_argc) {
+					rom_path = my_argv[i];
+				}
+			} else
+#if 0
+			if (0 == strcmp(my_argv[i], "-l")) {
+				SpeedValue = 0;
+			} else
+#endif
+			{
+				MacMsg(kStrBadArgTitle, kStrBadArgMessage, falseblnr);
+			}
+		} else {
+			(void) Sony_Insert1(my_argv[i], falseblnr);
+		}
+	}
+	return trueblnr;
+}
+
+/* --- main program flow --- */
+
+GLOBALOSGLUFUNC blnr ExtraTimeNotOver(void)
+{
+	UpdateTrueEmulatedTime();
+	return TrueEmulatedTime == OnTrueTime;
+}
+
+LOCALPROC WaitForTheNextEvent(void)
+{
+	(void) gtk_main_iteration_do(TRUE);
+}
+
+LOCALPROC CheckForSystemEvents(void)
+{
+	int i = 10;
+
+	while (gtk_events_pending() && (--i >= 0)) {
+		(void) gtk_main_iteration_do(FALSE);
+	}
+#if 0
+	XFlush(x_display);
+#endif
+}
+
+GLOBALOSGLUPROC WaitForNextTick(void)
+{
+label_retry:
+	CheckForSystemEvents();
+	CheckForSavedTasks();
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (CurSpeedStopped) {
+		DoneWithDrawingForTick();
+		WaitForTheNextEvent();
+		goto label_retry;
+	}
+
+	if (ExtraTimeNotOver()) {
+		si5b TimeDiff = GetTimeDiff();
+		if (TimeDiff < 0) {
+			g_usleep(- TimeDiff);
+		}
+		goto label_retry;
+	}
+
+	if (CheckDateTime()) {
+#if EnableDemoMsg
+		DemoModeSecondNotify();
+#endif
+	}
+
+	if ((! gBackgroundFlag || ADialogIsUp)
+		&& (! CaughtMouse)
+		)
+	{
+		CheckMouseState();
+	}
+
+	OnTrueTime = TrueEmulatedTime;
+}
+
+#include "PROGMAIN.h"
+
+static gboolean
+MainEventLoop0(gpointer data)
+{
+	(void) data;
+	fprintf(stderr, "hello from MainEventLoop0\n");
+	ProgramMain();
+	if (ForceMacOff) {
+		goto Label_01;
+	}
+#if 0
+	while (! gtk_main_iteration_do(FALSE)) {
+		if (! gtk_events_pending()) {
+			fprintf(stderr, "sleep\n");
+			g_usleep(1000000);
+		}
+	}
+#endif
+Label_01:
+	fprintf(stderr, "leaving MainEventLoop0\n");
+
+	gtk_main_quit();
+
+	return FALSE;
+}
+
+static gboolean
+focus_in_event(GtkWidget *widget, GdkEvent *event,
+	gpointer data)
+{
+	gTrueBackgroundFlag = falseblnr;
+
+	CheckMouseState();
+
+	return FALSE;
+}
+
+static gboolean
+focus_out_event(GtkWidget *widget, GdkEvent *event,
+	gpointer data)
+{
+	gTrueBackgroundFlag = trueblnr;
+	return FALSE;
+}
+
+static gboolean key_press_event(GtkWidget *widget,
+	GdkEventKey *event,
+	gpointer user_data)
+{
+#if 0
+	fprintf(stderr, "hello from key_press_event\n");
+	fprintf(stderr, "keyval %d\n", event->keyval);
+	fprintf(stderr, "hardware_keycode %d\n", event->hardware_keycode);
+#endif
+#if 0
+	{
+		GdkKeymapKey *keys;
+		gint n_keys;
+		int i;
+
+		if (gdk_keymap_get_entries_for_keyval(NULL,
+			event->keyval, &keys, &n_keys))
+		{
+			for (i = 0; i < n_keys; i++) {
+				fprintf(stderr, "keycode %d\n", keys[i].keycode);
+			}
+			g_free(keys);
+		}
+	}
+#endif
+	DoKeyCode(event->hardware_keycode, trueblnr);
+
+	return TRUE;
+}
+
+static gboolean key_release_event(GtkWidget *widget,
+	GdkEventKey *event,
+	gpointer user_data)
+{
+#if 0
+	fprintf(stderr, "hello from key_release_event\n");
+	fprintf(stderr, "keyval %d\n", event->keyval);
+	fprintf(stderr, "hardware_keycode %d\n", event->hardware_keycode);
+#endif
+	DoKeyCode(event->hardware_keycode, falseblnr);
+
+	return TRUE;
+}
+
+static void drag_data_received(GtkWidget *widget,
+	GdkDragContext *drag_context,
+	gint x,
+	gint y,
+	GtkSelectionData *data,
+	guint info,
+	guint time,
+	gpointer user_data)
+{
+	char **uris;
+	char *file;
+	int i;
+	gboolean handled = FALSE;
+
+	uris = g_strsplit((char *)data->data, "\r\n", -1);
+	if (uris != NULL) {
+		for (i = 0; uris[i] != NULL; i++) {
+			file = g_filename_from_uri(uris[i], NULL, NULL);
+			/* file = gnome_vfs_get_local_path_from_uri(uris[i]); */
+			if (file != NULL) {
+				(void) Sony_Insert1a(file, falseblnr);
+				handled = TRUE;
+				g_free(file);
+			}
+		}
+		g_strfreev(uris);
+	}
+	gtk_drag_finish(drag_context, handled, FALSE, time);
+	if (handled) {
+		gtk_window_present_with_time(GTK_WINDOW(window), time);
+	}
+}
+
+static void do_more_commands_item(GtkAction *action, gpointer user_data)
+{
+	DoMoreCommandsMsg();
+}
+
+static void do_about_item(GtkAction *action, gpointer user_data)
+{
+	DoAboutMsg();
+}
+
+static void do_quit_item(GtkAction *action, gpointer user_data)
+{
+	RequestMacOff = trueblnr;
+}
+
+static void do_open_item(GtkAction *action, gpointer user_data)
+{
+	RequestInsertDisk = trueblnr;
+}
+
+LOCALPROC MyAppendConvertMenuItem(GtkWidget *the_menu,
+	GCallback c_handler, gpointer gobject, char *s, blnr AddEllipsis)
+{
+	char ts[ClStrMaxLength + 1];
+	GtkWidget *the_item;
+
+	NativeStrFromCStr(ts, s, AddEllipsis);
+	the_item = gtk_menu_item_new_with_label(ts);
+	g_signal_connect(G_OBJECT(the_item), "activate",
+		c_handler, gobject);
+	gtk_menu_shell_append(GTK_MENU_SHELL(the_menu), the_item);
+}
+
+LOCALPROC MyAppendSubmenuConvertName(GtkWidget *menubar,
+	GtkWidget *the_menu, char *s)
+{
+	char ts[ClStrMaxLength + 1];
+	GtkWidget *the_item;
+
+	NativeStrFromCStr(ts, s, falseblnr);
+	the_item = gtk_menu_item_new_with_label(ts);
+	gtk_menu_item_set_submenu(GTK_MENU_ITEM(the_item), the_menu);
+	gtk_menu_shell_append(GTK_MENU_SHELL(menubar), the_item);
+}
+
+static GdkPixmap *blank_pixmap;
+static GdkColor blank_color = {
+	0, 0, 0, 0
+};
+
+static gchar blank_cursor_bits[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static GtkTargetEntry dnd_target =
+{
+	"text/uri-list", 0, 0
+};
+
+LOCALPROC ZapOSGLUVars(void)
+{
+	InitDrives();
+#if 0
+	{
+		int i;
+
+		for (i = 0; i < kNumMagStates; ++i) {
+			HavePositionWins[i] = falseblnr;
+		}
+	}
+#endif
+}
+
+LOCALPROC ReserveAllocAll(void)
+{
+#if dbglog_HAVE
+	dbglog_ReserveAlloc();
+#endif
+	ReserveAllocOneBlock(&ROM, kROM_Size, 5, falseblnr);
+	ReserveAllocOneBlock(&screencomparebuff,
+		vMacScreenNumBytes, 5, trueblnr);
+#if UseControlKeys
+	ReserveAllocOneBlock(&CntrlDisplayBuff,
+		vMacScreenNumBytes, 5, falseblnr);
+#endif
+
+	EmulationReserveAlloc();
+}
+
+LOCALFUNC blnr AllocMyMemory(void)
+{
+	uimr n;
+	blnr IsOk = falseblnr;
+
+	ReserveAllocOffset = 0;
+	ReserveAllocBigBlock = nullpr;
+	ReserveAllocAll();
+	n = ReserveAllocOffset;
+	ReserveAllocBigBlock = (ui3p)calloc(1, n);
+	if (NULL == ReserveAllocBigBlock) {
+		MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr);
+	} else {
+		ReserveAllocOffset = 0;
+		ReserveAllocAll();
+		if (n != ReserveAllocOffset) {
+			/* oops, program error */
+		} else {
+			IsOk = trueblnr;
+		}
+	}
+
+	return IsOk;
+}
+
+LOCALPROC UnallocMyMemory(void)
+{
+	if (nullpr != ReserveAllocBigBlock) {
+		free((char *)ReserveAllocBigBlock);
+	}
+}
+
+LOCALFUNC blnr InitOSGLU(void)
+{
+	if (AllocMyMemory())
+#if dbglog_HAVE
+	if (dbglog_open())
+#endif
+	if (ScanCommandLine())
+	if (LoadMacRom())
+	if (LoadInitialImages())
+	if (InitLocationDat())
+	/* if (ReCreateMainWindow()) */
+	if (KC2MKCInit())
+	if (WaitForRom())
+	{
+		return trueblnr;
+	}
+	return falseblnr;
+}
+
+LOCALPROC UnInitOSGLU(void)
+{
+	if (MacMsgDisplayed) {
+		MacMsgDisplayOff();
+	}
+
+	UnInitDrives();
+
+	ForceShowCursor();
+
+#if dbglog_HAVE
+	dbglog_close();
+#endif
+
+	UnallocMyMemory();
+
+	CheckSavedMacMsg();
+}
+
+int main(int argc, char *argv[])
+{
+	GtkWidget *vbox;
+
+#if 0
+	GtkWidget *button;
+#endif
+
+	GtkWidget *menubar;
+	GtkWidget *the_menu;
+	GtkWidget *the_item;
+
+	gtk_init(&argc, &argv);
+
+	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+	gtk_widget_set_name(window, "Test Input");
+	gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
+
+	vbox = gtk_vbox_new(FALSE, 0);
+	gtk_container_add(GTK_CONTAINER(window), vbox);
+	gtk_widget_show(vbox);
+
+	g_signal_connect(G_OBJECT(window), "delete-event",
+		G_CALLBACK(delete_event), NULL);
+	g_signal_connect(G_OBJECT(window), "focus-out-event",
+		(GCallback)focus_out_event,
+		NULL);
+	g_signal_connect(G_OBJECT(window), "focus-in-event",
+		(GCallback)focus_in_event, NULL);
+
+	g_signal_connect(G_OBJECT(window), "key-press-event",
+		G_CALLBACK(key_press_event), NULL);
+	g_signal_connect(G_OBJECT(window), "key-release-event",
+		G_CALLBACK(key_release_event), NULL);
+
+	menubar = gtk_menu_bar_new();
+
+	the_menu = gtk_menu_new();
+
+	MyAppendConvertMenuItem(the_menu,
+		G_CALLBACK(do_open_item), NULL, kStrMenuItemOpen, trueblnr);
+
+	the_item = gtk_separator_menu_item_new();
+	gtk_menu_shell_append(GTK_MENU_SHELL(the_menu), the_item);
+
+	MyAppendConvertMenuItem(the_menu,
+		G_CALLBACK(do_quit_item), NULL, kStrMenuItemQuit, falseblnr);
+
+	MyAppendSubmenuConvertName(menubar, the_menu, kStrMenuFile);
+
+	the_menu = gtk_menu_new();
+
+	MyAppendConvertMenuItem(the_menu, G_CALLBACK(do_more_commands_item),
+		NULL, kStrMenuItemMore, trueblnr);
+
+	MyAppendSubmenuConvertName(menubar, the_menu, kStrMenuSpecial);
+
+	the_menu = gtk_menu_new();
+
+	MyAppendConvertMenuItem(the_menu,
+		G_CALLBACK(do_about_item), NULL, kStrMenuItemAbout, trueblnr);
+
+	MyAppendSubmenuConvertName(menubar, the_menu, kStrMenuHelp);
+
+	gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
+
+	gtk_widget_show_all(menubar);
+
+
+	/* Create the drawing area */
+
+	drawing_area = gtk_drawing_area_new();
+	gtk_widget_set_size_request(GTK_WIDGET(drawing_area),
+		vMacScreenWidth, vMacScreenHeight);
+	gtk_box_pack_start(GTK_BOX(vbox), drawing_area, TRUE, TRUE, 0);
+
+	gtk_widget_show(drawing_area);
+
+	/* Signals used to handle backing pixmap */
+
+	g_signal_connect(G_OBJECT(drawing_area), "expose-event",
+		G_CALLBACK(expose_event), NULL);
+	g_signal_connect(G_OBJECT(drawing_area), "configure-event",
+		G_CALLBACK(configure_event), NULL);
+
+	/* Event signals */
+
+	g_signal_connect(G_OBJECT(drawing_area), "motion-notify-event",
+		G_CALLBACK(motion_notify_event), NULL);
+	g_signal_connect(G_OBJECT(drawing_area), "enter-notify-event",
+		G_CALLBACK(enter_notify_event), NULL);
+	g_signal_connect(G_OBJECT(drawing_area), "leave-notify-event",
+		G_CALLBACK(leave_notify_event), NULL);
+
+	g_signal_connect(G_OBJECT(drawing_area), "button-press-event",
+		G_CALLBACK(button_press_event), NULL);
+	g_signal_connect(G_OBJECT(drawing_area), "button-release-event",
+		G_CALLBACK(button_release_event), NULL);
+
+	gtk_widget_add_events(window,
+		GDK_KEY_PRESS_MASK
+		| GDK_KEY_RELEASE_MASK
+		);
+
+	gtk_widget_set_events(drawing_area, GDK_EXPOSURE_MASK
+		| GDK_LEAVE_NOTIFY_MASK
+		| GDK_BUTTON_PRESS_MASK
+		| GDK_BUTTON_RELEASE_MASK
+		| GDK_POINTER_MOTION_MASK
+		| GDK_ENTER_NOTIFY_MASK
+		| GDK_LEAVE_NOTIFY_MASK
+		| GDK_FOCUS_CHANGE_MASK
+		| GDK_KEY_PRESS_MASK
+		| GDK_KEY_RELEASE_MASK
+		/* | GDK_POINTER_MOTION_HINT_MASK */
+		);
+
+#if 0
+	/* .. And a quit button */
+	button = gtk_button_new_with_label("Quit");
+	gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
+
+	g_signal_connect_swapped(G_OBJECT(button), "clicked",
+		G_CALLBACK(delete_event), NULL
+		/*
+			G_CALLBACK(gtk_widget_destroy),
+			G_OBJECT(window)
+		*/
+		);
+	gtk_widget_show(button);
+#endif
+
+	gtk_drag_dest_set(drawing_area, GTK_DEST_DEFAULT_ALL,
+		&dnd_target, 1,
+		GDK_ACTION_COPY);
+	g_signal_connect(GTK_OBJECT(drawing_area), "drag-data-received",
+		G_CALLBACK(drag_data_received), NULL);
+
+	gtk_widget_show(window);
+
+	blank_pixmap = gdk_bitmap_create_from_data(NULL,
+		blank_cursor_bits, 16, 16);
+	blank_cursor = gdk_cursor_new_from_pixmap(blank_pixmap,
+		blank_pixmap, &blank_color, &blank_color, 8, 8);
+	gdk_pixmap_unref(blank_pixmap);
+
+	gdk_window_set_cursor(window->window, blank_cursor);
+
+	g_idle_add(MainEventLoop0, NULL);
+
+	my_argc = argc;
+	my_argv = argv;
+
+	ZapOSGLUVars();
+	if (InitOSGLU()) {
+		gtk_main ();
+	}
+	UnInitOSGLU();
+
+	return 0;
+}
--- /dev/null
+++ b/src/OSGLUMAC.c
@@ -1,0 +1,5775 @@
+/*
+	OSGLUMAC.c
+
+	Copyright (C) 2009 Philip Cummins, Richard F. Bannister,
+		Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Operating System GLUe for MACintosh
+
+	All operating system dependent code for the
+	Macintosh (pre OS X) platform should go here.
+
+	This is also the "reference" implementation. General
+	comments about what the platform dependent code
+	does should go here, and not be repeated for each
+	platform.
+
+	This code is descended from Richard F. Bannister's Macintosh
+	port of vMac, by Philip Cummins.
+
+	The main entry point 'main' is at the end of this file.
+*/
+
+#include "CNFGRAPI.h"
+#include "SYSDEPNS.h"
+#include "ENDIANAC.h"
+
+#include "MYOSGLUE.h"
+
+#include "STRCONST.h"
+
+#ifndef NavigationAvail
+#define NavigationAvail 1
+#endif
+
+#ifndef AppearanceAvail
+#define AppearanceAvail 1
+#endif
+
+#ifndef NewNamesAvail
+#define NewNamesAvail 1
+#endif
+
+#ifndef CALL_NOT_IN_CARBON
+#define CALL_NOT_IN_CARBON 1
+#endif /* !defined(CALL_NOT_IN_CARBON) */
+
+
+/* --- information about the environment --- */
+
+/*
+	code to determine characteristics
+	of the current run time environment.
+*/
+
+#define TestBit(i, p) (((uimr)(i) & ((uimr)1 << (p))) != 0)
+
+#ifndef HaveCPUfamM68K
+#define HaveCPUfamM68K 0
+#endif
+
+#if HaveCPUfamM68K
+
+/* MACENVRN.i */
+
+#ifndef Support64kROM
+#define Support64kROM 1
+#endif
+
+#define Have64kROM() (LMGetROM85() < 0)
+
+/* -- basic environment checking -- */
+
+#ifndef DebugTrapAvailableChecks
+#define DebugTrapAvailableChecks 0
+#endif
+
+LOCALFUNC blnr LowToolTrapAvailable(short trap_num)
+{
+#if DebugTrapAvailableChecks
+	if ((trap_num & 0x0800) == 0) {
+		DebugStr("\pOSTrap in LowToolTrapAvailable");
+		return falseblnr;
+	}
+	if ((trap_num & 0x07ff) >= 0x200) {
+		DebugStr("\pHiToolTrap in LowToolTrapAvailable");
+		return falseblnr;
+	}
+#endif
+	return GetToolTrapAddress(trap_num) !=
+		GetToolTrapAddress(_Unimplemented);
+}
+
+LOCALFUNC blnr HiToolTrapAvailable(short trap_num)
+{
+#if DebugTrapAvailableChecks
+	if ((trap_num & 0x0800) == 0) {
+		DebugStr("\pOSTrap in HiToolTrapAvailable");
+		return falseblnr;
+	}
+	if (((trap_num & 0x07ff) < 0x200)
+		|| ((trap_num & 0x07ff) >= 0x400))
+	{
+		DebugStr("\pLowToolTrap in HiToolTrapAvailable");
+		return falseblnr;
+	}
+#endif
+	if (GetToolTrapAddress(_InitGraf)
+		== GetToolTrapAddress(0xAA6E))
+	{
+		return falseblnr;
+	} else {
+		return GetToolTrapAddress(trap_num) !=
+			GetToolTrapAddress(_Unimplemented);
+	}
+}
+
+LOCALFUNC blnr OSTrapAvailable(short trap_num)
+{
+#if DebugTrapAvailableChecks
+	if ((trap_num & 0x0800) != 0) {
+		DebugStr("\pToolTrap in ToolTrapAvailable");
+		return falseblnr;
+	}
+#endif
+	return GetOSTrapAddress(trap_num) !=
+		GetToolTrapAddress(_Unimplemented);
+}
+
+LOCALVAR blnr MyEnvrAttrWaitNextEventAvail;
+LOCALVAR blnr HaveEnvrAttrWaitNextEventAvail = falseblnr;
+
+LOCALFUNC blnr HaveWaitNextEventAvail(void)
+{
+	if (! HaveEnvrAttrWaitNextEventAvail) {
+		MyEnvrAttrWaitNextEventAvail =
+			LowToolTrapAvailable(_WaitNextEvent);
+		HaveEnvrAttrWaitNextEventAvail = trueblnr;
+	}
+	return MyEnvrAttrWaitNextEventAvail;
+}
+
+LOCALVAR blnr MyEnvrAttrGestaltAvail;
+LOCALVAR blnr HaveEnvrAttrGestaltAvail = falseblnr;
+
+LOCALFUNC blnr HaveGestaltAvail(void)
+{
+	if (! HaveEnvrAttrGestaltAvail) {
+		MyEnvrAttrGestaltAvail =
+			(! Have64kROM()) &&
+			OSTrapAvailable(_Gestalt);
+			/*
+				contrary to all the documentation,
+				TrapAvailable check by itself doesn't
+				work on 64k ROM, because a tool box trap
+				has the same trap number, and both
+				GetOSTrapAddress and GetToolTrapAddress
+				are the same as GetTrapAddress on a 64k ROM.
+			*/
+		HaveEnvrAttrGestaltAvail = trueblnr;
+	}
+	return MyEnvrAttrGestaltAvail;
+}
+
+#else
+
+/* for PowerPC, assume always have these routines */
+
+#define HaveWaitNextEventAvail() trueblnr
+#define HaveGestaltAvail() trueblnr
+
+#endif
+
+LOCALVAR blnr MyEnvrAttrAliasMgrAvail;
+LOCALVAR blnr HaveEnvrAttrAliasMgrAvail = falseblnr;
+
+LOCALFUNC blnr HaveAliasMgrAvail(void)
+{
+	if (! HaveEnvrAttrAliasMgrAvail) {
+		long reply;
+
+		MyEnvrAttrAliasMgrAvail =
+			HaveGestaltAvail()
+			&& (noErr == Gestalt(gestaltAliasMgrAttr, &reply))
+			&& TestBit(reply, gestaltAliasMgrPresent);
+		HaveEnvrAttrAliasMgrAvail = trueblnr;
+	}
+	return MyEnvrAttrAliasMgrAvail;
+}
+
+LOCALVAR blnr MyEnvrAttrAppleEvtMgrAvail;
+LOCALVAR blnr HaveEnvrAttrAppleEvtMgrAvail = falseblnr;
+
+LOCALFUNC blnr HaveAppleEvtMgrAvail(void)
+{
+	if (! HaveEnvrAttrAppleEvtMgrAvail) {
+		long reply;
+
+		MyEnvrAttrAppleEvtMgrAvail =
+			HaveGestaltAvail()
+			&& (noErr == Gestalt(gestaltAppleEventsAttr, &reply))
+			&& TestBit(reply, gestaltAppleEventsPresent);
+		HaveEnvrAttrAppleEvtMgrAvail = trueblnr;
+	}
+	return MyEnvrAttrAppleEvtMgrAvail;
+}
+
+#if EnableDragDrop
+
+LOCALVAR blnr MyEnvrAttrDragMgrAvail;
+LOCALVAR blnr HaveEnvrAttrDragMgrAvail = falseblnr;
+
+LOCALFUNC blnr HaveDragMgrAvail(void)
+{
+	if (! HaveEnvrAttrDragMgrAvail) {
+		long reply;
+
+		MyEnvrAttrDragMgrAvail =
+			HaveGestaltAvail()
+			&& (noErr == Gestalt(gestaltDragMgrAttr, &reply))
+			&& TestBit(reply, gestaltDragMgrPresent);
+		HaveEnvrAttrDragMgrAvail = trueblnr;
+	}
+	return MyEnvrAttrDragMgrAvail;
+}
+
+#endif
+
+#ifndef Windows85APIAvail
+#define Windows85APIAvail 1
+#endif
+
+#if Windows85APIAvail
+LOCALVAR blnr MyEnvrAttrHideShowMenuAvail;
+LOCALVAR blnr HaveEnvrAttrHideShowMenuAvail = falseblnr;
+
+LOCALFUNC blnr HaveHideShowMenuAvail(void)
+{
+	if (! HaveEnvrAttrHideShowMenuAvail) {
+		long reply;
+
+		MyEnvrAttrHideShowMenuAvail =
+			HaveGestaltAvail()
+			&& (noErr == Gestalt(gestaltMenuMgrAttr, &reply));
+		HaveEnvrAttrHideShowMenuAvail = trueblnr;
+	}
+	return MyEnvrAttrHideShowMenuAvail;
+}
+#endif
+
+#if AppearanceAvail
+LOCALVAR blnr MyEnvrAttrAppearanceAvail;
+LOCALVAR blnr HaveEnvrAttrAppearanceAvail = falseblnr;
+
+LOCALFUNC blnr HaveAppearanceAvail(void)
+{
+	if (! HaveEnvrAttrAppearanceAvail) {
+		long reply;
+
+		MyEnvrAttrAppearanceAvail =
+			HaveGestaltAvail()
+			&& (noErr == Gestalt(gestaltAppearanceAttr, &reply));
+		HaveEnvrAttrAppearanceAvail = trueblnr;
+	}
+	return MyEnvrAttrAppearanceAvail;
+}
+#endif
+
+#if HaveCPUfamM68K
+LOCALVAR blnr MyEnvrAttrSndMngrAvail;
+LOCALVAR blnr HaveEnvrAttrSndMngrAvail = falseblnr;
+
+LOCALFUNC blnr HaveSndMngrAvail(void)
+{
+	if (! HaveEnvrAttrSndMngrAvail) {
+		MyEnvrAttrSndMngrAvail = LowToolTrapAvailable(_SndNewChannel);
+		HaveEnvrAttrSndMngrAvail = trueblnr;
+	}
+	return MyEnvrAttrSndMngrAvail;
+}
+#endif
+
+#if NavigationAvail
+LOCALVAR blnr MyEnvrAttrNavServicesAvail;
+LOCALVAR blnr HaveEnvrAttrNavServicesAvail = falseblnr;
+
+LOCALFUNC blnr HaveNavServicesAvail(void)
+{
+	if (! HaveEnvrAttrNavServicesAvail) {
+		MyEnvrAttrNavServicesAvail = NavServicesAvailable();
+		HaveEnvrAttrNavServicesAvail = trueblnr;
+	}
+	return MyEnvrAttrNavServicesAvail;
+}
+#endif
+
+#if HaveCPUfamM68K
+LOCALVAR blnr MyEnvrAttrFSSpecCallsAvail;
+LOCALVAR blnr HaveEnvrAttrFSSpecCallsAvail = falseblnr;
+
+LOCALFUNC blnr HaveFSSpecCallsAvail(void)
+{
+	if (! HaveEnvrAttrFSSpecCallsAvail) {
+		long reply;
+
+		MyEnvrAttrFSSpecCallsAvail =
+			HaveGestaltAvail()
+			&& (noErr == Gestalt(gestaltFSAttr, &reply))
+			&& TestBit(reply, gestaltHasFSSpecCalls);
+		HaveEnvrAttrFSSpecCallsAvail = trueblnr;
+	}
+	return MyEnvrAttrFSSpecCallsAvail;
+}
+#endif
+
+#if Windows85APIAvail
+LOCALVAR blnr MyEnvrAttrNewWndMgrAvail;
+LOCALVAR blnr HaveEnvrAttrNewWndMgrAvail = falseblnr;
+
+LOCALFUNC blnr HaveNewWndMgrAvail(void)
+{
+	if (! HaveEnvrAttrNewWndMgrAvail) {
+		long reply;
+
+		MyEnvrAttrNewWndMgrAvail =
+			HaveGestaltAvail()
+			&& (noErr == Gestalt(gestaltWindowMgrAttr, &reply))
+			&& TestBit(reply, gestaltWindowMgrPresentBit);
+		HaveEnvrAttrNewWndMgrAvail = trueblnr;
+	}
+	return MyEnvrAttrNewWndMgrAvail;
+}
+#endif
+
+/* --- initial initialization --- */
+
+#if defined(__SC__) || ((defined(powerc) || defined(__powerc)) \
+	&& ! defined(__MWERKS__))
+
+/* GLOBALVAR */ QDGlobals qd;
+#endif
+
+LOCALFUNC blnr InitMacManagers(void)
+{
+	MaxApplZone();
+
+	{
+		int i;
+
+		for (i = 7; --i >= 0; ) {
+			MoreMasters();
+		}
+	}
+
+	InitGraf(&qd.thePort);
+	InitFonts();
+	InitWindows();
+	InitMenus();
+	TEInit();
+	InitDialogs(NULL);
+	InitCursor();
+	return trueblnr;
+}
+
+
+/* --- mac style errors --- */
+
+#define CheckSavetMacErr(result) (mnvm_noErr == (err = (result)))
+	/*
+		where 'err' is a variable of type tMacErr in the function
+		this is used in
+	*/
+
+#define To_tMacErr(result) ((tMacErr)(ui4b)(result))
+
+#define CheckSaveMacErr(result) (CheckSavetMacErr(To_tMacErr(result)))
+
+
+/*
+	define NotAfileRef to some value that is different
+	from any valid open file reference.
+*/
+#define NotAfileRef (-1)
+
+struct MyDir_R {
+	long DirId;
+	short VRefNum;
+};
+typedef struct MyDir_R MyDir_R;
+
+LOCALFUNC tMacErr OpenNamedFileInFolder(MyDir_R *d,
+	ps3p fileName, short *refnum)
+{
+	tMacErr err;
+
+#if HaveCPUfamM68K
+	if (! HaveFSSpecCallsAvail()) {
+		err = To_tMacErr(FSOpen(fileName, d->VRefNum, refnum));
+	} else
+#endif
+	{
+		Boolean isFolder;
+		Boolean isAlias;
+		FSSpec spec;
+
+		if (CheckSaveMacErr(
+			FSMakeFSSpec(d->VRefNum, d->DirId, fileName, &spec)))
+		if (CheckSaveMacErr(
+			ResolveAliasFile(&spec, trueblnr, &isFolder, &isAlias)))
+		if (CheckSaveMacErr(
+			FSpOpenDF(&spec, fsRdPerm, refnum)))
+		{
+		}
+	}
+
+	return err;
+}
+
+/* --- sending debugging info to file --- */
+
+#if dbglog_HAVE
+
+#define Support64kROM 0
+#define tMyErr tMacErr
+
+typedef unsigned char * MyPtr;
+
+LOCALFUNC tMyErr MyHGetDir_v2(MyDir_R *d)
+{
+	tMyErr err;
+	WDPBRec r;
+
+	r.ioCompletion = NULL;
+	r.ioNamePtr = NULL;
+
+#if Support64kROM
+	if (Have64kROM()) {
+		err = PBGetVolSync((ParamBlockRec *)&r);
+		d->VRefNum = r.ioVRefNum;
+		d->DirId = 0;
+	} else
+#endif
+	{
+		err = PBHGetVolSync(&r);
+		d->VRefNum = r.ioWDVRefNum;
+		d->DirId = r.ioWDDirID;
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr MyWriteBytes_v2(short refNum, MyPtr p, uimr L)
+{
+	ParamBlockRec r;
+
+	r.ioParam.ioCompletion = NULL;
+	r.ioParam.ioRefNum = refNum;
+	r.ioParam.ioBuffer = (Ptr)p;
+	r.ioParam.ioReqCount = L;
+	r.ioParam.ioPosMode = (short) fsFromMark;
+	r.ioParam.ioPosOffset = 0;
+
+	return PBWriteSync(&r);
+}
+
+LOCALFUNC tMyErr MyCloseFile_v2(short refNum)
+{
+	ParamBlockRec r;
+
+	r.ioParam.ioCompletion = NULL;
+	r.ioParam.ioRefNum = refNum;
+
+	return PBCloseSync(&r);
+#if 0
+	return (tMyErr)FSClose(refNum);
+#endif
+}
+
+#define NotAfileRef (-1)
+
+/*
+	Probably should use PBHOpenDF instead
+	of PBHOpen when it is available.
+	(System 7 according to Technical Note FL515)
+*/
+
+LOCALFUNC tMyErr MyFileOpen_v2(MyDir_R *d, StringPtr s,
+	char Permssn, short *refnum)
+{
+	tMyErr err;
+	HParamBlockRec r;
+
+	r.ioParam.ioCompletion = NULL;
+	r.ioParam.ioNamePtr = s;
+	r.ioParam.ioVRefNum = d->VRefNum;
+	r.ioParam.ioPermssn = Permssn;
+	r.ioParam.ioMisc = 0; /* use volume buffer */
+	r.ioParam.ioVersNum = 0; /* needed if MFS volume */
+
+#if Support64kROM
+	if (Have64kROM()) {
+		err = PBOpenSync((ParamBlockRec *)&r);
+	} else
+#endif
+	{
+		r.fileParam.ioDirID = d->DirId;
+		err = PBHOpenSync(&r);
+	}
+
+	if (noErr == err) {
+		*refnum = r.ioParam.ioRefNum;
+		/*
+			Don't change *refnum unless file opened,
+			so can initialize to NotAfileRef, and
+			compare later before closing in uninit.
+		*/
+	}
+	return err;
+}
+
+LOCALFUNC tMyErr MyFileOpenWrite_v2(MyDir_R *d, StringPtr s,
+	short *refnum)
+{
+	return MyFileOpen_v2(d, s, (char)fsWrPerm, refnum);
+}
+
+LOCALFUNC tMyErr MyDeleteFile_v2(MyDir_R *d, StringPtr s)
+{
+	tMyErr err;
+	HParamBlockRec r;
+
+	r.fileParam.ioCompletion = NULL;
+	r.fileParam.ioVRefNum = d->VRefNum;
+	r.fileParam.ioNamePtr = s;
+	r.fileParam.ioFVersNum = 0; /* needed if MFS volume */
+
+#if Support64kROM
+	if (Have64kROM()) {
+		err = PBDeleteSync((ParamBlockRec *)&r);
+	} else
+#endif
+	{
+		r.fileParam.ioDirID = d->DirId;
+		err = PBHDeleteSync(&r);
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr MyCreateFile_v2(MyDir_R *d, StringPtr s)
+{
+	tMyErr err;
+	HParamBlockRec r;
+
+	r.fileParam.ioFlVersNum = 0;
+		/*
+			Think reference says to do this,
+			but not Inside Mac IV
+		*/
+
+	r.fileParam.ioCompletion = NULL;
+	r.fileParam.ioNamePtr = s;
+	r.fileParam.ioVRefNum = d->VRefNum;
+	r.fileParam.ioFVersNum = 0; /* needed if MFS volume */
+
+#if Support64kROM
+	if (Have64kROM()) {
+		err = PBCreateSync((ParamBlockRec *)&r);
+	} else
+#endif
+	{
+		r.fileParam.ioDirID = d->DirId;
+		err = PBHCreateSync(&r);
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr MyFileGetInfo_v2(MyDir_R *d, StringPtr s,
+	HParamBlockRec *r)
+{
+	tMyErr err;
+
+	r->fileParam.ioCompletion = NULL;
+	r->fileParam.ioNamePtr = s;
+	r->fileParam.ioVRefNum = d->VRefNum;
+	r->fileParam.ioFVersNum = (char)0; /* needed if MFS volume */
+	r->fileParam.ioFDirIndex = (short)0;
+
+#if Support64kROM
+	if (Have64kROM()) {
+		err = PBGetFInfoSync((ParamBlockRec *)r);
+	} else
+#endif
+	{
+		r->fileParam.ioDirID = d->DirId;
+		err = PBHGetFInfoSync(r);
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr MyFileSetInfo_v2(MyDir_R *d, StringPtr s,
+	HParamBlockRec *r)
+{
+	tMyErr err;
+
+	r->fileParam.ioCompletion = NULL;
+	r->fileParam.ioNamePtr = s;
+	r->fileParam.ioVRefNum = d->VRefNum;
+	r->fileParam.ioFVersNum = (char)0; /* needed if MFS volume */
+
+#if Support64kROM
+	if (Have64kROM()) {
+		err = PBSetFInfoSync((ParamBlockRec *)r);
+	} else
+#endif
+	{
+		r->fileParam.ioDirID = d->DirId;
+		err = PBHSetFInfoSync(r);
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr MyFileSetTypeCreator_v2(MyDir_R *d, StringPtr s,
+	OSType creator, OSType fileType)
+{
+	tMyErr err;
+	HParamBlockRec r;
+
+	if (noErr == (err = MyFileGetInfo_v2(d, s, &r))) {
+		r.fileParam.ioFlFndrInfo.fdType = fileType;
+		r.fileParam.ioFlFndrInfo.fdCreator = creator;
+		err = MyFileSetInfo_v2(d, s, &r);
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr MyCreateFileOverWrite_v2(MyDir_R *d, StringPtr s)
+{
+	tMyErr err;
+
+	err = MyCreateFile_v2(d, s);
+	if (dupFNErr == err) {
+		if (noErr == (err = MyDeleteFile_v2(d, s))) {
+			err = MyCreateFile_v2(d, s);
+		}
+	}
+
+	return err;
+}
+
+LOCALFUNC tMyErr MyOpenNewFile_v3(MyDir_R *d, StringPtr s,
+	OSType creator, OSType fileType,
+	short *refnum)
+/*
+	Deletes old file if already exists.
+*/
+{
+	tMyErr err;
+
+	err = MyCreateFileOverWrite_v2(d, s);
+	if (noErr == err) {
+		err = MyFileSetTypeCreator_v2(d, s,
+			creator, fileType);
+		if (noErr == err) {
+			err = MyFileOpenWrite_v2(d, s, refnum);
+		}
+
+		if (noErr != err) {
+			(void) MyDeleteFile_v2(d, s);
+				/* ignore any error, since already got one */
+		}
+	}
+
+	return err;
+}
+
+
+LOCALVAR short dbglog_File = NotAfileRef;
+LOCALVAR tMyErr dbglog_err = noErr;
+
+LOCALFUNC blnr dbglog_open0(void)
+{
+	tMacErr err;
+	MyDir_R d;
+
+	if (noErr == (err = MyHGetDir_v2(&d))) {
+		err = MyFileOpen_v2(&d, (StringPtr)"\pdbglog",
+				(char)fsWrPerm, &dbglog_File);
+		if (mnvm_noErr /* fnfErr */ == err) {
+			err = SetEOF(dbglog_File, 0);
+		} else {
+			err = MyOpenNewFile_v3(&d, (StringPtr)"\pdbglog",
+				'MPS ', 'TEXT', &dbglog_File);
+			err = mnvm_noErr;
+		}
+
+	}
+
+	return (mnvm_noErr == err);
+}
+
+LOCALPROC dbglog_write0(char *s, uimr L)
+{
+	if (NotAfileRef != dbglog_File)
+	if (noErr == dbglog_err)
+	{
+		dbglog_err = MyWriteBytes_v2(dbglog_File, (MyPtr)s, L);
+	}
+}
+
+LOCALPROC dbglog_close0(void)
+{
+	if (NotAfileRef != dbglog_File) {
+		(void)  MyCloseFile_v2(dbglog_File);
+		dbglog_File = NotAfileRef;
+	}
+}
+
+#endif /* dbglog_HAVE */
+
+
+/* --- control mode and internationalization --- */
+
+#define NeedCell2MacAsciiMap 1
+
+#define WantColorTransValid 1
+
+#include "INTLCHAR.h"
+
+#include "COMOSGLU.h"
+
+#define WantKeyboard_RemapMac 1
+
+#include "CONTROLM.h"
+
+/* --- some simple utilities --- */
+
+GLOBALOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount)
+{
+	BlockMove((Ptr)srcPtr, (Ptr)destPtr, byteCount);
+}
+
+/* don't want to include c libraries, so: */
+LOCALFUNC si5b CStrLen(char *src)
+{
+	char *p = src;
+	while (*p++ != 0) {
+	}
+	return ((si5b)p) - ((si5b)src) - 1;
+}
+
+#define PStrMaxLength 255
+
+LOCALPROC PStrFromCStr(ps3p r, /* CONST */ char *s)
+{
+	unsigned short L;
+
+	L = CStrLen(s);
+	if (L > PStrMaxLength) {
+		L = PStrMaxLength;
+	}
+	*r++ = L;
+	MyMoveBytes((anyp)s, (anyp)r, L);
+}
+
+LOCALPROC PStrFromChar(ps3p r, char x)
+{
+	r[0] = 1;
+	r[1] = (char)x;
+}
+
+LOCALPROC PStrFromHandle(ps3p r, Handle h, ui5b MaxL)
+{
+	ui5b L = GetHandleSize(h);
+
+	if (L > MaxL) {
+		L = MaxL;
+	}
+
+	*r++ = L;
+	BlockMove(*h, (Ptr)r, L);
+}
+
+LOCALFUNC tMacErr PStrToHand(ps3p s, Handle *r)
+{
+	return To_tMacErr(PtrToHand((Ptr)(s + 1), r, s[0]));
+}
+
+/* --- utilities for adapting to the environment --- */
+
+#ifndef MightNotHaveAppearanceMgrAvail
+#define MightNotHaveAppearanceMgrAvail 1
+#endif
+
+#ifndef MightNotHaveWindows85Avail
+#define MightNotHaveWindows85Avail MightNotHaveAppearanceMgrAvail
+#endif
+
+#ifndef LowMemAPIAvail
+#define LowMemAPIAvail 1
+#endif
+
+#ifndef My_LMGetTime
+#if LowMemAPIAvail
+#define My_LMGetTime LMGetTime
+#else
+#define My_LMGetTime() (*(SInt32 *)(0x020C))
+#endif
+#endif
+
+#ifndef My_LMGetMBarHeight
+#if LowMemAPIAvail
+#define My_LMGetMBarHeight LMGetMBarHeight
+#else
+#define My_LMGetMBarHeight() (*(short *)(0x0BAA))
+#endif
+#endif
+
+#ifndef My_GetGrayRgn
+#if /* LowMemAPIAvail */ 0
+#define My_GetGrayRgn LMGetGrayRgn
+#else
+#define My_GetGrayRgn() (*(RgnHandle *)(0x9EE))
+#endif
+#endif
+
+#ifndef My_LMGetCurApName
+#if LowMemAPIAvail
+#define My_LMGetCurApName LMGetCurApName
+#else
+#define My_LMGetCurApName() ((StringPtr) 0x0910)
+#endif
+#endif
+
+#define MyGetScreenBitsBounds(r) (*r) = qd.screenBits.bounds
+
+#define My_GetRegionBounds(region, bounds) *(bounds) = \
+	(**(region)).rgnBBox
+
+#define My_GetPortPixMap(p) ((p)->portPixMap)
+
+#ifndef My_WindowRef
+#if NewNamesAvail
+#define My_WindowRef WindowRef
+#else
+#define My_WindowRef WindowPtr
+#endif
+#endif
+
+#define My_SetPortWindowPort(w) SetPort(w)
+
+LOCALPROC My_InvalWindowRect(My_WindowRef mw, Rect *r)
+{
+	GrafPtr SavePort;
+
+	GetPort(&SavePort);
+	My_SetPortWindowPort(mw);
+	InvalRect(r);
+	SetPort(SavePort);
+}
+
+#define My_GetWindowPortBounds(w, r) *(r) = ((w)->portRect)
+
+LOCALPROC InvalWholeWindow(My_WindowRef mw)
+{
+	Rect bounds;
+
+	My_GetWindowPortBounds(mw, &bounds);
+	My_InvalWindowRect(mw, &bounds);
+}
+
+LOCALPROC MySetMacWindContRect(My_WindowRef mw, Rect *r)
+{
+#if Windows85APIAvail
+	if (HaveNewWndMgrAvail()) {
+		(void) SetWindowBounds (mw, kWindowContentRgn, r);
+	} else
+#endif
+	{
+#if MightNotHaveWindows85Avail
+		MoveWindow(mw, r->left, r->top, falseblnr);
+		SizeWindow(mw, r->right - r->left, r->bottom - r->top,
+			trueblnr);
+#endif
+	}
+	InvalWholeWindow(mw);
+}
+
+LOCALFUNC blnr MyGetWindowTitleBounds(My_WindowRef mw, Rect *r)
+{
+#if Windows85APIAvail
+	if (HaveNewWndMgrAvail()) {
+		return (noErr == GetWindowBounds(mw,
+				kWindowTitleBarRgn, r));
+	} else
+#endif
+	{
+#if MightNotHaveWindows85Avail
+		My_GetRegionBounds(((WindowPeek)mw)->strucRgn, r);
+		r->bottom = r->top + 15;
+		r->left += 4;
+		r->right -= 4;
+#endif
+		return trueblnr;
+	}
+}
+
+#define topLeft(r) (((Point *) &(r))[0])
+#define botRight(r) (((Point *) &(r))[1])
+
+LOCALFUNC blnr MyGetWindowContBounds(My_WindowRef mw, Rect *r)
+{
+#if Windows85APIAvail
+	if (HaveNewWndMgrAvail()) {
+		return (noErr == GetWindowBounds(mw,
+				kWindowContentRgn, r));
+	} else
+#endif
+	{
+#if MightNotHaveWindows85Avail
+		GrafPtr oldPort;
+		GetPort(&oldPort);
+		My_SetPortWindowPort(mw);
+		My_GetWindowPortBounds(mw, r);
+		LocalToGlobal(&topLeft(*r));
+		LocalToGlobal(&botRight(*r));
+		SetPort(oldPort);
+#endif
+		return trueblnr;
+	}
+}
+
+LOCALPROC MyGetGrayRgnBounds(Rect *r)
+{
+	My_GetRegionBounds(My_GetGrayRgn(), (Rect *)r);
+}
+
+/* --- main window data --- */
+
+LOCALVAR WindowPtr gMyMainWindow = NULL;
+
+#if MayFullScreen
+LOCALVAR short hOffset;
+LOCALVAR short vOffset;
+#endif
+
+#if MayFullScreen
+LOCALVAR blnr GrabMachine = falseblnr;
+#endif
+
+#if VarFullScreen
+LOCALVAR blnr UseFullScreen = (WantInitFullScreen != 0);
+#endif
+
+#if EnableMagnify
+LOCALVAR blnr UseMagnify = (WantInitMagnify != 0);
+#endif
+
+#if EnableMagnify
+LOCALPROC MyScaleRect(Rect *r)
+{
+	r->left *= MyWindowScale;
+	r->right *= MyWindowScale;
+	r->top *= MyWindowScale;
+	r->bottom *= MyWindowScale;
+}
+#endif
+
+LOCALPROC SetScrnRectFromCoords(Rect *r,
+	si4b top, si4b left, si4b bottom, si4b right)
+{
+	r->left = left;
+	r->right = right;
+	r->top = top;
+	r->bottom = bottom;
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		OffsetRect(r, - ViewHStart, - ViewVStart);
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+		MyScaleRect(r);
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		OffsetRect(r, hOffset, vOffset);
+	}
+#endif
+
+}
+
+#if EnableMagnify
+#define MyScaledHeight (MyWindowScale * vMacScreenHeight)
+#define MyScaledWidth (MyWindowScale * vMacScreenWidth)
+#endif
+
+#if EnableMagnify
+LOCALVAR ui3p ScalingBuff = nullpr;
+#endif
+
+#if EnableMagnify
+
+LOCALVAR ui3p ScalingTabl = nullpr;
+#define ScalingTablsz (256 * MyWindowScale)
+
+#define ScrnMapr_DoMap UpdateScaledBWCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 0
+#define ScrnMapr_Map ScalingTabl
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#endif
+
+#if EnableMagnify
+LOCALPROC SetUpScalingTabl(void)
+{
+	ui3b *p4;
+	int i;
+	int j;
+	int k;
+	ui3r bitsRemaining;
+	ui3b t1;
+	ui3b t2;
+
+	p4 = ScalingTabl;
+	for (i = 0; i < 256; ++i) {
+		bitsRemaining = 8;
+		t2 = 0;
+		for (j = 8; --j >= 0; ) {
+			t1 = (i >> j) & 1;
+			for (k = MyWindowScale; --k >= 0; ) {
+				t2 = (t2 << 1) | t1;
+				if (--bitsRemaining == 0) {
+					*p4++ = t2;
+					bitsRemaining = 8;
+					t2 = 0;
+				}
+			}
+		}
+	}
+}
+#endif
+
+LOCALPROC DefaultDrawScreenBuff(si4b top, si4b left,
+	si4b bottom, si4b right)
+{
+	BitMap src;
+	Rect SrcRect;
+	Rect DstRect;
+
+	SrcRect.left = left;
+	SrcRect.right = right;
+	SrcRect.top = top;
+	SrcRect.bottom = bottom;
+
+	src.rowBytes = vMacScreenMonoByteWidth;
+	SetRect(&src.bounds, 0, 0, vMacScreenWidth, vMacScreenHeight);
+#if EnableMagnify
+	if (UseMagnify) {
+
+		if (! ColorTransValid) {
+			SetUpScalingTabl();
+			ColorTransValid = trueblnr;
+		}
+
+		UpdateScaledBWCopy(top, left, bottom, right);
+
+		MyScaleRect(&SrcRect);
+		MyScaleRect(&src.bounds);
+
+		src.baseAddr = (Ptr)ScalingBuff;
+		src.rowBytes *= MyWindowScale;
+	} else
+#endif
+	{
+		src.baseAddr = (Ptr)GetCurDrawBuff();
+	}
+	SetScrnRectFromCoords(&DstRect, top, left, bottom, right);
+	CopyBits(&src,
+		&gMyMainWindow->portBits,
+		&SrcRect, &DstRect, srcCopy, NULL);
+	/* FrameRect(&SrcRect); for testing */
+}
+
+LOCALPROC Update_Screen(void)
+{
+	GrafPtr savePort;
+
+	GetPort(&savePort);
+	My_SetPortWindowPort(gMyMainWindow);
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		PaintRect(&gMyMainWindow->portRect);
+	}
+#endif
+
+	DefaultDrawScreenBuff(0, 0, vMacScreenHeight, vMacScreenWidth);
+	SetPort(savePort);
+}
+
+LOCALPROC HaveChangedScreenBuff(si4b top, si4b left,
+	si4b bottom, si4b right)
+{
+#if 0 /* experimental code in progress */
+	if (UseFullScreen)
+	{
+		{
+			PixMapHandle pm= (**GetMainDevice()).gdPMap;
+
+			/* LockPixels(pm); */
+#if EnableMagnify
+			if (! UseMagnify) {
+#define PixelT ui5b
+				PixelT *p1 = (PixelT *)GetPixBaseAddr(pm);
+				int i;
+				int j;
+				int k;
+				ui5b *p0 = (ui5b *)GetCurDrawBuff();
+				ui5b SkipBytes = GetPixRowBytes(pm)
+					- sizeof(PixelT) * vMacScreenWidth;
+				ui5b t0;
+				PixelT a[2];
+
+				((Ptr)p1) += (long)GetPixRowBytes(pm) * (top + vOffset);
+				p1 += hOffset;
+				p0 += (long)top * vMacScreenWidth / 32;
+
+				a[0] = (PixelT) -1;
+				a[1] = 0;
+
+#if 1
+				for (i = bottom - top; --i >= 0; ) {
+					for (j = vMacScreenWidth / 32; --j >= 0; ) {
+						t0 = *p0++;
+
+						for (k = 32; --k >= 0; ) {
+							PixelT v = a[(t0 >> k) & 1];
+							*p1++ = v;
+						}
+					}
+					((Ptr)p1) += SkipBytes;
+				}
+#endif
+			} else {
+#define PixelT ui5b
+				PixelT *p1 = (PixelT *)GetPixBaseAddr(pm);
+				int i;
+				int j;
+				int k;
+				ui5b *p0 = (ui5b *)GetCurDrawBuff();
+				PixelT *p2;
+				ui5b t0;
+				PixelT a[2];
+
+				p1 += vOffset * MyScaledWidth;
+				p1 += (long)MyWindowScale * (long)MyScaledWidth * top;
+				p0 += (long)top * vMacScreenWidth / 32;
+
+				a[0] = (PixelT) -1;
+				a[1] = 0;
+
+#if 1
+				for (i = bottom - top; --i >= 0; ) {
+					p2 = p1;
+					for (j = vMacScreenWidth / 32; --j >= 0; ) {
+						t0 = *p0++;
+
+						for (k = 32; --k >= 0; ) {
+							PixelT v = a[(t0 >> k) & 1];
+								/* ((t0 >> k) & 1) - 1 */
+							*p1++ = v;
+							*p1++ = v;
+						}
+					}
+					for (j = MyScaledWidth; --j >= 0; ) {
+						*p1++ = *p2++;
+					}
+				}
+#endif
+			}
+#endif
+			/* UnlockPixels(pm); */
+		}
+	} else
+#endif
+	{
+		GrafPtr savePort;
+
+		GetPort(&savePort);
+		My_SetPortWindowPort(gMyMainWindow);
+		DefaultDrawScreenBuff(top, left, bottom, right);
+		SetPort(savePort);
+	}
+}
+
+LOCALPROC MyDrawChangesAndClear(void)
+{
+	if (ScreenChangedBottom > ScreenChangedTop) {
+		HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft,
+			ScreenChangedBottom, ScreenChangedRight);
+		ScreenClearChanges();
+	}
+}
+
+GLOBALOSGLUPROC DoneWithDrawingForTick(void)
+{
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		AutoScrollScreen();
+	}
+#endif
+	MyDrawChangesAndClear();
+}
+
+/* --- keyboard --- */
+
+LOCALVAR ui5b LastEmKeys[4];
+
+LOCALPROC ZapEmKeys(void)
+{
+	LastEmKeys[0] = 0;
+	LastEmKeys[1] = 0;
+	LastEmKeys[2] = 0;
+	LastEmKeys[3] = 0;
+}
+
+LOCALPROC CheckKeyBoardState(void)
+{
+	int i;
+	int j;
+	ui5b NewKeys[4];
+
+	GetKeys(*(KeyMap *)NewKeys);
+
+	for (j = 0; j < 16; ++j) {
+		ui3b k1 = ((ui3b *)NewKeys)[j];
+		ui3b k2 = ((ui3b *)LastEmKeys)[j];
+		ui3b k3 = k1 ^ k2;
+
+		if (k3 != 0) {
+			for (i = 0; i < 8; ++i) {
+				if ((k3 & (1 << i)) != 0) {
+					Keyboard_UpdateKeyMap2(Keyboard_RemapMac(j * 8 + i),
+						(k1 & (1 << i)) != 0);
+				}
+			}
+		}
+	}
+	for (i = 0; i < 4; ++i) {
+		LastEmKeys[i] = NewKeys[i];
+	}
+}
+
+LOCALVAR WantCmdOptOnReconnect = falseblnr;
+
+#define KeyMap_TestBit(m, key) \
+	((((ui3b *)m)[(key) / 8] & (1 << ((key) & 7))) != 0)
+
+LOCALPROC ReconnectKeyCodes3(void)
+/* so keys already pressed will be ignored */
+{
+	int i;
+	int j;
+	blnr oldv;
+	blnr newv;
+	ui5b NewKeys[4];
+
+	GetKeys(*(KeyMap *)NewKeys);
+
+	/* except check CapsLock */
+	oldv = KeyMap_TestBit(LastEmKeys, MKC_CapsLock);
+	newv = KeyMap_TestBit(NewKeys, MKC_CapsLock);
+	if (oldv != newv) {
+		Keyboard_UpdateKeyMap2(MKC_formac_CapsLock, newv);
+	}
+
+	/* and except for command/option on receive drop */
+	if (WantCmdOptOnReconnect) {
+		WantCmdOptOnReconnect = falseblnr;
+
+		for (i = 0; i < 16; ++i) {
+			ui3b v = ((ui3b *)NewKeys)[i];
+			for (j = 0; j < 8; ++j) {
+				if (0 != ((1 << j) & v)) {
+					ui3r k = i * 8 + j;
+					if (MKC_CapsLock != k) {
+						Keyboard_UpdateKeyMap2(Keyboard_RemapMac(k),
+							trueblnr);
+					}
+				}
+			}
+		}
+	}
+
+	for (i = 0; i < 4; ++i) {
+		LastEmKeys[i] = NewKeys[i];
+	}
+}
+
+/* --- cursor hiding --- */
+
+LOCALVAR blnr HaveCursorHidden = falseblnr;
+LOCALVAR blnr WantCursorHidden = falseblnr;
+
+LOCALPROC ForceShowCursor(void)
+{
+	if (HaveCursorHidden) {
+		HaveCursorHidden = falseblnr;
+		ShowCursor();
+	}
+}
+
+LOCALPROC SetCursorArrow(void)
+{
+	SetCursor(&qd.arrow);
+}
+
+/* --- cursor moving --- */
+
+/*
+	When "EnableFSMouseMotion" the platform
+	specific code can get relative mouse
+	motion, instead of absolute coordinates
+	on the emulated screen. It should
+	set HaveMouseMotion to true when
+	it is doing this (normally when in
+	full screen mode.)
+
+	This can usually be implemented by
+	hiding the platform specific cursor,
+	and then keeping it within a box,
+	moving the cursor back to the center whenever
+	it leaves the box. This requires the
+	ability to move the cursor (in MyMoveMouse).
+*/
+
+/*
+	mouse moving code (non OS X) adapted from
+	MoveMouse.c by Dan Sears, which says that
+	"Based on code from Jon Wtte, Denis Pelli,
+	Apple, and a timely suggestion from Bo Lindbergh."
+	Also says 'For documentation of the CDM, see Apple
+	Tech Note "HW 01 - ADB (The Untold Story: Space Aliens
+	ate my mouse)"'
+*/
+
+#ifndef TARGET_CPU_PPC
+#error "TARGET_CPU_PPC undefined"
+#endif
+
+#if TARGET_CPU_PPC
+enum {
+	glueUppCursorDeviceMoveToProcInfo =
+		kD0DispatchedPascalStackBased |
+		DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(kTwoByteCode) |
+		RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
+		DISPATCHED_STACK_ROUTINE_PARAMETER(1,
+			SIZE_CODE(sizeof(CursorDevicePtr))) |
+		DISPATCHED_STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(long))) |
+		DISPATCHED_STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(long))),
+	glueUppCursorDeviceNextDeviceProcInfo =
+		kD0DispatchedPascalStackBased |
+		DISPATCHED_STACK_ROUTINE_SELECTOR_SIZE(kTwoByteCode) |
+		RESULT_SIZE(SIZE_CODE(sizeof(OSErr))) |
+		DISPATCHED_STACK_ROUTINE_PARAMETER(1,
+			SIZE_CODE(sizeof(CursorDevicePtr *)))
+};
+#endif
+
+#if TARGET_CPU_PPC
+LOCALFUNC OSErr
+CallCursorDeviceMoveTo(
+	CursorDevicePtr ourDevice,
+	long absX,
+	long absY)
+{
+	return CallUniversalProc(
+		GetToolboxTrapAddress(_CursorDeviceDispatch),
+		glueUppCursorDeviceMoveToProcInfo,
+		1, ourDevice, absX, absY);
+}
+#else
+#define CallCursorDeviceMoveTo CursorDeviceMoveTo
+#endif
+
+#if TARGET_CPU_PPC
+LOCALFUNC OSErr
+CallCursorDeviceNextDevice(
+	CursorDevicePtr *ourDevice)
+{
+	return CallUniversalProc(
+		GetToolboxTrapAddress(_CursorDeviceDispatch),
+		glueUppCursorDeviceNextDeviceProcInfo,
+		0xB, ourDevice);
+}
+#else
+#define CallCursorDeviceNextDevice CursorDeviceNextDevice
+#endif
+
+#if ! TARGET_CPU_PPC
+pascal void CallCursorTask(void) =
+{
+	0x2078, 0x08EE,  /* MOVE.L jCrsrTask,A0 */
+	0x4E90           /* JSR (A0) */
+};
+#endif
+
+/*
+	Low memory globals for the mouse
+*/
+
+#define MyRawMouse   0x082C
+	/* low memory global that has current mouse loc */
+#define MyMTemp      0x0828
+	/* low memory global that has current mouse loc */
+#define MyCrsrNew    0x08CE
+	/* set after you change mtemp and rawmouse */
+#define MyCrsrCouple 0x08CF
+	/* true if the cursor is tied to the mouse */
+
+LOCALFUNC blnr MyMoveMouse(si4b h, si4b v)
+{
+	/*
+		Move the cursor to the point h, v
+		on the emulated screen.
+		if detect that this fails return falseblnr,
+		otherwise return trueblnr.
+		(on some platforms it is possible to
+		move the curser, but there is no
+		way to detect failure.)
+	*/
+	GrafPtr oldPort;
+	Point CurMousePos;
+	Point NewMousePos;
+	ui5b difftime;
+	blnr IsOk;
+	long int StartTime = TickCount();
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		h -= ViewHStart;
+		v -= ViewVStart;
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+		h *= MyWindowScale;
+		v *= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		h += hOffset;
+		v += vOffset;
+	}
+#endif
+
+	CurMousePos.h = h;
+	CurMousePos.v = v;
+
+	GetPort(&oldPort);
+	My_SetPortWindowPort(gMyMainWindow);
+	LocalToGlobal(&CurMousePos);
+
+	do {
+
+#if HaveCPUfamM68K
+		if (! HiToolTrapAvailable(_CursorDeviceDispatch)) {
+			*(Point *)MyRawMouse = CurMousePos;
+			*(Point *)MyMTemp = CurMousePos;
+			*(Ptr)MyCrsrNew = *(Ptr)MyCrsrCouple;
+#if ! TARGET_CPU_PPC
+			CallCursorTask();
+#endif
+		} else
+#endif
+		{
+			CursorDevice *firstMouse = NULL;
+			CallCursorDeviceNextDevice(&firstMouse);
+			if (firstMouse != NULL) {
+				CallCursorDeviceMoveTo(firstMouse,
+					(long) CurMousePos.h,
+					(long) CurMousePos.v);
+			}
+		}
+
+		GetMouse(&NewMousePos);
+		IsOk = (h == NewMousePos.h) && (v == NewMousePos.v);
+		difftime = (ui5b)(TickCount() - StartTime);
+	} while ((! IsOk) && (difftime < 5));
+
+	SetPort(oldPort);
+	return IsOk;
+}
+
+#if EnableFSMouseMotion
+LOCALPROC AdjustMouseMotionGrab(void)
+{
+	if (gMyMainWindow != NULL) {
+#if MayFullScreen
+		if (GrabMachine) {
+			/*
+				if magnification changes, need to reset,
+				even if HaveMouseMotion already true
+			*/
+			if (MyMoveMouse(ViewHStart + (ViewHSize / 2),
+				ViewVStart + (ViewVSize / 2)))
+			{
+				SavedMouseH = ViewHStart + (ViewHSize / 2);
+				SavedMouseV = ViewVStart + (ViewVSize / 2);
+				HaveMouseMotion = trueblnr;
+			}
+		} else
+#endif
+		{
+			if (HaveMouseMotion) {
+				(void) MyMoveMouse(CurMouseH, CurMouseV);
+				HaveMouseMotion = falseblnr;
+			}
+		}
+	}
+}
+#endif
+
+#if EnableFSMouseMotion
+LOCALPROC MyMouseConstrain(void)
+{
+	si4b shiftdh;
+	si4b shiftdv;
+
+	if (SavedMouseH < ViewHStart + (ViewHSize / 4)) {
+		shiftdh = ViewHSize / 2;
+	} else if (SavedMouseH > ViewHStart + ViewHSize - (ViewHSize / 4)) {
+		shiftdh = - ViewHSize / 2;
+	} else {
+		shiftdh = 0;
+	}
+	if (SavedMouseV < ViewVStart + (ViewVSize / 4)) {
+		shiftdv = ViewVSize / 2;
+	} else if (SavedMouseV > ViewVStart + ViewVSize - (ViewVSize / 4)) {
+		shiftdv = - ViewVSize / 2;
+	} else {
+		shiftdv = 0;
+	}
+	if ((shiftdh != 0) || (shiftdv != 0)) {
+		SavedMouseH += shiftdh;
+		SavedMouseV += shiftdv;
+		if (! MyMoveMouse(SavedMouseH, SavedMouseV)) {
+			HaveMouseMotion = falseblnr;
+		}
+	}
+}
+#endif
+
+LOCALPROC MousePositionNotify(Point NewMousePos)
+{
+	blnr ShouldHaveCursorHidden = trueblnr;
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		NewMousePos.h -= hOffset;
+		NewMousePos.v -= vOffset;
+	}
+#endif
+#if VarFullScreen
+	else
+#endif
+#if MayNotFullScreen
+	{
+		if (! PtInRgn(NewMousePos, gMyMainWindow->visRgn)) {
+			ShouldHaveCursorHidden = falseblnr;
+		}
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+		NewMousePos.h /= MyWindowScale;
+		NewMousePos.v /= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		NewMousePos.h += ViewHStart;
+		NewMousePos.v += ViewVStart;
+	}
+#endif
+
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		MyMousePositionSetDelta(
+			NewMousePos.h - SavedMouseH, NewMousePos.v - SavedMouseV);
+		SavedMouseH = NewMousePos.h;
+		SavedMouseV = NewMousePos.v;
+	} else
+#endif
+	{
+		if (NewMousePos.h < 0) {
+			NewMousePos.h = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePos.h >= vMacScreenWidth) {
+			NewMousePos.h = vMacScreenWidth - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+		if (NewMousePos.v < 0) {
+			NewMousePos.v = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePos.v >= vMacScreenHeight) {
+			NewMousePos.v = vMacScreenHeight - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+
+#if VarFullScreen
+		if (UseFullScreen)
+#endif
+#if MayFullScreen
+		{
+			ShouldHaveCursorHidden = trueblnr;
+		}
+#endif
+
+		/* if (ShouldHaveCursorHidden || CurMouseButton) */
+		/*
+			for a game like arkanoid, would like mouse to still
+			move even when outside window in one direction
+		*/
+		MyMousePositionSet(NewMousePos.h, NewMousePos.v);
+	}
+
+	WantCursorHidden = ShouldHaveCursorHidden;
+}
+
+LOCALPROC MousePositionNotifyFromGlobal(Point NewMousePos)
+{
+	GrafPtr oldPort;
+
+	GetPort(&oldPort);
+	My_SetPortWindowPort(gMyMainWindow);
+	GlobalToLocal(&NewMousePos);
+	SetPort(oldPort);
+
+	MousePositionNotify(NewMousePos);
+}
+
+LOCALPROC CheckMouseState(void)
+{
+	Point NewMousePos;
+	GrafPtr oldPort;
+
+	GetPort(&oldPort);
+	My_SetPortWindowPort(gMyMainWindow);
+	GetMouse(&NewMousePos);
+	SetPort(oldPort);
+
+	MousePositionNotify(NewMousePos);
+}
+
+LOCALPROC DisconnectKeyCodes3(void)
+{
+	DisconnectKeyCodes2();
+
+	MyMouseButtonSet(falseblnr);
+
+	ForceShowCursor();
+}
+
+
+/* --- time, date, location --- */
+
+#define dbglog_TimeStuff (0 && dbglog_HAVE)
+
+/*
+	be sure to avoid getting confused if TickCount
+	overflows and wraps.
+*/
+
+LOCALVAR ui5b TrueEmulatedTime = 0;
+	/*
+		The amount of time the program has
+		been running, measured in Macintosh
+		"ticks". There are 60.14742 ticks per
+		second.
+
+		(time when the emulation is
+		stopped for more than a few ticks
+		should not be counted.)
+	*/
+
+LOCALVAR long int LastTime;
+
+LOCALPROC StartUpTimeAdjust(void)
+{
+	/*
+		prepare to call UpdateTrueEmulatedTime.
+
+		will be called again when haven't been
+		regularly calling UpdateTrueEmulatedTime,
+		(such as the emulation has been stopped).
+	*/
+	LastTime = TickCount();
+}
+
+LOCALPROC UpdateTrueEmulatedTime(void)
+{
+	/*
+		Update TrueEmulatedTime. usually
+		need to convert between how the
+		host operating system measures
+		time and Macintosh ticks. But
+		not for this port.
+	*/
+	long int LatestTime = TickCount();
+	si5b TimeDiff = LatestTime - LastTime;
+
+	if (TimeDiff != 0) {
+		LastTime = LatestTime;
+
+		if (TimeDiff >= 0) {
+			if (TimeDiff > 16) {
+				/* emulation interrupted, forget it */
+				++TrueEmulatedTime;
+
+#if dbglog_TimeStuff
+				dbglog_writelnNum("emulation interrupted",
+					TrueEmulatedTime);
+#endif
+			} else {
+				TrueEmulatedTime += TimeDiff;
+			}
+		}
+	}
+}
+
+LOCALFUNC blnr CheckDateTime(void)
+{
+	/*
+		Update CurMacDateInSeconds, the number
+		of seconds since midnight January 1, 1904.
+
+		return true if CurMacDateInSeconds is
+		different than it was on the last
+		call to CheckDateTime.
+	*/
+	ui5b NewMacDateInSecond;
+
+	NewMacDateInSecond = My_LMGetTime();
+	if (CurMacDateInSeconds != NewMacDateInSecond) {
+		CurMacDateInSeconds = NewMacDateInSecond;
+		return trueblnr;
+	} else {
+		return falseblnr;
+	}
+}
+
+LOCALFUNC blnr InitLocationDat(void)
+{
+#if AutoLocation || AutoTimeZone
+	MachineLocation loc;
+
+	ReadLocation(&loc);
+#if AutoLocation
+	CurMacLatitude = (ui5b)loc.latitude;
+	CurMacLongitude = (ui5b)loc.longitude;
+#endif
+#if AutoTimeZone
+	CurMacDelta = (ui5b)loc.u.gmtDelta;
+#endif
+#endif
+
+	(void) CheckDateTime();
+
+	return trueblnr;
+}
+
+/* --- sound --- */
+
+#if MySoundEnabled
+
+#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */
+#define kSoundBuffers (1 << kLn2SoundBuffers)
+#define kSoundBuffMask (kSoundBuffers - 1)
+
+#define DesiredMinFilledSoundBuffs 3
+	/*
+		if too big then sound lags behind emulation.
+		if too small then sound will have pauses.
+	*/
+
+#define kLnOneBuffLen 9
+#define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen)
+#define kOneBuffLen (1UL << kLnOneBuffLen)
+#define kAllBuffLen (1UL << kLnAllBuffLen)
+#define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3)
+#define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3)
+#define kOneBuffSz (1UL << kLnOneBuffSz)
+#define kAllBuffSz (1UL << kLnAllBuffSz)
+#define kOneBuffMask (kOneBuffLen - 1)
+#define kAllBuffMask (kAllBuffLen - 1)
+#define dbhBufferSize (kAllBuffSz + kOneBuffSz)
+
+#define dbglog_SoundStuff (0 && dbglog_HAVE)
+#define dbglog_SoundBuffStats (0 && dbglog_HAVE)
+
+LOCALVAR tpSoundSamp TheSoundBuffer = nullpr;
+volatile static ui4b ThePlayOffset;
+volatile static ui4b TheFillOffset;
+volatile static ui4b MinFilledSoundBuffs;
+#if dbglog_SoundBuffStats
+LOCALVAR ui4b MaxFilledSoundBuffs;
+#endif
+LOCALVAR ui4b TheWriteOffset;
+
+LOCALPROC MySound_Start0(void)
+{
+	/* Reset variables */
+	ThePlayOffset = 0;
+	TheFillOffset = 0;
+	TheWriteOffset = 0;
+	MinFilledSoundBuffs = kSoundBuffers + 1;
+#if dbglog_SoundBuffStats
+	MaxFilledSoundBuffs = 0;
+#endif
+}
+
+GLOBALOSGLUFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL)
+{
+	ui4b ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset);
+	ui4b WriteBuffContig =
+		kOneBuffLen - (TheWriteOffset & kOneBuffMask);
+
+	if (WriteBuffContig < n) {
+		n = WriteBuffContig;
+	}
+	if (ToFillLen < n) {
+		/* overwrite previous buffer */
+#if dbglog_SoundStuff
+		dbglog_writeln("sound buffer over flow");
+#endif
+		TheWriteOffset -= kOneBuffLen;
+	}
+
+	*actL = n;
+	return TheSoundBuffer + (TheWriteOffset & kAllBuffMask);
+}
+
+#if 4 == kLn2SoundSampSz
+LOCALPROC ConvertSoundBlockToNative(tpSoundSamp p)
+{
+	int i;
+
+	for (i = kOneBuffLen; --i >= 0; ) {
+		*p++ -= 0x8000;
+	}
+}
+#else
+#define ConvertSoundBlockToNative(p)
+#endif
+
+LOCALPROC MySound_WroteABlock(void)
+{
+#if (4 == kLn2SoundSampSz)
+	ui4b PrevWriteOffset = TheWriteOffset - kOneBuffLen;
+	tpSoundSamp p = TheSoundBuffer + (PrevWriteOffset & kAllBuffMask);
+#endif
+
+#if dbglog_SoundStuff
+	dbglog_writeln("enter MySound_WroteABlock");
+#endif
+
+	ConvertSoundBlockToNative(p);
+
+	TheFillOffset = TheWriteOffset;
+
+#if dbglog_SoundBuffStats
+	{
+		ui4b ToPlayLen = TheFillOffset
+			- ThePlayOffset;
+		ui4b ToPlayBuffs = ToPlayLen >> kLnOneBuffLen;
+
+		if (ToPlayBuffs > MaxFilledSoundBuffs) {
+			MaxFilledSoundBuffs = ToPlayBuffs;
+		}
+	}
+#endif
+}
+
+LOCALFUNC blnr MySound_EndWrite0(ui4r actL)
+{
+	blnr v;
+
+	TheWriteOffset += actL;
+
+	if (0 != (TheWriteOffset & kOneBuffMask)) {
+		v = falseblnr;
+	} else {
+		/* just finished a block */
+
+		MySound_WroteABlock();
+
+		v = trueblnr;
+	}
+
+	return v;
+}
+
+LOCALPROC MySound_SecondNotify0(void)
+{
+	if (MinFilledSoundBuffs <= kSoundBuffers) {
+		if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) {
+#if dbglog_SoundStuff
+			dbglog_writeln("MinFilledSoundBuffs too high");
+#endif
+			++LastTime;
+		} else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) {
+#if dbglog_SoundStuff
+			dbglog_writeln("MinFilledSoundBuffs too low");
+#endif
+			++TrueEmulatedTime;
+		}
+#if dbglog_SoundBuffStats
+		dbglog_writelnNum("MinFilledSoundBuffs",
+			MinFilledSoundBuffs);
+		dbglog_writelnNum("MaxFilledSoundBuffs",
+			MaxFilledSoundBuffs);
+		MaxFilledSoundBuffs = 0;
+#endif
+		MinFilledSoundBuffs = kSoundBuffers + 1;
+	}
+}
+
+LOCALPROC RampSound(tpSoundSamp p,
+	trSoundSamp BeginVal, trSoundSamp EndVal)
+{
+	int i;
+	ui5r v = (((ui5r)BeginVal) << kLnOneBuffLen) + (kLnOneBuffLen >> 1);
+
+	for (i = kOneBuffLen; --i >= 0; ) {
+		*p++ = v >> kLnOneBuffLen;
+		v = v + EndVal - BeginVal;
+	}
+}
+
+#if 4 == kLn2SoundSampSz
+#define ConvertSoundSampleFromNative(v) ((v) + 0x8000)
+#else
+#define ConvertSoundSampleFromNative(v) (v)
+#endif
+
+struct MySoundR {
+	tpSoundSamp fTheSoundBuffer;
+	volatile ui4b (*fPlayOffset);
+	volatile ui4b (*fFillOffset);
+	volatile ui4b (*fMinFilledSoundBuffs);
+
+	volatile blnr PlayingBuffBlock;
+	volatile trSoundSamp lastv;
+	volatile blnr wantplaying;
+	volatile blnr StartingBlocks;
+
+	CmpSoundHeader /* ExtSoundHeader */ soundHeader;
+};
+typedef struct MySoundR   MySoundR;
+
+
+/*
+	Some of this code descended from CarbonSndPlayDB, an
+	example from Apple, as found being used in vMac for Mac OS.
+*/
+
+LOCALPROC InsertSndDoCommand(SndChannelPtr chan, SndCommand * newCmd)
+{
+	if (-1 == chan->qHead) {
+		chan->qHead = chan->qTail;
+	}
+
+	if (1 <= chan->qHead) {
+		chan->qHead--;
+	} else {
+		chan->qHead = chan->qTail;
+	}
+
+	chan->queue[chan->qHead] = *newCmd;
+}
+
+/* call back */ static pascal void
+MySound_CallBack(SndChannelPtr theChannel, SndCommand * theCallBackCmd)
+{
+	MySoundR *datp =
+		(MySoundR *)(theCallBackCmd->param2);
+	blnr wantplaying0 = datp->wantplaying;
+	trSoundSamp v0 = datp->lastv;
+
+#if dbglog_SoundStuff
+	dbglog_writeln("Enter MySound_CallBack");
+#endif
+
+	if (datp->PlayingBuffBlock) {
+		/* finish with last sample */
+#if dbglog_SoundStuff
+		dbglog_writeln("done with sample");
+#endif
+
+		*datp->fPlayOffset += kOneBuffLen;
+		datp->PlayingBuffBlock = falseblnr;
+	}
+
+	if ((! wantplaying0) && (kCenterSound == v0)) {
+#if dbglog_SoundStuff
+		dbglog_writeln("terminating");
+#endif
+	} else {
+		SndCommand playCmd;
+		tpSoundSamp p;
+		trSoundSamp v1 = v0;
+		blnr WantRamp = falseblnr;
+		ui4b CurPlayOffset = *datp->fPlayOffset;
+		ui4b ToPlayLen = *datp->fFillOffset - CurPlayOffset;
+		ui4b FilledSoundBuffs = ToPlayLen >> kLnOneBuffLen;
+
+		if (FilledSoundBuffs < *datp->fMinFilledSoundBuffs) {
+			*datp->fMinFilledSoundBuffs = FilledSoundBuffs;
+		}
+
+		if (! wantplaying0) {
+#if dbglog_SoundStuff
+			dbglog_writeln("playing end transistion");
+#endif
+			v1 = kCenterSound;
+
+			WantRamp = trueblnr;
+		} else
+		if (datp->StartingBlocks) {
+#if dbglog_SoundStuff
+			dbglog_writeln("playing start block");
+#endif
+
+			if ((ToPlayLen >> kLnOneBuffLen) < 12) {
+				datp->StartingBlocks = falseblnr;
+#if dbglog_SoundStuff
+				dbglog_writeln("have enough samples to start");
+#endif
+
+				p = datp->fTheSoundBuffer
+					+ (CurPlayOffset & kAllBuffMask);
+				v1 = ConvertSoundSampleFromNative(*p);
+			}
+
+			WantRamp = trueblnr;
+		} else
+		if (0 == FilledSoundBuffs) {
+#if dbglog_SoundStuff
+			dbglog_writeln("playing under run");
+#endif
+
+			WantRamp = trueblnr;
+		} else
+		{
+			/* play next sample */
+			p = datp->fTheSoundBuffer
+				+ (CurPlayOffset & kAllBuffMask);
+			datp->PlayingBuffBlock = trueblnr;
+			v1 =
+				ConvertSoundSampleFromNative(*(p + kOneBuffLen - 1));
+#if dbglog_SoundStuff
+			dbglog_writeln("playing sample");
+#endif
+		}
+
+		if (WantRamp) {
+			p = datp->fTheSoundBuffer + kAllBuffLen;
+
+#if dbglog_SoundStuff
+			dbglog_writelnNum("v0", v0);
+			dbglog_writelnNum("v1", v1);
+#endif
+
+			RampSound(p, v0, v1);
+			ConvertSoundBlockToNative(p);
+		}
+
+		datp->soundHeader.samplePtr = (Ptr)p;
+		datp->soundHeader.numFrames =
+			(unsigned long)kOneBuffLen;
+
+		/* Insert our callback command */
+		InsertSndDoCommand (theChannel, theCallBackCmd);
+
+#if 0
+		{
+			int i;
+			tpSoundSamp pS =
+				(tpSoundSamp)datp->soundHeader.samplePtr;
+
+			for (i = datp->soundHeader.numFrames; --i >= 0; )
+			{
+				fprintf(stderr, "%d\n", *pS++);
+			}
+		}
+#endif
+
+		/* Play the next buffer */
+		playCmd.cmd = bufferCmd;
+		playCmd.param1 = 0;
+		playCmd.param2 = (long)&(datp->soundHeader);
+		InsertSndDoCommand (theChannel, &playCmd);
+
+		datp->lastv = v1;
+	}
+}
+
+LOCALVAR MySoundR cur_audio;
+
+LOCALVAR SndCallBackUPP gCarbonSndPlayDoubleBufferCallBackUPP = NULL;
+
+LOCALVAR SndChannelPtr sndChannel = NULL; /* our sound channel */
+
+LOCALPROC MySound_Start(void)
+{
+	if (NULL == sndChannel)
+#if HaveCPUfamM68K
+	if (HaveSndMngrAvail())
+#endif
+	{
+		SndCommand callBack;
+		SndChannelPtr chan = NULL;
+
+		cur_audio.wantplaying = falseblnr;
+		cur_audio.StartingBlocks = falseblnr;
+
+		MySound_Start0();
+
+		SndNewChannel(&chan, sampledSynth, initMono, nil);
+		if (NULL != chan) {
+			sndChannel = chan;
+
+			cur_audio.PlayingBuffBlock = falseblnr;
+			cur_audio.lastv = kCenterSound;
+			cur_audio.StartingBlocks = trueblnr;
+			cur_audio.wantplaying = trueblnr;
+
+			callBack.cmd = callBackCmd;
+			callBack.param1 = 0; /* unused */
+			callBack.param2 = (long)&cur_audio;
+
+			sndChannel->callBack =
+				gCarbonSndPlayDoubleBufferCallBackUPP;
+
+			(void) SndDoCommand (sndChannel, &callBack, true);
+		}
+	}
+}
+
+#define IgnorableEventMask \
+	(mUpMask | keyDownMask | keyUpMask | autoKeyMask)
+
+LOCALPROC MySound_Stop(void)
+{
+#if dbglog_SoundStuff
+	dbglog_writeln("enter MySound_Stop");
+#endif
+
+	if (NULL != sndChannel) {
+		ui4r retry_limit = 50; /* half of a second */
+		SCStatus r;
+
+		cur_audio.wantplaying = falseblnr;
+#if dbglog_SoundStuff
+		dbglog_writeln("cleared wantplaying");
+#endif
+
+label_retry:
+		r.scChannelBusy = falseblnr; /* what is this for? */
+		if (noErr != SndChannelStatus(sndChannel,
+			sizeof(SCStatus), &r))
+		{
+			/* fail */
+		} else
+		if ((! r.scChannelBusy) && (kCenterSound == cur_audio.lastv)) {
+			/* done */
+
+			/*
+				observed reporting not busy unexpectedly,
+				so also check lastv.
+			*/
+		} else
+		if (0 == --retry_limit) {
+#if dbglog_SoundStuff
+			dbglog_writeln("retry limit reached");
+#endif
+			/*
+				don't trust SndChannelStatus, make
+				sure don't get in infinite loop.
+			*/
+
+			/* done */
+		} else
+		{
+			/*
+				give time back, particularly important
+				if got here on a suspend event.
+			*/
+			EventRecord theEvent;
+
+#if dbglog_SoundStuff
+			dbglog_writeln("busy, so sleep");
+#endif
+
+#if HaveCPUfamM68K
+			if (! HaveWaitNextEventAvail()) {
+				(void) GetNextEvent(IgnorableEventMask, &theEvent);
+			} else
+#endif
+			{
+				(void) WaitNextEvent(IgnorableEventMask,
+					&theEvent, 1, NULL);
+			}
+			goto label_retry;
+		}
+
+		SndDisposeChannel(sndChannel, true);
+		sndChannel = NULL;
+	}
+
+#if dbglog_SoundStuff
+	dbglog_writeln("leave MySound_Stop");
+#endif
+}
+
+#define SOUND_SAMPLERATE rate22khz
+	/* = 0x56EE8BA3 = (7833600 * 2 / 704) << 16 */
+
+LOCALFUNC blnr MySound_Init(void)
+{
+#if dbglog_SoundStuff
+	dbglog_writeln("enter MySound_Init");
+#endif
+
+	cur_audio.fTheSoundBuffer = TheSoundBuffer;
+
+	cur_audio.fPlayOffset = &ThePlayOffset;
+	cur_audio.fFillOffset = &TheFillOffset;
+	cur_audio.fMinFilledSoundBuffs = &MinFilledSoundBuffs;
+	cur_audio.wantplaying = falseblnr;
+
+	/* Init basic per channel information */
+	cur_audio.soundHeader.sampleRate = SOUND_SAMPLERATE;
+		/* sample rate */
+	cur_audio.soundHeader.numChannels = 1; /* one channel */
+	cur_audio.soundHeader.loopStart = 0;
+	cur_audio.soundHeader.loopEnd = 0;
+	cur_audio.soundHeader.encode = cmpSH /* extSH */;
+	cur_audio.soundHeader.baseFrequency = kMiddleC;
+	cur_audio.soundHeader.numFrames =
+		(unsigned long)kOneBuffLen;
+	/* cur_audio.soundHeader.AIFFSampleRate = 0; */
+		/* unused */
+	cur_audio.soundHeader.markerChunk = nil;
+	cur_audio.soundHeader.futureUse2 = 0;
+	cur_audio.soundHeader.stateVars = nil;
+	cur_audio.soundHeader.leftOverSamples = nil;
+	cur_audio.soundHeader.compressionID = 0;
+		/* no compression */
+	cur_audio.soundHeader.packetSize = 0;
+		/* no compression */
+	cur_audio.soundHeader.snthID = 0;
+	cur_audio.soundHeader.sampleSize = (1 << kLn2SoundSampSz);
+		/* 8 or 16 bits per sample */
+	cur_audio.soundHeader.sampleArea[0] = 0;
+#if 3 == kLn2SoundSampSz
+	cur_audio.soundHeader.format = kSoundNotCompressed;
+#elif 4 == kLn2SoundSampSz
+	cur_audio.soundHeader.format = k16BitNativeEndianFormat;
+#else
+#error "unsupported kLn2SoundSampSz"
+#endif
+	cur_audio.soundHeader.samplePtr = (Ptr)TheSoundBuffer;
+
+	gCarbonSndPlayDoubleBufferCallBackUPP =
+		NewSndCallBackUPP(MySound_CallBack);
+	if (gCarbonSndPlayDoubleBufferCallBackUPP != NULL) {
+
+		MySound_Start();
+			/*
+				This should be taken care of by LeaveSpeedStopped,
+				but since takes a while to get going properly,
+				start early.
+			*/
+
+		return trueblnr;
+	}
+	return falseblnr;
+}
+
+GLOBALOSGLUPROC MySound_EndWrite(ui4r actL)
+{
+	if (MySound_EndWrite0(actL)) {
+	}
+}
+
+LOCALPROC MySound_SecondNotify(void)
+{
+	if (sndChannel != NULL) {
+		MySound_SecondNotify0();
+	}
+}
+
+#endif
+
+#if MayFullScreen
+LOCALPROC AdjustMachineGrab(void)
+{
+#if EnableFSMouseMotion
+	AdjustMouseMotionGrab();
+#endif
+#if 0
+	AdjustMainScreenGrab();
+#endif
+}
+#endif
+
+#if MayFullScreen
+LOCALPROC UngrabMachine(void)
+{
+	GrabMachine = falseblnr;
+	AdjustMachineGrab();
+}
+#endif
+
+/* --- basic dialogs --- */
+
+LOCALPROC NativeStrFromCStr(ps3p r, char *s, blnr AddEllipsis)
+{
+	int i;
+	int L;
+	ui3b ps[ClStrMaxLength];
+
+	ClStrFromSubstCStr(&L, ps, s);
+	if (AddEllipsis) {
+		ClStrAppendChar(&L, ps, kCellEllipsis);
+	}
+
+	if (L > 255) {
+		L = 255;
+	}
+
+	for (i = 0; i < L; ++i) {
+		r[i + 1] = Cell2MacAsciiMap[ps[i]];
+	}
+
+	r[0] = L;
+}
+
+#ifndef HogCPU
+#define HogCPU 1
+#endif
+
+#if HogCPU
+LOCALVAR long NoEventsCounter = 0;
+#endif
+
+LOCALVAR blnr gBackgroundFlag = falseblnr;
+LOCALVAR blnr gTrueBackgroundFlag = falseblnr;
+LOCALVAR blnr CurSpeedStopped = trueblnr;
+
+LOCALVAR blnr ADialogIsUp = falseblnr;
+
+LOCALPROC MyBeginDialog(void)
+{
+	DisconnectKeyCodes3();
+	ADialogIsUp = trueblnr;
+#if MayFullScreen
+	UngrabMachine();
+#endif
+}
+
+LOCALPROC MyEndDialog(void)
+{
+#if HogCPU
+	NoEventsCounter = 0;
+#endif
+	ADialogIsUp = falseblnr;
+	ReconnectKeyCodes3();
+}
+
+
+#define kMyStandardAlert 128
+
+LOCALPROC CheckSavedMacMsg(void)
+{
+	/*
+		This is currently only used in the
+		rare case where there is a message
+		still pending as the program quits.
+	*/
+	Str255 briefMsgp;
+	Str255 longMsgp;
+
+	if (nullpr != SavedBriefMsg) {
+		NativeStrFromCStr(briefMsgp, SavedBriefMsg, falseblnr);
+		NativeStrFromCStr(longMsgp, SavedLongMsg, falseblnr);
+#if AppearanceAvail
+		if (HaveAppearanceAvail()) {
+			AlertStdAlertParamRec param;
+			short itemHit;
+
+			param.movable = 0;
+			param.filterProc = nil;
+			param.defaultText = "\pOK";
+			param.cancelText = nil;
+			param.otherText = nil;
+			param.helpButton = false;
+			param.defaultButton = kAlertStdAlertOKButton;
+			param.cancelButton = 0;
+			param.position = kWindowDefaultPosition;
+
+			StandardAlert(
+				(SavedFatalMsg) ? kAlertStopAlert : kAlertCautionAlert,
+				briefMsgp, longMsgp, &param, &itemHit);
+		} else
+#endif
+		{
+			ParamText(briefMsgp, longMsgp, "\p", "\p");
+			if (SavedFatalMsg) {
+				while (StopAlert(kMyStandardAlert, NULL) != 1) {
+				}
+			} else {
+				while (CautionAlert(kMyStandardAlert, NULL) != 1) {
+				}
+			}
+			/* Alert (kMyStandardAlert, 0L); */
+		}
+
+		SavedBriefMsg = nullpr;
+	}
+}
+
+/* --- hide/show menubar --- */
+
+#if MayFullScreen
+#if MightNotHaveWindows85Avail
+LOCALVAR RgnHandle GrayRgnSave = NULL;
+LOCALVAR short mBarHeightSave;
+#endif
+#endif
+
+#if MayFullScreen
+LOCALPROC My_HideMenuBar(void)
+{
+#if Windows85APIAvail
+	if (HaveHideShowMenuAvail()) {
+		if (IsMenuBarVisible()) {
+			HideMenuBar();
+		}
+	} else
+#endif
+	{
+#if MightNotHaveWindows85Avail
+		if (NULL == GrayRgnSave) {
+			RgnHandle mBarRgn = NewRgn();
+			if (mBarRgn != NULL) {
+				GrayRgnSave = NewRgn();
+				if (GrayRgnSave != NULL) {
+					CopyRgn(My_GetGrayRgn(), GrayRgnSave);
+					RectRgn(mBarRgn, &qd.screenBits.bounds);
+					DiffRgn(mBarRgn, My_GetGrayRgn(), mBarRgn);
+						/*
+							menu bar rgn, plus corner areas
+							of main screen
+						*/
+					mBarHeightSave = My_LMGetMBarHeight();
+					LMSetMBarHeight(0);
+					UnionRgn(My_GetGrayRgn(), mBarRgn, My_GetGrayRgn());
+					PaintBehind(LMGetWindowList(), mBarRgn);
+					CalcVisBehind(LMGetWindowList(), mBarRgn);
+#if 0
+					controlStripHidden = false;
+					if (noErr == Gestalt(
+						gestaltControlStripVersion, &result))
+					{
+						if (SBIsControlStripVisible()) {
+							controlStripHidden = true;
+							SBShowHideControlStrip(false);
+						}
+					}
+#endif
+				}
+				DisposeRgn(mBarRgn);
+			}
+		}
+#endif
+	}
+}
+#endif
+
+#if MayFullScreen
+LOCALPROC My_ShowMenuBar(void)
+{
+#if Windows85APIAvail
+	if (HaveHideShowMenuAvail()) {
+		if (! IsMenuBarVisible()) {
+			ShowMenuBar();
+		}
+	} else
+#endif
+	{
+#if MightNotHaveWindows85Avail
+		if (GrayRgnSave != NULL) {
+			LMSetMBarHeight(mBarHeightSave);
+			CopyRgn(GrayRgnSave, My_GetGrayRgn());
+			/*
+				PaintBehind(LMGetWindowList(), GrayRgnSave);
+				CalcVisBehind(LMGetWindowList(), GrayRgnSave);
+			*/
+			DisposeRgn(GrayRgnSave);
+			DrawMenuBar();
+			GrayRgnSave = NULL;
+#if 0
+			if (controlStripHidden) {
+				controlStripHidden = falseblnr;
+				if (noErr ==
+					Gestalt(gestaltControlStripVersion, &result))
+				{
+					SBShowHideControlStrip(true);
+				}
+			}
+#endif
+		}
+#endif
+	}
+}
+#endif
+
+#if IncludePbufs
+LOCALVAR Handle PbufDat[NumPbufs];
+#endif
+
+#if IncludePbufs
+LOCALFUNC tMacErr PbufNewFromHandle(Handle h, ui5b count, tPbuf *r)
+{
+	tPbuf i;
+	tMacErr err;
+
+	if (! FirstFreePbuf(&i)) {
+		DisposeHandle(h);
+		err = mnvm_miscErr;
+	} else {
+		*r = i;
+		PbufDat[i] = h;
+		PbufNewNotify(i, count);
+		err = mnvm_noErr;
+	}
+
+	return err;
+}
+#endif
+
+#if IncludePbufs
+GLOBALOSGLUFUNC tMacErr PbufNew(ui5b count, tPbuf *r)
+{
+	Handle h;
+	tMacErr err = mnvm_miscErr;
+
+	h = NewHandleClear(count);
+	if (h != NULL) {
+		err = PbufNewFromHandle(h, count, r);
+	}
+
+	return err;
+}
+#endif
+
+#if IncludePbufs
+GLOBALOSGLUPROC PbufDispose(tPbuf i)
+{
+	DisposeHandle(PbufDat[i]);
+	PbufDisposeNotify(i);
+}
+#endif
+
+#if IncludePbufs
+LOCALPROC UnInitPbufs(void)
+{
+	tPbuf i;
+
+	for (i = 0; i < NumPbufs; ++i) {
+		if (PbufIsAllocated(i)) {
+			PbufDispose(i);
+		}
+	}
+}
+#endif
+
+#if IncludePbufs
+#define PbufHaveLock 1
+#endif
+
+#if IncludePbufs
+LOCALFUNC ui3p PbufLock(tPbuf i)
+{
+	ui3p p;
+
+	Handle h = PbufDat[i];
+
+	if (NULL == h) {
+		p = nullpr;
+	} else {
+		HLock(h);
+		p = (ui3p)*h;
+	}
+
+	return p;
+}
+#endif
+
+#if IncludePbufs
+LOCALPROC PbufUnlock(tPbuf i)
+{
+	HUnlock(PbufDat[i]);
+}
+#endif
+
+#if IncludePbufs
+GLOBALOSGLUPROC PbufTransfer(ui3p Buffer,
+	tPbuf i, ui5r offset, ui5r count, blnr IsWrite)
+{
+	Handle h = PbufDat[i];
+
+	HLock(h);
+	{
+		void *p = ((ui3p)*h) + offset;
+		if (IsWrite) {
+			BlockMove(Buffer, p, count);
+		} else {
+			BlockMove(p, Buffer, count);
+		}
+	}
+	HUnlock(h);
+}
+#endif
+
+/* --- clipboard --- */
+
+#if IncludeHostTextClipExchange
+GLOBALOSGLUFUNC tMacErr HTCEexport(tPbuf i)
+{
+	/*
+		PBuf i is an array of macintosh
+		style characters. (using the
+		MacRoman character set.)
+
+		Should export this Buffer to the
+		native clipboard, performing character
+		set translation, and eof character translation
+		as needed. (Not needed for this port.)
+
+		return 0 if it succeeds, nonzero (a
+		Macintosh style error code, but -1
+		will do) on failure.
+	*/
+	OSErr err;
+
+	err = ZeroScrap();
+	if (noErr == err) {
+		ui5b L = PbufSize[i];
+		Handle h = PbufDat[i];
+		HLock(h);
+		err = PutScrap(L, 'TEXT', *h);
+		HUnlock(h);
+	}
+
+	PbufDispose(i);
+
+	return (tMacErr)err;
+}
+#endif
+
+#if IncludeHostTextClipExchange
+GLOBALOSGLUFUNC tMacErr HTCEimport(tPbuf *r)
+{
+	/*
+		Import the native clipboard as text,
+		and convert it to Macintosh format,
+		in a Pbuf.
+
+		return 0 if it succeeds, nonzero (a
+		Macintosh style error code, but -1
+		will do) on failure.
+	*/
+
+	long off;
+	long v;
+	Handle h;
+	OSErr err = (OSErr)mnvm_miscErr;
+
+	h = NewHandle(0);
+	if (h != NULL) {
+		v = GetScrap(h, 'TEXT', &off);
+		if (v < 0) {
+			err = v;
+		} else {
+			err = (OSErr)PbufNewFromHandle(h, v, r);
+			h = NULL;
+		}
+		if (NULL != h) {
+			DisposeHandle(h);
+		}
+	}
+
+	return (tMacErr)err;
+}
+#endif
+
+/* --- drives --- */
+
+LOCALVAR short Drives[NumDrives]; /* open disk image files */
+#if (IncludeSonyGetName || IncludeSonyNew) && HaveCPUfamM68K
+LOCALVAR Handle DriveNames[NumDrives];
+#endif
+
+LOCALPROC InitDrives(void)
+{
+	/*
+		This isn't really needed, Drives[i] and DriveNames[i]
+		need not have valid values when not vSonyIsInserted[i].
+	*/
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		Drives[i] = NotAfileRef;
+#if (IncludeSonyGetName || IncludeSonyNew) && HaveCPUfamM68K
+		DriveNames[i] = NULL;
+#endif
+	}
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer,
+	tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count,
+	ui5r *Sony_ActCount)
+{
+	/*
+		return 0 if it succeeds, nonzero (a
+		Macintosh style error code, but -1
+		will do) on failure.
+	*/
+	tMacErr result;
+	ui5r NewSony_Count = Sony_Count;
+
+	result =
+		(tMacErr)SetFPos(Drives[Drive_No], fsFromStart, Sony_Start);
+	if (mnvm_noErr == result) {
+		if (IsWrite) {
+			/*
+				write Sony_Count bytes from Buffer, to disk image
+				number Drive_No, starting at offset Sony_Start.
+			*/
+
+			result = (tMacErr)FSWrite(Drives[Drive_No],
+				(long *)&NewSony_Count, Buffer);
+		} else {
+			/*
+				read Sony_Count bytes into Buffer, from disk image
+				number Drive_No, starting at offset Sony_Start.
+			*/
+
+			result = (tMacErr)FSRead(Drives[Drive_No],
+				(long *)&NewSony_Count, Buffer);
+		}
+	}
+
+	if (nullpr != Sony_ActCount) {
+		*Sony_ActCount = NewSony_Count;
+	}
+
+	return result;
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count)
+{
+	/*
+		set Sony_Count to the size of disk image number Drive_No.
+
+		return 0 if it succeeds, nonzero (a
+		Macintosh style error code, but -1
+		will do) on failure.
+	*/
+	return GetEOF(Drives[Drive_No], (long *)Sony_Count);
+}
+
+LOCALFUNC OSErr vSonyEject0(tDrive Drive_No)
+{
+	/*
+		close disk image number Drive_No.
+
+		return 0 if it succeeds, nonzero (a
+		Macintosh style error code, but -1
+		will do) on failure.
+	*/
+	short refnum = Drives[Drive_No];
+	Drives[Drive_No] = NotAfileRef; /* not really needed */
+
+	DiskEjectedNotify(Drive_No);
+
+#if (IncludeSonyGetName || IncludeSonyNew) && HaveCPUfamM68K
+	{
+		Handle h = DriveNames[Drive_No];
+		if (NULL != h) {
+			DisposeHandle(h);
+			DriveNames[Drive_No] = NULL; /* not really needed */
+		}
+	}
+#endif
+
+	return FSClose(refnum);
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
+{
+	OSErr result;
+	short vRefNum;
+	blnr DidEject = falseblnr;
+	short refnum = Drives[Drive_No];
+
+	result = GetVRefNum(refnum, &vRefNum);
+	if (noErr == result) {
+		DidEject = trueblnr;
+		result = vSonyEject0(Drive_No);
+		(void) FlushVol(NULL, vRefNum);
+	}
+
+	if (! DidEject) {
+		result = vSonyEject0(Drive_No);
+	}
+
+	return (tMacErr)result;
+}
+
+#if IncludeSonyNew
+GLOBALOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No)
+{
+	OSErr result;
+	Str255 s;
+	blnr DidEject = falseblnr;
+	short refnum = Drives[Drive_No];
+
+#if HaveCPUfamM68K
+	if (! HaveFSSpecCallsAvail()) {
+		Handle h = DriveNames[Drive_No];
+		if (NULL != h) {
+			short vRefNum;
+			result = GetVRefNum(refnum, &vRefNum);
+			if (noErr == result) {
+				PStrFromHandle(s, h, 255);
+				result = vSonyEject0(Drive_No);
+				DidEject = trueblnr;
+				(void) FSDelete(s, vRefNum);
+			}
+		}
+	} else
+#endif
+	{
+		FCBPBRec b;
+
+		b.ioCompletion = NULL;
+		b.ioNamePtr = (StringPtr)s;
+		b.ioVRefNum = 0;
+		b.ioRefNum = refnum;
+		b.ioFCBIndx = 0;
+		result = PBGetFCBInfoSync(&b);
+		if (noErr == result) {
+			FSSpec spec;
+			result = FSMakeFSSpec(b.ioFCBVRefNum, b.ioFCBParID,
+				s, &spec);
+			if (noErr == result) {
+				result = vSonyEject0(Drive_No);
+				DidEject = trueblnr;
+				(void) FSpDelete(&spec);
+			}
+		}
+	}
+
+	if (! DidEject) {
+		(void) vSonyEject0(Drive_No);
+	}
+
+	return (tMacErr)result;
+}
+#endif
+
+LOCALPROC UnInitDrives(void)
+{
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		if (vSonyIsInserted(i)) {
+			(void) vSonyEject(i);
+		}
+	}
+}
+
+#if IncludeSonyGetName
+GLOBALOSGLUFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r)
+{
+	FCBPBRec b;
+	Str255 s;
+	tMacErr err = mnvm_miscErr;
+
+#if HaveCPUfamM68K
+	if (! HaveFSSpecCallsAvail()) {
+		Handle h = DriveNames[Drive_No];
+		if (NULL != h) {
+			PStrFromHandle(s, h, 255);
+			err = mnvm_noErr;
+		}
+	} else
+#endif
+	{
+		b.ioCompletion = NULL;
+		b.ioNamePtr = (StringPtr)s;
+		b.ioVRefNum = 0;
+		b.ioRefNum = Drives[Drive_No];
+		b.ioFCBIndx = 0;
+		err = To_tMacErr(PBGetFCBInfoSync(&b));
+	}
+
+	if (mnvm_noErr == err) {
+		Handle h;
+		err = PStrToHand(s, &h);
+		if (noErr == err) {
+			err = PbufNewFromHandle(h, s[0], r);
+		}
+	}
+
+	return err;
+}
+#endif
+
+LOCALFUNC tMacErr Sony_Insert0(short refnum, blnr locked, ps3p s)
+{
+	/*
+		Given reference to open file, mount it as
+		a disk image file. if "locked", then mount
+		it as a locked disk.
+	*/
+
+	tDrive Drive_No;
+
+#if ! ((IncludeSonyGetName || IncludeSonyNew) && HaveCPUfamM68K)
+	UnusedParam(s);
+#endif
+
+	if (! FirstFreeDisk(&Drive_No)) {
+		(void) FSClose(refnum);
+		return mnvm_tmfoErr; /* too many files open */
+	} else {
+		Drives[Drive_No] = refnum;
+		DiskInsertNotify(Drive_No, locked);
+#if (IncludeSonyGetName || IncludeSonyNew) && HaveCPUfamM68K
+		if (s != NULL) {
+			Handle h;
+
+			if (mnvm_noErr != PStrToHand(s, &h)) {
+				h = NULL;
+			}
+			DriveNames[Drive_No] = h;
+		}
+#endif
+		return mnvm_noErr;
+	}
+}
+
+LOCALPROC ReportStandardOpenDiskError(tMacErr err)
+{
+	if (mnvm_noErr != err) {
+		if (mnvm_tmfoErr == err) {
+			MacMsg(kStrTooManyImagesTitle,
+				kStrTooManyImagesMessage, falseblnr);
+		} else if (mnvm_opWrErr == err) {
+			MacMsg(kStrImageInUseTitle,
+				kStrImageInUseMessage, falseblnr);
+		} else {
+			MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
+		}
+	}
+}
+
+LOCALFUNC tMacErr InsertADiskFromFileRef(FSSpec *spec)
+{
+	short refnum;
+	tMacErr err;
+	blnr locked = falseblnr;
+
+	err = To_tMacErr(FSpOpenDF(spec, fsRdWrPerm, &refnum));
+	switch (err) {
+		case mnvm_permErr:
+		case mnvm_wrPermErr:
+		case mnvm_afpAccessDenied:
+			locked = trueblnr;
+			err = To_tMacErr(FSpOpenDF(spec, fsRdPerm, &refnum));
+			break;
+		default:
+			break;
+	}
+	if (mnvm_noErr == err) {
+		err = Sony_Insert0(refnum, locked, NULL);
+	}
+
+	return err;
+}
+
+#if HaveCPUfamM68K
+LOCALFUNC tMacErr InsertADiskFromNamevRef(ConstStr255Param fileName,
+	short vRefNum)
+{
+	ParamBlockRec R;
+	tMacErr err;
+	blnr locked = falseblnr;
+
+	R.ioParam.ioCompletion = NULL;
+	R.ioParam.ioNamePtr = (StringPtr)fileName;
+	R.ioParam.ioVRefNum = vRefNum;
+	R.ioParam.ioVersNum = 0;
+	R.ioParam.ioPermssn = fsRdWrPerm;
+	R.ioParam.ioMisc = NULL;
+	err = To_tMacErr(PBOpen(&R, false));
+	switch (err) {
+		case mnvm_permErr:
+		case mnvm_wrPermErr:
+		case mnvm_afpAccessDenied:
+			locked = trueblnr;
+			R.ioParam.ioPermssn = fsRdPerm;
+			err = To_tMacErr(PBOpen(&R, false));
+			break;
+		default:
+			break;
+	}
+	if (mnvm_noErr == err) {
+		err = Sony_Insert0(R.ioParam.ioRefNum, locked, (ps3p)fileName);
+	}
+
+	return err;
+}
+#endif
+
+LOCALFUNC tMacErr LoadMacRomFromRefNum(short refnum)
+{
+	/*
+		load the ROM image file into ptr ROM
+	*/
+	tMacErr err;
+	long count = kROM_Size;
+
+	if (mnvm_noErr != (err = To_tMacErr(
+		FSRead(refnum, &count, ROM))))
+	{
+		if (mnvm_eofErr == err) {
+			MacMsgOverride(kStrShortROMTitle, kStrShortROMMessage);
+		} else {
+			MacMsgOverride(kStrNoReadROMTitle, kStrNoReadROMMessage);
+		}
+	} else
+	{
+		err = ROM_IsValid();
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr LoadMacRomFromFSSpec(FSSpec *spec)
+{
+	tMacErr err;
+	short refnum;
+
+	if (mnvm_noErr == (err =
+		To_tMacErr(FSpOpenDF(spec, fsRdPerm, &refnum))))
+	{
+		err = LoadMacRomFromRefNum(refnum);
+		(void) FSClose(refnum);
+	}
+
+	return err;
+}
+
+#if HaveCPUfamM68K
+LOCALFUNC tMacErr LoadMacRomFromNamevRef(ConstStr255Param fileName,
+	short vRefNum)
+{
+	tMacErr err;
+	ParamBlockRec R;
+
+	R.ioParam.ioCompletion = NULL;
+	R.ioParam.ioNamePtr = (StringPtr)fileName;
+	R.ioParam.ioVRefNum = vRefNum;
+	R.ioParam.ioVersNum = 0;
+	R.ioParam.ioPermssn = fsRdPerm;
+	R.ioParam.ioMisc = NULL;
+	if (mnvm_noErr == (err = To_tMacErr(PBOpen(&R, false)))) {
+		err = LoadMacRomFromRefNum(R.ioParam.ioRefNum);
+		(void) FSClose(R.ioParam.ioRefNum);
+	}
+
+	return err;
+}
+#endif
+
+#if HaveCPUfamM68K
+LOCALFUNC tMacErr InsertADiskFromNamevRef1(ConstStr255Param fileName,
+	short vRefNum)
+{
+	tMacErr err;
+
+	if (! ROM_loaded) {
+		err = LoadMacRomFromNamevRef(fileName, vRefNum);
+	} else {
+		err = InsertADiskFromNamevRef(fileName, vRefNum);
+	}
+
+	return err;
+}
+#endif
+
+LOCALFUNC tMacErr InsertADiskOrAliasFromSpec(FSSpec *spec,
+	blnr MaybeROM, blnr MaybeAlias)
+{
+	Boolean isFolder;
+	Boolean isAlias;
+	tMacErr err;
+
+	if ((! MaybeAlias)
+		|| CheckSaveMacErr(ResolveAliasFile(spec, true,
+			&isFolder, &isAlias)))
+	{
+		if (MaybeROM && ! ROM_loaded) {
+			err = LoadMacRomFromFSSpec(spec);
+		} else {
+			err = InsertADiskFromFileRef(spec);
+		}
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr InsertDisksFromDocList(AEDescList *docList)
+{
+	tMacErr err = mnvm_noErr;
+	long itemsInList;
+	long index;
+	AEKeyword keyword;
+	DescType typeCode;
+	FSSpec spec;
+	Size actualSize;
+
+	if (CheckSaveMacErr(AECountItems(docList, &itemsInList))) {
+		for (index = 1; index <= itemsInList; ++index) {
+			if (CheckSaveMacErr(AEGetNthPtr(docList, index, typeFSS,
+				&keyword, &typeCode, (Ptr)&spec, sizeof(FSSpec),
+				&actualSize)))
+			if (CheckSavetMacErr(InsertADiskOrAliasFromSpec(&spec,
+				trueblnr, falseblnr)))
+			{
+			}
+			if (mnvm_noErr != err) {
+				goto label_fail;
+			}
+		}
+	}
+
+label_fail:
+	return err;
+}
+
+LOCALFUNC tMacErr InsertADiskFromNameEtc(MyDir_R *d,
+	ConstStr255Param fileName)
+{
+	tMacErr err;
+
+#if HaveCPUfamM68K
+	if (! HaveFSSpecCallsAvail()) {
+		err = InsertADiskFromNamevRef(fileName, d->VRefNum);
+	} else
+#endif
+	{
+		FSSpec spec;
+
+		if (CheckSaveMacErr(
+			FSMakeFSSpec(d->VRefNum, d->DirId, fileName, &spec)))
+		{
+			err = InsertADiskOrAliasFromSpec(&spec,
+				falseblnr, trueblnr);
+		}
+	}
+
+	return err;
+}
+
+#if NavigationAvail
+pascal Boolean NavigationFilterProc(
+	AEDesc* theItem, void* info, void* NavCallBackUserData,
+	NavFilterModes theNavFilterModes);
+pascal Boolean NavigationFilterProc(
+	AEDesc* theItem, void* info, void* NavCallBackUserData,
+	NavFilterModes theNavFilterModes)
+{
+	Boolean display = true;
+	NavFileOrFolderInfo* theInfo = (NavFileOrFolderInfo*)info;
+	UnusedParam(theNavFilterModes);
+	UnusedParam(NavCallBackUserData);
+
+	if (typeFSS == theItem->descriptorType) {
+		if (! theInfo->isFolder) {
+			/*
+				use:
+					'theInfo->fileAndFolder.fileInfo.finderInfo.fdType'
+				to check for the file type you want to filter.
+			*/
+		}
+	}
+	return display;
+}
+#endif
+
+
+#if NavigationAvail
+pascal void NavigationEventProc(
+	NavEventCallbackMessage callBackSelector,
+	NavCBRecPtr callBackParms, void *NavCallBackUserData);
+pascal void NavigationEventProc(
+	NavEventCallbackMessage callBackSelector,
+	NavCBRecPtr callBackParms, void *NavCallBackUserData)
+{
+	UnusedParam(NavCallBackUserData);
+
+	if (kNavCBEvent == callBackSelector) {
+		switch (callBackParms->eventData.eventDataParms.event->what) {
+			case updateEvt:
+				{
+					WindowPtr which =
+						(WindowPtr)callBackParms
+							->eventData.eventDataParms.event
+							->message;
+
+					BeginUpdate(which);
+
+					if (which == gMyMainWindow) {
+						Update_Screen();
+					}
+
+					EndUpdate(which);
+				}
+				break;
+		}
+	}
+}
+#endif
+
+#define PStrConstBlank ((ps3p)"\000")
+
+LOCALPROC InsertADisk0(void)
+{
+#if NavigationAvail
+#define MyDisposeNavEventUPP(userUPP) \
+	DisposeRoutineDescriptor(userUPP)
+#define MyDisposeNavObjectFilterUPP(userUPP) \
+	DisposeRoutineDescriptor(userUPP)
+#define MyNewNavObjectFilterUPP NewNavObjectFilterProc
+#define MyNewNavEventUPP NewNavEventProc
+
+	if (HaveNavServicesAvail()) {
+		NavReplyRecord theReply;
+		NavDialogOptions dialogOptions;
+		OSErr theErr = noErr;
+		NavTypeListHandle openList = NULL;
+		NavObjectFilterUPP filterUPP =
+			MyNewNavObjectFilterUPP(
+				/* (NavObjectFilterProcPtr) */ NavigationFilterProc);
+		NavEventUPP eventUPP = MyNewNavEventUPP(
+			/* (NavEventProcPtr) */ NavigationEventProc);
+
+		theErr = NavGetDefaultDialogOptions(&dialogOptions);
+
+		dialogOptions.dialogOptionFlags |= kNavDontAutoTranslate;
+		/*
+			dialogOptions.dialogOptionFlags &= ~ kNavAllowMultipleFiles;
+		*/
+		dialogOptions.dialogOptionFlags &= ~ kNavAllowPreviews;
+
+		MyBeginDialog();
+		theErr = NavGetFile(NULL,
+						&theReply,
+						&dialogOptions,
+						/* NULL */ eventUPP,
+						NULL,
+						filterUPP,
+						(NavTypeListHandle)openList,
+						NULL);
+		MyEndDialog();
+
+		MyDisposeNavObjectFilterUPP(filterUPP);
+		MyDisposeNavEventUPP(eventUPP);
+
+
+		if (noErr == theErr) {
+			if (theReply.validRecord) {
+				ReportStandardOpenDiskError(InsertDisksFromDocList(
+					&theReply.selection));
+			}
+
+			NavDisposeReply(&theReply);
+		}
+
+	} else
+#endif
+#if HaveCPUfamM68K
+	if (! HaveFSSpecCallsAvail()) {
+		Point where;
+		SFReply reply;
+
+		where.h = 50;
+		where.v = 50;
+		MyBeginDialog();
+		SFGetFile(*(Point *)&where, PStrConstBlank, NULL,
+			-1 /* kNumFileTypes */, NULL /* fileTypes */,
+			NULL, &reply);
+		MyEndDialog();
+		if (reply.good) {
+			ReportStandardOpenDiskError(
+				InsertADiskFromNamevRef1(reply.fName, reply.vRefNum));
+		}
+	} else
+#endif
+	{
+		StandardFileReply reply;
+
+		MyBeginDialog();
+		StandardGetFile(0L, -1, 0L, &reply);
+		MyEndDialog();
+		if (reply.sfGood) {
+			ReportStandardOpenDiskError(
+				InsertADiskOrAliasFromSpec(&reply.sfFile,
+					trueblnr, falseblnr));
+		}
+	}
+}
+
+#ifndef MyAppIsBundle
+#define MyAppIsBundle 0
+#endif
+
+LOCALVAR MyDir_R MyDatDir;
+
+#if MyAppIsBundle
+LOCALFUNC blnr DirectorySpec2DirId(FSSpec *spec, long *dirID)
+{
+	CInfoPBRec b;
+
+	b.hFileInfo.ioCompletion = NULL;
+	b.hFileInfo.ioNamePtr = (StringPtr)spec->name;
+	b.hFileInfo.ioVRefNum = spec->vRefNum;
+	b.dirInfo.ioFDirIndex = 0;
+	b.dirInfo.ioDrDirID = spec->parID;
+	if (noErr == PBGetCatInfo(&b, false)) {
+		*dirID = b.dirInfo.ioDrDirID;
+		return trueblnr;
+	} else {
+		return falseblnr;
+	}
+}
+#endif
+
+#if MyAppIsBundle
+LOCALFUNC blnr FindNamedChildDirId(short TrueParentVol,
+	long ParentDirId, StringPtr ChildName,
+	short *TrueChildVol, long *ChildDirId)
+{
+
+	FSSpec temp_spec;
+	Boolean isFolder;
+	Boolean isAlias;
+
+	if (noErr == FSMakeFSSpec(TrueParentVol, ParentDirId,
+		ChildName, &temp_spec))
+	if (noErr == ResolveAliasFile(&temp_spec, true,
+		&isFolder, &isAlias))
+	if (isFolder)
+	if (DirectorySpec2DirId(&temp_spec, ChildDirId))
+	{
+		*TrueChildVol = temp_spec.vRefNum;
+		return trueblnr;
+	}
+	return falseblnr;
+}
+#endif
+
+LOCALFUNC blnr InitMyApplInfo(void)
+{
+#if HaveCPUfamM68K
+	if (! HaveFSSpecCallsAvail()) {
+		if (noErr == GetVol(NULL, &MyDatDir.VRefNum)) {
+			MyDatDir.DirId = 0;
+			return trueblnr;
+		}
+	} else
+#endif
+	{
+		FCBPBRec pb;
+		Str255 fileName;
+
+		pb.ioCompletion = NULL;
+		pb.ioNamePtr = fileName;
+		pb.ioVRefNum = 0;
+		pb.ioRefNum = CurResFile();
+		pb.ioFCBIndx = 0;
+		if (noErr == PBGetFCBInfoSync(&pb)) {
+			MyDatDir.VRefNum = pb.ioFCBVRefNum;
+			MyDatDir.DirId = pb.ioFCBParID;
+			return trueblnr;
+		}
+	}
+
+	return falseblnr;
+}
+
+LOCALFUNC tMacErr MyDirFromWD_v2(short VRefNum, MyDir_R *d)
+{
+	tMacErr err;
+	Str63 s;
+	WDPBRec pb;
+
+#if Support64kROM
+	if (Have64kROM()) {
+		d->VRefNum = VRefNum;
+		d->DirId = 0;
+		err = mnvm_noErr;
+	} else
+#endif
+	{
+		pb.ioCompletion = NULL;
+		pb.ioNamePtr = s;
+		pb.ioVRefNum = VRefNum;
+		pb.ioWDIndex = 0;
+		pb.ioWDProcID = 0;
+		err = To_tMacErr(PBGetWDInfoSync(&pb));
+		if (mnvm_noErr == err) {
+			d->VRefNum = pb.ioWDVRefNum;
+			d->DirId = pb.ioWDDirID;
+		}
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr FindPrefFolder(MyDir_R *d)
+{
+	tMacErr err;
+	long reply;
+
+	if (HaveGestaltAvail()
+		&& (noErr == Gestalt(gestaltFindFolderAttr, &reply))
+		&& TestBit(reply, gestaltFindFolderPresent)
+		)
+	{
+		err = To_tMacErr(FindFolder(
+			kOnSystemDisk,
+			kPreferencesFolderType,
+			kDontCreateFolder,
+			&d->VRefNum,
+			&d->DirId));
+	} else {
+		SysEnvRec info;
+
+		err = To_tMacErr(SysEnvirons(1, &info));
+		if (mnvm_noErr == err) {
+			err = MyDirFromWD_v2(info.sysVRefNum, d);
+		}
+	}
+
+	return err;
+}
+
+#define CatInfoIsFolder(cPB) \
+	(((cPB)->hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0)
+
+#define PStrLength(s) (*(s))
+#define SizeOfListMyChar(n) (n)
+#define PStrToTotSize(s) (SizeOfListMyChar(PStrLength(s) + 1))
+	/* + 1 for length byte */
+
+LOCALPROC PStrCopy(ps3p r, ps3p s)
+{
+	MyMoveBytes((anyp)s, (anyp)r, PStrToTotSize(s));
+}
+
+LOCALFUNC tMacErr MyFindNamedChildDir_v2(MyDir_R *src_d, StringPtr s,
+	MyDir_R *dst_d)
+{
+	tMacErr err;
+	Str255 NameBuffer;
+	CInfoPBRec cPB;
+
+	cPB.hFileInfo.ioCompletion = NULL;
+	cPB.hFileInfo.ioVRefNum = src_d->VRefNum;
+	cPB.dirInfo.ioDrDirID = src_d->DirId;
+	cPB.hFileInfo.ioNamePtr = NameBuffer;
+	PStrCopy(NameBuffer, s);
+	cPB.dirInfo.ioFDirIndex = 0;
+
+	err = To_tMacErr(PBGetCatInfoSync(&cPB));
+
+	if (mnvm_noErr == err) {
+		if (! CatInfoIsFolder(&cPB)) {
+			err = mnvm_dirNFErr;
+		} else {
+			dst_d->VRefNum = cPB.hFileInfo.ioVRefNum;
+			dst_d->DirId = cPB.dirInfo.ioDrDirID;
+		}
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr MyResolveAliasDir_v2(MyDir_R *src_d, StringPtr s,
+	MyDir_R *dst_d)
+{
+	tMacErr err;
+	FSSpec spec;
+	Boolean isFolder;
+	Boolean isAlias;
+	MyDir_R src2_d;
+
+	spec.vRefNum = src_d->VRefNum;
+	spec.parID = src_d->DirId;
+	PStrCopy(spec.name, s);
+	err = To_tMacErr(
+		ResolveAliasFile(&spec, true, &isFolder, &isAlias));
+	if (mnvm_noErr == err) {
+		if (! isAlias) {
+			err = mnvm_dirNFErr;
+		} else {
+			src2_d.VRefNum = spec.vRefNum;
+			src2_d.DirId = spec.parID;
+			err = MyFindNamedChildDir_v2(&src2_d, spec.name, dst_d);
+		}
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr MyResolveNamedChildDir_v2(MyDir_R *src_d, StringPtr s,
+	MyDir_R *dst_d)
+{
+	tMacErr err;
+
+	err = MyFindNamedChildDir_v2(src_d, s, dst_d);
+	if (mnvm_dirNFErr == err) {
+		if (HaveAliasMgrAvail()) {
+			err = MyResolveAliasDir_v2(src_d, s, dst_d);
+		}
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr OpenNamedFileInFolderCStr(MyDir_R *d,
+	char *s, short *refnum)
+{
+	Str255 fileName;
+
+	PStrFromCStr(fileName, s);
+	return OpenNamedFileInFolder(d, fileName, refnum);
+}
+
+LOCALFUNC tMacErr MyResolveNamedChildDirCStr(MyDir_R *src_d,
+	char *s, MyDir_R *dst_d)
+{
+	Str255 fileName;
+
+	PStrFromCStr(fileName, s);
+	return MyResolveNamedChildDir_v2(src_d, fileName, dst_d);
+}
+
+LOCALFUNC tMacErr LoadMacRomFromNameFolder(MyDir_R *d,
+	char *s)
+{
+	tMacErr err;
+	short refnum;
+
+	if (mnvm_noErr == (err =
+		OpenNamedFileInFolderCStr(d, s, &refnum)))
+	{
+		err = LoadMacRomFromRefNum(refnum);
+		(void) FSClose(refnum);
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr LoadMacRomFromPrefDir(void)
+{
+	tMacErr err;
+	MyDir_R PrefRef;
+	MyDir_R GryphelRef;
+	MyDir_R ROMsRef;
+
+	if (mnvm_noErr == (err = FindPrefFolder(&PrefRef)))
+	if (mnvm_noErr == (err = MyResolveNamedChildDirCStr(&PrefRef,
+		"Gryphel", &GryphelRef)))
+	if (mnvm_noErr == (err = MyResolveNamedChildDirCStr(&GryphelRef,
+		"mnvm_rom", &ROMsRef)))
+	if (mnvm_noErr == (err = LoadMacRomFromNameFolder(&ROMsRef,
+		RomFileName)))
+	{
+		/* ok */
+	}
+
+	return err;
+}
+
+LOCALFUNC blnr LoadMacRom(void)
+{
+	tMacErr err;
+
+	if (mnvm_fnfErr == (err =
+		LoadMacRomFromNameFolder(&MyDatDir, RomFileName)))
+	if (mnvm_fnfErr == (err =
+		LoadMacRomFromPrefDir()))
+	{
+	}
+
+	return trueblnr; /* keep launching Mini vMac, regardless */
+}
+
+LOCALFUNC blnr Sony_InsertIth(int i)
+{
+	if ((i > 9) || ! FirstFreeDisk(nullpr)) {
+		return falseblnr;
+	} else {
+		Str255 s;
+		tMacErr err = mnvm_noErr;
+
+		PStrFromCStr(s, "disk?.dsk");
+
+		s[5] = '0' + i;
+		if (! CheckSavetMacErr(InsertADiskFromNameEtc(&MyDatDir, s))) {
+			if (mnvm_fnfErr != err) {
+				ReportStandardOpenDiskError(err);
+			}
+			return falseblnr;
+		}
+
+		return trueblnr;
+	}
+}
+
+LOCALFUNC blnr LoadInitialImages(void)
+{
+	int i;
+
+	for (i = 1; Sony_InsertIth(i); ++i) {
+		/* stop on first error (including file not found) */
+	}
+
+	return trueblnr;
+}
+
+#if IncludeSonyNew
+LOCALFUNC tMacErr WriteZero(SInt16 refnum, ui5b L)
+{
+#define ZeroBufferSize 2048
+	tMacErr err;
+	ui5b i;
+	ui3b buffer[ZeroBufferSize];
+
+	if (CheckSaveMacErr(SetFPos(refnum, fsFromStart, 0))) {
+
+		for (i = 0; i < ZeroBufferSize; ++i) {
+			buffer[i] = 0;
+		}
+		while (L > 0) {
+			i = (L > ZeroBufferSize) ? ZeroBufferSize : L;
+			err = To_tMacErr(FSWrite(refnum, (long *)&i, buffer));
+			if (mnvm_noErr != err) {
+				goto label_fail;
+			}
+			L -= i;
+		}
+	}
+
+label_fail:
+	return err;
+}
+#endif
+
+#if HaveCPUfamM68K && IncludeSonyNew
+LOCALPROC MakeNewDiskFromNamevRef(ps3p Name, short vRefNum,
+	ui5b L)
+{
+	short refNum;
+	tMacErr err;
+
+	err = To_tMacErr(Create(Name, vRefNum, '????', '????'));
+	if (mnvm_dupFNErr == err) {
+		if (CheckSaveMacErr(FSDelete(Name, vRefNum))) {
+			err = To_tMacErr(Create(Name, vRefNum, '????', '????'));
+		}
+	}
+	if (mnvm_noErr == err) {
+		if (CheckSaveMacErr(FSOpen(Name, vRefNum, &refNum))) {
+			if (CheckSaveMacErr(SetEOF(refNum, L))) {
+				if (CheckSavetMacErr(WriteZero(refNum, L))) {
+					err = Sony_Insert0(refNum, falseblnr, Name);
+					ReportStandardOpenDiskError(err);
+					refNum = NotAfileRef;
+				}
+			}
+			if (NotAfileRef != refNum) {
+				(void) FSClose(refNum);
+			}
+		}
+		if (mnvm_noErr != err) {
+			(void) FSDelete(Name, vRefNum);
+		}
+	}
+}
+#endif
+
+#if IncludeSonyNew
+LOCALPROC MakeNewDiskFromSpec(FSSpec *NewFileSpec,
+	ui5b L)
+{
+	short refNum;
+	tMacErr err;
+
+	err = To_tMacErr(FSpCreate(NewFileSpec,
+		'????', '????', smSystemScript));
+	if (mnvm_dupFNErr == err) {
+		err = To_tMacErr(FSpDelete(NewFileSpec));
+		if (mnvm_noErr == err) {
+			err = To_tMacErr(FSpCreate(NewFileSpec,
+				'????', '????', smSystemScript));
+		}
+	}
+	if (mnvm_noErr == err) {
+		if (CheckSaveMacErr(
+			FSpOpenDF(NewFileSpec, fsRdWrPerm, &refNum)))
+		{
+			if (CheckSaveMacErr(SetEOF(refNum, L))) {
+				if (CheckSavetMacErr(WriteZero(refNum, L))) {
+					err = Sony_Insert0(refNum, falseblnr, NULL);
+					ReportStandardOpenDiskError(err);
+					refNum = NotAfileRef;
+				}
+			}
+			if (NotAfileRef != refNum) {
+				(void) FSClose(refNum);
+			}
+		}
+		if (mnvm_noErr != err) {
+			(void) FSpDelete(NewFileSpec);
+		}
+	}
+}
+#endif
+
+#if UseActvFile || (IncludeSonyNew && ! SaveDialogEnable)
+LOCALFUNC tMacErr MyMakeNamedDir_v2(MyDir_R *d, StringPtr s,
+	MyDir_R *new_d)
+{
+	tMacErr err;
+	HParamBlockRec r;
+
+	r.fileParam.ioCompletion = NULL;
+	r.fileParam.ioVRefNum = d->VRefNum;
+	r.fileParam.ioDirID = d->DirId;
+	r.fileParam.ioNamePtr = s;
+	err = To_tMacErr(PBDirCreateSync(&r));
+	if (mnvm_noErr == err) {
+		new_d->VRefNum = d->VRefNum;
+		new_d->DirId = r.fileParam.ioDirID;
+	}
+
+	return err;
+}
+#endif
+
+#if UseActvFile || (IncludeSonyNew && ! SaveDialogEnable)
+LOCALFUNC tMacErr FindOrMakeMakeNamedDir_v2(MyDir_R *new_d,
+	MyDir_R *d, StringPtr s)
+{
+	tMacErr err;
+
+	err = MyResolveNamedChildDir_v2(d, s, new_d);
+	if (mnvm_fnfErr == err) {
+		err = MyMakeNamedDir_v2(d, s, new_d);
+	}
+
+	return err;
+}
+#endif
+
+#if UseActvFile || (IncludeSonyNew && ! SaveDialogEnable)
+LOCALFUNC tMacErr FindOrMakeChildDirCStr(MyDir_R *new_d,
+	MyDir_R *d, char *name)
+{
+	Str255 s;
+
+	PStrFromCStr(s, name);
+	return FindOrMakeMakeNamedDir_v2(new_d, d, s);
+}
+#endif
+
+#if IncludeSonyNew
+LOCALPROC MakeNewDisk(ui5b L, Handle NewDiskName)
+{
+#if SaveDialogEnable
+	OSErr theErr;
+
+#if NavigationAvail
+	if (HaveNavServicesAvail()) {
+		NavReplyRecord theReply;
+		NavDialogOptions dialogOptions;
+		NavEventUPP eventUPP = MyNewNavEventUPP(
+			/* (NavEventProcPtr) */ NavigationEventProc);
+
+		theErr = NavGetDefaultDialogOptions(&dialogOptions);
+		dialogOptions.dialogOptionFlags |= kNavNoTypePopup;
+#if IncludeSonyNameNew
+		if (NewDiskName != NULL) {
+			PStrFromHandle(dialogOptions.savedFileName,
+				NewDiskName, 255);
+		}
+#endif
+		MyBeginDialog();
+		theErr = NavPutFile(NULL, &theReply, &dialogOptions,
+			/* NULL */ eventUPP, '????', '????', NULL);
+		MyEndDialog();
+
+		MyDisposeNavEventUPP(eventUPP);
+
+		if (noErr == theErr) {
+			if (theReply.validRecord) {
+				long itemsInList;
+				AEKeyword keyword;
+				DescType typeCode;
+				Size actualSize;
+				FSSpec NewFileSpec;
+
+				if (noErr ==
+					AECountItems(&theReply.selection, &itemsInList))
+				if (1 == itemsInList)
+				if (noErr == AEGetNthPtr(&theReply.selection,
+					1, typeFSS, &keyword, &typeCode,
+					(Ptr)&NewFileSpec, sizeof(FSSpec), &actualSize))
+				{
+					MakeNewDiskFromSpec(&NewFileSpec, L);
+				}
+			}
+			NavDisposeReply(&theReply);
+		}
+	} else
+#endif
+	{
+		Str255 Title;
+		Str255 prompt;
+
+#if IncludeSonyNameNew
+		if (NewDiskName != NULL) {
+			PStrFromHandle(Title, NewDiskName, 255);
+		} else
+#endif
+		{
+			NativeStrFromCStr(Title, "untitled", falseblnr);
+		}
+		NativeStrFromCStr(prompt, "Please select a file", falseblnr);
+
+#if HaveCPUfamM68K
+		if (! HaveFSSpecCallsAvail()) {
+			Point where;
+			SFReply reply;
+
+			where.h = 50;
+			where.v = 50;
+			MyBeginDialog();
+			SFPutFile(*(Point *)&where, prompt, Title, NULL, &reply);
+			MyEndDialog();
+
+			if (reply.good) {
+				MakeNewDiskFromNamevRef(reply.fName,
+					reply.vRefNum, L);
+			}
+		} else
+#endif
+		{
+			StandardFileReply reply;
+
+			MyBeginDialog();
+			StandardPutFile(prompt, Title, &reply);
+			MyEndDialog();
+
+			if (reply.sfGood) {
+				MakeNewDiskFromSpec(&reply.sfFile, L);
+			}
+		}
+	}
+#else /* SaveDialogEnable */
+	tMacErr err;
+	Str255 Title;
+	MyDir_R OutDir;
+	FSSpec spec;
+
+#if IncludeSonyNameNew
+	if (NewDiskName != NULL) {
+		PStrFromHandle(Title, NewDiskName, 255);
+	} else
+#endif
+	{
+		NativeStrFromCStr(Title, "untitled", falseblnr);
+	}
+
+	if (mnvm_noErr == (err = FindOrMakeChildDirCStr(&OutDir,
+		&MyDatDir, "out")))
+	{
+#if HaveCPUfamM68K
+		if (! HaveFSSpecCallsAvail()) {
+			MakeNewDiskFromNamevRef(Title, OutDir.VRefNum, L);
+		} else
+#endif
+		{
+			err = To_tMacErr(FSMakeFSSpec(OutDir.VRefNum, OutDir.DirId,
+				Title, &spec));
+			if ((mnvm_noErr == err) || (mnvm_fnfErr == err)) {
+				MakeNewDiskFromSpec(&spec, L);
+			}
+		}
+	}
+#endif /* SaveDialogEnable */
+}
+#endif
+
+#if UseActvFile
+
+LOCALFUNC tMacErr MyCreateFile_v2(MyDir_R *d, StringPtr s)
+{
+	tMacErr err;
+	HParamBlockRec r;
+
+	r.fileParam.ioFlVersNum = 0;
+		/*
+			Think reference says to do this,
+			but not Inside Mac IV
+		*/
+
+	r.fileParam.ioCompletion = NULL;
+	r.fileParam.ioNamePtr = s;
+	r.fileParam.ioVRefNum = d->VRefNum;
+	r.fileParam.ioFVersNum = 0; /* needed if MFS volume */
+
+#if Support64kROM
+	if (Have64kROM()) {
+		err = To_tMacErr(PBCreateSync((ParamBlockRec *)&r));
+	} else
+#endif
+	{
+		r.fileParam.ioDirID = d->DirId;
+		err = To_tMacErr(PBHCreateSync(&r));
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr MyDeleteFile_v2(MyDir_R *d, StringPtr s)
+{
+	tMacErr err;
+	HParamBlockRec r;
+
+	r.fileParam.ioCompletion = NULL;
+	r.fileParam.ioVRefNum = d->VRefNum;
+	r.fileParam.ioNamePtr = s;
+	r.fileParam.ioFVersNum = 0; /* needed if MFS volume */
+
+#if Support64kROM
+	if (Have64kROM()) {
+		err = To_tMacErr(PBDeleteSync((ParamBlockRec *)&r));
+	} else
+#endif
+	{
+		r.fileParam.ioDirID = d->DirId;
+		err = To_tMacErr(PBHDeleteSync(&r));
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr MyCreateFileOverWrite_v2(MyDir_R *d, StringPtr s)
+{
+	tMacErr err;
+
+	err = MyCreateFile_v2(d, s);
+	if (mnvm_dupFNErr == err) {
+		if (mnvm_noErr == (err = MyDeleteFile_v2(d, s))) {
+			err = MyCreateFile_v2(d, s);
+		}
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr MyFileOpen_v2(MyDir_R *d, StringPtr s,
+	char Permssn, short *refnum)
+{
+	tMacErr err;
+	HParamBlockRec r;
+
+	r.ioParam.ioCompletion = NULL;
+	r.ioParam.ioNamePtr = s;
+	r.ioParam.ioVRefNum = d->VRefNum;
+	r.ioParam.ioPermssn = Permssn;
+	r.ioParam.ioMisc = 0; /* use volume buffer */
+	r.ioParam.ioVersNum = 0; /* needed if MFS volume */
+
+#if Support64kROM
+	if (Have64kROM()) {
+		err = To_tMacErr(PBOpenSync((ParamBlockRec *)&r));
+	} else
+#endif
+	{
+		r.fileParam.ioDirID = d->DirId;
+		err = To_tMacErr(PBHOpenSync(&r));
+	}
+
+	if (noErr == err) {
+		*refnum = r.ioParam.ioRefNum;
+		/*
+			Don't change *refnum unless file opened,
+			so can initialize to NotAfileRef, and
+			compare later before closing in uninit.
+		*/
+	}
+	return err;
+}
+
+LOCALFUNC tMacErr MyFileOpenWrite_v2(MyDir_R *d, StringPtr s,
+	short *refnum)
+{
+	return MyFileOpen_v2(d, s, (char)fsWrPerm, refnum);
+}
+
+LOCALFUNC tMacErr MyOpenOverWriteFile_v2(MyDir_R *d, StringPtr s,
+	short *refnum)
+{
+	tMacErr err;
+
+	err = MyCreateFileOverWrite_v2(d, s);
+	if (mnvm_noErr == err) {
+		err = MyFileOpenWrite_v2(d, s, refnum);
+
+		if (mnvm_noErr != err) {
+			(void) MyDeleteFile_v2(d, s);
+				/* ignore any error, since already got one */
+		}
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr MyOpenOverWriteFileCStr(MyDir_R *d, char *name,
+	short *refnum)
+{
+	Str255 s;
+
+	PStrFromCStr(s, name);
+	return MyOpenOverWriteFile_v2(d, s, refnum);
+}
+
+#define ActvCodeFileName "act_1"
+
+LOCALFUNC tMacErr OpenActvCodeFile(short *refnum)
+{
+	tMacErr err;
+	MyDir_R PrefRef;
+	MyDir_R GryphelRef;
+	MyDir_R ActRef;
+
+	if (mnvm_noErr == (err = FindPrefFolder(&PrefRef)))
+	if (mnvm_noErr == (err = MyResolveNamedChildDirCStr(&PrefRef,
+		"Gryphel", &GryphelRef)))
+	if (mnvm_noErr == (err = MyResolveNamedChildDirCStr(&GryphelRef,
+		"mnvm_act", &ActRef)))
+	if (mnvm_noErr == (err = OpenNamedFileInFolderCStr(&ActRef,
+		ActvCodeFileName, refnum)))
+	{
+		/* ok */
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr ActvCodeFileLoad(ui3p p)
+{
+	tMacErr err;
+	short refnum;
+
+	if (CheckSavetMacErr(OpenActvCodeFile(&refnum))) {
+		long count = ActvCodeFileLen;
+		err = To_tMacErr(FSRead(refnum, &count, p));
+		(void) FSClose(refnum);
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr ActvCodeFileSave(ui3p p)
+{
+	tMacErr err;
+	short refnum;
+	MyDir_R PrefRef;
+	MyDir_R GryphelRef;
+	MyDir_R ActRef;
+	long count = ActvCodeFileLen;
+
+	if (mnvm_noErr == (err = FindPrefFolder(&PrefRef)))
+	if (mnvm_noErr == (err = FindOrMakeChildDirCStr(&GryphelRef,
+		&PrefRef, "Gryphel")))
+	if (mnvm_noErr == (err = FindOrMakeChildDirCStr(&ActRef,
+		&GryphelRef, "mnvm_act")))
+	if (mnvm_noErr == (err = MyOpenOverWriteFileCStr(&ActRef,
+		ActvCodeFileName, &refnum)))
+	{
+		err = To_tMacErr(FSWrite(refnum, &count, p));
+		(void) FSClose(refnum);
+	}
+
+	return err;
+	/* return mnvm_miscErr; */
+}
+
+#endif /* UseActvFile */
+
+#define openOnly 1
+#define openPrint 2
+
+LOCALFUNC blnr GotRequiredParams(AppleEvent *theAppleEvent)
+{
+	DescType typeCode;
+	Size actualSize;
+	OSErr theErr;
+
+	theErr = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr,
+				typeWildCard, &typeCode, NULL, 0, &actualSize);
+	if (errAEDescNotFound == theErr) { /* No more required params. */
+		return trueblnr;
+	} else if (noErr == theErr) { /* More required params! */
+		return /* CheckSysCode(errAEEventNotHandled) */ falseblnr;
+	} else { /* Unexpected Error! */
+		return /* CheckSysCode(theErr) */ falseblnr;
+	}
+}
+
+LOCALFUNC blnr GotRequiredParams0(AppleEvent *theAppleEvent)
+{
+	DescType typeCode;
+	Size actualSize;
+	OSErr theErr;
+
+	theErr = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr,
+				typeWildCard, &typeCode, NULL, 0, &actualSize);
+	if (errAEDescNotFound == theErr) { /* No more required params. */
+		return trueblnr;
+	} else if (noErr == theErr) { /* More required params! */
+		return trueblnr; /* errAEEventNotHandled; */ /*^*/
+	} else { /* Unexpected Error! */
+		return /* CheckSysCode(theErr) */ falseblnr;
+	}
+}
+
+/* call back */ static pascal OSErr OpenOrPrintFiles(
+	AppleEvent *theAppleEvent, AppleEvent *reply, long aRefCon)
+{
+	/*
+		Adapted from IM VI: AppleEvent Manager:
+		Handling Required AppleEvents
+	*/
+	AEDescList docList;
+
+	UnusedParam(reply);
+	UnusedParam(aRefCon);
+	/* put the direct parameter (a list of descriptors) into docList */
+	if (noErr == (AEGetParamDesc(theAppleEvent,
+		keyDirectObject, typeAEList, &docList)))
+	{
+		if (GotRequiredParams0(theAppleEvent)) {
+			/* Check for missing required parameters */
+			/* printIt = (openPrint == aRefCon) */
+			ReportStandardOpenDiskError(
+				InsertDisksFromDocList(&docList));
+		}
+		/* vCheckSysCode */ (void) (AEDisposeDesc(&docList));
+	}
+	return /* GetASysResultCode() */ 0;
+}
+
+/* call back */ static pascal OSErr DoOpenEvent(
+	AppleEvent *theAppleEvent, AppleEvent *reply, long aRefCon)
+/*
+	This is the alternative to getting an
+	open document event on startup.
+*/
+{
+	UnusedParam(reply);
+	UnusedParam(aRefCon);
+	if (GotRequiredParams0(theAppleEvent)) {
+	}
+	return /* GetASysResultCode() */ 0;
+		/* Make sure there are no additional "required" parameters. */
+}
+
+
+/* call back */ static pascal OSErr DoQuitEvent(
+	AppleEvent *theAppleEvent, AppleEvent *reply, long aRefCon)
+{
+	UnusedParam(reply);
+	UnusedParam(aRefCon);
+	if (GotRequiredParams(theAppleEvent)) {
+		RequestMacOff = trueblnr;
+	}
+
+	return /* GetASysResultCode() */ 0;
+}
+
+#define MyNewAEEventHandlerUPP NewAEEventHandlerProc
+
+LOCALFUNC blnr MyInstallEventHandler(AEEventClass theAEEventClass,
+	AEEventID theAEEventID, ProcPtr p,
+	long handlerRefcon, blnr isSysHandler)
+{
+	return noErr == (AEInstallEventHandler(theAEEventClass,
+		theAEEventID,
+#if /* useUPP */ 1
+		MyNewAEEventHandlerUPP((AEEventHandlerProcPtr)p),
+#else
+		(AEEventHandlerUPP)p,
+#endif
+		handlerRefcon, isSysHandler));
+}
+
+LOCALPROC InstallAppleEventHandlers(void)
+{
+	if (noErr == AESetInteractionAllowed(kAEInteractWithLocal))
+	if (MyInstallEventHandler(kCoreEventClass, kAEOpenApplication,
+		(ProcPtr)DoOpenEvent, 0, falseblnr))
+	if (MyInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
+		(ProcPtr)OpenOrPrintFiles, openOnly, falseblnr))
+	if (MyInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
+		(ProcPtr)OpenOrPrintFiles, openPrint, falseblnr))
+	if (MyInstallEventHandler(kCoreEventClass, kAEQuitApplication,
+		(ProcPtr)DoQuitEvent, 0, falseblnr))
+	{
+	}
+}
+
+#if EnableDragDrop
+static pascal OSErr GlobalTrackingHandler(short message,
+	WindowRef pWindow, void *handlerRefCon, DragReference theDragRef)
+{
+	RgnHandle hilightRgn;
+	Rect Bounds;
+
+	UnusedParam(pWindow);
+	UnusedParam(handlerRefCon);
+	if (! ADialogIsUp) {
+		switch(message) {
+			case kDragTrackingEnterWindow:
+				hilightRgn = NewRgn();
+				if (hilightRgn != NULL) {
+					SetScrnRectFromCoords(&Bounds,
+						0, 0, vMacScreenHeight, vMacScreenWidth);
+					RectRgn(hilightRgn, &Bounds);
+					ShowDragHilite(theDragRef, hilightRgn, true);
+					DisposeRgn(hilightRgn);
+				}
+				break;
+			case kDragTrackingLeaveWindow:
+				HideDragHilite(theDragRef);
+				break;
+		}
+	}
+
+	return noErr;
+}
+#endif
+
+#if EnableDragDrop
+static DragTrackingHandlerUPP gGlobalTrackingHandler = NULL;
+#endif
+
+#if EnableDragDrop
+static pascal OSErr GlobalReceiveHandler(WindowRef pWindow,
+	void *handlerRefCon, DragReference theDragRef)
+{
+	unsigned short items;
+	unsigned short index;
+	ItemReference theItem;
+	Size SentSize;
+	HFSFlavor r;
+
+	UnusedParam(pWindow);
+	UnusedParam(handlerRefCon);
+	if (! ADialogIsUp)
+	if (noErr == CountDragItems(theDragRef, &items))
+	{
+		for (index = 1; index <= items; ++index) {
+			if (noErr == GetDragItemReferenceNumber(theDragRef,
+				index, &theItem))
+			if (noErr == GetFlavorDataSize(theDragRef,
+				theItem, flavorTypeHFS, &SentSize))
+				/*
+					On very old macs SentSize might only be big enough
+					to hold the actual file name. Have not seen this
+					in OS X, but still leave the check
+					as '<=' instead of '=='.
+				*/
+			if (SentSize <= sizeof(HFSFlavor))
+			if (noErr == GetFlavorData(theDragRef, theItem,
+				flavorTypeHFS, (Ptr)&r, &SentSize, 0))
+			{
+				ReportStandardOpenDiskError(
+					InsertADiskOrAliasFromSpec(&r.fileSpec,
+						trueblnr, trueblnr));
+			}
+		}
+
+		if (gTrueBackgroundFlag) {
+			ProcessSerialNumber currentProcess = {0, kCurrentProcess};
+
+			(void) SetFrontProcess(&currentProcess);
+
+			WantCmdOptOnReconnect = trueblnr;
+		}
+	}
+
+	return noErr;
+}
+#endif
+
+#if EnableDragDrop
+static DragReceiveHandlerUPP gGlobalReceiveHandler = NULL;
+#endif
+
+#if EnableDragDrop
+#define MyNewDragTrackingHandlerUPP NewDragTrackingHandlerProc
+#define MyNewDragReceiveHandlerUPP NewDragReceiveHandlerProc
+#if ! OPAQUE_UPP_TYPES
+#define MyDisposeDragReceiveHandlerUPP(userUPP) \
+	DisposeRoutineDescriptor(userUPP)
+#define MyDisposeDragTrackingHandlerUPP(userUPP) \
+	DisposeRoutineDescriptor(userUPP)
+#else
+#define MyDisposeDragReceiveHandlerUPP DisposeDragReceiveHandlerUPP
+#define MyDisposeDragTrackingHandlerUPP DisposeDragTrackingHandlerUPP
+#endif
+#endif
+
+#if EnableDragDrop
+LOCALPROC UnPrepareForDragging(void)
+{
+	if (NULL != gGlobalReceiveHandler) {
+		RemoveReceiveHandler(gGlobalReceiveHandler, gMyMainWindow);
+		MyDisposeDragReceiveHandlerUPP(gGlobalReceiveHandler);
+		gGlobalReceiveHandler = NULL;
+	}
+	if (NULL != gGlobalTrackingHandler) {
+		RemoveTrackingHandler(gGlobalTrackingHandler, gMyMainWindow);
+		MyDisposeDragTrackingHandlerUPP(gGlobalTrackingHandler);
+		gGlobalTrackingHandler = NULL;
+	}
+}
+#endif
+
+#if EnableDragDrop
+LOCALFUNC blnr PrepareForDragging(void)
+{
+	blnr IsOk = falseblnr;
+
+	gGlobalTrackingHandler = MyNewDragTrackingHandlerUPP(
+		GlobalTrackingHandler);
+	if (gGlobalTrackingHandler != NULL) {
+		gGlobalReceiveHandler = MyNewDragReceiveHandlerUPP(
+			GlobalReceiveHandler);
+		if (gGlobalReceiveHandler != NULL) {
+			if (noErr == InstallTrackingHandler(gGlobalTrackingHandler,
+				gMyMainWindow, nil))
+			{
+				if (noErr == InstallReceiveHandler(
+					gGlobalReceiveHandler, gMyMainWindow, nil))
+				{
+					IsOk = trueblnr;
+				}
+			}
+		}
+	}
+
+	return IsOk;
+}
+#endif
+
+#if EnableMagnify
+#define ScaleBuffSzMult (MyWindowScale * MyWindowScale)
+#endif
+
+LOCALFUNC blnr MyCreateNewWindow(Rect *Bounds, WindowPtr *theWindow)
+{
+	WindowPtr ResultWin;
+	blnr IsOk = falseblnr;
+
+	ResultWin = NewWindow(
+		0L, Bounds, LMGetCurApName() /* "\pMini vMac" */, false,
+		noGrowDocProc, /* Could use kWindowSimpleProc for Full Screen */
+		(WindowPtr) -1, true, 0);
+	if (ResultWin != NULL) {
+		*theWindow = ResultWin;
+
+		IsOk = trueblnr;
+	}
+
+	return IsOk;
+}
+
+LOCALPROC ZapMyWState(void)
+{
+	gMyMainWindow = NULL;
+	gGlobalReceiveHandler = NULL;
+	gGlobalTrackingHandler = NULL;
+}
+
+LOCALPROC CloseMainWindow(void)
+{
+	/*
+		Dispose of anything set up by CreateMainWindow.
+	*/
+
+#if EnableDragDrop
+	UnPrepareForDragging();
+#endif
+
+	if (gMyMainWindow != NULL) {
+		DisposeWindow(gMyMainWindow);
+		gMyMainWindow = NULL;
+	}
+}
+
+enum {
+	kMagStateNormal,
+#if EnableMagnify
+	kMagStateMagnifgy,
+#endif
+	kNumMagStates
+};
+
+#define kMagStateAuto kNumMagStates
+
+#if MayNotFullScreen
+LOCALVAR int CurWinIndx;
+LOCALVAR blnr HavePositionWins[kNumMagStates];
+LOCALVAR Point WinPositionWins[kNumMagStates];
+#endif
+
+LOCALFUNC blnr CreateMainWindow(void)
+{
+	/*
+		Set up somewhere for us to draw the emulated screen and
+		receive mouse input. i.e. usually a window, as is the case
+		for this port.
+
+		The window should not be resizeable.
+
+		Should look at the current value of UseMagnify and
+		UseFullScreen.
+
+	*/
+#if MayNotFullScreen
+	int WinIndx;
+#endif
+	Rect MainScrnBounds;
+	Rect AllScrnBounds;
+	Rect NewWinRect;
+	short leftPos;
+	short topPos;
+	short NewWindowHeight = vMacScreenHeight;
+	short NewWindowWidth = vMacScreenWidth;
+	blnr IsOk = falseblnr;
+
+#if VarFullScreen
+	if (UseFullScreen) {
+		My_HideMenuBar();
+	}  else {
+		My_ShowMenuBar();
+	}
+#else
+#if MayFullScreen
+		My_HideMenuBar();
+#endif
+#endif
+
+	MyGetGrayRgnBounds(&AllScrnBounds);
+	MyGetScreenBitsBounds(&MainScrnBounds);
+
+#if EnableMagnify
+	if (UseMagnify) {
+		NewWindowHeight *= MyWindowScale;
+		NewWindowWidth *= MyWindowScale;
+	}
+#endif
+
+	leftPos = MainScrnBounds.left
+		+ ((MainScrnBounds.right - MainScrnBounds.left)
+			- NewWindowWidth) / 2;
+	topPos = MainScrnBounds.top
+		+ ((MainScrnBounds.bottom - MainScrnBounds.top)
+			- NewWindowHeight) / 2;
+	if (leftPos < MainScrnBounds.left) {
+		leftPos = MainScrnBounds.left;
+	}
+	if (topPos < MainScrnBounds.top) {
+		topPos = MainScrnBounds.top;
+	}
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		ViewHSize = MainScrnBounds.right - MainScrnBounds.left;
+		ViewVSize = MainScrnBounds.bottom - MainScrnBounds.top;
+#if EnableMagnify
+		if (UseMagnify) {
+			ViewHSize /= MyWindowScale;
+			ViewVSize /= MyWindowScale;
+		}
+#endif
+		if (ViewHSize >= vMacScreenWidth) {
+			ViewHStart = 0;
+			ViewHSize = vMacScreenWidth;
+		} else {
+			ViewHSize &= ~ 1;
+		}
+		if (ViewVSize >= vMacScreenHeight) {
+			ViewVStart = 0;
+			ViewVSize = vMacScreenHeight;
+		} else {
+			ViewVSize &= ~ 1;
+		}
+	}
+#endif
+
+	/* Create window rectangle and centre it on the screen */
+	SetRect(&MainScrnBounds, 0, 0, NewWindowWidth, NewWindowHeight);
+	OffsetRect(&MainScrnBounds, leftPos, topPos);
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		NewWinRect = AllScrnBounds;
+	}
+#endif
+#if VarFullScreen
+	else
+#endif
+#if MayNotFullScreen
+	{
+#if EnableMagnify
+		if (UseMagnify) {
+			WinIndx = kMagStateMagnifgy;
+		} else
+#endif
+		{
+			WinIndx = kMagStateNormal;
+		}
+
+		if (! HavePositionWins[WinIndx]) {
+			WinPositionWins[WinIndx].h = leftPos;
+			WinPositionWins[WinIndx].v = topPos;
+			HavePositionWins[WinIndx] = trueblnr;
+			NewWinRect = MainScrnBounds;
+		} else {
+			SetRect(&NewWinRect, 0, 0, NewWindowWidth, NewWindowHeight);
+			OffsetRect(&NewWinRect,
+				WinPositionWins[WinIndx].h, WinPositionWins[WinIndx].v);
+		}
+	}
+#endif
+
+#if MayNotFullScreen
+	CurWinIndx = WinIndx;
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		hOffset = MainScrnBounds.left - AllScrnBounds.left;
+		vOffset = MainScrnBounds.top - AllScrnBounds.top;
+	}
+#endif
+
+	if (MyCreateNewWindow(&NewWinRect, &gMyMainWindow)) {
+		ShowWindow(gMyMainWindow);
+
+		/* check if window rect valid */
+#if VarFullScreen
+		if (! UseFullScreen)
+#endif
+#if MayNotFullScreen
+		{
+			Rect tr;
+
+			if (MyGetWindowTitleBounds(gMyMainWindow, &tr)) {
+				if (! RectInRgn(&tr, My_GetGrayRgn())) {
+					MySetMacWindContRect(gMyMainWindow,
+						&MainScrnBounds);
+					if (MyGetWindowTitleBounds(gMyMainWindow, &tr)) {
+						if (! RectInRgn(&tr, My_GetGrayRgn())) {
+							OffsetRect(&MainScrnBounds,
+								0, AllScrnBounds.top - tr.top);
+							MySetMacWindContRect(gMyMainWindow,
+								&MainScrnBounds);
+						}
+					}
+				}
+			}
+		}
+#endif
+
+#if EnableDragDrop
+		if (HaveDragMgrAvail()) {
+			(void) PrepareForDragging();
+		}
+#endif
+
+		IsOk = trueblnr;
+	}
+
+	return IsOk;
+}
+
+struct MyWState {
+	WindowPtr f_MainWindow;
+#if MayFullScreen
+	short f_hOffset;
+	short f_vOffset;
+	ui4r f_ViewHSize;
+	ui4r f_ViewVSize;
+	ui4r f_ViewHStart;
+	ui4r f_ViewVStart;
+#endif
+#if VarFullScreen
+	blnr f_UseFullScreen;
+#endif
+#if EnableMagnify
+	blnr f_UseMagnify;
+#endif
+#if MayNotFullScreen
+	int f_CurWinIndx;
+#endif
+	DragTrackingHandlerUPP f_gGlobalTrackingHandler;
+	DragReceiveHandlerUPP f_gGlobalReceiveHandler;
+};
+typedef struct MyWState MyWState;
+
+LOCALPROC GetMyWState(MyWState *r)
+{
+	r->f_MainWindow = gMyMainWindow;
+#if MayFullScreen
+	r->f_hOffset = hOffset;
+	r->f_vOffset = vOffset;
+	r->f_ViewHSize = ViewHSize;
+	r->f_ViewVSize = ViewVSize;
+	r->f_ViewHStart = ViewHStart;
+	r->f_ViewVStart = ViewVStart;
+#endif
+#if VarFullScreen
+	r->f_UseFullScreen = UseFullScreen;
+#endif
+#if EnableMagnify
+	r->f_UseMagnify = UseMagnify;
+#endif
+#if MayNotFullScreen
+	r->f_CurWinIndx = CurWinIndx;
+#endif
+	r->f_gGlobalTrackingHandler = gGlobalTrackingHandler;
+	r->f_gGlobalReceiveHandler = gGlobalReceiveHandler;
+}
+
+LOCALPROC SetMyWState(MyWState *r)
+{
+	gMyMainWindow = r->f_MainWindow;
+#if MayFullScreen
+	hOffset = r->f_hOffset;
+	vOffset = r->f_vOffset;
+	ViewHSize = r->f_ViewHSize;
+	ViewVSize = r->f_ViewVSize;
+	ViewHStart = r->f_ViewHStart;
+	ViewVStart = r->f_ViewVStart;
+#endif
+#if VarFullScreen
+	UseFullScreen = r->f_UseFullScreen;
+#endif
+#if EnableMagnify
+	UseMagnify = r->f_UseMagnify;
+#endif
+#if MayNotFullScreen
+	CurWinIndx = r->f_CurWinIndx;
+#endif
+	gGlobalTrackingHandler = r->f_gGlobalTrackingHandler;
+	gGlobalReceiveHandler = r->f_gGlobalReceiveHandler;
+}
+
+LOCALFUNC blnr ReCreateMainWindow(void)
+{
+	/*
+		Like CreateMainWindow (which it calls), except may be
+		called when already have window, without CloseMainWindow
+		being called first. (Usually with different
+		values of WantMagnify and WantFullScreen than
+		on the previous call.)
+
+		If there is existing window, and fail to create
+		the new one, then existing window must be left alone,
+		in valid state. (and return falseblnr. otherwise,
+		if succeed, return trueblnr)
+
+		i.e. can allocate the new one before disposing
+		of the old one.
+	*/
+	MyWState old_state;
+	MyWState new_state;
+
+#if VarFullScreen
+	if (! UseFullScreen)
+#endif
+#if MayNotFullScreen
+	{
+		/* save old position */
+		if (gMyMainWindow != NULL) {
+			Rect r;
+
+			if (MyGetWindowContBounds(gMyMainWindow, &r)) {
+				WinPositionWins[CurWinIndx].h = r.left;
+				WinPositionWins[CurWinIndx].v = r.top;
+			}
+		}
+	}
+#endif
+
+#if MayFullScreen
+	UngrabMachine();
+#endif
+
+	GetMyWState(&old_state);
+
+	ZapMyWState();
+
+#if VarFullScreen
+	UseFullScreen = WantFullScreen;
+#endif
+#if EnableMagnify
+	UseMagnify = WantMagnify;
+#endif
+
+	ColorTransValid = falseblnr;
+
+	if (! CreateMainWindow()) {
+		CloseMainWindow();
+		SetMyWState(&old_state);
+
+#if VarFullScreen
+		if (UseFullScreen) {
+			My_HideMenuBar();
+		} else {
+			My_ShowMenuBar();
+		}
+#endif
+
+		/* avoid retry */
+#if VarFullScreen
+		WantFullScreen = UseFullScreen;
+#endif
+#if EnableMagnify
+		WantMagnify = UseMagnify;
+#endif
+
+		return falseblnr;
+	} else {
+		GetMyWState(&new_state);
+		SetMyWState(&old_state);
+		CloseMainWindow();
+		SetMyWState(&new_state);
+
+		if (HaveCursorHidden) {
+			(void) MyMoveMouse(CurMouseH, CurMouseV);
+			WantCursorHidden = trueblnr;
+		}
+
+		return trueblnr;
+	}
+}
+
+#if VarFullScreen && EnableMagnify
+enum {
+	kWinStateWindowed,
+#if EnableMagnify
+	kWinStateFullScreen,
+#endif
+	kNumWinStates
+};
+#endif
+
+#if VarFullScreen && EnableMagnify
+LOCALVAR int WinMagStates[kNumWinStates];
+#endif
+
+LOCALPROC ZapWinStateVars(void)
+{
+#if MayNotFullScreen
+	{
+		int i;
+
+		for (i = 0; i < kNumMagStates; ++i) {
+			HavePositionWins[i] = falseblnr;
+		}
+	}
+#endif
+#if VarFullScreen && EnableMagnify
+	{
+		int i;
+
+		for (i = 0; i < kNumWinStates; ++i) {
+			WinMagStates[i] = kMagStateAuto;
+		}
+	}
+#endif
+}
+
+#if VarFullScreen
+LOCALPROC ToggleWantFullScreen(void)
+{
+	WantFullScreen = ! WantFullScreen;
+
+#if EnableMagnify
+	{
+		int OldWinState =
+			UseFullScreen ? kWinStateFullScreen : kWinStateWindowed;
+		int OldMagState =
+			UseMagnify ? kMagStateMagnifgy : kMagStateNormal;
+		int NewWinState =
+			WantFullScreen ? kWinStateFullScreen : kWinStateWindowed;
+		int NewMagState = WinMagStates[NewWinState];
+
+		WinMagStates[OldWinState] = OldMagState;
+		if (kMagStateAuto != NewMagState) {
+			WantMagnify = (kMagStateMagnifgy == NewMagState);
+		} else {
+			WantMagnify = falseblnr;
+			if (WantFullScreen) {
+				Rect r;
+
+				MyGetScreenBitsBounds(&r);
+				if (((r.right - r.left)
+					>= vMacScreenWidth * MyWindowScale)
+					&& ((r.bottom - r.top)
+					>= vMacScreenHeight * MyWindowScale)
+					)
+				{
+					WantMagnify = trueblnr;
+				}
+			}
+		}
+	}
+#endif
+}
+#endif
+
+LOCALPROC LeaveBackground(void)
+{
+#if HogCPU
+	NoEventsCounter = 0;
+#endif
+
+	SetCursorArrow();
+	ReconnectKeyCodes3();
+}
+
+LOCALPROC EnterBackground(void)
+{
+	DisconnectKeyCodes3();
+
+#if VarFullScreen
+	if (WantFullScreen) {
+		ToggleWantFullScreen();
+	}
+#endif
+}
+
+LOCALPROC LeaveSpeedStopped(void)
+{
+#if MySoundEnabled
+	MySound_Start();
+#endif
+
+	StartUpTimeAdjust();
+}
+
+LOCALPROC EnterSpeedStopped(void)
+{
+#if MySoundEnabled
+	MySound_Stop();
+#endif
+}
+
+LOCALPROC CheckForSavedTasks(void)
+{
+	if (MyEvtQNeedRecover) {
+		MyEvtQNeedRecover = falseblnr;
+
+		/* attempt cleanup, MyEvtQNeedRecover may get set again */
+		MyEvtQTryRecoverFromFull();
+	}
+
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		MyMouseConstrain();
+	}
+#endif
+
+	if (RequestMacOff) {
+		RequestMacOff = falseblnr;
+		if (AnyDiskInserted()) {
+			MacMsgOverride(kStrQuitWarningTitle,
+				kStrQuitWarningMessage);
+		} else {
+			ForceMacOff = trueblnr;
+		}
+	}
+
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (gTrueBackgroundFlag != gBackgroundFlag) {
+		gBackgroundFlag = gTrueBackgroundFlag;
+		if (gTrueBackgroundFlag) {
+			EnterBackground();
+		} else {
+			LeaveBackground();
+		}
+	}
+
+	if (CurSpeedStopped != (SpeedStopped ||
+		(gBackgroundFlag && ! RunInBackground
+#if EnableAutoSlow && 0
+			&& (QuietSubTicks >= 4092)
+#endif
+		)))
+	{
+		CurSpeedStopped = ! CurSpeedStopped;
+		if (CurSpeedStopped) {
+			EnterSpeedStopped();
+		} else {
+			LeaveSpeedStopped();
+		}
+	}
+
+#if EnableRecreateW
+	if (! (gTrueBackgroundFlag)) {
+		if (0
+#if EnableMagnify
+			|| (UseMagnify != WantMagnify)
+#endif
+#if VarFullScreen
+			|| (UseFullScreen != WantFullScreen)
+#endif
+			)
+		{
+			(void) ReCreateMainWindow();
+#if HogCPU
+			NoEventsCounter = 0;
+#endif
+		}
+	}
+#endif
+
+#if MayFullScreen
+	if (GrabMachine != (
+#if VarFullScreen
+		UseFullScreen &&
+#endif
+		! (gTrueBackgroundFlag || CurSpeedStopped)))
+	{
+		GrabMachine = ! GrabMachine;
+		AdjustMachineGrab();
+	}
+#endif
+
+	if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
+		MacMsgDisplayOn();
+	}
+
+	if (NeedWholeScreenDraw) {
+		NeedWholeScreenDraw = falseblnr;
+		ScreenChangedAll();
+	}
+
+	if (gTrueBackgroundFlag) {
+		/*
+			dialog during drag and drop hangs if in background
+				and don't want recursive dialogs
+			so wait til later to display dialog
+		*/
+	} else {
+#if IncludeSonyNew
+		if (vSonyNewDiskWanted) {
+#if IncludeSonyNameNew
+			if (vSonyNewDiskName != NotAPbuf) {
+				MakeNewDisk(vSonyNewDiskSize,
+					PbufDat[vSonyNewDiskName]);
+				PbufDispose(vSonyNewDiskName);
+				vSonyNewDiskName = NotAPbuf;
+			} else
+#endif
+			{
+				MakeNewDisk(vSonyNewDiskSize, NULL);
+			}
+			vSonyNewDiskWanted = falseblnr;
+				/* must be done after may have gotten disk */
+		}
+#endif
+		if (RequestInsertDisk) {
+			RequestInsertDisk = falseblnr;
+			InsertADisk0();
+		}
+	}
+
+#if NeedRequestIthDisk
+	if (0 != RequestIthDisk) {
+		Sony_InsertIth(RequestIthDisk);
+		RequestIthDisk = 0;
+	}
+#endif
+
+	if (HaveCursorHidden != (WantCursorHidden
+		&& ! (gTrueBackgroundFlag || CurSpeedStopped)))
+	{
+		HaveCursorHidden = ! HaveCursorHidden;
+		if (HaveCursorHidden) {
+			HideCursor();
+		} else {
+			ShowCursor();
+		}
+	}
+}
+
+GLOBALOSGLUFUNC blnr ExtraTimeNotOver(void)
+{
+	UpdateTrueEmulatedTime();
+	return TrueEmulatedTime == OnTrueTime;
+}
+
+#define CheckItem CheckMenuItem
+
+/* Menu Constants */
+
+#define kAppleMenu   128
+#define kFileMenu    129
+#define kSpecialMenu 130
+
+/* Apple */
+
+enum {
+	kAppleNull,
+
+	kAppleAboutItem,
+	kAppleSep1,
+
+	kNumAppleItems
+};
+
+/* File */
+
+enum {
+	kFileNull,
+
+	kFileOpenDiskImage,
+	kFileSep1,
+	kFileQuitItem,
+
+	kNumFileItems
+};
+
+/* Special */
+
+enum {
+	kSpecialNull,
+
+	kSpecialMoreCommandsItem,
+
+	kNumSpecialItems
+};
+
+LOCALPROC DoOpenDA(short menuItem)
+{
+	Str32 name;
+	GrafPtr savePort;
+
+	GetPort(&savePort);
+	GetMenuItemText(GetMenuHandle(kAppleMenu), menuItem, name);
+	OpenDeskAcc(name);
+	SystemTask();
+	SetPort(savePort);
+}
+
+LOCALPROC MacOS_HandleMenu(short menuID, short menuItem)
+{
+	switch (menuID) {
+		case kAppleMenu:
+			if (kAppleAboutItem == menuItem) {
+				DoAboutMsg();
+			} else {
+				DoOpenDA(menuItem);
+			}
+			break;
+
+		case kFileMenu:
+			switch (menuItem) {
+				case kFileOpenDiskImage:
+					RequestInsertDisk = trueblnr;
+					break;
+
+				case kFileQuitItem:
+					RequestMacOff = trueblnr;
+					break;
+			}
+			break;
+
+		case kSpecialMenu:
+			switch (menuItem) {
+				case kSpecialMoreCommandsItem:
+					DoMoreCommandsMsg();
+					break;
+			}
+			break;
+
+		default:
+			/* if 0 == menuID, then no command chosen from menu */
+			/* do nothing */
+			break;
+	}
+}
+
+LOCALPROC HandleMacEvent(EventRecord *theEvent)
+{
+	WindowPtr whichWindow;
+	GrafPtr savePort;
+
+	switch(theEvent->what) {
+		case mouseDown:
+			switch (FindWindow(theEvent->where, &whichWindow)) {
+				case inSysWindow:
+					SystemClick(theEvent, whichWindow);
+					break;
+				case inMenuBar:
+					ForceShowCursor();
+					{
+						long menuSelection =
+							MenuSelect(theEvent->where);
+						MacOS_HandleMenu(HiWord(menuSelection),
+							LoWord(menuSelection));
+					}
+					HiliteMenu(0);
+					break;
+
+				case inDrag:
+					{
+						Rect r;
+
+						MyGetScreenBitsBounds(&r);
+						DragWindow(whichWindow, theEvent->where, &r);
+					}
+					break;
+
+				case inContent:
+					if (FrontWindow() != whichWindow) {
+						SelectWindow(whichWindow);
+					}
+					if (whichWindow == gMyMainWindow) {
+						MousePositionNotifyFromGlobal(theEvent->where);
+						MyMouseButtonSet(trueblnr);
+					}
+					break;
+
+				case inGoAway:
+					if (TrackGoAway(whichWindow, theEvent->where)) {
+						RequestMacOff = trueblnr;
+					}
+					break;
+
+				case inZoomIn:
+				case inZoomOut:
+					/* Zoom Boxes */
+					break;
+			}
+			break;
+		case mouseUp:
+			MousePositionNotifyFromGlobal(theEvent->where);
+			MyMouseButtonSet(falseblnr);
+			break;
+
+		case updateEvt:
+			GetPort(&savePort);
+			BeginUpdate((WindowPtr) theEvent->message);
+
+			if ((WindowPtr)theEvent->message == gMyMainWindow) {
+				Update_Screen();
+			}
+
+			EndUpdate((WindowPtr) theEvent->message);
+			SetPort(savePort);
+			break;
+
+		case keyDown:
+		case autoKey:
+		case keyUp:
+			/* ignore it */
+			break;
+		case osEvt:
+			if ((theEvent->message >> 24) & suspendResumeMessage) {
+				if (theEvent->message & 1) {
+					gTrueBackgroundFlag = falseblnr;
+				} else {
+					gTrueBackgroundFlag = trueblnr;
+				}
+			}
+			break;
+		case kHighLevelEvent:
+			if (kCoreEventClass == (AEEventClass)theEvent->message) {
+				if (/* CheckSysCode */ noErr ==
+					(AEProcessAppleEvent(theEvent)))
+				{
+				}
+			} else {
+				/* vCheckSysCode(errAENotAppleEvent); */
+			}
+			break;
+	}
+}
+
+LOCALPROC WaitForTheNextEvent(void)
+{
+	/*
+		Wait for the next event
+		from the operating system, we have nothing better
+		to do. Call HandleTheEvent and return (only
+		wait for one event).
+	*/
+
+	EventRecord theEvent;
+
+	if (
+#if HaveCPUfamM68K
+		(! HaveWaitNextEventAvail()) ?
+		GetNextEvent(everyEvent, &theEvent) :
+#endif
+		WaitNextEvent(everyEvent, &theEvent,
+			(gTrueBackgroundFlag && ! RunInBackground)
+				? 5 * 60 * 60
+				: 5,
+				/*
+					still need to check for
+					control key when SpeedStopped,
+					don't get event
+				*/
+			NULL))
+	{
+		HandleMacEvent(&theEvent);
+	}
+}
+
+LOCALPROC DontWaitForEvent(void)
+{
+	/* we're busy, but see what system wants */
+
+	EventRecord theEvent;
+	int i = 0;
+
+#if 0 /* this seems to cause crashes on some machines */
+	if (EventAvail(everyEvent, &theEvent)) {
+		NoEventsCounter = 0;
+#endif
+
+		while ((
+#if HaveCPUfamM68K
+			(! HaveWaitNextEventAvail()) ?
+			GetNextEvent(everyEvent, &theEvent) :
+#endif
+			WaitNextEvent(everyEvent, &theEvent, 0, NULL))
+			&& (i < 10))
+		{
+			HandleMacEvent(&theEvent);
+#if HogCPU
+			NoEventsCounter = 0;
+#endif
+			++i;
+		}
+#if 0
+	}
+#endif
+}
+
+#define PrivateEventMask \
+	(mDownMask | mUpMask | keyDownMask | keyUpMask | autoKeyMask)
+
+#define IsPowOf2(x) (0 == ((x) & ((x) - 1)))
+
+LOCALPROC CheckForSystemEvents(void)
+{
+	/*
+		Handle any events that are waiting for us.
+		Return immediately when no more events
+		are waiting, don't wait for more.
+	*/
+
+#if HogCPU && MayFullScreen
+	/*
+		only hog cpu in full screen mode
+	*/
+	if (
+#if VarFullScreen
+		UseFullScreen &&
+#endif
+		((ui3b) -1 == SpeedValue) && ! CurSpeedStopped)
+	{
+		EventRecord theEvent;
+
+		if (! OSEventAvail(everyEvent, &theEvent)) {
+			/*
+				if no OSEvent now, and not looking for aftermath of
+				event, assume there is no event of any kind we need
+				to look at
+			*/
+			if (NoEventsCounter < 256) {
+				++NoEventsCounter;
+				if (IsPowOf2(NoEventsCounter)) {
+					DontWaitForEvent();
+				}
+			}
+		} else {
+			WindowPtr whichWindow;
+
+			blnr PrivateEvent = falseblnr;
+			switch (theEvent.what) {
+				case keyDown:
+				case autoKey:
+				case keyUp:
+				case mouseUp:
+					PrivateEvent = trueblnr;
+					break;
+				case mouseDown:
+					if ((inContent ==
+							FindWindow(theEvent.where, &whichWindow))
+						&& (whichWindow == gMyMainWindow)
+						&& (FrontWindow() == whichWindow))
+					{
+						PrivateEvent = trueblnr;
+					}
+					break;
+			}
+			if (PrivateEvent) {
+				/*
+					if event can effect only us, and not looking out
+					for aftermath of another event, then hog the cpu
+				*/
+				if (GetOSEvent(PrivateEventMask, &theEvent)) {
+					HandleMacEvent(&theEvent);
+				}
+			} else {
+				NoEventsCounter = 0;
+				/*
+					Have an Event, so reset NoEventsCounter, no matter
+					what. WaitNextEvent can return false, even if it did
+					handle an event. Such as a click in the collapse
+					box. In this case we need to look out for update
+					events.
+				*/
+				DontWaitForEvent();
+			}
+		}
+	} else
+#endif
+	{
+		DontWaitForEvent();
+	}
+
+	if (! gBackgroundFlag) {
+		CheckKeyBoardState();
+	}
+}
+
+GLOBALOSGLUPROC WaitForNextTick(void)
+{
+label_retry:
+	CheckForSystemEvents();
+	CheckForSavedTasks();
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (CurSpeedStopped) {
+		DoneWithDrawingForTick();
+		WaitForTheNextEvent();
+		goto label_retry;
+	}
+
+	/*
+		Wait until the end of the current
+		tick, then emulate the next tick.
+	*/
+
+	if (ExtraTimeNotOver()) {
+#if HaveCPUfamM68K
+		if (HaveWaitNextEventAvail())
+#endif
+		{
+			EventRecord theEvent;
+
+			if (WaitNextEvent(everyEvent, &theEvent, 1, NULL)) {
+				HandleMacEvent(&theEvent);
+#if HogCPU
+				NoEventsCounter = 0;
+#endif
+			}
+		}
+		goto label_retry;
+	}
+
+	if (CheckDateTime()) {
+#if MySoundEnabled
+		MySound_SecondNotify();
+#endif
+#if EnableDemoMsg
+		DemoModeSecondNotify();
+#endif
+	}
+
+	if (! (gBackgroundFlag)) {
+		CheckMouseState();
+	}
+
+	OnTrueTime = TrueEmulatedTime;
+
+#if dbglog_TimeStuff
+	dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime);
+#endif
+}
+
+#include "PROGMAIN.h"
+
+LOCALPROC AppendMenuCStr(MenuHandle menu, char *s)
+{
+	Str255 t;
+
+	PStrFromCStr(t, s);
+	AppendMenu(menu, t);
+}
+
+LOCALPROC AppendMenuConvertCStr(MenuHandle menu,
+	char *s, blnr WantEllipsis)
+{
+	Str255 t;
+
+	NativeStrFromCStr(t, s, WantEllipsis);
+	AppendMenu(menu, t);
+}
+
+LOCALPROC AppendMenuSep(MenuHandle menu)
+{
+	AppendMenuCStr(menu, "(-");
+}
+
+LOCALFUNC MenuHandle NewMenuFromConvertCStr(short menuID, char *s)
+{
+	Str255 r;
+
+	NativeStrFromCStr(r, s, falseblnr);
+	return NewMenu(menuID, r);
+}
+
+LOCALFUNC blnr InstallOurMenus(void)
+{
+	MenuHandle menu;
+	Str255 s;
+
+	PStrFromChar(s, (char)20);
+	menu = NewMenu(kAppleMenu, s);
+	if (menu != NULL) {
+		AppendMenuConvertCStr(menu,
+			kStrMenuItemAbout, trueblnr);
+		AppendMenuSep(menu);
+		AppendResMenu(menu, 'DRVR');
+		InsertMenu(menu, 0);
+	}
+
+	menu = NewMenuFromConvertCStr(kFileMenu, kStrMenuFile);
+	if (menu != NULL) {
+		AppendMenuConvertCStr(menu,
+			kStrMenuItemOpen, trueblnr);
+		{
+			AppendMenuSep(menu);
+			AppendMenuConvertCStr(menu,
+				kStrMenuItemQuit, falseblnr);
+		}
+		InsertMenu(menu, 0);
+	}
+
+	menu = NewMenuFromConvertCStr(kSpecialMenu, kStrMenuSpecial);
+	if (menu != NULL) {
+		AppendMenuConvertCStr(menu,
+			kStrMenuItemMore, trueblnr);
+		InsertMenu(menu, 0);
+	}
+
+	DrawMenuBar();
+
+	return trueblnr;
+}
+
+#if AppearanceAvail
+LOCALFUNC blnr InstallOurAppearanceClient(void)
+{
+	if (HaveAppearanceAvail()) {
+		RegisterAppearanceClient();
+	}
+	return trueblnr;
+}
+#endif
+
+LOCALFUNC blnr InstallOurEventHandlers(void)
+{
+	InitKeyCodes();
+
+	if (HaveAppleEvtMgrAvail()) {
+		InstallAppleEventHandlers();
+	}
+	return trueblnr;
+}
+
+LOCALPROC ZapOSGLUVars(void)
+{
+	/*
+		Set initial values of variables for
+		platform dependent code, where not
+		done using c initializers. (such
+		as for arrays.)
+	*/
+
+	ZapEmKeys();
+	InitDrives();
+	ZapWinStateVars();
+}
+
+LOCALPROC ReserveAllocAll(void)
+{
+	/* !! must match ChooseTotMemSize in build system !! */
+
+#if dbglog_HAVE
+	dbglog_ReserveAlloc();
+#endif
+	ReserveAllocOneBlock(&ROM, kROM_Size, 5, falseblnr);
+	ReserveAllocOneBlock(&screencomparebuff,
+		vMacScreenNumBytes, 5, trueblnr);
+#if UseControlKeys
+	ReserveAllocOneBlock(&CntrlDisplayBuff,
+		vMacScreenNumBytes, 5, falseblnr);
+#endif
+#if EnableMagnify
+	ReserveAllocOneBlock(&ScalingBuff,
+		vMacScreenNumBytes * (ScaleBuffSzMult), 5, falseblnr);
+	ReserveAllocOneBlock(&ScalingTabl,
+		ScalingTablsz, 5, falseblnr);
+#endif
+#if MySoundEnabled
+	ReserveAllocOneBlock((ui3p *)&TheSoundBuffer,
+		dbhBufferSize, 5, falseblnr);
+#endif
+
+	EmulationReserveAlloc();
+}
+
+LOCALFUNC blnr AllocMyMemory(void)
+{
+	uimr n;
+	blnr IsOk = falseblnr;
+
+	ReserveAllocOffset = 0;
+	ReserveAllocBigBlock = nullpr;
+	ReserveAllocAll();
+	n = ReserveAllocOffset;
+	ReserveAllocBigBlock = (ui3p)NewPtr(n);
+	if (NULL == ReserveAllocBigBlock) {
+		MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr);
+	} else {
+		ReserveAllocOffset = 0;
+		ReserveAllocAll();
+		if (n != ReserveAllocOffset) {
+			/* oops, program error */
+		} else {
+			IsOk = trueblnr;
+		}
+	}
+
+	return IsOk;
+}
+
+LOCALFUNC blnr InitOSGLU(void)
+{
+	/*
+		run all the initializations
+		needed for the program.
+	*/
+
+	if (InitMacManagers())
+	if (AllocMyMemory())
+	if (InitMyApplInfo())
+#if dbglog_HAVE
+	if (dbglog_open())
+#endif
+#if AppearanceAvail
+	if (InstallOurAppearanceClient())
+#endif
+	if (InstallOurEventHandlers())
+	if (InstallOurMenus())
+#if MySoundEnabled
+	if (MySound_Init())
+#endif
+	if (ReCreateMainWindow())
+	if (LoadMacRom())
+	if (LoadInitialImages())
+#if UseActvCode
+	if (ActvCodeInit())
+#endif
+	if (InitLocationDat())
+	if (WaitForRom())
+	{
+		return trueblnr;
+	}
+	return falseblnr;
+}
+
+LOCALPROC UnInitOSGLU(void)
+{
+	/*
+		Do all clean ups needed
+		before the program quits.
+	*/
+
+	if (MacMsgDisplayed) {
+		MacMsgDisplayOff();
+	}
+
+#if MayFullScreen
+	UngrabMachine();
+#endif
+
+#if MySoundEnabled
+	MySound_Stop();
+#endif
+
+	CloseMainWindow();
+
+#if MayFullScreen
+	My_ShowMenuBar();
+#endif
+
+#if IncludePbufs
+	UnInitPbufs();
+#endif
+	UnInitDrives();
+
+#if dbglog_HAVE
+	dbglog_close();
+#endif
+
+	ForceShowCursor();
+
+	if (! gTrueBackgroundFlag) {
+		CheckSavedMacMsg();
+	}
+}
+
+#ifndef MainReturnsInt
+#define MainReturnsInt 0
+#endif
+
+#ifndef NeedLongGlue
+#define NeedLongGlue 0
+#endif
+
+#if NeedLongGlue
+#define main long_main
+#endif
+
+#if MainReturnsInt
+int
+#else
+void
+#endif
+main(void)
+{
+	ZapOSGLUVars();
+	if (InitOSGLU()) {
+		ProgramMain();
+	}
+	UnInitOSGLU();
+
+#if MainReturnsInt
+	return 0;
+#endif
+}
--- /dev/null
+++ b/src/OSGLUNDS.c
@@ -1,0 +1,1387 @@
+/*
+	OSGLUNDS.c
+
+	Copyright (C) 2012 Lazyone, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Operating System GLUe for Nintendo DS
+*/
+
+#include "CNFGRAPI.h"
+#include "SYSDEPNS.h"
+#include "ENDIANAC.h"
+
+#include "MYOSGLUE.h"
+
+#include "STRCONST.h"
+
+#include "FB1BPP2I.h"
+
+#define CONSOLE_TRACE() \
+	fprintf(stderr, "%s() at line %d\n", __FUNCTION__, __LINE__)
+
+/* --- some simple utilities --- */
+
+GLOBALOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount)
+{
+	(void) memcpy((char *)destPtr, (char *)srcPtr, byteCount);
+}
+
+/*
+	Nintendo DS port globals
+*/
+#define DS_ScreenWidth 256
+#define DS_ScreenHeight 192
+
+LOCALVAR volatile int VBlankCounter = 0;
+LOCALVAR volatile int HBlankCounter = 0;
+LOCALVAR volatile unsigned int TimerBaseMSec = 0;
+LOCALVAR Keyboard* DSKeyboard = NULL;
+LOCALVAR volatile int LastKeyboardKey = NOKEY;
+LOCALVAR volatile int KeyboardKey = NOKEY;
+LOCALVAR volatile int KeysHeld = 0;
+LOCALVAR volatile int CursorX = 0;
+LOCALVAR volatile int CursorY = 0;
+LOCALVAR int Display_bg2_Main = 0;
+
+/* --- control mode and internationalization --- */
+
+#define NeedCell2PlainAsciiMap 1
+
+#include "INTLCHAR.h"
+
+/* --- sending debugging info to file --- */
+
+#if dbglog_HAVE
+
+#define dbglog_ToStdErr 1
+
+#if ! dbglog_ToStdErr
+LOCALVAR FILE *dbglog_File = NULL;
+#endif
+
+LOCALFUNC blnr dbglog_open0(void)
+{
+#if dbglog_ToStdErr
+	return trueblnr;
+#else
+	dbglog_File = fopen("dbglog.txt", "w");
+	return (NULL != dbglog_File);
+#endif
+}
+
+LOCALPROC dbglog_write0(char *s, uimr L)
+{
+#if dbglog_ToStdErr
+	(void) fwrite(s, 1, L, stderr);
+#else
+	if (dbglog_File != NULL) {
+		(void) fwrite(s, 1, L, dbglog_File);
+	}
+#endif
+}
+
+LOCALPROC dbglog_close0(void)
+{
+#if ! dbglog_ToStdErr
+	if (dbglog_File != NULL) {
+		fclose(dbglog_File);
+		dbglog_File = NULL;
+	}
+#endif
+}
+
+#endif
+
+/* --- debug settings and utilities --- */
+
+#if ! dbglog_HAVE
+#define WriteExtraErr(s)
+#else
+LOCALPROC WriteExtraErr(char *s)
+{
+	dbglog_writeCStr("*** error: ");
+	dbglog_writeCStr(s);
+	dbglog_writeReturn();
+}
+#endif
+
+/* --- information about the environment --- */
+
+#define WantColorTransValid 0
+
+#include "COMOSGLU.h"
+#include "CONTROLM.h"
+
+LOCALPROC NativeStrFromCStr(char *r, char *s)
+{
+	ui3b ps[ClStrMaxLength];
+	int i;
+	int L;
+
+	ClStrFromSubstCStr(&L, ps, s);
+
+	for (i = 0; i < L; ++i) {
+		r[i] = Cell2PlainAsciiMap[ps[i]];
+	}
+
+	r[L] = 0;
+}
+
+/* --- drives --- */
+
+#define NotAfileRef NULL
+
+LOCALVAR FILE *Drives[NumDrives]; /* open disk image files */
+#if IncludeSonyGetName || IncludeSonyNew
+LOCALVAR char *DriveNames[NumDrives];
+#endif
+
+LOCALPROC InitDrives(void)
+{
+	/*
+		This isn't really needed, Drives[i] and DriveNames[i]
+		need not have valid values when not vSonyIsInserted[i].
+	*/
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		Drives[i] = NotAfileRef;
+#if IncludeSonyGetName || IncludeSonyNew
+		DriveNames[i] = NULL;
+#endif
+	}
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer,
+	tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count,
+	ui5r *Sony_ActCount)
+{
+	tMacErr err = mnvm_miscErr;
+	FILE *refnum = Drives[Drive_No];
+	ui5r NewSony_Count = 0;
+
+	if (0 == fseek(refnum, Sony_Start, SEEK_SET)) {
+		if (IsWrite) {
+			NewSony_Count = fwrite(Buffer, 1, Sony_Count, refnum);
+		} else {
+			NewSony_Count = fread(Buffer, 1, Sony_Count, refnum);
+		}
+
+		if (NewSony_Count == Sony_Count) {
+			err = mnvm_noErr;
+		}
+	}
+
+	if (nullpr != Sony_ActCount) {
+		*Sony_ActCount = NewSony_Count;
+	}
+
+	return err; /*& figure out what really to return &*/
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count)
+{
+	tMacErr err = mnvm_miscErr;
+	FILE *refnum = Drives[Drive_No];
+	long v;
+
+	if (0 == fseek(refnum, 0, SEEK_END)) {
+		v = ftell(refnum);
+		if (v >= 0) {
+			*Sony_Count = v;
+			err = mnvm_noErr;
+		}
+	}
+
+	return err; /*& figure out what really to return &*/
+}
+
+LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, blnr deleteit)
+{
+	FILE *refnum = Drives[Drive_No];
+
+	DiskEjectedNotify(Drive_No);
+
+	fclose(refnum);
+	Drives[Drive_No] = NotAfileRef; /* not really needed */
+
+#if IncludeSonyGetName || IncludeSonyNew
+	{
+		char *s = DriveNames[Drive_No];
+		if (NULL != s) {
+			if (deleteit) {
+				remove(s);
+			}
+			free(s);
+			DriveNames[Drive_No] = NULL; /* not really needed */
+		}
+	}
+#endif
+
+	return mnvm_noErr;
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
+{
+	return vSonyEject0(Drive_No, falseblnr);
+}
+
+#if IncludeSonyNew
+GLOBALOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No)
+{
+	return vSonyEject0(Drive_No, trueblnr);
+}
+#endif
+
+LOCALPROC UnInitDrives(void)
+{
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		if (vSonyIsInserted(i)) {
+			(void) vSonyEject(i);
+		}
+	}
+}
+
+#if IncludeSonyGetName
+GLOBALOSGLUFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r)
+{
+	char *drivepath = DriveNames[Drive_No];
+	if (NULL == drivepath) {
+		return mnvm_miscErr;
+	} else {
+		char *s = strrchr(drivepath, '/');
+		if (NULL == s) {
+			s = drivepath;
+		} else {
+			++s;
+		}
+		return NativeTextToMacRomanPbuf(s, r);
+	}
+}
+#endif
+
+LOCALFUNC blnr Sony_Insert0(FILE *refnum, blnr locked,
+	char *drivepath)
+{
+	tDrive Drive_No;
+	blnr IsOk = falseblnr;
+
+	if (! FirstFreeDisk(&Drive_No)) {
+		MacMsg(kStrTooManyImagesTitle, kStrTooManyImagesMessage,
+			falseblnr);
+	} else {
+		/* printf("Sony_Insert0 %d\n", (int)Drive_No); */
+
+		{
+			Drives[Drive_No] = refnum;
+			DiskInsertNotify(Drive_No, locked);
+
+#if IncludeSonyGetName || IncludeSonyNew
+			{
+				ui5b L = strlen(drivepath);
+				char *p = malloc(L + 1);
+				if (p != NULL) {
+					(void) memcpy(p, drivepath, L + 1);
+				}
+				DriveNames[Drive_No] = p;
+			}
+#endif
+
+			IsOk = trueblnr;
+		}
+	}
+
+	if (! IsOk) {
+		fclose(refnum);
+	}
+
+	return IsOk;
+}
+
+LOCALFUNC blnr Sony_Insert1(char *drivepath, blnr silentfail)
+{
+	blnr locked = falseblnr;
+	/* printf("Sony_Insert1 %s\n", drivepath); */
+	FILE *refnum = fopen(drivepath, "rb+");
+	if (NULL == refnum) {
+		locked = trueblnr;
+		refnum = fopen(drivepath, "rb");
+		CONSOLE_TRACE();
+	}
+	if (NULL == refnum) {
+		if (! silentfail) {
+			MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
+			CONSOLE_TRACE();
+		}
+	} else {
+		CONSOLE_TRACE();
+		return Sony_Insert0(refnum, locked, drivepath);
+	}
+
+	return falseblnr;
+}
+
+#define Sony_Insert2(s) Sony_Insert1(s, trueblnr)
+
+LOCALFUNC blnr Sony_InsertIth(int i)
+{
+	blnr v;
+
+	if ((i > 9) || ! FirstFreeDisk(nullpr)) {
+		v = falseblnr;
+	} else {
+		char s[] = "disk?.dsk";
+
+		s[4] = '0' + i;
+
+		v = Sony_Insert2(s);
+	}
+
+	return v;
+}
+
+LOCALFUNC blnr LoadInitialImages(void)
+{
+	int i;
+
+	CONSOLE_TRACE();
+
+	for (i = 1; Sony_InsertIth(i); ++i) {
+		/* stop on first error (including file not found) */
+	}
+
+	return trueblnr;
+}
+
+#if IncludeSonyNew
+LOCALFUNC blnr WriteZero(FILE *refnum, ui5b L)
+{
+#define ZeroBufferSize 2048
+	ui5b i;
+	ui3b buffer[ZeroBufferSize];
+
+	memset(&buffer, 0, ZeroBufferSize);
+
+	while (L > 0) {
+		i = (L > ZeroBufferSize) ? ZeroBufferSize : L;
+		if (fwrite(buffer, 1, i, refnum) != i) {
+			return falseblnr;
+		}
+		L -= i;
+	}
+	return trueblnr;
+}
+#endif
+
+#if IncludeSonyNew
+LOCALPROC MakeNewDisk(ui5b L, char *drivepath)
+{
+	blnr IsOk = falseblnr;
+	FILE *refnum = fopen(drivepath, "wb+");
+	if (NULL == refnum) {
+		MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
+	} else {
+		if (WriteZero(refnum, L)) {
+			IsOk = Sony_Insert0(refnum, falseblnr, drivepath);
+			refnum = NULL;
+		}
+		if (refnum != NULL) {
+			fclose(refnum);
+		}
+		if (! IsOk) {
+			(void) remove(drivepath);
+		}
+	}
+}
+#endif
+
+#if IncludeSonyNew
+LOCALPROC MakeNewDiskAtDefault(ui5b L)
+{
+	char s[ClStrMaxLength + 1];
+
+	NativeStrFromCStr(s, "untitled.dsk");
+	MakeNewDisk(L, s);
+}
+#endif
+
+/* --- ROM --- */
+
+LOCALFUNC tMacErr LoadMacRomFrom(char *path)
+{
+	tMacErr err;
+	FILE *ROM_File;
+	int File_Size;
+
+	ROM_File = fopen(path, "rb");
+	if (NULL == ROM_File) {
+		err = mnvm_fnfErr;
+	} else {
+		File_Size = fread(ROM, 1, kROM_Size, ROM_File);
+		if (kROM_Size != File_Size) {
+			if (feof(ROM_File)) {
+				MacMsgOverride(kStrShortROMTitle,
+					kStrShortROMMessage);
+				err = mnvm_eofErr;
+			} else {
+				MacMsgOverride(kStrNoReadROMTitle,
+					kStrNoReadROMMessage);
+				err = mnvm_miscErr;
+			}
+		} else {
+			err = ROM_IsValid();
+		}
+		fclose(ROM_File);
+	}
+
+	return err;
+}
+
+LOCALFUNC blnr LoadMacRom(void)
+{
+	tMacErr err;
+
+	if (mnvm_fnfErr == (err = LoadMacRomFrom(RomFileName)))
+	{
+	}
+
+	return trueblnr; /* keep launching Mini vMac, regardless */
+}
+
+/* --- video out --- */
+
+#if MayFullScreen
+LOCALVAR short hOffset;
+LOCALVAR short vOffset;
+#endif
+
+#if VarFullScreen
+LOCALVAR blnr UseFullScreen = (WantInitFullScreen != 0);
+#endif
+
+#if EnableMagnify
+LOCALVAR blnr UseMagnify = (WantInitMagnify != 0);
+#endif
+
+LOCALVAR blnr CurSpeedStopped = trueblnr;
+
+#if EnableMagnify
+#define MaxScale MyWindowScale
+#else
+#define MaxScale 1
+#endif
+
+LOCALPROC HaveChangedScreenBuff(ui4r top, ui4r left,
+	ui4r bottom, ui4r right)
+{
+	/*
+		Oh god, clean this up.
+	*/
+	u8 *octpix = NULL;
+	u32 *vram = NULL;
+
+	octpix = (u8 *)GetCurDrawBuff();
+	vram = (u32 *)BG_BMP_RAM(0);
+
+	octpix += ((top * vMacScreenWidth ) >> 3);
+	vram += ((top * vMacScreenWidth ) >> 2);
+
+	FB1BPPtoIndexed(vram, octpix,
+		((bottom - top) * vMacScreenWidth) >> 3);
+}
+
+LOCALPROC MyDrawChangesAndClear(void)
+{
+	if (ScreenChangedBottom > ScreenChangedTop) {
+		HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft,
+			ScreenChangedBottom, ScreenChangedRight);
+		ScreenClearChanges();
+	}
+}
+
+GLOBALOSGLUPROC DoneWithDrawingForTick(void)
+{
+#if 0 && EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		AutoScrollScreen();
+	}
+#endif
+	MyDrawChangesAndClear();
+}
+
+/* --- mouse --- */
+
+/* cursor state */
+
+LOCALPROC CheckMouseState(void)
+{
+	si5b MotionX;
+	si5b MotionY;
+
+	/*
+		TODO:
+
+		- Don't hardcode motion values
+		- Acceleration?
+		- Allow key remapping
+		- Handle touchscreen input (non-mouse motion)
+		- Handle touchscreen input (trackpad style mouse motion)
+	*/
+
+	if (0 != (KeysHeld & KEY_LEFT)) {
+		MotionX = -4;
+	} else if (0 != (KeysHeld & KEY_RIGHT)) {
+		MotionX = 4;
+	}
+
+	if (0 != (KeysHeld & KEY_UP)) {
+		MotionY = -4;
+	} else if (0 != (KeysHeld & KEY_DOWN)) {
+		MotionY = 4;
+	}
+
+	HaveMouseMotion = trueblnr;
+
+	MyMousePositionSetDelta(MotionX, MotionY);
+	MyMouseButtonSet(0 != (KeysHeld & KEY_A));
+}
+
+/* --- keyboard input --- */
+
+LOCALVAR ui3b KC2MKC[256];
+
+/*
+	AHA!
+	GCC Was turning this into a macro of some sort which of course
+	broke horribly with libnds's keyboard having some negative values.
+*/
+LOCALPROC AssignKeyToMKC(int UKey, int LKey, ui3r MKC)
+{
+	if (UKey != NOKEY) {
+		KC2MKC[UKey] = MKC;
+	}
+
+	if (LKey != NOKEY) {
+		KC2MKC[LKey] = MKC;
+	}
+}
+
+LOCALFUNC blnr KC2MKCInit(void)
+{
+	int i;
+
+	for (i = 0; i < 256; ++i) {
+		KC2MKC[i] = MKC_None;
+	}
+
+	AssignKeyToMKC('A', 'a', MKC_A);
+	AssignKeyToMKC('B', 'b', MKC_B);
+	AssignKeyToMKC('C', 'c', MKC_C);
+	AssignKeyToMKC('D', 'd', MKC_D);
+	AssignKeyToMKC('E', 'e', MKC_E);
+	AssignKeyToMKC('F', 'f', MKC_F);
+	AssignKeyToMKC('G', 'g', MKC_G);
+	AssignKeyToMKC('H', 'h', MKC_H);
+	AssignKeyToMKC('I', 'i', MKC_I);
+	AssignKeyToMKC('J', 'j', MKC_J);
+	AssignKeyToMKC('K', 'k', MKC_K);
+	AssignKeyToMKC('L', 'l', MKC_L);
+	AssignKeyToMKC('M', 'm', MKC_M);
+	AssignKeyToMKC('N', 'n', MKC_N);
+	AssignKeyToMKC('O', 'o', MKC_O);
+	AssignKeyToMKC('P', 'p', MKC_P);
+	AssignKeyToMKC('Q', 'q', MKC_Q);
+	AssignKeyToMKC('R', 'r', MKC_R);
+	AssignKeyToMKC('S', 's', MKC_S);
+	AssignKeyToMKC('T', 't', MKC_T);
+	AssignKeyToMKC('U', 'u', MKC_U);
+	AssignKeyToMKC('V', 'v', MKC_V);
+	AssignKeyToMKC('W', 'w', MKC_W);
+	AssignKeyToMKC('X', 'x', MKC_X);
+	AssignKeyToMKC('Y', 'y', MKC_Y);
+	AssignKeyToMKC('Z', 'z', MKC_Z);
+
+	AssignKeyToMKC(')', '0', MKC_0);
+	AssignKeyToMKC('!', '1', MKC_1);
+	AssignKeyToMKC('@', '2', MKC_2);
+	AssignKeyToMKC('#', '3', MKC_3);
+	AssignKeyToMKC('$', '4', MKC_4);
+	AssignKeyToMKC('%', '5', MKC_5);
+	AssignKeyToMKC('^', '6', MKC_6);
+	AssignKeyToMKC('&', '7', MKC_7);
+	AssignKeyToMKC('*', '8', MKC_8);
+	AssignKeyToMKC('(', '9', MKC_9);
+
+	AssignKeyToMKC('~', '`', MKC_formac_Grave);
+	AssignKeyToMKC('_', '-', MKC_Minus);
+	AssignKeyToMKC('+', '=', MKC_Equal);
+	AssignKeyToMKC(':', ';', MKC_SemiColon);
+	AssignKeyToMKC('\"', '\'', MKC_SingleQuote);
+	AssignKeyToMKC('{', '[', MKC_LeftBracket);
+	AssignKeyToMKC('}', ']', MKC_RightBracket);
+	AssignKeyToMKC('|', '\\', MKC_formac_BackSlash);
+	AssignKeyToMKC('<', ',', MKC_Comma);
+	AssignKeyToMKC('>', '.', MKC_Period);
+	AssignKeyToMKC('?', '/', MKC_formac_Slash);
+
+	AssignKeyToMKC(NOKEY, DVK_SPACE, MKC_Space);
+	AssignKeyToMKC(NOKEY, DVK_BACKSPACE, MKC_BackSpace);
+	AssignKeyToMKC(NOKEY, DVK_ENTER, MKC_formac_Enter);
+	AssignKeyToMKC(NOKEY, DVK_TAB, MKC_Tab);
+
+	InitKeyCodes();
+
+	return trueblnr;
+}
+
+LOCALPROC DoKeyCode0(int i, blnr down)
+{
+	ui3r key = KC2MKC[i];
+	if (MKC_None != key) {
+		fprintf(stderr, "%s() :: %c (%d) == %d\n",
+			__FUNCTION__, (char) i, key, down);
+		Keyboard_UpdateKeyMap2(key, down);
+	}
+}
+
+LOCALPROC DoKeyCode(int i, blnr down)
+{
+	if ((i >= 0) && (i < 256)) {
+		DoKeyCode0(i, down);
+	}
+}
+
+/*
+	TODO:
+
+	Rethink keyboard input...
+	Especially shift and capslock, the libnds keyboard
+	is weird about those.
+*/
+
+LOCALVAR blnr DS_Keystate_Menu = falseblnr;
+LOCALVAR blnr DS_Keystate_Shift = falseblnr;
+
+LOCALPROC DS_HandleKey(si5b Key, blnr Down)
+{
+	if (Key == NOKEY) {
+		return;
+	}
+
+	switch (Key) {
+		case DVK_UP:
+			Keyboard_UpdateKeyMap2(MKC_Up, Down);
+			break;
+
+		case DVK_DOWN:
+			Keyboard_UpdateKeyMap2(MKC_Down, Down);
+			break;
+
+		case DVK_LEFT:
+			Keyboard_UpdateKeyMap2(MKC_Left, Down);
+			break;
+
+		case DVK_RIGHT:
+			Keyboard_UpdateKeyMap2(MKC_Right, Down);
+			break;
+
+		case DVK_SHIFT:
+			Keyboard_UpdateKeyMap2(MKC_formac_Shift, trueblnr);
+			break;
+
+		default:
+			if (Key > 0) {
+				DoKeyCode(Key, Down);
+				Keyboard_UpdateKeyMap2(MKC_formac_Shift, falseblnr);
+			}
+			break;
+	}
+}
+
+LOCALPROC DS_HandleKeyboard(void)
+{
+	LastKeyboardKey = KeyboardKey;
+	KeyboardKey = keyboardUpdate();
+
+	if ((KeyboardKey == NOKEY) && (LastKeyboardKey != NOKEY)) {
+		DS_HandleKey(LastKeyboardKey, falseblnr);
+		LastKeyboardKey = NOKEY;
+	} else {
+		DS_HandleKey(KeyboardKey, trueblnr);
+		LastKeyboardKey = KeyboardKey;
+	}
+}
+
+/* --- time, date, location --- */
+
+LOCALVAR ui5b TrueEmulatedTime = 0;
+
+#include "DATE2SEC.h"
+
+#define TicksPerSecond 1000000
+/* #define TicksPerSecond  1000 */
+
+LOCALVAR blnr HaveTimeDelta = falseblnr;
+LOCALVAR ui5b TimeDelta;
+
+LOCALVAR ui5b NewMacDateInSeconds;
+
+LOCALVAR ui5b LastTimeSec;
+LOCALVAR ui5b LastTimeUsec;
+
+LOCALPROC GetCurrentTicks(void)
+{
+	struct timeval t;
+
+	gettimeofday(&t, NULL);
+
+	/*
+		HACKHACKHACK
+	*/
+	t.tv_usec = TimerBaseMSec + TIMER1_DATA;
+	t.tv_usec = t.tv_usec * 1000;
+
+	if (! HaveTimeDelta) {
+		time_t Current_Time;
+		struct tm *s;
+
+		(void) time(&Current_Time);
+		s = localtime(&Current_Time);
+		TimeDelta = Date2MacSeconds(s->tm_sec, s->tm_min, s->tm_hour,
+			s->tm_mday, 1 + s->tm_mon, 1900 + s->tm_year) - t.tv_sec;
+#if 0 && AutoTimeZone /* how portable is this ? */
+		CurMacDelta = ((ui5b)(s->tm_gmtoff) & 0x00FFFFFF)
+			| ((s->tm_isdst ? 0x80 : 0) << 24);
+#endif
+		HaveTimeDelta = trueblnr;
+	}
+
+	NewMacDateInSeconds = t.tv_sec + TimeDelta;
+	LastTimeSec = (ui5b)t.tv_sec;
+	LastTimeUsec = (ui5b)t.tv_usec;
+}
+
+/* #define MyInvTimeStep 16626 */ /* TicksPerSecond / 60.14742 */
+#define MyInvTimeStep 17
+
+LOCALVAR ui5b NextTimeSec;
+LOCALVAR ui5b NextTimeUsec;
+
+LOCALPROC IncrNextTime(void)
+{
+	NextTimeUsec += MyInvTimeStep;
+	if (NextTimeUsec >= TicksPerSecond) {
+		NextTimeUsec -= TicksPerSecond;
+		NextTimeSec += 1;
+	}
+}
+
+LOCALPROC InitNextTime(void)
+{
+	NextTimeSec = LastTimeSec;
+	NextTimeUsec = LastTimeUsec;
+	IncrNextTime();
+}
+
+LOCALPROC StartUpTimeAdjust(void)
+{
+	GetCurrentTicks();
+	InitNextTime();
+}
+
+LOCALFUNC si5b GetTimeDiff(void)
+{
+	return ((si5b)(LastTimeSec - NextTimeSec)) * TicksPerSecond
+		+ ((si5b)(LastTimeUsec - NextTimeUsec));
+}
+
+LOCALPROC UpdateTrueEmulatedTime(void)
+{
+	si5b TimeDiff;
+
+	GetCurrentTicks();
+
+	TimeDiff = GetTimeDiff();
+	if (TimeDiff >= 0) {
+		if (TimeDiff > 4 * MyInvTimeStep) {
+			/* emulation interrupted, forget it */
+			++TrueEmulatedTime;
+			InitNextTime();
+		} else {
+			do {
+				++TrueEmulatedTime;
+				IncrNextTime();
+				TimeDiff -= TicksPerSecond;
+			} while (TimeDiff >= 0);
+		}
+	} else if (TimeDiff < - 2 * MyInvTimeStep) {
+		/* clock goofed if ever get here, reset */
+		InitNextTime();
+	}
+}
+
+LOCALFUNC blnr CheckDateTime(void)
+{
+	if (CurMacDateInSeconds != NewMacDateInSeconds) {
+		CurMacDateInSeconds = NewMacDateInSeconds;
+		return trueblnr;
+	} else {
+		return falseblnr;
+	}
+}
+
+LOCALFUNC blnr InitLocationDat(void)
+{
+	GetCurrentTicks();
+	CurMacDateInSeconds = NewMacDateInSeconds;
+
+	return trueblnr;
+}
+
+/* --- basic dialogs --- */
+
+LOCALPROC CheckSavedMacMsg(void)
+{
+	/* called only on quit, if error saved but not yet reported */
+
+	if (nullpr != SavedBriefMsg) {
+		char briefMsg0[ClStrMaxLength + 1];
+		char longMsg0[ClStrMaxLength + 1];
+
+		NativeStrFromCStr(briefMsg0, SavedBriefMsg);
+		NativeStrFromCStr(longMsg0, SavedLongMsg);
+
+		fprintf(stderr, "%s\n", briefMsg0);
+		fprintf(stderr, "%s\n", longMsg0);
+
+		SavedBriefMsg = nullpr;
+	}
+}
+
+/* --- main window creation and disposal --- */
+
+/*
+	Screen_Init
+
+	Mode 5 gives us 2 text backgrounds 0-1 (tiled mode) and
+	2 extended rotation backgrounds 2-3. (linear fb)
+
+	Also we need to map 2 banks of vram so we have enough space for
+	our 512x512 surface.
+*/
+LOCALFUNC blnr Screen_Init(void)
+{
+	videoSetMode(MODE_5_2D);
+	vramSetBankA(VRAM_A_MAIN_BG_0x06000000);
+	vramSetBankB(VRAM_B_MAIN_BG_0x06020000);
+
+	Display_bg2_Main = bgInit(2, BgType_Bmp8, BgSize_B8_512x512, 0, 0);
+
+	BG_PALETTE[0] = RGB15(31, 31, 31);
+	BG_PALETTE[1] = RGB15(0, 0, 0);
+
+	return trueblnr;
+}
+
+#if VarFullScreen
+LOCALPROC ToggleWantFullScreen(void)
+{
+	WantFullScreen = ! WantFullScreen;
+}
+#endif
+
+/* --- SavedTasks --- */
+
+LOCALPROC LeaveSpeedStopped(void)
+{
+#if MySoundEnabled
+	MySound_Start();
+#endif
+
+	StartUpTimeAdjust();
+}
+
+LOCALPROC EnterSpeedStopped(void)
+{
+#if MySoundEnabled
+	MySound_Stop();
+#endif
+}
+
+LOCALPROC CheckForSavedTasks(void)
+{
+	if (MyEvtQNeedRecover) {
+		MyEvtQNeedRecover = falseblnr;
+
+		/* attempt cleanup, MyEvtQNeedRecover may get set again */
+		MyEvtQTryRecoverFromFull();
+	}
+
+	if (RequestMacOff) {
+		RequestMacOff = falseblnr;
+		if (AnyDiskInserted()) {
+			MacMsgOverride(kStrQuitWarningTitle,
+				kStrQuitWarningMessage);
+		} else {
+			ForceMacOff = trueblnr;
+		}
+	}
+
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (CurSpeedStopped != SpeedStopped) {
+		CurSpeedStopped = ! CurSpeedStopped;
+		if (CurSpeedStopped) {
+			EnterSpeedStopped();
+		} else {
+			LeaveSpeedStopped();
+		}
+	}
+
+#if IncludeSonyNew
+	if (vSonyNewDiskWanted) {
+#if IncludeSonyNameNew
+		if (vSonyNewDiskName != NotAPbuf) {
+			ui3p NewDiskNameDat;
+			if (MacRomanTextToNativePtr(vSonyNewDiskName, trueblnr,
+				&NewDiskNameDat))
+			{
+				MakeNewDisk(vSonyNewDiskSize, (char *)NewDiskNameDat);
+				free(NewDiskNameDat);
+			}
+			PbufDispose(vSonyNewDiskName);
+			vSonyNewDiskName = NotAPbuf;
+		} else
+#endif
+		{
+			MakeNewDiskAtDefault(vSonyNewDiskSize);
+		}
+		vSonyNewDiskWanted = falseblnr;
+			/* must be done after may have gotten disk */
+	}
+#endif
+
+	if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
+		MacMsgDisplayOn();
+	}
+
+	if (NeedWholeScreenDraw) {
+		NeedWholeScreenDraw = falseblnr;
+		ScreenChangedAll();
+	}
+
+#if NeedRequestIthDisk
+	if (0 != RequestIthDisk) {
+		Sony_InsertIth(RequestIthDisk);
+		RequestIthDisk = 0;
+	}
+#endif
+}
+
+/* --- main program flow --- */
+
+GLOBALOSGLUFUNC blnr ExtraTimeNotOver(void)
+{
+	UpdateTrueEmulatedTime();
+	return TrueEmulatedTime == OnTrueTime;
+}
+
+LOCALPROC WaitForTheNextEvent(void)
+{
+}
+
+LOCALPROC CheckForSystemEvents(void)
+{
+	DS_HandleKeyboard();
+}
+
+GLOBALOSGLUPROC WaitForNextTick(void)
+{
+label_retry:
+	CheckForSystemEvents();
+	CheckForSavedTasks();
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (CurSpeedStopped) {
+		MyDrawChangesAndClear();
+		WaitForTheNextEvent();
+		goto label_retry;
+	}
+
+	if (ExtraTimeNotOver()) {
+		si5b TimeDiff = GetTimeDiff();
+		if (TimeDiff < 0) {
+			/*
+				FIXME:
+
+				Implement this?
+
+				struct timespec rqt;
+				struct timespec rmt;
+
+				rqt.tv_sec = 0;
+				rqt.tv_nsec = (- TimeDiff) * 1000;
+
+				(void) nanosleep(&rqt, &rmt);
+			*/
+		}
+		goto label_retry;
+	}
+
+	if (CheckDateTime()) {
+#if MySoundEnabled
+		MySound_SecondNotify();
+#endif
+#if EnableDemoMsg
+		DemoModeSecondNotify();
+#endif
+	}
+
+	CheckMouseState();
+
+	OnTrueTime = TrueEmulatedTime;
+}
+
+/*
+	DS_ScrollBackground:
+
+	Positions the screen as to center it over the emulated cursor.
+*/
+LOCALPROC DS_ScrollBackground(void)
+{
+	int ScrollX = 0;
+	int ScrollY = 0;
+	int Scale = 0;
+
+	/*
+		TODO:
+		Lots of magic numbers here.
+	*/
+#if EnableMagnify
+	if (WantMagnify) {
+		ScrollX = ((int) CurMouseH) - (DS_ScreenWidth / 4);
+		ScrollY = ((int) CurMouseV) - (DS_ScreenHeight / 4);
+		Scale = 128;
+
+		ScrollX = ScrollX > vMacScreenWidth - (DS_ScreenWidth / 2)
+			? vMacScreenWidth - (DS_ScreenWidth / 2)
+			: ScrollX;
+		ScrollY = ScrollY > vMacScreenHeight - (DS_ScreenHeight / 2)
+			? vMacScreenHeight - (DS_ScreenHeight / 2)
+			: ScrollY;
+	} else
+#endif
+	{
+		ScrollX = ((int) CurMouseH) - (DS_ScreenWidth / 2);
+		ScrollY = ((int) CurMouseV) - (DS_ScreenHeight / 2);
+		Scale = 256;
+
+		ScrollX = ScrollX > vMacScreenWidth - DS_ScreenWidth
+			? vMacScreenWidth - DS_ScreenWidth
+			: ScrollX;
+		ScrollY = ScrollY > vMacScreenHeight - DS_ScreenHeight
+			? vMacScreenHeight - DS_ScreenHeight
+			: ScrollY;
+	}
+
+	ScrollX = ScrollX < 0 ? 0 : ScrollX;
+	ScrollY = ScrollY < 0 ? 0 : ScrollY;
+
+	if (Display_bg2_Main) {
+		bgSetScale(Display_bg2_Main, Scale, Scale);
+		bgSetScroll(Display_bg2_Main, ScrollX, ScrollY);
+	}
+}
+
+/*
+	DS_Timer1_IRQ
+
+	Called when TIMER0_DATA overflows.
+*/
+LOCALPROC DS_Timer1_IRQ(void)
+{
+	TimerBaseMSec += 65536;
+}
+
+/*
+	DS_VBlank_IRQ
+
+	Vertical blank interrupt callback.
+*/
+LOCALPROC DS_VBlank_IRQ(void)
+{
+	scanKeys();
+
+	KeysHeld = keysHeld();
+
+	if (++VBlankCounter == 60) {
+		VBlankCounter = 0;
+	}
+
+	/*
+		TODO:
+		Rewrite this at some point, I'm not sure I like it.
+	*/
+	if (0 != (KeysHeld & KEY_LEFT)) {
+		--CursorX;
+	} else if (0 != (KeysHeld & KEY_RIGHT)) {
+		++CursorX;
+	}
+
+	if (0 != (KeysHeld & KEY_UP)) {
+		--CursorY;
+	} else if (0 != (KeysHeld & KEY_DOWN)) {
+		++CursorY;
+	}
+
+	CursorX = CursorX < 0 ? 0 : CursorX;
+	CursorX = CursorX > vMacScreenWidth ? vMacScreenWidth : CursorX;
+
+	CursorY = CursorY < 0 ? 0 : CursorY;
+	CursorY = CursorY > vMacScreenHeight ? vMacScreenHeight : CursorY;
+
+	DS_ScrollBackground();
+	bgUpdate();
+}
+
+/*
+	DS_HBlank_IRQ
+
+	Called at the start of the horizontal blanking period.
+	This is here mainly as a simple performance test.
+*/
+LOCALPROC DS_HBlank_IRQ(void)
+{
+	++HBlankCounter;
+}
+
+/*
+	DS_SysInit
+
+	Initializes DS specific system hardware and interrupts.
+*/
+LOCALPROC DS_SysInit(void)
+{
+	defaultExceptionHandler();
+	powerOn(POWER_ALL_2D);
+	lcdMainOnTop();
+
+	irqSet(IRQ_VBLANK, DS_VBlank_IRQ);
+	irqSet(IRQ_HBLANK, DS_HBlank_IRQ);
+	irqSet(IRQ_TIMER1, DS_Timer1_IRQ);
+
+	irqEnable(IRQ_VBLANK);
+	irqEnable(IRQ_HBLANK);
+	irqEnable(IRQ_TIMER1);
+
+	/*
+		This sets up 2 timers as a milisecond counter.
+		TIMER0_DATA Will overflow roughly every 1 msec into TIMER1_DATA.
+		When TIMER1_DATA overflows an interrupt will be generated
+		and DS_Timer1_IRQ will be called.
+	*/
+	TIMER0_DATA = 32768;
+
+	TIMER0_CR = TIMER_DIV_1 | TIMER_ENABLE;
+
+
+
+	TIMER1_DATA = 0;
+
+	TIMER1_CR = TIMER_ENABLE | TIMER_CASCADE | TIMER_IRQ_REQ;
+
+	/*
+		Testing.
+	*/
+	consoleDemoInit();
+	consoleDebugInit(DebugDevice_NOCASH);
+
+	/*
+		Use the default keyboard until I design a (good) UI...
+	*/
+	DSKeyboard = keyboardDemoInit();
+	keyboardShow();
+
+	/*
+		Drop back to a read only filesystem embedded in the
+		Mini vMac binary if we cannot open a media device.
+	*/
+	if (! fatInitDefault()) {
+		nitroFSInit();
+	}
+}
+
+/*
+	DS_ClearVRAM:
+
+	Make sure all of the video memory and background/object palettes
+	are zeroed out just in-case the loader doesn't do it for us.
+*/
+LOCALPROC DS_ClearVRAM(void)
+{
+	vramSetPrimaryBanks(VRAM_A_LCD, VRAM_B_LCD, VRAM_C_LCD, VRAM_D_LCD);
+
+	dmaFillWords(0, (void *) VRAM_A, 128 * 1024 * 4);
+	dmaFillWords(0, (void *) BG_PALETTE, 256 * 2);
+	dmaFillWords(0, (void *) BG_PALETTE_SUB, 256 * 2);
+	dmaFillWords(0, (void *) SPRITE_PALETTE, 256 * 2);
+	dmaFillWords(0, (void *) SPRITE_PALETTE_SUB, 256 * 2);
+
+	vramDefault();
+}
+
+/* --- platform independent code can be thought of as going here --- */
+
+#include "PROGMAIN.h"
+
+LOCALPROC ReserveAllocAll(void)
+{
+#if dbglog_HAVE
+	dbglog_ReserveAlloc();
+#endif
+	ReserveAllocOneBlock(&ROM, kROM_Size, 5, falseblnr);
+
+	ReserveAllocOneBlock(&screencomparebuff,
+		vMacScreenNumBytes, 5, trueblnr);
+#if UseControlKeys
+	ReserveAllocOneBlock(&CntrlDisplayBuff,
+		vMacScreenNumBytes, 5, falseblnr);
+#endif
+
+#if MySoundEnabled
+	ReserveAllocOneBlock((ui3p *)&TheSoundBuffer,
+		dbhBufferSize, 5, falseblnr);
+#endif
+
+	EmulationReserveAlloc();
+}
+
+LOCALFUNC blnr AllocMyMemory(void)
+{
+	uimr n;
+	blnr IsOk = falseblnr;
+
+	ReserveAllocOffset = 0;
+	ReserveAllocBigBlock = nullpr;
+	ReserveAllocAll();
+	n = ReserveAllocOffset;
+	ReserveAllocBigBlock = (ui3p)calloc(1, n);
+	if (NULL == ReserveAllocBigBlock) {
+		MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr);
+	} else {
+		ReserveAllocOffset = 0;
+		ReserveAllocAll();
+		if (n != ReserveAllocOffset) {
+			/* oops, program error */
+		} else {
+			IsOk = trueblnr;
+		}
+	}
+
+	return IsOk;
+}
+
+LOCALPROC UnallocMyMemory(void)
+{
+	if (nullpr != ReserveAllocBigBlock) {
+		free((char *)ReserveAllocBigBlock);
+	}
+}
+
+LOCALPROC ZapOSGLUVars(void)
+{
+	InitDrives();
+	DS_ClearVRAM();
+}
+
+LOCALFUNC blnr InitOSGLU(void)
+{
+	DS_SysInit();
+
+	if (AllocMyMemory())
+#if dbglog_HAVE
+	if (dbglog_open())
+#endif
+	if (LoadMacRom())
+	if (LoadInitialImages())
+	if (InitLocationDat())
+#if MySoundEnabled
+	if (MySound_Init())
+#endif
+	if (Screen_Init())
+	if (KC2MKCInit())
+	if (WaitForRom())
+	{
+		return trueblnr;
+	}
+
+	return falseblnr;
+}
+
+LOCALPROC UnInitOSGLU(void)
+{
+	if (MacMsgDisplayed) {
+		MacMsgDisplayOff();
+	}
+
+#if MySoundEnabled
+	MySound_Stop();
+#endif
+#if MySoundEnabled
+	MySound_UnInit();
+#endif
+
+	UnInitDrives();
+
+#if dbglog_HAVE
+	dbglog_close();
+#endif
+
+	UnallocMyMemory();
+	CheckSavedMacMsg();
+}
+
+int main(int argc, char **argv)
+{
+	ZapOSGLUVars();
+
+	if (InitOSGLU()) {
+		iprintf("Entering ProgramMain...\n");
+
+		ProgramMain();
+
+		iprintf("Leaving ProgramMain...\n");
+	}
+
+	UnInitOSGLU();
+
+	/*
+		On some homebrew launchers this could return to
+		the menu by default.
+	*/
+	exit(1);
+
+	while (1) {
+		swiWaitForVBlank();
+	}
+
+	return 0;
+}
--- /dev/null
+++ b/src/OSGLUOSX.c
@@ -1,0 +1,5564 @@
+/*
+	OSGLUOSX.c
+
+	Copyright (C) 2009 Philip Cummins, Richard F. Bannister,
+		Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Operating System GLUe for macintosh OS X
+
+	All operating system dependent code for the
+	Macintosh platform should go here.
+
+	This code is descended from Richard F. Bannister's Macintosh
+	port of vMac, by Philip Cummins.
+
+	The main entry point 'main' is at the end of this file.
+*/
+
+#include "CNFGRAPI.h"
+#include "SYSDEPNS.h"
+#include "ENDIANAC.h"
+
+#include "MYOSGLUE.h"
+
+/* --- adapting to API/ABI version differences --- */
+
+/*
+	if UsingCarbonLib, instead of native Macho,
+	then some APIs are missing
+*/
+#ifndef UsingCarbonLib
+#define UsingCarbonLib 0
+#endif
+
+LOCALVAR CFBundleRef AppServBunRef;
+
+LOCALVAR blnr DidApplicationServicesBun = falseblnr;
+
+LOCALFUNC blnr HaveApplicationServicesBun(void)
+{
+	if (! DidApplicationServicesBun) {
+		AppServBunRef = CFBundleGetBundleWithIdentifier(
+			CFSTR("com.apple.ApplicationServices"));
+		DidApplicationServicesBun = trueblnr;
+	}
+	return (AppServBunRef != NULL);
+}
+
+#if MayFullScreen || UsingCarbonLib
+
+LOCALVAR CFBundleRef HIToolboxBunRef;
+
+LOCALVAR blnr DidHIToolboxBunRef = falseblnr;
+
+LOCALFUNC blnr HaveHIToolboxBunRef(void)
+{
+	if (! DidHIToolboxBunRef) {
+		HIToolboxBunRef = CFBundleGetBundleWithIdentifier(
+			CFSTR("com.apple.HIToolbox"));
+		DidHIToolboxBunRef = trueblnr;
+	}
+	return (HIToolboxBunRef != NULL);
+}
+
+#endif
+
+LOCALVAR CFBundleRef AGLBunRef;
+
+LOCALVAR blnr DidAGLBunRef = falseblnr;
+
+LOCALFUNC blnr HaveAGLBunRef(void)
+{
+	if (! DidAGLBunRef) {
+		AGLBunRef = CFBundleGetBundleWithIdentifier(
+			CFSTR("com.apple.agl"));
+		DidAGLBunRef = trueblnr;
+	}
+	return (AGLBunRef != NULL);
+}
+
+
+#if MayFullScreen
+
+/* SetSystemUIModeProcPtr API always not available */
+
+typedef UInt32                          MySystemUIMode;
+typedef OptionBits                      MySystemUIOptions;
+
+enum {
+	MykUIModeNormal                 = 0,
+	MykUIModeAllHidden              = 3
+};
+
+enum {
+	MykUIOptionAutoShowMenuBar      = 1 << 0,
+	MykUIOptionDisableAppleMenu     = 1 << 2,
+	MykUIOptionDisableProcessSwitch = 1 << 3,
+	MykUIOptionDisableForceQuit     = 1 << 4,
+	MykUIOptionDisableSessionTerminate = 1 << 5,
+	MykUIOptionDisableHide          = 1 << 6
+};
+
+typedef OSStatus (*SetSystemUIModeProcPtr)
+	(MySystemUIMode inMode, MySystemUIOptions inOptions);
+LOCALVAR SetSystemUIModeProcPtr MySetSystemUIMode = NULL;
+LOCALVAR blnr DidSetSystemUIMode = falseblnr;
+
+LOCALFUNC blnr HaveMySetSystemUIMode(void)
+{
+	if (! DidSetSystemUIMode) {
+		if (HaveHIToolboxBunRef()) {
+			MySetSystemUIMode =
+				(SetSystemUIModeProcPtr)
+				CFBundleGetFunctionPointerForName(
+					HIToolboxBunRef, CFSTR("SetSystemUIMode"));
+		}
+		DidSetSystemUIMode = trueblnr;
+	}
+	return (MySetSystemUIMode != NULL);
+}
+
+#endif
+
+/* In 10.1 or later */
+
+typedef OSStatus (*LSCopyDisplayNameForRefProcPtr)
+	(const FSRef *inRef, CFStringRef *outDisplayName);
+LOCALVAR LSCopyDisplayNameForRefProcPtr MyLSCopyDisplayNameForRef
+	= NULL;
+LOCALVAR blnr DidLSCopyDisplayNameForRef = falseblnr;
+
+LOCALFUNC blnr HaveMyLSCopyDisplayNameForRef(void)
+{
+	if (! DidLSCopyDisplayNameForRef) {
+		if (HaveApplicationServicesBun()) {
+			MyLSCopyDisplayNameForRef =
+				(LSCopyDisplayNameForRefProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AppServBunRef, CFSTR("LSCopyDisplayNameForRef"));
+		}
+		DidLSCopyDisplayNameForRef = trueblnr;
+	}
+	return (MyLSCopyDisplayNameForRef != NULL);
+}
+
+/* In 10.5 or later */
+
+typedef GLboolean (*aglSetWindowRefProcPtr)
+	(AGLContext ctx, WindowRef window);
+LOCALVAR aglSetWindowRefProcPtr MyaglSetWindowRef = NULL;
+LOCALVAR blnr DidaglSetWindowRef = falseblnr;
+
+LOCALFUNC blnr HaveMyaglSetWindowRef(void)
+{
+	if (! DidaglSetWindowRef) {
+		if (HaveAGLBunRef()) {
+			MyaglSetWindowRef =
+				(aglSetWindowRefProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AGLBunRef, CFSTR("aglSetWindowRef"));
+		}
+		DidaglSetWindowRef = trueblnr;
+	}
+	return (MyaglSetWindowRef != NULL);
+}
+
+/* Deprecated as of 10.5 */
+
+typedef CGrafPtr My_AGLDrawable;
+typedef GLboolean (*aglSetDrawableProcPtr)
+	(AGLContext ctx, My_AGLDrawable draw);
+LOCALVAR aglSetDrawableProcPtr MyaglSetDrawable = NULL;
+LOCALVAR blnr DidaglSetDrawable = falseblnr;
+
+LOCALFUNC blnr HaveMyaglSetDrawable(void)
+{
+	if (! DidaglSetDrawable) {
+		if (HaveAGLBunRef()) {
+			MyaglSetDrawable =
+				(aglSetDrawableProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AGLBunRef, CFSTR("aglSetDrawable"));
+		}
+		DidaglSetDrawable = trueblnr;
+	}
+	return (MyaglSetDrawable != NULL);
+}
+
+/* routines not in carbon lib */
+
+
+#if UsingCarbonLib
+
+typedef CGDisplayErr
+(*CGGetActiveDisplayListProcPtr) (
+	CGDisplayCount       maxDisplays,
+	CGDirectDisplayID *  activeDspys,
+	CGDisplayCount *     dspyCnt);
+LOCALVAR CGGetActiveDisplayListProcPtr MyCGGetActiveDisplayList = NULL;
+LOCALVAR blnr DidCGGetActiveDisplayList = falseblnr;
+
+LOCALFUNC blnr HaveMyCGGetActiveDisplayList(void)
+{
+	if (! DidCGGetActiveDisplayList) {
+		if (HaveApplicationServicesBun()) {
+			MyCGGetActiveDisplayList =
+				(CGGetActiveDisplayListProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AppServBunRef, CFSTR("CGGetActiveDisplayList"));
+		}
+		DidCGGetActiveDisplayList = trueblnr;
+	}
+	return (MyCGGetActiveDisplayList != NULL);
+}
+
+#else
+
+#define HaveMyCGGetActiveDisplayList() trueblnr
+#define MyCGGetActiveDisplayList CGGetActiveDisplayList
+
+#endif /* ! UsingCarbonLib */
+
+
+#if UsingCarbonLib
+
+typedef CGRect
+(*CGDisplayBoundsProcPtr) (CGDirectDisplayID display);
+LOCALVAR CGDisplayBoundsProcPtr MyCGDisplayBounds = NULL;
+LOCALVAR blnr DidCGDisplayBounds = falseblnr;
+
+LOCALFUNC blnr HaveMyCGDisplayBounds(void)
+{
+	if (! DidCGDisplayBounds) {
+		if (HaveApplicationServicesBun()) {
+			MyCGDisplayBounds =
+				(CGDisplayBoundsProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AppServBunRef, CFSTR("CGDisplayBounds"));
+		}
+		DidCGDisplayBounds = trueblnr;
+	}
+	return (MyCGDisplayBounds != NULL);
+}
+
+#else
+
+#define HaveMyCGDisplayBounds() trueblnr
+#define MyCGDisplayBounds CGDisplayBounds
+
+#endif /* ! UsingCarbonLib */
+
+
+#if UsingCarbonLib
+
+typedef size_t
+(*CGDisplayPixelsWideProcPtr) (CGDirectDisplayID display);
+LOCALVAR CGDisplayPixelsWideProcPtr MyCGDisplayPixelsWide = NULL;
+LOCALVAR blnr DidCGDisplayPixelsWide = falseblnr;
+
+LOCALFUNC blnr HaveMyCGDisplayPixelsWide(void)
+{
+	if (! DidCGDisplayPixelsWide) {
+		if (HaveApplicationServicesBun()) {
+			MyCGDisplayPixelsWide =
+				(CGDisplayPixelsWideProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AppServBunRef, CFSTR("CGDisplayPixelsWide"));
+		}
+		DidCGDisplayPixelsWide = trueblnr;
+	}
+	return (MyCGDisplayPixelsWide != NULL);
+}
+
+#else
+
+#define HaveMyCGDisplayPixelsWide() trueblnr
+#define MyCGDisplayPixelsWide CGDisplayPixelsWide
+
+#endif /* ! UsingCarbonLib */
+
+
+#if UsingCarbonLib
+
+typedef size_t
+(*CGDisplayPixelsHighProcPtr) (CGDirectDisplayID display);
+LOCALVAR CGDisplayPixelsHighProcPtr MyCGDisplayPixelsHigh = NULL;
+LOCALVAR blnr DidCGDisplayPixelsHigh = falseblnr;
+
+LOCALFUNC blnr HaveMyCGDisplayPixelsHigh(void)
+{
+	if (! DidCGDisplayPixelsHigh) {
+		if (HaveApplicationServicesBun()) {
+			MyCGDisplayPixelsHigh =
+				(CGDisplayPixelsHighProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AppServBunRef, CFSTR("CGDisplayPixelsHigh"));
+		}
+		DidCGDisplayPixelsHigh = trueblnr;
+	}
+	return (MyCGDisplayPixelsHigh != NULL);
+}
+
+#else
+
+#define HaveMyCGDisplayPixelsHigh() trueblnr
+#define MyCGDisplayPixelsHigh CGDisplayPixelsHigh
+
+#endif /* ! UsingCarbonLib */
+
+
+#if UsingCarbonLib
+
+typedef CGDisplayErr
+(*CGDisplayHideCursorProcPtr) (CGDirectDisplayID display);
+LOCALVAR CGDisplayHideCursorProcPtr MyCGDisplayHideCursor = NULL;
+LOCALVAR blnr DidCGDisplayHideCursor = falseblnr;
+
+LOCALFUNC blnr HaveMyCGDisplayHideCursor(void)
+{
+	if (! DidCGDisplayHideCursor) {
+		if (HaveApplicationServicesBun()) {
+			MyCGDisplayHideCursor =
+				(CGDisplayHideCursorProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AppServBunRef, CFSTR("CGDisplayHideCursor"));
+		}
+		DidCGDisplayHideCursor = trueblnr;
+	}
+	return (MyCGDisplayHideCursor != NULL);
+}
+
+#else
+
+#define HaveMyCGDisplayHideCursor() trueblnr
+#define MyCGDisplayHideCursor CGDisplayHideCursor
+
+#endif /* ! UsingCarbonLib */
+
+
+#if UsingCarbonLib
+
+typedef CGDisplayErr
+(*CGDisplayShowCursorProcPtr) (CGDirectDisplayID display);
+LOCALVAR CGDisplayShowCursorProcPtr MyCGDisplayShowCursor = NULL;
+LOCALVAR blnr DidCGDisplayShowCursor = falseblnr;
+
+LOCALFUNC blnr HaveMyCGDisplayShowCursor(void)
+{
+	if (! DidCGDisplayShowCursor) {
+		if (HaveApplicationServicesBun()) {
+			MyCGDisplayShowCursor =
+				(CGDisplayShowCursorProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AppServBunRef, CFSTR("CGDisplayShowCursor"));
+		}
+		DidCGDisplayShowCursor = trueblnr;
+	}
+	return (MyCGDisplayShowCursor != NULL);
+}
+
+#else
+
+#define HaveMyCGDisplayShowCursor() trueblnr
+#define MyCGDisplayShowCursor CGDisplayShowCursor
+
+#endif /* ! UsingCarbonLib */
+
+
+#if 0
+
+typedef CGDisplayErr (*CGDisplayMoveCursorToPointProcPtr)
+	(CGDirectDisplayID display, CGPoint point);
+LOCALVAR CGDisplayMoveCursorToPointProcPtr MyCGDisplayMoveCursorToPoint
+	= NULL;
+LOCALVAR blnr DidCGDisplayMoveCursorToPoint = falseblnr;
+
+LOCALFUNC blnr HaveMyCGDisplayMoveCursorToPoint(void)
+{
+	if (! DidCGDisplayMoveCursorToPoint) {
+		if (HaveApplicationServicesBun()) {
+			MyCGDisplayMoveCursorToPoint =
+				(CGDisplayMoveCursorToPointProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AppServBunRef, CFSTR("CGDisplayMoveCursorToPoint"));
+		}
+		DidCGDisplayMoveCursorToPoint = trueblnr;
+	}
+	return (MyCGDisplayMoveCursorToPoint != NULL);
+}
+
+#endif /* 0 */
+
+
+#if UsingCarbonLib
+
+typedef CGEventErr
+(*CGWarpMouseCursorPositionProcPtr) (CGPoint newCursorPosition);
+LOCALVAR CGWarpMouseCursorPositionProcPtr MyCGWarpMouseCursorPosition
+	= NULL;
+LOCALVAR blnr DidCGWarpMouseCursorPosition = falseblnr;
+
+LOCALFUNC blnr HaveMyCGWarpMouseCursorPosition(void)
+{
+	if (! DidCGWarpMouseCursorPosition) {
+		if (HaveApplicationServicesBun()) {
+			MyCGWarpMouseCursorPosition =
+				(CGWarpMouseCursorPositionProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AppServBunRef, CFSTR("CGWarpMouseCursorPosition"));
+		}
+		DidCGWarpMouseCursorPosition = trueblnr;
+	}
+	return (MyCGWarpMouseCursorPosition != NULL);
+}
+
+#else
+
+#define HaveMyCGWarpMouseCursorPosition() trueblnr
+#define MyCGWarpMouseCursorPosition CGWarpMouseCursorPosition
+
+#endif /* ! UsingCarbonLib */
+
+
+#if UsingCarbonLib
+
+typedef CGEventErr
+(*CGSetLocalEventsSuppressionIntervalProcPtr) (CFTimeInterval seconds);
+LOCALVAR CGSetLocalEventsSuppressionIntervalProcPtr
+	MyCGSetLocalEventsSuppressionInterval = NULL;
+LOCALVAR blnr DidCGSetLocalEventsSuppressionInterval = falseblnr;
+
+LOCALFUNC blnr HaveMyCGSetLocalEventsSuppressionInterval(void)
+{
+	if (! DidCGSetLocalEventsSuppressionInterval) {
+		if (HaveApplicationServicesBun()) {
+			MyCGSetLocalEventsSuppressionInterval =
+				(CGSetLocalEventsSuppressionIntervalProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AppServBunRef,
+					CFSTR("CGSetLocalEventsSuppressionInterval"));
+		}
+		DidCGSetLocalEventsSuppressionInterval = trueblnr;
+	}
+	return (MyCGSetLocalEventsSuppressionInterval != NULL);
+}
+
+#else
+
+#define HaveMyCGSetLocalEventsSuppressionInterval() trueblnr
+#define MyCGSetLocalEventsSuppressionInterval \
+	CGSetLocalEventsSuppressionInterval
+
+#endif /* ! UsingCarbonLib */
+
+
+#if UsingCarbonLib
+
+typedef OSStatus (*CreateStandardAlertProcPtr) (
+	AlertType alertType,
+	CFStringRef error,
+	CFStringRef explanation,
+	const AlertStdCFStringAlertParamRec * param,
+	DialogRef * outAlert
+);
+LOCALVAR CreateStandardAlertProcPtr MyCreateStandardAlert = NULL;
+LOCALVAR blnr DidCreateStandardAlert = falseblnr;
+
+LOCALFUNC blnr HaveMyCreateStandardAlert(void)
+{
+	if (! DidCreateStandardAlert) {
+		if (HaveHIToolboxBunRef()) {
+			MyCreateStandardAlert =
+				(CreateStandardAlertProcPtr)
+				CFBundleGetFunctionPointerForName(
+					HIToolboxBunRef, CFSTR("CreateStandardAlert"));
+		}
+		DidCreateStandardAlert = trueblnr;
+	}
+	return (MyCreateStandardAlert != NULL);
+}
+
+#else
+
+#define HaveMyCreateStandardAlert() trueblnr
+#define MyCreateStandardAlert CreateStandardAlert
+
+#endif /* ! UsingCarbonLib */
+
+
+#if UsingCarbonLib
+
+typedef OSStatus (*RunStandardAlertProcPtr) (
+	DialogRef inAlert,
+	ModalFilterUPP filterProc,
+	DialogItemIndex * outItemHit
+);
+LOCALVAR RunStandardAlertProcPtr MyRunStandardAlert = NULL;
+LOCALVAR blnr DidRunStandardAlert = falseblnr;
+
+LOCALFUNC blnr HaveMyRunStandardAlert(void)
+{
+	if (! DidRunStandardAlert) {
+		if (HaveHIToolboxBunRef()) {
+			MyRunStandardAlert =
+				(RunStandardAlertProcPtr)
+				CFBundleGetFunctionPointerForName(
+					HIToolboxBunRef, CFSTR("RunStandardAlert"));
+		}
+		DidRunStandardAlert = trueblnr;
+	}
+	return (MyRunStandardAlert != NULL);
+}
+
+#else
+
+#define HaveMyRunStandardAlert() trueblnr
+#define MyRunStandardAlert RunStandardAlert
+
+#endif /* ! UsingCarbonLib */
+
+
+typedef CGDirectDisplayID (*CGMainDisplayIDProcPtr)(void);
+
+LOCALVAR CGMainDisplayIDProcPtr MyCGMainDisplayID = NULL;
+LOCALVAR blnr DidCGMainDisplayID = falseblnr;
+
+LOCALFUNC blnr HaveMyCGMainDisplayID(void)
+{
+	if (! DidCGMainDisplayID) {
+		if (HaveApplicationServicesBun()) {
+			MyCGMainDisplayID =
+				(CGMainDisplayIDProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AppServBunRef, CFSTR("CGMainDisplayID"));
+		}
+		DidCGMainDisplayID = trueblnr;
+	}
+	return (MyCGMainDisplayID != NULL);
+}
+
+#ifndef kCGNullDirectDisplay /* not in MPW Headers */
+#define kCGNullDirectDisplay ((CGDirectDisplayID)0)
+#endif
+
+typedef CGError
+(*CGDisplayRegisterReconfigurationCallbackProcPtr) (
+	CGDisplayReconfigurationCallBack proc,
+	void *userInfo
+	);
+LOCALVAR CGDisplayRegisterReconfigurationCallbackProcPtr
+	MyCGDisplayRegisterReconfigurationCallback = NULL;
+LOCALVAR blnr DidCGDisplayRegisterReconfigurationCallback = falseblnr;
+
+LOCALFUNC blnr HaveMyCGDisplayRegisterReconfigurationCallback(void)
+{
+	if (! DidCGDisplayRegisterReconfigurationCallback) {
+		if (HaveApplicationServicesBun()) {
+			MyCGDisplayRegisterReconfigurationCallback =
+				(CGDisplayRegisterReconfigurationCallbackProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AppServBunRef,
+					CFSTR("CGDisplayRegisterReconfigurationCallback"));
+		}
+		DidCGDisplayRegisterReconfigurationCallback = trueblnr;
+	}
+	return (MyCGDisplayRegisterReconfigurationCallback != NULL);
+}
+
+
+typedef CGError
+(*CGDisplayRemoveReconfigurationCallbackProcPtr) (
+	CGDisplayReconfigurationCallBack proc,
+	void *userInfo
+	);
+LOCALVAR CGDisplayRemoveReconfigurationCallbackProcPtr
+	MyCGDisplayRemoveReconfigurationCallback = NULL;
+LOCALVAR blnr DidCGDisplayRemoveReconfigurationCallback = falseblnr;
+
+LOCALFUNC blnr HaveMyCGDisplayRemoveReconfigurationCallback(void)
+{
+	if (! DidCGDisplayRemoveReconfigurationCallback) {
+		if (HaveApplicationServicesBun()) {
+			MyCGDisplayRemoveReconfigurationCallback =
+				(CGDisplayRemoveReconfigurationCallbackProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AppServBunRef,
+					CFSTR("CGDisplayRemoveReconfigurationCallback"));
+		}
+		DidCGDisplayRemoveReconfigurationCallback = trueblnr;
+	}
+	return (MyCGDisplayRemoveReconfigurationCallback != NULL);
+}
+
+
+typedef boolean_t (*CGCursorIsVisibleProcPtr)(void);
+
+LOCALVAR CGCursorIsVisibleProcPtr MyCGCursorIsVisible = NULL;
+LOCALVAR blnr DidCGCursorIsVisible = falseblnr;
+
+LOCALFUNC blnr HaveMyCGCursorIsVisible(void)
+{
+	if (! DidCGCursorIsVisible) {
+		if (HaveApplicationServicesBun()) {
+			MyCGCursorIsVisible =
+				(CGCursorIsVisibleProcPtr)
+				CFBundleGetFunctionPointerForName(
+					AppServBunRef, CFSTR("CGCursorIsVisible"));
+		}
+		DidCGCursorIsVisible = trueblnr;
+	}
+	return (MyCGCursorIsVisible != NULL);
+}
+
+
+/* --- end of adapting to API/ABI version differences --- */
+
+/* --- some simple utilities --- */
+
+GLOBALOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount)
+{
+	(void) memcpy((char *)destPtr, (char *)srcPtr, byteCount);
+}
+
+LOCALPROC PStrFromChar(ps3p r, char x)
+{
+	r[0] = 1;
+	r[1] = (char)x;
+}
+
+/* --- mac style errors --- */
+
+#define CheckSavetMacErr(result) (mnvm_noErr == (err = (result)))
+	/*
+		where 'err' is a variable of type tMacErr in the function
+		this is used in
+	*/
+
+#define To_tMacErr(result) ((tMacErr)(ui4b)(result))
+
+#define CheckSaveMacErr(result) (CheckSavetMacErr(To_tMacErr(result)))
+
+
+#include "STRCONST.h"
+
+#define NeedCell2UnicodeMap 1
+
+#include "INTLCHAR.h"
+
+LOCALPROC UniCharStrFromSubstCStr(int *L, UniChar *x, char *s)
+{
+	int i;
+	int L0;
+	ui3b ps[ClStrMaxLength];
+
+	ClStrFromSubstCStr(&L0, ps, s);
+
+	for (i = 0; i < L0; ++i) {
+		x[i] = Cell2UnicodeMap[ps[i]];
+	}
+
+	*L = L0;
+}
+
+#define NotAfileRef (-1)
+
+LOCALFUNC tMacErr MyMakeFSRefUniChar(FSRef *ParentRef,
+	UniCharCount fileNameLength, const UniChar *fileName,
+	blnr *isFolder, FSRef *ChildRef)
+{
+	tMacErr err;
+	Boolean isFolder0;
+	Boolean isAlias;
+
+	if (CheckSaveMacErr(FSMakeFSRefUnicode(ParentRef,
+		fileNameLength, fileName, kTextEncodingUnknown,
+		ChildRef)))
+	if (CheckSaveMacErr(FSResolveAliasFile(ChildRef,
+		TRUE, &isFolder0, &isAlias)))
+	{
+		*isFolder = isFolder0;
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr MyMakeFSRefC(FSRef *ParentRef, char *fileName,
+	blnr *isFolder, FSRef *ChildRef)
+{
+	int L;
+	UniChar x[ClStrMaxLength];
+
+	UniCharStrFromSubstCStr(&L, x, fileName);
+	return MyMakeFSRefUniChar(ParentRef, L, x,
+		isFolder, ChildRef);
+}
+
+#if UseActvFile
+LOCALFUNC tMacErr OpenNamedFileInFolderRef(FSRef *ParentRef,
+	char *fileName, short *refnum)
+{
+	tMacErr err;
+	blnr isFolder;
+	FSRef ChildRef;
+	HFSUniStr255 forkName;
+
+	if (CheckSavetMacErr(MyMakeFSRefC(ParentRef, fileName,
+		&isFolder, &ChildRef)))
+	if (CheckSaveMacErr(FSGetDataForkName(&forkName)))
+	if (CheckSaveMacErr(FSOpenFork(&ChildRef, forkName.length,
+		forkName.unicode, fsRdPerm, refnum)))
+	{
+		/* ok */
+	}
+
+	return err;
+}
+#endif
+
+#if dbglog_HAVE || UseActvFile
+LOCALFUNC tMacErr OpenWriteNamedFileInFolderRef(FSRef *ParentRef,
+	char *fileName, short *refnum)
+{
+	tMacErr err;
+	blnr isFolder;
+	FSRef ChildRef;
+	HFSUniStr255 forkName;
+	int L;
+	UniChar x[ClStrMaxLength];
+
+	UniCharStrFromSubstCStr(&L, x, fileName);
+	err = MyMakeFSRefUniChar(ParentRef, L, x, &isFolder, &ChildRef);
+	if (mnvm_fnfErr == err) {
+		err = To_tMacErr(FSCreateFileUnicode(ParentRef, L, x, 0, NULL,
+			&ChildRef, NULL));
+	}
+	if (mnvm_noErr == err) {
+		if (CheckSaveMacErr(FSGetDataForkName(&forkName)))
+		if (CheckSaveMacErr(FSOpenFork(&ChildRef, forkName.length,
+			forkName.unicode, fsRdWrPerm, refnum)))
+		{
+			/* ok */
+		}
+	}
+
+	return err;
+}
+#endif
+
+LOCALFUNC tMacErr FindNamedChildRef(FSRef *ParentRef,
+	char *ChildName, FSRef *ChildRef)
+{
+	tMacErr err;
+	blnr isFolder;
+
+	if (CheckSavetMacErr(MyMakeFSRefC(ParentRef, ChildName,
+		&isFolder, ChildRef)))
+	{
+		if (! isFolder) {
+			err = mnvm_miscErr;
+		}
+	}
+
+	return err;
+}
+
+#if UseActvFile || (IncludeSonyNew && ! SaveDialogEnable)
+LOCALFUNC tMacErr FindOrMakeNamedChildRef(FSRef *ParentRef,
+	char *ChildName, FSRef *ChildRef)
+{
+	tMacErr err;
+	blnr isFolder;
+	int L;
+	UniChar x[ClStrMaxLength];
+
+	UniCharStrFromSubstCStr(&L, x, ChildName);
+	if (CheckSavetMacErr(MyMakeFSRefUniChar(ParentRef, L, x,
+		&isFolder, ChildRef)))
+	{
+		if (! isFolder) {
+			err = mnvm_miscErr;
+		}
+	}
+	if (mnvm_fnfErr == err) {
+		err = To_tMacErr(FSCreateDirectoryUnicode(
+			ParentRef, L, x, kFSCatInfoNone, NULL,
+			ChildRef, NULL, NULL));
+	}
+
+	return err;
+}
+#endif
+
+LOCALVAR FSRef MyDatDirRef;
+
+LOCALVAR CFStringRef MyAppName = NULL;
+
+LOCALPROC UnInitMyApplInfo(void)
+{
+	if (MyAppName != NULL) {
+		CFRelease(MyAppName);
+	}
+}
+
+LOCALFUNC blnr InitMyApplInfo(void)
+{
+	ProcessSerialNumber currentProcess = {0, kCurrentProcess};
+	FSRef fsRef;
+	FSRef parentRef;
+
+	if (noErr == GetProcessBundleLocation(&currentProcess,
+		&fsRef))
+	if (noErr == FSGetCatalogInfo(&fsRef, kFSCatInfoNone,
+		NULL, NULL, NULL, &parentRef))
+	{
+		FSRef ContentsRef;
+		FSRef DatRef;
+
+		MyDatDirRef = parentRef;
+		if (mnvm_noErr == FindNamedChildRef(&fsRef, "Contents",
+			&ContentsRef))
+		if (mnvm_noErr == FindNamedChildRef(&ContentsRef, "mnvm_dat",
+			&DatRef))
+		{
+			MyDatDirRef = DatRef;
+		}
+
+		if (HaveMyLSCopyDisplayNameForRef()) {
+			if (noErr == MyLSCopyDisplayNameForRef(&fsRef, &MyAppName))
+			{
+				return trueblnr;
+			}
+		}
+
+		if (noErr == CopyProcessName(&currentProcess, &MyAppName)) {
+			return trueblnr;
+		}
+	}
+	return falseblnr;
+}
+
+/* --- sending debugging info to file --- */
+
+#if dbglog_HAVE
+
+LOCALVAR SInt16 dbglog_File = NotAfileRef;
+
+LOCALFUNC blnr dbglog_open0(void)
+{
+	tMacErr err;
+
+	err = OpenWriteNamedFileInFolderRef(&MyDatDirRef,
+		"dbglog.txt", &dbglog_File);
+
+	return (mnvm_noErr == err);
+}
+
+LOCALPROC dbglog_write0(char *s, uimr L)
+{
+	ByteCount actualCount;
+
+	if (dbglog_File != NotAfileRef) {
+		(void) FSWriteFork(
+			dbglog_File,
+			fsFromMark,
+			0,
+			L,
+			s,
+			&actualCount);
+	}
+}
+
+LOCALPROC dbglog_close0(void)
+{
+	if (dbglog_File != NotAfileRef) {
+		(void) FSSetForkSize(dbglog_File, fsFromMark, 0);
+		(void) FSCloseFork(dbglog_File);
+		dbglog_File = NotAfileRef;
+	}
+}
+
+#endif
+
+#if 1 /* (0 != vMacScreenDepth) && (vMacScreenDepth < 4) */
+#define WantColorTransValid 1
+#endif
+
+#include "COMOSGLU.h"
+
+/* --- time, date --- */
+
+/*
+	be sure to avoid getting confused if TickCount
+	overflows and wraps.
+*/
+
+#define dbglog_TimeStuff (0 && dbglog_HAVE)
+
+LOCALVAR ui5b TrueEmulatedTime = 0;
+
+LOCALVAR EventTime NextTickChangeTime;
+
+#define MyTickDuration (kEventDurationSecond / 60.14742)
+
+LOCALPROC UpdateTrueEmulatedTime(void)
+{
+	EventTime LatestTime = GetCurrentEventTime();
+	EventTime TimeDiff = LatestTime - NextTickChangeTime;
+
+	if (TimeDiff >= 0.0) {
+		if (TimeDiff > 16 * MyTickDuration) {
+			/* emulation interrupted, forget it */
+			++TrueEmulatedTime;
+			NextTickChangeTime = LatestTime + MyTickDuration;
+
+#if dbglog_TimeStuff
+			dbglog_writelnNum("emulation interrupted",
+				TrueEmulatedTime);
+#endif
+		} else {
+			do {
+				++TrueEmulatedTime;
+				TimeDiff -= MyTickDuration;
+				NextTickChangeTime += MyTickDuration;
+			} while (TimeDiff >= 0.0);
+		}
+	}
+}
+
+GLOBALOSGLUFUNC blnr ExtraTimeNotOver(void)
+{
+	UpdateTrueEmulatedTime();
+	return TrueEmulatedTime == OnTrueTime;
+}
+
+/* LOCALVAR EventTime ETimeBase; */
+LOCALVAR CFAbsoluteTime ATimeBase;
+LOCALVAR ui5b TimeSecBase;
+
+LOCALFUNC blnr CheckDateTime(void)
+{
+	ui5b NewMacDateInSecond = TimeSecBase
+		+ (ui5b)(CFAbsoluteTimeGetCurrent() - ATimeBase);
+	/*
+		ui5b NewMacDateInSecond = TimeSecBase
+			+ (ui5b)(GetCurrentEventTime() - ETimeBase);
+	*/
+	/*
+		ui5b NewMacDateInSecond = ((ui5b)(CFAbsoluteTimeGetCurrent()))
+			+ 3061137600UL;
+	*/
+
+	if (CurMacDateInSeconds != NewMacDateInSecond) {
+		CurMacDateInSeconds = NewMacDateInSecond;
+		return trueblnr;
+	} else {
+		return falseblnr;
+	}
+}
+
+/* --- parameter buffers --- */
+
+#include "PBUFSTDC.h"
+
+/* --- drives --- */
+
+LOCALVAR SInt16 Drives[NumDrives]; /* open disk image files */
+
+GLOBALOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer,
+	tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count,
+	ui5r *Sony_ActCount)
+{
+	ByteCount actualCount;
+	tMacErr result;
+
+	if (IsWrite) {
+		result = To_tMacErr(FSWriteFork(
+			Drives[Drive_No],
+			fsFromStart,
+			Sony_Start,
+			Sony_Count,
+			Buffer,
+			&actualCount));
+	} else {
+		result = To_tMacErr(FSReadFork(
+			Drives[Drive_No],
+			fsFromStart,
+			Sony_Start,
+			Sony_Count,
+			Buffer,
+			&actualCount));
+	}
+
+	if (nullpr != Sony_ActCount) {
+		*Sony_ActCount = actualCount;
+	}
+
+	return result;
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count)
+{
+	SInt64 forkSize;
+	tMacErr err = To_tMacErr(
+		FSGetForkSize(Drives[Drive_No], &forkSize));
+	*Sony_Count = forkSize;
+	return err;
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
+{
+	SInt16 refnum = Drives[Drive_No];
+	Drives[Drive_No] = NotAfileRef;
+
+	DiskEjectedNotify(Drive_No);
+
+	(void) FSCloseFork(refnum);
+
+	return mnvm_noErr;
+}
+
+#if IncludeSonyNew
+GLOBALOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No)
+{
+	FSRef ref;
+	tMacErr err0;
+	tMacErr err;
+
+	err0 = To_tMacErr(FSGetForkCBInfo(Drives[Drive_No], 0,
+		NULL /* iterator */,
+		NULL /* actualRefNum */,
+		NULL /* forkInfo */,
+		&ref /* ref */,
+		NULL /* outForkName */));
+	err = vSonyEject(Drive_No);
+
+	if (mnvm_noErr != err0) {
+		err = err0;
+	} else {
+		(void) FSDeleteObject(&ref);
+	}
+
+	return err;
+}
+#endif
+
+#if IncludeSonyGetName
+GLOBALOSGLUFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r)
+{
+	FSRef ref;
+	HFSUniStr255 outName;
+	CFStringRef DiskName;
+	tMacErr err;
+
+	if (CheckSaveMacErr(FSGetForkCBInfo(Drives[Drive_No], 0,
+		NULL /* iterator */,
+		NULL /* actualRefNum */,
+		NULL /* forkInfo */,
+		&ref /* ref */,
+		NULL /* outForkName */)))
+	if (CheckSaveMacErr(FSGetCatalogInfo(&ref,
+		kFSCatInfoNone /* whichInfo */,
+		NULL /* catalogInfo */,
+		&outName /* outName */,
+		NULL /* fsSpec */,
+		NULL /* parentRef */)))
+	{
+		DiskName = CFStringCreateWithCharacters(
+			kCFAllocatorDefault, outName.unicode,
+			outName.length);
+		if (NULL != DiskName) {
+			tPbuf i;
+
+			if (CheckSavetMacErr(PbufNew(outName.length, &i))) {
+				if (CFStringGetBytes(DiskName,
+					CFRangeMake(0, outName.length),
+					kCFStringEncodingMacRoman,
+					'?', false,
+					PbufDat[i],
+					outName.length,
+					NULL) != outName.length)
+				{
+					err = mnvm_miscErr;
+				}
+				if (mnvm_noErr != err) {
+					PbufDispose(i);
+				} else {
+					*r = i;
+				}
+			}
+			CFRelease(DiskName);
+		}
+	}
+
+	return err;
+}
+#endif
+
+#if IncludeHostTextClipExchange
+GLOBALOSGLUFUNC tMacErr HTCEexport(tPbuf i)
+{
+	tMacErr err;
+	ScrapRef scrapRef;
+
+	if (CheckSaveMacErr(ClearCurrentScrap()))
+	if (CheckSaveMacErr(GetCurrentScrap(&scrapRef)))
+	if (CheckSaveMacErr(PutScrapFlavor(
+		scrapRef,
+		FOUR_CHAR_CODE('TEXT'),
+		kScrapFlavorMaskNone,
+		PbufSize[i],
+		PbufDat[i])))
+	{
+		/* ok */
+	}
+
+	PbufDispose(i);
+
+	return err;
+}
+#endif
+
+#if IncludeHostTextClipExchange
+GLOBALOSGLUFUNC tMacErr HTCEimport(tPbuf *r)
+{
+	tMacErr err;
+	ScrapRef scrap;
+	ScrapFlavorFlags flavorFlags;
+	Size byteCount;
+	tPbuf i;
+
+	if (CheckSaveMacErr(GetCurrentScrap(&scrap)))
+	if (CheckSaveMacErr(GetScrapFlavorFlags(scrap,
+		'TEXT', &flavorFlags)))
+	if (CheckSaveMacErr(GetScrapFlavorSize(scrap,
+		'TEXT', &byteCount)))
+	if (CheckSavetMacErr(PbufNew(byteCount, &i)))
+	{
+		Size byteCount2 = byteCount;
+		if (CheckSaveMacErr(GetScrapFlavorData(scrap,
+			'TEXT', &byteCount2,
+			PbufDat[i])))
+		{
+			if (byteCount != byteCount2) {
+				err = mnvm_miscErr;
+			}
+		}
+		if (mnvm_noErr != err) {
+			PbufDispose(i);
+		} else {
+			*r = i;
+		}
+	}
+
+	return err;
+}
+#endif
+
+
+#if EmLocalTalk
+
+#include "BPFILTER.h"
+
+#endif
+
+
+/* --- control mode and internationalization --- */
+
+#define WantKeyboard_RemapMac 1
+
+#include "CONTROLM.h"
+
+
+/* --- video out --- */
+
+LOCALVAR WindowPtr gMyMainWindow = NULL;
+LOCALVAR WindowPtr gMyOldWindow = NULL;
+
+#if MayFullScreen
+LOCALVAR short hOffset;
+LOCALVAR short vOffset;
+#endif
+
+#if MayFullScreen
+LOCALVAR blnr GrabMachine = falseblnr;
+#endif
+
+#if VarFullScreen
+LOCALVAR blnr UseFullScreen = (WantInitFullScreen != 0);
+#endif
+
+#if EnableMagnify
+LOCALVAR blnr UseMagnify = (WantInitMagnify != 0);
+#endif
+
+#if EnableMagnify
+LOCALPROC MyScaleRect(Rect *r)
+{
+	r->left *= MyWindowScale;
+	r->right *= MyWindowScale;
+	r->top *= MyWindowScale;
+	r->bottom *= MyWindowScale;
+}
+#endif
+
+LOCALPROC SetScrnRectFromCoords(Rect *r,
+	si4b top, si4b left, si4b bottom, si4b right)
+{
+	r->left = left;
+	r->right = right;
+	r->top = top;
+	r->bottom = bottom;
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		OffsetRect(r, - ViewHStart, - ViewVStart);
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+		MyScaleRect(r);
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		OffsetRect(r, hOffset, vOffset);
+	}
+#endif
+}
+
+LOCALVAR ui3p ScalingBuff = nullpr;
+
+LOCALVAR ui3p CLUT_final;
+
+#define CLUT_finalsz1 (256 * 8)
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+
+#define CLUT_finalClrSz (256 << (5 - vMacScreenDepth))
+
+#define CLUT_finalsz ((CLUT_finalClrSz > CLUT_finalsz1) \
+	? CLUT_finalClrSz : CLUT_finalsz1)
+
+#else
+#define CLUT_finalsz CLUT_finalsz1
+#endif
+
+
+#define ScrnMapr_DoMap UpdateBWLuminanceCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 3
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+
+#define ScrnMapr_DoMap UpdateMappedColorCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#endif
+
+#if vMacScreenDepth >= 4
+
+#define ScrnTrns_DoTrans UpdateTransColorCopy
+#define ScrnTrns_Src GetCurDrawBuff()
+#define ScrnTrns_Dst ScalingBuff
+#define ScrnTrns_SrcDepth vMacScreenDepth
+#define ScrnTrns_DstDepth 5
+#define ScrnTrns_DstZLo 1
+
+#include "SCRNTRNS.h"
+
+#endif
+
+LOCALPROC UpdateLuminanceCopy(si4b top, si4b left,
+	si4b bottom, si4b right)
+{
+	int i;
+
+#if 0 != vMacScreenDepth
+	if (UseColorMode) {
+
+#if vMacScreenDepth < 4
+
+		if (! ColorTransValid) {
+			int j;
+			int k;
+			ui5p p4;
+
+			p4 = (ui5p)CLUT_final;
+			for (i = 0; i < 256; ++i) {
+				for (k = 1 << (3 - vMacScreenDepth); --k >= 0; ) {
+					j = (i >> (k << vMacScreenDepth)) & (CLUT_size - 1);
+					*p4++ = (((long)CLUT_reds[j] & 0xFF00) << 16)
+						| (((long)CLUT_greens[j] & 0xFF00) << 8)
+						| ((long)CLUT_blues[j] & 0xFF00);
+				}
+			}
+			ColorTransValid = trueblnr;
+		}
+
+		UpdateMappedColorCopy(top, left, bottom, right);
+
+#else
+		UpdateTransColorCopy(top, left, bottom, right);
+#endif
+
+	} else
+#endif
+	{
+		if (! ColorTransValid) {
+			int k;
+			ui3p p4 = (ui3p)CLUT_final;
+
+			for (i = 0; i < 256; ++i) {
+				for (k = 8; --k >= 0; ) {
+					*p4++ = ((i >> k) & 0x01) - 1;
+				}
+			}
+			ColorTransValid = trueblnr;
+		}
+
+		UpdateBWLuminanceCopy(top, left, bottom, right);
+	}
+}
+
+LOCALVAR AGLContext ctx = NULL;
+LOCALVAR short GLhOffset;
+LOCALVAR short GLvOffset;
+
+#ifndef UseAGLdoublebuff
+#define UseAGLdoublebuff 0
+#endif
+
+LOCALPROC MyDrawWithOpenGL(ui4r top, ui4r left, ui4r bottom, ui4r right)
+{
+	if (NULL == ctx) {
+		/* oops */
+	} else if (GL_TRUE != aglSetCurrentContext(ctx)) {
+		/* err = aglReportError() */
+	} else {
+		si4b top2;
+		si4b left2;
+
+#if UseAGLdoublebuff
+		/* redraw all */
+		top = 0;
+		left = 0;
+		bottom = vMacScreenHeight;
+		right = vMacScreenWidth;
+#endif
+
+#if VarFullScreen
+		if (UseFullScreen)
+#endif
+#if MayFullScreen
+		{
+			if (top < ViewVStart) {
+				top = ViewVStart;
+			}
+			if (left < ViewHStart) {
+				left = ViewHStart;
+			}
+			if (bottom > ViewVStart + ViewVSize) {
+				bottom = ViewVStart + ViewVSize;
+			}
+			if (right > ViewHStart + ViewHSize) {
+				right = ViewHStart + ViewHSize;
+			}
+
+			if ((top >= bottom) || (left >= right)) {
+				goto label_exit;
+			}
+		}
+#endif
+
+		top2 = top;
+		left2 = left;
+
+#if VarFullScreen
+		if (UseFullScreen)
+#endif
+#if MayFullScreen
+		{
+			left2 -= ViewHStart;
+			top2 -= ViewVStart;
+		}
+#endif
+
+#if EnableMagnify
+		if (UseMagnify) {
+			top2 *= MyWindowScale;
+			left2 *= MyWindowScale;
+		}
+#endif
+
+#if 0
+		glClear(GL_COLOR_BUFFER_BIT);
+		glBitmap(vMacScreenWidth,
+			vMacScreenHeight,
+			0,
+			0,
+			0,
+			0,
+			(const GLubyte *)GetCurDrawBuff());
+#endif
+#if 1
+		UpdateLuminanceCopy(top, left, bottom, right);
+		glRasterPos2i(GLhOffset + left2, GLvOffset - top2);
+#if 0 != vMacScreenDepth
+		if (UseColorMode) {
+			glDrawPixels(right - left,
+				bottom - top,
+				GL_RGBA,
+				GL_UNSIGNED_INT_8_8_8_8,
+				ScalingBuff + (left + top * vMacScreenWidth) * 4
+				);
+		} else
+#endif
+		{
+			glDrawPixels(right - left,
+				bottom - top,
+				GL_LUMINANCE,
+				GL_UNSIGNED_BYTE,
+				ScalingBuff + (left + top * vMacScreenWidth)
+				);
+		}
+#endif
+
+#if 0 /* a very quick and dirty check of where drawing */
+		glDrawPixels(right - left,
+			1,
+			GL_RED,
+			GL_UNSIGNED_BYTE,
+			ScalingBuff + (left + top * vMacScreenWidth)
+			);
+
+		glDrawPixels(1,
+			bottom - top,
+			GL_RED,
+			GL_UNSIGNED_BYTE,
+			ScalingBuff + (left + top * vMacScreenWidth)
+			);
+#endif
+
+#if UseAGLdoublebuff
+		aglSwapBuffers(ctx);
+#else
+		glFlush();
+#endif
+	}
+
+#if MayFullScreen
+label_exit:
+	;
+#endif
+}
+
+LOCALPROC Update_Screen(void)
+{
+	MyDrawWithOpenGL(0, 0, vMacScreenHeight, vMacScreenWidth);
+}
+
+LOCALPROC MyDrawChangesAndClear(void)
+{
+	if (ScreenChangedBottom > ScreenChangedTop) {
+		MyDrawWithOpenGL(ScreenChangedTop, ScreenChangedLeft,
+			ScreenChangedBottom, ScreenChangedRight);
+		ScreenClearChanges();
+	}
+}
+
+
+LOCALVAR blnr MouseIsOutside = falseblnr;
+	/*
+		MouseIsOutside true if sure mouse outside our window. If in
+		our window, or not sure, set false.
+	*/
+
+LOCALVAR blnr WantCursorHidden = falseblnr;
+
+LOCALPROC MousePositionNotify(Point NewMousePos)
+{
+	/*
+		Not MouseIsOutside includes in the title bar, etc, so have
+		to check if in content area.
+	*/
+
+	Rect r;
+	blnr ShouldHaveCursorHidden = ! MouseIsOutside;
+
+	GetWindowBounds(gMyMainWindow, kWindowContentRgn, &r);
+
+	NewMousePos.h -= r.left;
+	NewMousePos.v -= r.top;
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		NewMousePos.h -= hOffset;
+		NewMousePos.v -= vOffset;
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+		NewMousePos.h /= MyWindowScale;
+		NewMousePos.v /= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		NewMousePos.h += ViewHStart;
+		NewMousePos.v += ViewVStart;
+	}
+#endif
+
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		MyMousePositionSetDelta(NewMousePos.h - SavedMouseH,
+			NewMousePos.v - SavedMouseV);
+		SavedMouseH = NewMousePos.h;
+		SavedMouseV = NewMousePos.v;
+	} else
+#endif
+	{
+		if (NewMousePos.h < 0) {
+			NewMousePos.h = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePos.h >= vMacScreenWidth) {
+			NewMousePos.h = vMacScreenWidth - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+		if (NewMousePos.v < 0) {
+			NewMousePos.v = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePos.v >= vMacScreenHeight) {
+			NewMousePos.v = vMacScreenHeight - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+
+		/* if (ShouldHaveCursorHidden || CurMouseButton) */
+		/*
+			for a game like arkanoid, would like mouse to still
+			move even when outside window in one direction
+		*/
+		MyMousePositionSet(NewMousePos.h, NewMousePos.v);
+	}
+
+	WantCursorHidden = ShouldHaveCursorHidden;
+}
+
+LOCALPROC CheckMouseState(void)
+{
+	Point NewMousePos;
+	GetGlobalMouse(&NewMousePos);
+		/*
+			Deprecated, but haven't found usable replacement.
+			Between window deactivate and then reactivate,
+			mouse can move without getting kEventMouseMoved.
+			Also no way to get initial position.
+			(Also don't get kEventMouseMoved after
+			using menu bar. Or while using menubar, but
+			that isn't too important.)
+		*/
+	MousePositionNotify(NewMousePos);
+}
+
+LOCALVAR blnr gLackFocusFlag = falseblnr;
+LOCALVAR blnr gWeAreActive = falseblnr;
+
+GLOBALOSGLUPROC DoneWithDrawingForTick(void)
+{
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		AutoScrollScreen();
+	}
+#endif
+	MyDrawChangesAndClear();
+}
+
+LOCALVAR blnr CurSpeedStopped = trueblnr;
+
+/* --- keyboard --- */
+
+LOCALVAR UInt32 SavedModifiers = 0;
+
+LOCALPROC MyUpdateKeyboardModifiers(UInt32 theModifiers)
+{
+	UInt32 ChangedModifiers = theModifiers ^ SavedModifiers;
+
+	if (0 != ChangedModifiers) {
+		if (0 != (ChangedModifiers & shiftKey)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_Shift,
+				(shiftKey & theModifiers) != 0);
+		}
+		if (0 != (ChangedModifiers & cmdKey)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_Command,
+				(cmdKey & theModifiers) != 0);
+		}
+		if (0 != (ChangedModifiers & alphaLock)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_CapsLock,
+				(alphaLock & theModifiers) != 0);
+		}
+		if (0 != (ChangedModifiers & optionKey)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_Option,
+				(optionKey & theModifiers) != 0);
+		}
+		if (0 != (ChangedModifiers & controlKey)) {
+			Keyboard_UpdateKeyMap2(MKC_formac_Control,
+				(controlKey & theModifiers) != 0);
+		}
+
+		SavedModifiers = theModifiers;
+	}
+}
+
+LOCALPROC ReconnectKeyCodes3(void)
+{
+	/*
+		turn off any modifiers (other than alpha)
+		that were turned on by drag and drop,
+		unless still being held down.
+	*/
+
+	UInt32 theModifiers = GetCurrentKeyModifiers();
+
+	MyUpdateKeyboardModifiers(theModifiers
+		& (SavedModifiers | alphaLock));
+
+	SavedModifiers = theModifiers;
+}
+
+/* --- display utilities --- */
+
+/* DoForEachDisplay adapted from Apple Technical Q&A QA1168 */
+
+typedef void
+(*ForEachDisplayProcPtr) (CGDirectDisplayID display);
+
+LOCALPROC DoForEachDisplay0(CGDisplayCount dspCount,
+	CGDirectDisplayID *displays, ForEachDisplayProcPtr p)
+{
+	CGDisplayCount i;
+
+	if (noErr == MyCGGetActiveDisplayList(dspCount,
+		displays, &dspCount))
+	{
+		for (i = 0; i < dspCount; ++i) {
+			p(displays[i]);
+		}
+	}
+}
+
+LOCALPROC DoForEachDisplay(ForEachDisplayProcPtr p)
+{
+	CGDisplayCount dspCount = 0;
+
+	if (HaveMyCGGetActiveDisplayList()
+		&& (noErr == MyCGGetActiveDisplayList(0, NULL, &dspCount)))
+	{
+		if (dspCount <= 2) {
+			CGDirectDisplayID displays[2];
+			DoForEachDisplay0(dspCount, displays, p);
+		} else {
+			CGDirectDisplayID *displays =
+				calloc((size_t)dspCount, sizeof(CGDirectDisplayID));
+			if (NULL != displays) {
+				DoForEachDisplay0(dspCount, displays, p);
+				free(displays);
+			}
+		}
+	}
+}
+
+LOCALVAR void *datp;
+
+LOCALPROC MyMainDisplayIDProc(CGDirectDisplayID display)
+{
+	CGDirectDisplayID *p = (CGDirectDisplayID *)datp;
+
+	if (kCGNullDirectDisplay == *p) {
+		*p = display;
+	}
+}
+
+LOCALFUNC CGDirectDisplayID MyMainDisplayID(void)
+{
+	if (HaveMyCGMainDisplayID()) {
+		return MyCGMainDisplayID();
+	} else {
+		/* for before OS X 10.2 */
+		CGDirectDisplayID r = kCGNullDirectDisplay;
+		void *savedatp = datp;
+		datp = (void *)&r;
+		DoForEachDisplay(MyMainDisplayIDProc);
+		datp = savedatp;
+		return r;
+	}
+}
+
+/* --- cursor hiding --- */
+
+#if 0
+LOCALPROC MyShowCursorProc(CGDirectDisplayID display)
+{
+	(void) CGDisplayShowCursor(display);
+}
+#endif
+
+LOCALPROC MyShowCursor(void)
+{
+#if 0
+	/* ShowCursor(); deprecated */
+	DoForEachDisplay(MyShowCursorProc);
+#endif
+	if (HaveMyCGDisplayShowCursor()) {
+		(void) MyCGDisplayShowCursor(MyMainDisplayID());
+			/* documentation now claims argument ignored */
+	}
+}
+
+#if 0
+LOCALPROC MyHideCursorProc(CGDirectDisplayID display)
+{
+	(void) CGDisplayHideCursor(display);
+}
+#endif
+
+LOCALPROC MyHideCursor(void)
+{
+#if 0
+	/* HideCursor(); deprecated */
+	DoForEachDisplay(MyHideCursorProc);
+#endif
+	if (HaveMyCGDisplayHideCursor()) {
+		(void) MyCGDisplayHideCursor(MyMainDisplayID());
+			/* documentation now claims argument ignored */
+	}
+}
+
+LOCALVAR blnr HaveCursorHidden = falseblnr;
+
+LOCALPROC ForceShowCursor(void)
+{
+	if (HaveCursorHidden) {
+		HaveCursorHidden = falseblnr;
+		MyShowCursor();
+	}
+}
+
+/* --- cursor moving --- */
+
+LOCALPROC SetCursorArrow(void)
+{
+	SetThemeCursor(kThemeArrowCursor);
+}
+
+#if EnableMoveMouse
+LOCALFUNC blnr MyMoveMouse(si4b h, si4b v)
+{
+	Point CurMousePos;
+	Rect r;
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		h -= ViewHStart;
+		v -= ViewVStart;
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+		h *= MyWindowScale;
+		v *= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		h += hOffset;
+		v += vOffset;
+	}
+#endif
+
+	GetWindowBounds(gMyMainWindow, kWindowContentRgn, &r);
+	CurMousePos.h = r.left + h;
+	CurMousePos.v = r.top + v;
+
+	/*
+		This method from SDL_QuartzWM.m, "Simple DirectMedia Layer",
+		Copyright (C) 1997-2003 Sam Lantinga
+	*/
+	if (HaveMyCGSetLocalEventsSuppressionInterval()) {
+		if (noErr != MyCGSetLocalEventsSuppressionInterval(0.0)) {
+			/* don't use MacMsg which can call MyMoveMouse */
+		}
+	}
+	if (HaveMyCGWarpMouseCursorPosition()) {
+		CGPoint pt;
+		pt.x = CurMousePos.h;
+		pt.y = CurMousePos.v;
+		if (noErr != MyCGWarpMouseCursorPosition(pt)) {
+			/* don't use MacMsg which can call MyMoveMouse */
+		}
+	}
+#if 0
+	if (HaveMyCGDisplayMoveCursorToPoint()) {
+		CGPoint pt;
+		pt.x = CurMousePos.h;
+		pt.y = CurMousePos.v;
+		if (noErr != MyCGDisplayMoveCursorToPoint(
+			MyMainDisplayID(), pt))
+		{
+			/* don't use MacMsg which can call MyMoveMouse */
+		}
+	}
+#endif
+
+	return trueblnr;
+}
+#endif
+
+#if EnableFSMouseMotion
+LOCALPROC AdjustMouseMotionGrab(void)
+{
+	if (gMyMainWindow != NULL) {
+#if MayFullScreen
+		if (GrabMachine) {
+			/*
+				if magnification changes, need to reset,
+				even if HaveMouseMotion already true
+			*/
+			if (MyMoveMouse(ViewHStart + (ViewHSize / 2),
+				ViewVStart + (ViewVSize / 2)))
+			{
+				SavedMouseH = ViewHStart + (ViewHSize / 2);
+				SavedMouseV = ViewVStart + (ViewVSize / 2);
+				HaveMouseMotion = trueblnr;
+			}
+		} else
+#endif
+		{
+			if (HaveMouseMotion) {
+				(void) MyMoveMouse(CurMouseH, CurMouseV);
+				HaveMouseMotion = falseblnr;
+			}
+		}
+	}
+}
+#endif
+
+#if EnableFSMouseMotion
+LOCALPROC MyMouseConstrain(void)
+{
+	si4b shiftdh;
+	si4b shiftdv;
+
+	if (SavedMouseH < ViewHStart + (ViewHSize / 4)) {
+		shiftdh = ViewHSize / 2;
+	} else if (SavedMouseH > ViewHStart + ViewHSize - (ViewHSize / 4)) {
+		shiftdh = - ViewHSize / 2;
+	} else {
+		shiftdh = 0;
+	}
+	if (SavedMouseV < ViewVStart + (ViewVSize / 4)) {
+		shiftdv = ViewVSize / 2;
+	} else if (SavedMouseV > ViewVStart + ViewVSize - (ViewVSize / 4)) {
+		shiftdv = - ViewVSize / 2;
+	} else {
+		shiftdv = 0;
+	}
+	if ((shiftdh != 0) || (shiftdv != 0)) {
+		SavedMouseH += shiftdh;
+		SavedMouseV += shiftdv;
+		if (! MyMoveMouse(SavedMouseH, SavedMouseV)) {
+			HaveMouseMotion = falseblnr;
+		}
+	}
+}
+#endif
+
+#if 0
+LOCALFUNC blnr InitMousePosition(void)
+{
+	/*
+		Since there doesn't seem to be any nondeprecated
+		way to get initial cursor position, instead
+		start by moving cursor to known position.
+	*/
+
+#if VarFullScreen
+	if (! UseFullScreen)
+#endif
+#if MayNotFullScreen
+	{
+		CurMouseH = 16;
+		CurMouseV = 16;
+		WantCursorHidden = trueblnr;
+		(void) MyMoveMouse(CurMouseH, CurMouseV);
+	}
+#endif
+
+	return trueblnr;
+}
+#endif
+
+/* --- time, date, location, part 2 --- */
+
+#include "DATE2SEC.h"
+
+LOCALFUNC blnr InitLocationDat(void)
+{
+#if AutoLocation || AutoTimeZone
+	MachineLocation loc;
+
+	ReadLocation(&loc);
+#if AutoLocation
+	CurMacLatitude = (ui5b)loc.latitude;
+	CurMacLongitude = (ui5b)loc.longitude;
+#endif
+#if AutoTimeZone
+	CurMacDelta = (ui5b)loc.u.gmtDelta;
+#endif
+#endif
+
+	{
+		CFTimeZoneRef tz = CFTimeZoneCopySystem();
+		if (tz) {
+			/* CFAbsoluteTime */ ATimeBase = CFAbsoluteTimeGetCurrent();
+			/* ETimeBase = GetCurrentEventTime(); */
+			{
+				CFGregorianDate d = CFAbsoluteTimeGetGregorianDate(
+					ATimeBase, tz);
+				double floorsec = floor(d.second);
+				ATimeBase -= (d.second - floorsec);
+				/* ETimeBase -= (d.second - floorsec); */
+				TimeSecBase = Date2MacSeconds(floorsec,
+					d.minute, d.hour,
+					d.day, d.month, d.year);
+
+				(void) CheckDateTime();
+			}
+			CFRelease(tz);
+		}
+	}
+
+	OnTrueTime = TrueEmulatedTime;
+
+	return trueblnr;
+}
+
+LOCALPROC StartUpTimeAdjust(void)
+{
+	NextTickChangeTime = GetCurrentEventTime() + MyTickDuration;
+}
+
+/* --- sound --- */
+
+#if MySoundEnabled
+
+#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */
+#define kSoundBuffers (1 << kLn2SoundBuffers)
+#define kSoundBuffMask (kSoundBuffers - 1)
+
+#define DesiredMinFilledSoundBuffs 3
+	/*
+		if too big then sound lags behind emulation.
+		if too small then sound will have pauses.
+	*/
+
+#define kLnOneBuffLen 9
+#define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen)
+#define kOneBuffLen (1UL << kLnOneBuffLen)
+#define kAllBuffLen (1UL << kLnAllBuffLen)
+#define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3)
+#define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3)
+#define kOneBuffSz (1UL << kLnOneBuffSz)
+#define kAllBuffSz (1UL << kLnAllBuffSz)
+#define kOneBuffMask (kOneBuffLen - 1)
+#define kAllBuffMask (kAllBuffLen - 1)
+#define dbhBufferSize (kAllBuffSz + kOneBuffSz)
+
+#define dbglog_SoundStuff (0 && dbglog_HAVE)
+#define dbglog_SoundBuffStats (0 && dbglog_HAVE)
+
+LOCALVAR tpSoundSamp TheSoundBuffer = nullpr;
+volatile static ui4b ThePlayOffset;
+volatile static ui4b TheFillOffset;
+volatile static ui4b MinFilledSoundBuffs;
+#if dbglog_SoundBuffStats
+LOCALVAR ui4b MaxFilledSoundBuffs;
+#endif
+LOCALVAR ui4b TheWriteOffset;
+
+LOCALPROC MySound_Start0(void)
+{
+	/* Reset variables */
+	ThePlayOffset = 0;
+	TheFillOffset = 0;
+	TheWriteOffset = 0;
+	MinFilledSoundBuffs = kSoundBuffers + 1;
+#if dbglog_SoundBuffStats
+	MaxFilledSoundBuffs = 0;
+#endif
+}
+
+GLOBALOSGLUFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL)
+{
+	ui4b ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset);
+	ui4b WriteBuffContig =
+		kOneBuffLen - (TheWriteOffset & kOneBuffMask);
+
+	if (WriteBuffContig < n) {
+		n = WriteBuffContig;
+	}
+	if (ToFillLen < n) {
+		/* overwrite previous buffer */
+#if dbglog_SoundStuff
+		dbglog_writeln("sound buffer over flow");
+#endif
+		TheWriteOffset -= kOneBuffLen;
+	}
+
+	*actL = n;
+	return TheSoundBuffer + (TheWriteOffset & kAllBuffMask);
+}
+
+#if 4 == kLn2SoundSampSz
+LOCALPROC ConvertSoundBlockToNative(tpSoundSamp p)
+{
+	int i;
+
+	for (i = kOneBuffLen; --i >= 0; ) {
+		*p++ -= 0x8000;
+	}
+}
+#else
+#define ConvertSoundBlockToNative(p)
+#endif
+
+LOCALPROC MySound_WroteABlock(void)
+{
+#if (4 == kLn2SoundSampSz)
+	ui4b PrevWriteOffset = TheWriteOffset - kOneBuffLen;
+	tpSoundSamp p = TheSoundBuffer + (PrevWriteOffset & kAllBuffMask);
+#endif
+
+#if dbglog_SoundStuff
+	dbglog_writeln("enter MySound_WroteABlock");
+#endif
+
+	ConvertSoundBlockToNative(p);
+
+	TheFillOffset = TheWriteOffset;
+
+#if dbglog_SoundBuffStats
+	{
+		ui4b ToPlayLen = TheFillOffset
+			- ThePlayOffset;
+		ui4b ToPlayBuffs = ToPlayLen >> kLnOneBuffLen;
+
+		if (ToPlayBuffs > MaxFilledSoundBuffs) {
+			MaxFilledSoundBuffs = ToPlayBuffs;
+		}
+	}
+#endif
+}
+
+LOCALFUNC blnr MySound_EndWrite0(ui4r actL)
+{
+	blnr v;
+
+	TheWriteOffset += actL;
+
+	if (0 != (TheWriteOffset & kOneBuffMask)) {
+		v = falseblnr;
+	} else {
+		/* just finished a block */
+
+		MySound_WroteABlock();
+
+		v = trueblnr;
+	}
+
+	return v;
+}
+
+LOCALPROC MySound_SecondNotify0(void)
+{
+	if (MinFilledSoundBuffs <= kSoundBuffers) {
+		if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) {
+#if dbglog_SoundStuff
+			dbglog_writeln("MinFilledSoundBuffs too high");
+#endif
+			NextTickChangeTime += MyTickDuration;
+		} else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) {
+#if dbglog_SoundStuff
+			dbglog_writeln("MinFilledSoundBuffs too low");
+#endif
+			++TrueEmulatedTime;
+		}
+#if dbglog_SoundBuffStats
+		dbglog_writelnNum("MinFilledSoundBuffs",
+			MinFilledSoundBuffs);
+		dbglog_writelnNum("MaxFilledSoundBuffs",
+			MaxFilledSoundBuffs);
+		MaxFilledSoundBuffs = 0;
+#endif
+		MinFilledSoundBuffs = kSoundBuffers + 1;
+	}
+}
+
+LOCALPROC RampSound(tpSoundSamp p,
+	trSoundSamp BeginVal, trSoundSamp EndVal)
+{
+	int i;
+	ui5r v = (((ui5r)BeginVal) << kLnOneBuffLen) + (kLnOneBuffLen >> 1);
+
+	for (i = kOneBuffLen; --i >= 0; ) {
+		*p++ = v >> kLnOneBuffLen;
+		v = v + EndVal - BeginVal;
+	}
+}
+
+#if 4 == kLn2SoundSampSz
+#define ConvertSoundSampleFromNative(v) ((v) + 0x8000)
+#else
+#define ConvertSoundSampleFromNative(v) (v)
+#endif
+
+struct MySoundR {
+	tpSoundSamp fTheSoundBuffer;
+	volatile ui4b (*fPlayOffset);
+	volatile ui4b (*fFillOffset);
+	volatile ui4b (*fMinFilledSoundBuffs);
+
+	volatile blnr PlayingBuffBlock;
+	volatile trSoundSamp lastv;
+	volatile blnr wantplaying;
+	volatile blnr StartingBlocks;
+
+	CmpSoundHeader /* ExtSoundHeader */ soundHeader;
+};
+typedef struct MySoundR   MySoundR;
+
+
+/*
+	Some of this code descended from CarbonSndPlayDB, an
+	example from Apple, as found being used in vMac for Mac OS.
+*/
+
+LOCALPROC InsertSndDoCommand(SndChannelPtr chan, SndCommand * newCmd)
+{
+	if (-1 == chan->qHead) {
+		chan->qHead = chan->qTail;
+	}
+
+	if (1 <= chan->qHead) {
+		chan->qHead--;
+	} else {
+		chan->qHead = chan->qTail;
+	}
+
+	chan->queue[chan->qHead] = *newCmd;
+}
+
+/* call back */ static pascal void
+MySound_CallBack(SndChannelPtr theChannel, SndCommand * theCallBackCmd)
+{
+	MySoundR *datp =
+		(MySoundR *)(theCallBackCmd->param2);
+	blnr wantplaying0 = datp->wantplaying;
+	trSoundSamp v0 = datp->lastv;
+
+#if dbglog_SoundStuff
+	dbglog_writeln("Enter MySound_CallBack");
+#endif
+
+	if (datp->PlayingBuffBlock) {
+		/* finish with last sample */
+#if dbglog_SoundStuff
+		dbglog_writeln("done with sample");
+#endif
+
+		*datp->fPlayOffset += kOneBuffLen;
+		datp->PlayingBuffBlock = falseblnr;
+	}
+
+	if ((! wantplaying0) && (kCenterSound == v0)) {
+#if dbglog_SoundStuff
+		dbglog_writeln("terminating");
+#endif
+	} else {
+		SndCommand playCmd;
+		tpSoundSamp p;
+		trSoundSamp v1 = v0;
+		blnr WantRamp = falseblnr;
+		ui4b CurPlayOffset = *datp->fPlayOffset;
+		ui4b ToPlayLen = *datp->fFillOffset - CurPlayOffset;
+		ui4b FilledSoundBuffs = ToPlayLen >> kLnOneBuffLen;
+
+		if (FilledSoundBuffs < *datp->fMinFilledSoundBuffs) {
+			*datp->fMinFilledSoundBuffs = FilledSoundBuffs;
+		}
+
+		if (! wantplaying0) {
+#if dbglog_SoundStuff
+			dbglog_writeln("playing end transistion");
+#endif
+			v1 = kCenterSound;
+
+			WantRamp = trueblnr;
+		} else
+		if (datp->StartingBlocks) {
+#if dbglog_SoundStuff
+			dbglog_writeln("playing start block");
+#endif
+
+			if ((ToPlayLen >> kLnOneBuffLen) < 12) {
+				datp->StartingBlocks = falseblnr;
+#if dbglog_SoundStuff
+				dbglog_writeln("have enough samples to start");
+#endif
+
+				p = datp->fTheSoundBuffer
+					+ (CurPlayOffset & kAllBuffMask);
+				v1 = ConvertSoundSampleFromNative(*p);
+			}
+
+			WantRamp = trueblnr;
+		} else
+		if (0 == FilledSoundBuffs) {
+#if dbglog_SoundStuff
+			dbglog_writeln("playing under run");
+#endif
+
+			WantRamp = trueblnr;
+		} else
+		{
+			/* play next sample */
+			p = datp->fTheSoundBuffer
+				+ (CurPlayOffset & kAllBuffMask);
+			datp->PlayingBuffBlock = trueblnr;
+			v1 =
+				ConvertSoundSampleFromNative(*(p + kOneBuffLen - 1));
+#if dbglog_SoundStuff
+			dbglog_writeln("playing sample");
+#endif
+		}
+
+		if (WantRamp) {
+			p = datp->fTheSoundBuffer + kAllBuffLen;
+
+#if dbglog_SoundStuff
+			dbglog_writelnNum("v0", v0);
+			dbglog_writelnNum("v1", v1);
+#endif
+
+			RampSound(p, v0, v1);
+			ConvertSoundBlockToNative(p);
+		}
+
+		datp->soundHeader.samplePtr = (Ptr)p;
+		datp->soundHeader.numFrames =
+			(unsigned long)kOneBuffLen;
+
+		/* Insert our callback command */
+		InsertSndDoCommand (theChannel, theCallBackCmd);
+
+#if 0
+		{
+			int i;
+			tpSoundSamp pS =
+				(tpSoundSamp)datp->soundHeader.samplePtr;
+
+			for (i = datp->soundHeader.numFrames; --i >= 0; )
+			{
+				fprintf(stderr, "%d\n", *pS++);
+			}
+		}
+#endif
+
+		/* Play the next buffer */
+		playCmd.cmd = bufferCmd;
+		playCmd.param1 = 0;
+		playCmd.param2 = (long)&(datp->soundHeader);
+		InsertSndDoCommand (theChannel, &playCmd);
+
+		datp->lastv = v1;
+	}
+}
+
+LOCALVAR MySoundR cur_audio;
+
+LOCALVAR SndCallBackUPP gCarbonSndPlayDoubleBufferCallBackUPP = NULL;
+
+LOCALVAR SndChannelPtr sndChannel = NULL; /* our sound channel */
+
+LOCALPROC MySound_Start(void)
+{
+#if dbglog_SoundStuff
+	dbglog_writeln("MySound_Start");
+#endif
+
+	if (NULL == sndChannel) {
+		SndCommand callBack;
+		SndChannelPtr chan = NULL;
+
+		cur_audio.wantplaying = falseblnr;
+		cur_audio.StartingBlocks = falseblnr;
+
+		MySound_Start0();
+
+		SndNewChannel(&chan, sampledSynth, initMono, nil);
+		if (NULL != chan) {
+			sndChannel = chan;
+
+			cur_audio.PlayingBuffBlock = falseblnr;
+			cur_audio.lastv = kCenterSound;
+			cur_audio.StartingBlocks = trueblnr;
+			cur_audio.wantplaying = trueblnr;
+
+			callBack.cmd = callBackCmd;
+			callBack.param1 = 0; /* unused */
+			callBack.param2 = (long)&cur_audio;
+
+			sndChannel->callBack =
+				gCarbonSndPlayDoubleBufferCallBackUPP;
+
+			(void) SndDoCommand (sndChannel, &callBack, true);
+		}
+	}
+}
+
+LOCALPROC MySound_Stop(void)
+{
+#if dbglog_SoundStuff
+	dbglog_writeln("enter MySound_Stop");
+#endif
+
+	if (NULL != sndChannel) {
+		ui4r retry_limit = 50; /* half of a second */
+		SCStatus r;
+
+		cur_audio.wantplaying = falseblnr;
+#if dbglog_SoundStuff
+		dbglog_writeln("cleared wantplaying");
+#endif
+
+label_retry:
+		r.scChannelBusy = falseblnr; /* what is this for? */
+		if (noErr != SndChannelStatus(sndChannel,
+			sizeof(SCStatus), &r))
+		{
+			/* fail */
+		} else
+		if ((! r.scChannelBusy) && (kCenterSound == cur_audio.lastv)) {
+			/* done */
+
+			/*
+				observed reporting not busy unexpectedly,
+				so also check lastv.
+			*/
+		} else
+		if (0 == --retry_limit) {
+#if dbglog_SoundStuff
+			dbglog_writeln("retry limit reached");
+#endif
+			/*
+				don't trust SndChannelStatus, make
+				sure don't get in infinite loop.
+			*/
+
+			/* done */
+		} else
+		{
+			/*
+				give time back, particularly important
+				if got here on a suspend event.
+			*/
+			struct timespec rqt;
+			struct timespec rmt;
+
+#if dbglog_SoundStuff
+			dbglog_writeln("busy, so sleep");
+#endif
+
+			rqt.tv_sec = 0;
+			rqt.tv_nsec = 10000000;
+			(void) nanosleep(&rqt, &rmt);
+
+			goto label_retry;
+		}
+
+		SndDisposeChannel(sndChannel, true);
+		sndChannel = NULL;
+	}
+
+#if dbglog_SoundStuff
+	dbglog_writeln("leave MySound_Stop");
+#endif
+}
+
+#define SOUND_SAMPLERATE rate22khz
+	/* = 0x56EE8BA3 = (7833600 * 2 / 704) << 16 */
+
+LOCALFUNC blnr MySound_Init(void)
+{
+#if dbglog_SoundStuff
+	dbglog_writeln("enter MySound_Init");
+#endif
+
+	cur_audio.fTheSoundBuffer = TheSoundBuffer;
+
+	cur_audio.fPlayOffset = &ThePlayOffset;
+	cur_audio.fFillOffset = &TheFillOffset;
+	cur_audio.fMinFilledSoundBuffs = &MinFilledSoundBuffs;
+	cur_audio.wantplaying = falseblnr;
+
+	/* Init basic per channel information */
+	cur_audio.soundHeader.sampleRate = SOUND_SAMPLERATE;
+		/* sample rate */
+	cur_audio.soundHeader.numChannels = 1; /* one channel */
+	cur_audio.soundHeader.loopStart = 0;
+	cur_audio.soundHeader.loopEnd = 0;
+	cur_audio.soundHeader.encode = cmpSH /* extSH */;
+	cur_audio.soundHeader.baseFrequency = kMiddleC;
+	cur_audio.soundHeader.numFrames =
+		(unsigned long)kOneBuffLen;
+	/* cur_audio.soundHeader.AIFFSampleRate = 0; */
+		/* unused */
+	cur_audio.soundHeader.markerChunk = nil;
+	cur_audio.soundHeader.futureUse2 = 0;
+	cur_audio.soundHeader.stateVars = nil;
+	cur_audio.soundHeader.leftOverSamples = nil;
+	cur_audio.soundHeader.compressionID = 0;
+		/* no compression */
+	cur_audio.soundHeader.packetSize = 0;
+		/* no compression */
+	cur_audio.soundHeader.snthID = 0;
+	cur_audio.soundHeader.sampleSize = (1 << kLn2SoundSampSz);
+		/* 8 or 16 bits per sample */
+	cur_audio.soundHeader.sampleArea[0] = 0;
+#if 3 == kLn2SoundSampSz
+	cur_audio.soundHeader.format = kSoundNotCompressed;
+#elif 4 == kLn2SoundSampSz
+	cur_audio.soundHeader.format = k16BitNativeEndianFormat;
+#else
+#error "unsupported kLn2SoundSampSz"
+#endif
+	cur_audio.soundHeader.samplePtr = (Ptr)TheSoundBuffer;
+
+	gCarbonSndPlayDoubleBufferCallBackUPP =
+		NewSndCallBackUPP(MySound_CallBack);
+	if (gCarbonSndPlayDoubleBufferCallBackUPP != NULL) {
+
+		MySound_Start();
+			/*
+				This should be taken care of by LeaveSpeedStopped,
+				but since takes a while to get going properly,
+				start early.
+			*/
+
+		return trueblnr;
+	}
+	return falseblnr;
+}
+
+GLOBALOSGLUPROC MySound_EndWrite(ui4r actL)
+{
+	if (MySound_EndWrite0(actL)) {
+	}
+}
+
+LOCALPROC MySound_SecondNotify(void)
+{
+	if (sndChannel != NULL) {
+		MySound_SecondNotify0();
+	}
+}
+
+#endif
+
+
+LOCALPROC MyAdjustGLforSize(int h, int v)
+{
+	if (GL_TRUE != aglSetCurrentContext(ctx)) {
+		/* err = aglReportError() */
+	} else {
+
+		glClearColor (0.0, 0.0, 0.0, 1.0);
+
+#if 1
+		glViewport(0, 0, h, v);
+		glMatrixMode(GL_PROJECTION);
+		glLoadIdentity();
+		glOrtho(0, h, 0, v, -1.0, 1.0);
+		glMatrixMode(GL_MODELVIEW);
+#endif
+
+		glColor3f(0.0, 0.0, 0.0);
+#if EnableMagnify
+		if (UseMagnify) {
+			glPixelZoom(MyWindowScale, - MyWindowScale);
+		} else
+#endif
+		{
+			glPixelZoom(1, -1);
+		}
+		glPixelStorei(GL_UNPACK_ROW_LENGTH, vMacScreenWidth);
+
+		glClear(GL_COLOR_BUFFER_BIT);
+
+		if (GL_TRUE != aglSetCurrentContext(NULL)) {
+			/* err = aglReportError() */
+		}
+
+		ScreenChangedAll();
+	}
+}
+
+LOCALVAR blnr WantScreensChangedCheck = falseblnr;
+
+LOCALPROC MyUpdateOpenGLContext(void)
+{
+	if (NULL == ctx) {
+		/* oops */
+	} else if (GL_TRUE != aglSetCurrentContext(ctx)) {
+		/* err = aglReportError() */
+	} else {
+		aglUpdateContext(ctx);
+	}
+}
+
+#if 0 /* some experiments */
+LOCALVAR CGrafPtr GrabbedPort = NULL;
+#endif
+
+#if 0
+LOCALPROC AdjustMainScreenGrab(void)
+{
+	if (GrabMachine) {
+		if (NULL == GrabbedPort) {
+			/* CGDisplayCapture(MyMainDisplayID()); */
+			CGCaptureAllDisplays();
+			/* CGDisplayHideCursor( MyMainDisplayID() ); */
+			GrabbedPort =
+				CreateNewPortForCGDisplayID((UInt32)MyMainDisplayID());
+			LockPortBits (GrabbedPort);
+		}
+	} else {
+		if (GrabbedPort != NULL) {
+			UnlockPortBits (GrabbedPort);
+			/* CGDisplayShowCursor( MyMainDisplayID() ); */
+			/* CGDisplayRelease(MyMainDisplayID()); */
+			CGReleaseAllDisplays();
+			GrabbedPort = NULL;
+		}
+	}
+}
+#endif
+
+#if 0
+typedef CGDisplayErr (*CGReleaseAllDisplaysProcPtr)
+	(void);
+
+LOCALPROC MyReleaseAllDisplays(void)
+{
+	if (HaveApplicationServicesBun()) {
+		CGReleaseAllDisplaysProcPtr ReleaseAllDisplaysProc =
+			(CGReleaseAllDisplaysProcPtr)
+			CFBundleGetFunctionPointerForName(
+				AppServBunRef, CFSTR("CGReleaseAllDisplays"));
+		if (ReleaseAllDisplaysProc != NULL) {
+			ReleaseAllDisplaysProc();
+		}
+	}
+}
+
+typedef CGDisplayErr (*CGCaptureAllDisplaysProcPtr)
+	(void);
+
+LOCALPROC MyCaptureAllDisplays(void)
+{
+	if (HaveApplicationServicesBun()) {
+		CGCaptureAllDisplaysProcPtr CaptureAllDisplaysProc =
+			(CGCaptureAllDisplaysProcPtr)
+			CFBundleGetFunctionPointerForName(
+				AppServBunRef, CFSTR("CGCaptureAllDisplays"));
+		if (CaptureAllDisplaysProc != NULL) {
+			CaptureAllDisplaysProc();
+		}
+	}
+}
+#endif
+
+LOCALVAR AGLPixelFormat window_fmt = NULL;
+LOCALVAR AGLContext window_ctx = NULL;
+
+#ifndef UseAGLfullscreen
+#define UseAGLfullscreen 0
+#endif
+
+#if UseAGLfullscreen
+LOCALVAR AGLPixelFormat fullscreen_fmt = NULL;
+LOCALVAR AGLContext fullscreen_ctx = NULL;
+#endif
+
+#if UseAGLfullscreen
+LOCALPROC MaybeFullScreen(void)
+{
+	if (
+#if VarFullScreen
+		UseFullScreen &&
+#endif
+		(NULL == fullscreen_ctx)
+		&& HaveMyCGDisplayPixelsWide()
+		&& HaveMyCGDisplayPixelsHigh())
+	{
+		static const GLint fullscreen_attrib[] = {AGL_RGBA,
+			AGL_NO_RECOVERY,
+			AGL_FULLSCREEN,
+			AGL_SINGLE_RENDERER, AGL_ACCELERATED,
+#if UseAGLdoublebuff
+			AGL_DOUBLEBUFFER,
+#endif
+			AGL_NONE};
+		GDHandle theDevice;
+		CGDirectDisplayID CurMainDisplayID = MyMainDisplayID();
+
+		DMGetGDeviceByDisplayID(
+			(DisplayIDType)CurMainDisplayID, &theDevice, false);
+		fullscreen_fmt = aglChoosePixelFormat(
+			&theDevice, 1, fullscreen_attrib);
+		if (NULL == fullscreen_fmt) {
+			/* err = aglReportError() */
+		} else {
+			fullscreen_ctx = aglCreateContext(fullscreen_fmt, NULL);
+			if (NULL == fullscreen_ctx) {
+				/* err = aglReportError() */
+			} else {
+				/* MyCaptureAllDisplays(); */
+				if (GL_TRUE != aglSetFullScreen(fullscreen_ctx,
+					0, 0, 0, 0))
+				{
+					/* err = aglReportError() */
+				} else {
+					Rect r;
+
+					int h = MyCGDisplayPixelsWide(CurMainDisplayID);
+					int v = MyCGDisplayPixelsHigh(CurMainDisplayID);
+
+					GetWindowBounds(gMyMainWindow, kWindowContentRgn,
+						&r);
+
+					GLhOffset = r.left + hOffset;
+					GLvOffset = v - (r.top + vOffset);
+
+					ctx = fullscreen_ctx;
+					MyAdjustGLforSize(h, v);
+					return;
+				}
+				/* MyReleaseAllDisplays(); */
+
+				if (GL_TRUE != aglDestroyContext(fullscreen_ctx)) {
+					/* err = aglReportError() */
+				}
+				fullscreen_ctx = NULL;
+			}
+
+			aglDestroyPixelFormat (fullscreen_fmt);
+			fullscreen_fmt = NULL;
+		}
+	}
+}
+#endif
+
+#if UseAGLfullscreen
+LOCALPROC NoFullScreen(void)
+{
+	if (fullscreen_ctx != NULL) {
+		Rect r;
+		int h;
+		int v;
+
+		GetWindowBounds(gMyMainWindow, kWindowContentRgn, &r);
+
+		h = r.right - r.left;
+		v = r.bottom - r.top;
+
+		GLhOffset = hOffset;
+		GLvOffset = v - vOffset;
+
+		ctx = window_ctx;
+
+		MyAdjustGLforSize(h, v);
+
+		Update_Screen();
+
+		if (fullscreen_ctx != NULL) {
+			if (GL_TRUE != aglDestroyContext(fullscreen_ctx)) {
+				/* err = aglReportError() */
+			}
+			fullscreen_ctx = NULL;
+		}
+		if (fullscreen_fmt != NULL) {
+			aglDestroyPixelFormat(fullscreen_fmt);
+			fullscreen_fmt = NULL;
+		}
+	}
+}
+#endif
+
+#if UseAGLfullscreen
+LOCALPROC AdjustOpenGLGrab(void)
+{
+	if (GrabMachine) {
+		MaybeFullScreen();
+	} else {
+		NoFullScreen();
+	}
+}
+#endif
+
+#if MayFullScreen
+LOCALPROC AdjustMachineGrab(void)
+{
+#if EnableFSMouseMotion
+	AdjustMouseMotionGrab();
+#endif
+#if UseAGLfullscreen
+	AdjustOpenGLGrab();
+#endif
+#if 0
+	AdjustMainScreenGrab();
+#endif
+}
+#endif
+
+#if MayFullScreen
+LOCALPROC UngrabMachine(void)
+{
+	GrabMachine = falseblnr;
+	AdjustMachineGrab();
+}
+#endif
+
+LOCALPROC ClearWeAreActive(void)
+{
+	if (gWeAreActive) {
+		gWeAreActive = falseblnr;
+
+		DisconnectKeyCodes2();
+
+		SavedModifiers &= alphaLock;
+
+		MyMouseButtonSet(falseblnr);
+
+#if MayFullScreen
+		UngrabMachine();
+#endif
+
+		ForceShowCursor();
+	}
+}
+
+/* --- basic dialogs --- */
+
+LOCALFUNC CFStringRef CFStringCreateFromSubstCStr(char *s)
+{
+	int L;
+	UniChar x[ClStrMaxLength];
+
+	UniCharStrFromSubstCStr(&L, x, s);
+
+	return CFStringCreateWithCharacters(kCFAllocatorDefault, x, L);
+}
+
+#define kMyStandardAlert 128
+
+LOCALPROC CheckSavedMacMsg(void)
+{
+	/* called only on quit, if error saved but not yet reported */
+
+	if (nullpr != SavedBriefMsg) {
+		if (HaveMyCreateStandardAlert() && HaveMyRunStandardAlert()) {
+			CFStringRef briefMsgu = CFStringCreateFromSubstCStr(
+				SavedBriefMsg);
+			if (NULL != briefMsgu) {
+				CFStringRef longMsgu = CFStringCreateFromSubstCStr(
+					SavedLongMsg);
+				if (NULL != longMsgu) {
+					DialogRef TheAlert;
+					OSStatus err = MyCreateStandardAlert(
+						(SavedFatalMsg) ? kAlertStopAlert
+							: kAlertCautionAlert,
+						briefMsgu, longMsgu, NULL,
+						&TheAlert);
+					if (noErr == err) {
+						(void) MyRunStandardAlert(TheAlert, NULL, NULL);
+					}
+					CFRelease(longMsgu);
+				}
+				CFRelease(briefMsgu);
+			}
+		}
+
+		SavedBriefMsg = nullpr;
+	}
+}
+
+LOCALVAR blnr gTrueBackgroundFlag = falseblnr;
+
+LOCALPROC MyBeginDialog(void)
+{
+	ClearWeAreActive();
+}
+
+LOCALPROC MyEndDialog(void)
+{
+}
+
+/* --- hide/show menubar --- */
+
+#if MayFullScreen
+LOCALPROC My_HideMenuBar(void)
+{
+	if (HaveMySetSystemUIMode()) {
+		(void) MySetSystemUIMode(MykUIModeAllHidden,
+			MykUIOptionDisableAppleMenu
+#if GrabKeysFullScreen
+			| MykUIOptionDisableProcessSwitch
+#if GrabKeysMaxFullScreen /* dangerous !! */
+			| MykUIOptionDisableForceQuit
+			| MykUIOptionDisableSessionTerminate
+#endif
+#endif
+			);
+	} else {
+		if (IsMenuBarVisible()) {
+			HideMenuBar();
+		}
+	}
+}
+#endif
+
+#if MayFullScreen
+LOCALPROC My_ShowMenuBar(void)
+{
+	if (HaveMySetSystemUIMode()) {
+		(void) MySetSystemUIMode(MykUIModeNormal,
+			0);
+	} else {
+		if (! IsMenuBarVisible()) {
+			ShowMenuBar();
+		}
+	}
+}
+#endif
+
+/* --- drives, part 2 --- */
+
+LOCALPROC InitDrives(void)
+{
+	/*
+		This isn't really needed, Drives[i]
+		need not have valid value when not vSonyIsInserted[i].
+	*/
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		Drives[i] = NotAfileRef;
+	}
+}
+
+LOCALPROC UnInitDrives(void)
+{
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		if (vSonyIsInserted(i)) {
+			(void) vSonyEject(i);
+		}
+	}
+}
+
+LOCALFUNC tMacErr Sony_Insert0(SInt16 refnum, blnr locked)
+{
+	tDrive Drive_No;
+
+	if (! FirstFreeDisk(&Drive_No)) {
+		(void) FSCloseFork(refnum);
+		return mnvm_tmfoErr;
+	} else {
+		Drives[Drive_No] = refnum;
+		DiskInsertNotify(Drive_No, locked);
+		return mnvm_noErr;
+	}
+}
+
+LOCALPROC ReportStandardOpenDiskError(tMacErr err)
+{
+	if (mnvm_noErr != err) {
+		if (mnvm_tmfoErr == err) {
+			MacMsg(kStrTooManyImagesTitle,
+				kStrTooManyImagesMessage, falseblnr);
+		} else if (mnvm_opWrErr == err) {
+			MacMsg(kStrImageInUseTitle,
+				kStrImageInUseMessage, falseblnr);
+		} else {
+			MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
+		}
+	}
+}
+
+LOCALFUNC tMacErr InsertADiskFromFSRef(FSRef *theRef)
+{
+	tMacErr err;
+	HFSUniStr255 forkName;
+	SInt16 refnum;
+	blnr locked = falseblnr;
+
+	if (CheckSaveMacErr(FSGetDataForkName(&forkName))) {
+		err = To_tMacErr(FSOpenFork(theRef, forkName.length,
+			forkName.unicode, fsRdWrPerm, &refnum));
+		switch (err) {
+			case mnvm_permErr:
+			case mnvm_wrPermErr:
+			case mnvm_afpAccessDenied:
+				locked = trueblnr;
+				err = To_tMacErr(FSOpenFork(theRef, forkName.length,
+					forkName.unicode, fsRdPerm, &refnum));
+				break;
+			default:
+				break;
+		}
+		if (mnvm_noErr == err) {
+			err = Sony_Insert0(refnum, locked);
+		}
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr LoadMacRomFromRefNum(SInt16 refnum)
+{
+	tMacErr err;
+	ByteCount actualCount;
+
+	if (mnvm_noErr != (err = To_tMacErr(
+		FSReadFork(refnum, fsFromStart, 0,
+			kROM_Size, ROM, &actualCount))))
+	{
+		if (mnvm_eofErr == err) {
+			MacMsgOverride(kStrShortROMTitle, kStrShortROMMessage);
+		} else {
+			MacMsgOverride(kStrNoReadROMTitle, kStrNoReadROMMessage);
+		}
+	} else
+	{
+		err = ROM_IsValid();
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr LoadMacRomFromFSRef(FSRef *theRef)
+{
+	tMacErr err;
+	HFSUniStr255 forkName;
+	SInt16 refnum;
+
+	if (mnvm_noErr == (err =
+		To_tMacErr(FSGetDataForkName(&forkName))))
+	if (mnvm_noErr == (err = To_tMacErr(
+		FSOpenFork(theRef, forkName.length,
+			forkName.unicode, fsRdPerm, &refnum))))
+	{
+		err = LoadMacRomFromRefNum(refnum);
+
+		(void) FSCloseFork(refnum);
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr InsertADiskFromFSRef1(FSRef *theRef)
+{
+	tMacErr err;
+
+	if (! ROM_loaded) {
+		err = LoadMacRomFromFSRef(theRef);
+	} else {
+		err = InsertADiskFromFSRef(theRef);
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr InsertDisksFromDocList(AEDescList *docList)
+{
+	tMacErr err = mnvm_noErr;
+	long itemsInList;
+	long index;
+	AEKeyword keyword;
+	DescType typeCode;
+	FSRef theRef;
+	Size actualSize;
+
+	if (CheckSaveMacErr(AECountItems(docList, &itemsInList))) {
+		for (index = 1; index <= itemsInList; ++index) {
+			if (CheckSaveMacErr(AEGetNthPtr(docList, index, typeFSRef,
+				&keyword, &typeCode, (Ptr)&theRef,
+				sizeof(FSRef), &actualSize)))
+			if (CheckSavetMacErr(InsertADiskFromFSRef1(&theRef)))
+			{
+			}
+			if (mnvm_noErr != err) {
+				goto label_fail;
+			}
+		}
+	}
+
+label_fail:
+	return err;
+}
+
+LOCALFUNC tMacErr InsertADiskFromNameEtc(FSRef *ParentRef,
+	char *fileName)
+{
+	tMacErr err;
+	blnr isFolder;
+	FSRef ChildRef;
+
+	if (CheckSavetMacErr(MyMakeFSRefC(ParentRef, fileName,
+		&isFolder, &ChildRef)))
+	{
+		if (isFolder) {
+			err = mnvm_miscErr;
+		} else {
+			if (CheckSavetMacErr(InsertADiskFromFSRef(&ChildRef))) {
+				/* ok */
+			}
+		}
+	}
+
+	return err;
+}
+
+#if IncludeSonyNew
+LOCALFUNC tMacErr WriteZero(SInt16 refnum, ui5b L)
+{
+#define ZeroBufferSize 2048
+	tMacErr err = mnvm_noErr;
+	ui5b i;
+	ui3b buffer[ZeroBufferSize];
+	ByteCount actualCount;
+	ui5b offset = 0;
+
+	memset(&buffer, 0, ZeroBufferSize);
+
+	while (L > 0) {
+		i = (L > ZeroBufferSize) ? ZeroBufferSize : L;
+		if (! CheckSaveMacErr(FSWriteFork(refnum,
+			fsFromStart,
+			offset,
+			i,
+			buffer,
+			&actualCount)))
+		{
+			goto label_fail;
+		}
+		L -= i;
+		offset += i;
+	}
+
+label_fail:
+	return err;
+}
+#endif
+
+#if IncludeSonyNew
+LOCALFUNC tMacErr MyCreateFileCFStringRef(FSRef *saveFileParent,
+	CFStringRef saveFileName, FSRef *NewRef)
+{
+	tMacErr err;
+	UniChar buffer[255];
+
+	CFIndex len = CFStringGetLength(saveFileName);
+
+	if (len > 255) {
+		len = 255;
+	}
+
+	CFStringGetCharacters(saveFileName, CFRangeMake(0, len), buffer);
+
+	err = To_tMacErr(FSMakeFSRefUnicode(saveFileParent, len,
+		buffer, kTextEncodingUnknown, NewRef));
+	if (mnvm_fnfErr == err) { /* file is not there yet - create it */
+		err = To_tMacErr(FSCreateFileUnicode(saveFileParent,
+			len, buffer, 0, NULL, NewRef, NULL));
+	}
+
+	return err;
+}
+#endif
+
+#if IncludeSonyNew
+LOCALFUNC tMacErr MakeNewDisk0(FSRef *saveFileParent,
+	CFStringRef saveFileName, ui5b L)
+{
+	tMacErr err;
+	FSRef NewRef;
+	HFSUniStr255 forkName;
+	SInt16 refnum;
+
+	if (CheckSavetMacErr(
+		MyCreateFileCFStringRef(saveFileParent, saveFileName, &NewRef)))
+	{
+		if (CheckSaveMacErr(FSGetDataForkName(&forkName)))
+		if (CheckSaveMacErr(FSOpenFork(&NewRef, forkName.length,
+			forkName.unicode, fsRdWrPerm, &refnum)))
+		{
+			SInt64 forkSize = L;
+			if (CheckSaveMacErr(
+				FSSetForkSize(refnum, fsFromStart, forkSize)))
+			/*
+				zero out fork. It looks like this is already done,
+				but documentation says this isn't guaranteed.
+			*/
+			if (CheckSavetMacErr(WriteZero(refnum, L)))
+			{
+				err = Sony_Insert0(refnum, falseblnr);
+				refnum = NotAfileRef;
+			}
+			if (NotAfileRef != refnum) {
+				(void) FSCloseFork(refnum);
+			}
+		}
+		if (mnvm_noErr != err) {
+			(void) FSDeleteObject(&NewRef);
+		}
+	}
+
+	return err;
+}
+#endif
+
+#if IncludeSonyNameNew
+LOCALFUNC CFStringRef CFStringCreateWithPbuf(tPbuf i)
+{
+	return CFStringCreateWithBytes(NULL,
+		(UInt8 *)PbufDat[i], PbufSize[i],
+		kCFStringEncodingMacRoman, false);
+}
+#endif
+
+pascal Boolean NavigationFilterProc(
+	AEDesc* theItem, void* info, void* NavCallBackUserData,
+	NavFilterModes theNavFilterModes);
+pascal Boolean NavigationFilterProc(
+	AEDesc* theItem, void* info, void* NavCallBackUserData,
+	NavFilterModes theNavFilterModes)
+{
+	/* NavFileOrFolderInfo* theInfo = (NavFileOrFolderInfo*)info; */
+	UnusedParam(theItem);
+	UnusedParam(info);
+	UnusedParam(theNavFilterModes);
+	UnusedParam(NavCallBackUserData);
+
+	return true; /* display all items */
+}
+
+
+pascal void NavigationEventProc(
+	NavEventCallbackMessage callBackSelector,
+	NavCBRecPtr callBackParms, void *NavCallBackUserData);
+pascal void NavigationEventProc(
+	NavEventCallbackMessage callBackSelector,
+	NavCBRecPtr callBackParms, void *NavCallBackUserData)
+{
+	UnusedParam(NavCallBackUserData);
+
+	switch (callBackSelector) {
+		case kNavCBEvent: /* probably not needed in os x */
+			switch (callBackParms->eventData.eventDataParms.event->what)
+			{
+				case updateEvt:
+					{
+						WindowPtr which =
+							(WindowPtr)callBackParms
+								->eventData.eventDataParms.event
+								->message;
+
+						BeginUpdate(which);
+
+						if (which == gMyMainWindow) {
+							Update_Screen();
+						}
+
+						EndUpdate(which);
+					}
+					break;
+			}
+			break;
+#if 0
+		case kNavCBUserAction:
+			{
+				NavUserAction userAction = NavDialogGetUserAction(
+					callBackParms->context);
+				switch (userAction) {
+					case kNavUserActionOpen: {
+						/* got something to open */
+						break;
+					}
+				}
+			}
+			break;
+		case kNavCBTerminate:
+			break;
+#endif
+	}
+}
+
+LOCALPROC InsertADisk0(void)
+{
+	NavDialogRef theOpenDialog;
+	NavDialogCreationOptions dialogOptions;
+	NavReplyRecord theReply;
+	NavTypeListHandle openList = NULL;
+	NavEventUPP gEventProc = NewNavEventUPP(NavigationEventProc);
+	NavObjectFilterUPP filterUPP =
+		NewNavObjectFilterUPP(NavigationFilterProc);
+
+	if (noErr == NavGetDefaultDialogCreationOptions(&dialogOptions)) {
+		dialogOptions.modality = kWindowModalityAppModal;
+		dialogOptions.optionFlags |= kNavDontAutoTranslate;
+		dialogOptions.optionFlags &= ~ kNavAllowPreviews;
+		if (noErr == NavCreateGetFileDialog(&dialogOptions,
+			(NavTypeListHandle)openList,
+			gEventProc, NULL,
+			filterUPP, NULL, &theOpenDialog))
+		{
+			MyBeginDialog();
+			(void) NavDialogRun(theOpenDialog);
+			MyEndDialog();
+			if (noErr == NavDialogGetReply(theOpenDialog,
+				&theReply))
+			{
+				if (theReply.validRecord) {
+					ReportStandardOpenDiskError(
+						InsertDisksFromDocList(&theReply.selection));
+				}
+				(void) NavDisposeReply(&theReply);
+			}
+			NavDialogDispose(theOpenDialog);
+		}
+	}
+
+	DisposeNavEventUPP(gEventProc);
+	DisposeNavObjectFilterUPP(filterUPP);
+}
+
+#if IncludeSonyNew
+LOCALPROC MakeNewDisk(ui5b L, CFStringRef NewDiskName)
+{
+#if SaveDialogEnable
+	NavDialogRef theSaveDialog;
+	NavDialogCreationOptions dialogOptions;
+	NavReplyRecord theReply;
+	NavEventUPP gEventProc = NewNavEventUPP(NavigationEventProc);
+
+	if (noErr == NavGetDefaultDialogCreationOptions(&dialogOptions)) {
+		dialogOptions.modality = kWindowModalityAppModal;
+		dialogOptions.saveFileName = NewDiskName;
+		if (noErr == NavCreatePutFileDialog(&dialogOptions,
+			'TEXT', 'MPS ',
+			gEventProc, NULL,
+			&theSaveDialog))
+		{
+			MyBeginDialog();
+			(void) NavDialogRun(theSaveDialog);
+			MyEndDialog();
+			if (noErr == NavDialogGetReply(theSaveDialog,
+				&theReply))
+			{
+				if (theReply.validRecord) {
+					long itemsInList;
+					AEKeyword keyword;
+					DescType typeCode;
+					FSRef theRef;
+					Size actualSize;
+
+					if (noErr == AECountItems(
+						&theReply.selection, &itemsInList))
+					{
+						if (itemsInList == 1) {
+							if (noErr == AEGetNthPtr(
+								&theReply.selection, 1, typeFSRef,
+								&keyword, &typeCode, (Ptr)&theRef,
+								sizeof(FSRef), &actualSize))
+							{
+								ReportStandardOpenDiskError(
+									MakeNewDisk0(&theRef,
+										theReply.saveFileName, L));
+							}
+						}
+					}
+				}
+				(void) NavDisposeReply(&theReply);
+			}
+			NavDialogDispose(theSaveDialog);
+		}
+	}
+
+	DisposeNavEventUPP(gEventProc);
+#else /* SaveDialogEnable */
+	FSRef OutRef;
+
+	if (mnvm_noErr == FindOrMakeNamedChildRef(&MyDatDirRef,
+		"out", &OutRef))
+	{
+		MakeNewDisk0(&OutRef, NewDiskName, L);
+	}
+#endif /* SaveDialogEnable */
+}
+#endif
+
+LOCALFUNC tMacErr LoadMacRomFromNameFolder(FSRef *ParentRef,
+	char *fileName)
+{
+	tMacErr err;
+	blnr isFolder;
+	FSRef ChildRef;
+
+	if (mnvm_noErr == (err =
+		MyMakeFSRefC(ParentRef, fileName, &isFolder, &ChildRef)))
+	if (mnvm_noErr == (err =
+		LoadMacRomFromFSRef(&ChildRef)))
+	{
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr LoadMacRomFromPrefDir(void)
+{
+	tMacErr err;
+	FSRef PrefRef;
+	FSRef GryphelRef;
+	FSRef ROMsRef;
+
+	if (mnvm_noErr == (err = To_tMacErr(FSFindFolder(kUserDomain,
+		kPreferencesFolderType, kDontCreateFolder, &PrefRef))))
+	if (mnvm_noErr == (err = FindNamedChildRef(&PrefRef,
+		"Gryphel", &GryphelRef)))
+	if (mnvm_noErr == (err = FindNamedChildRef(&GryphelRef,
+		"mnvm_rom", &ROMsRef)))
+	if (mnvm_noErr == (err = LoadMacRomFromNameFolder(&ROMsRef,
+		RomFileName)))
+	{
+		/* ok */
+	}
+
+	return err;
+}
+
+LOCALFUNC blnr LoadMacRom(void)
+{
+	tMacErr err;
+
+	if (mnvm_fnfErr == (err =
+		LoadMacRomFromNameFolder(&MyDatDirRef, RomFileName)))
+	if (mnvm_fnfErr == (err =
+		LoadMacRomFromPrefDir()))
+	{
+	}
+
+	return trueblnr; /* keep launching Mini vMac, regardless */
+}
+
+LOCALFUNC blnr Sony_InsertIth(int i)
+{
+	tMacErr err = mnvm_noErr;
+
+	if ((i > 9) || ! FirstFreeDisk(nullpr)) {
+		return falseblnr;
+	} else {
+		char s[16] = "disk?.dsk";
+
+		s[4] = '0' + i;
+
+		if (! CheckSavetMacErr(InsertADiskFromNameEtc(&MyDatDirRef, s)))
+		{
+			if (mnvm_fnfErr != err) {
+				ReportStandardOpenDiskError(err);
+			}
+			/* stop on first error (including file not found) */
+			return falseblnr;
+		}
+	}
+
+	return trueblnr;
+}
+
+LOCALFUNC blnr LoadInitialImages(void)
+{
+	int i;
+
+	for (i = 1; Sony_InsertIth(i); ++i) {
+		/* stop on first error (including file not found) */
+	}
+
+	return trueblnr;
+}
+
+#if UseActvFile
+
+#define ActvCodeFileName "act_1"
+
+LOCALFUNC tMacErr OpenActvCodeFile(SInt16 *refnum)
+{
+	tMacErr err;
+	FSRef PrefRef;
+	FSRef GryphelRef;
+	FSRef ActRef;
+
+	if (CheckSaveMacErr(FSFindFolder(kUserDomain,
+		kPreferencesFolderType, kDontCreateFolder, &PrefRef)))
+	if (CheckSavetMacErr(FindNamedChildRef(&PrefRef,
+		"Gryphel", &GryphelRef)))
+	if (CheckSavetMacErr(FindNamedChildRef(&GryphelRef,
+		"mnvm_act", &ActRef)))
+	if (CheckSavetMacErr(OpenNamedFileInFolderRef(&ActRef,
+		ActvCodeFileName, refnum)))
+	{
+		/* ok */
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr ActvCodeFileLoad(ui3p p)
+{
+	tMacErr err;
+	SInt16 refnum;
+
+	if (CheckSavetMacErr(OpenActvCodeFile(&refnum))) {
+		ByteCount actualCount;
+		err = To_tMacErr(FSReadFork(refnum, fsFromStart, 0,
+			ActvCodeFileLen, p, &actualCount));
+		(void) FSCloseFork(refnum);
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr ActvCodeFileSave(ui3p p)
+{
+	tMacErr err;
+	SInt16 refnum;
+	FSRef PrefRef;
+	FSRef GryphelRef;
+	FSRef ActRef;
+	ByteCount count = ActvCodeFileLen;
+
+	if (CheckSaveMacErr(FSFindFolder(kUserDomain,
+		kPreferencesFolderType, kDontCreateFolder, &PrefRef)))
+	if (CheckSavetMacErr(FindOrMakeNamedChildRef(&PrefRef,
+		"Gryphel", &GryphelRef)))
+	if (CheckSavetMacErr(FindOrMakeNamedChildRef(&GryphelRef,
+		"mnvm_act", &ActRef)))
+	if (CheckSavetMacErr(OpenWriteNamedFileInFolderRef(&ActRef,
+		ActvCodeFileName, &refnum)))
+	{
+		ByteCount actualCount;
+		err = To_tMacErr(FSWriteFork(refnum, fsFromStart, 0,
+			count, p, &actualCount));
+		(void) FSCloseFork(refnum);
+	}
+
+	return err;
+}
+
+#endif /* UseActvFile */
+
+/* --- utilities for adapting to the environment --- */
+
+LOCALPROC MyGetScreenBitsBounds(Rect *r)
+{
+	if (HaveMyCGDisplayBounds()) {
+		CGRect cgr = MyCGDisplayBounds(MyMainDisplayID());
+
+		r->left = cgr.origin.x;
+		r->top = cgr.origin.y;
+		r->right = cgr.origin.x + cgr.size.width;
+		r->bottom = cgr.origin.y + cgr.size.height;
+	}
+}
+
+#if MayNotFullScreen
+LOCALPROC InvalWholeWindow(WindowRef mw)
+{
+	Rect bounds;
+
+	GetWindowPortBounds(mw, &bounds);
+	InvalWindowRect(mw, &bounds);
+}
+#endif
+
+#if MayNotFullScreen
+LOCALPROC MySetMacWindContRect(WindowRef mw, Rect *r)
+{
+	(void) SetWindowBounds (mw, kWindowContentRgn, r);
+	InvalWholeWindow(mw);
+}
+#endif
+
+#if MayNotFullScreen
+LOCALFUNC blnr MyGetWindowTitleBounds(WindowRef mw, Rect *r)
+{
+	return (noErr == GetWindowBounds(mw, kWindowTitleBarRgn, r));
+}
+#endif
+
+#if EnableRecreateW && MayNotFullScreen
+LOCALFUNC blnr MyGetWindowContBounds(WindowRef mw, Rect *r)
+{
+	return (noErr == GetWindowBounds(mw, kWindowContentRgn, r));
+}
+#endif
+
+LOCALPROC MyGetGrayRgnBounds(Rect *r)
+{
+	GetRegionBounds(GetGrayRgn(), (Rect *)r);
+}
+
+#define openOnly 1
+#define openPrint 2
+
+LOCALFUNC blnr GotRequiredParams(AppleEvent *theAppleEvent)
+{
+	DescType typeCode;
+	Size actualSize;
+	OSErr theErr;
+
+	theErr = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr,
+				typeWildCard, &typeCode, NULL, 0, &actualSize);
+	if (errAEDescNotFound == theErr) { /* No more required params. */
+		return trueblnr;
+	} else if (noErr == theErr) { /* More required params! */
+		return /* CheckSysCode(errAEEventNotHandled) */ falseblnr;
+	} else { /* Unexpected Error! */
+		return /* CheckSysCode(theErr) */ falseblnr;
+	}
+}
+
+LOCALFUNC blnr GotRequiredParams0(AppleEvent *theAppleEvent)
+{
+	DescType typeCode;
+	Size actualSize;
+	OSErr theErr;
+
+	theErr = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr,
+				typeWildCard, &typeCode, NULL, 0, &actualSize);
+	if (errAEDescNotFound == theErr) { /* No more required params. */
+		return trueblnr;
+	} else if (noErr == theErr) { /* More required params! */
+		return trueblnr; /* errAEEventNotHandled; */ /*^*/
+	} else { /* Unexpected Error! */
+		return /* CheckSysCode(theErr) */ falseblnr;
+	}
+}
+
+/* call back */ static pascal OSErr OpenOrPrintFiles(
+	AppleEvent *theAppleEvent, AppleEvent *reply, long aRefCon)
+{
+	/*
+		Adapted from IM VI: AppleEvent Manager:
+		Handling Required AppleEvents
+	*/
+	AEDescList docList;
+
+	UnusedParam(reply);
+	UnusedParam(aRefCon);
+	/* put the direct parameter (a list of descriptors) into docList */
+	if (noErr == (AEGetParamDesc(theAppleEvent, keyDirectObject,
+		typeAEList, &docList)))
+	{
+		if (GotRequiredParams0(theAppleEvent)) {
+			/* Check for missing required parameters */
+			/* printIt = (openPrint == aRefCon) */
+			ReportStandardOpenDiskError(
+				InsertDisksFromDocList(&docList));
+		}
+		/* vCheckSysCode */ (void) (AEDisposeDesc(&docList));
+	}
+
+	return /* GetASysResultCode() */ 0;
+}
+
+/* call back */ static pascal OSErr DoOpenEvent(
+	AppleEvent *theAppleEvent, AppleEvent *reply, long aRefCon)
+/*
+	This is the alternative to getting an
+	open document event on startup.
+*/
+{
+	UnusedParam(reply);
+	UnusedParam(aRefCon);
+	if (GotRequiredParams0(theAppleEvent)) {
+	}
+	return /* GetASysResultCode() */ 0;
+		/* Make sure there are no additional "required" parameters. */
+}
+
+
+/* call back */ static pascal OSErr DoQuitEvent(
+	AppleEvent *theAppleEvent, AppleEvent *reply, long aRefCon)
+{
+	UnusedParam(reply);
+	UnusedParam(aRefCon);
+	if (GotRequiredParams(theAppleEvent)) {
+		RequestMacOff = trueblnr;
+	}
+
+	return /* GetASysResultCode() */ 0;
+}
+
+LOCALFUNC blnr MyInstallEventHandler(AEEventClass theAEEventClass,
+	AEEventID theAEEventID, ProcPtr p,
+	long handlerRefcon, blnr isSysHandler)
+{
+	return noErr == (AEInstallEventHandler(theAEEventClass,
+		theAEEventID, NewAEEventHandlerUPP((AEEventHandlerProcPtr)p),
+		handlerRefcon, isSysHandler));
+}
+
+LOCALPROC InstallAppleEventHandlers(void)
+{
+	if (noErr == AESetInteractionAllowed(kAEInteractWithLocal))
+	if (MyInstallEventHandler(kCoreEventClass, kAEOpenApplication,
+		(ProcPtr)DoOpenEvent, 0, falseblnr))
+	if (MyInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
+		(ProcPtr)OpenOrPrintFiles, openOnly, falseblnr))
+	if (MyInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
+		(ProcPtr)OpenOrPrintFiles, openPrint, falseblnr))
+	if (MyInstallEventHandler(kCoreEventClass, kAEQuitApplication,
+		(ProcPtr)DoQuitEvent, 0, falseblnr))
+	{
+	}
+}
+
+static pascal OSErr GlobalTrackingHandler(DragTrackingMessage message,
+	WindowRef theWindow, void *handlerRefCon, DragReference theDragRef)
+{
+	RgnHandle hilightRgn;
+	Rect Bounds;
+
+	UnusedParam(theWindow);
+	UnusedParam(handlerRefCon);
+	switch(message) {
+		case kDragTrackingEnterWindow:
+			hilightRgn = NewRgn();
+			if (hilightRgn != NULL) {
+				SetScrnRectFromCoords(&Bounds,
+					0, 0, vMacScreenHeight, vMacScreenWidth);
+				RectRgn(hilightRgn, &Bounds);
+				ShowDragHilite(theDragRef, hilightRgn, true);
+				DisposeRgn(hilightRgn);
+			}
+			break;
+		case kDragTrackingLeaveWindow:
+			HideDragHilite(theDragRef);
+			break;
+	}
+
+	return noErr;
+}
+
+LOCALFUNC tMacErr InsertADiskOrAliasFromFSRef(FSRef *theRef)
+{
+	tMacErr err;
+	Boolean isFolder;
+	Boolean isAlias;
+
+	if (CheckSaveMacErr(FSResolveAliasFile(theRef, true,
+		&isFolder, &isAlias)))
+	{
+		err = InsertADiskFromFSRef1(theRef);
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr InsertADiskOrAliasFromSpec(FSSpec *spec)
+{
+	tMacErr err;
+	FSRef newRef;
+
+	if (CheckSaveMacErr(FSpMakeFSRef(spec, &newRef)))
+	if (CheckSavetMacErr(InsertADiskOrAliasFromFSRef(&newRef)))
+	{
+		/* ok */
+	}
+
+	return err;
+}
+
+static pascal OSErr GlobalReceiveHandler(WindowRef pWindow,
+	void *handlerRefCon, DragReference theDragRef)
+{
+	SInt16 mouseUpModifiers;
+	unsigned short items;
+	unsigned short index;
+	ItemReference theItem;
+	Size SentSize;
+	HFSFlavor r;
+
+	UnusedParam(pWindow);
+	UnusedParam(handlerRefCon);
+
+	if (noErr == GetDragModifiers(theDragRef,
+		NULL, NULL, &mouseUpModifiers))
+	{
+		MyUpdateKeyboardModifiers(mouseUpModifiers);
+	}
+
+	if (noErr == CountDragItems(theDragRef, &items)) {
+		for (index = 1; index <= items; ++index) {
+			if (noErr == GetDragItemReferenceNumber(theDragRef,
+				index, &theItem))
+			if (noErr == GetFlavorDataSize(theDragRef,
+				theItem, flavorTypeHFS, &SentSize))
+				/*
+					On very old macs SentSize might only be big enough
+					to hold the actual file name. Have not seen this
+					in OS X, but still leave the check
+					as '<=' instead of '=='.
+				*/
+			if (SentSize <= sizeof(HFSFlavor))
+			if (noErr == GetFlavorData(theDragRef, theItem,
+				flavorTypeHFS, (Ptr)&r, &SentSize, 0))
+			{
+				ReportStandardOpenDiskError(
+					InsertADiskOrAliasFromSpec(&r.fileSpec));
+			}
+		}
+
+#if 1
+		if (gTrueBackgroundFlag) {
+			ProcessSerialNumber currentProcess = {0, kCurrentProcess};
+
+			(void) SetFrontProcess(&currentProcess);
+		}
+#endif
+	}
+
+	return noErr;
+}
+
+LOCALVAR DragTrackingHandlerUPP gGlobalTrackingHandler = NULL;
+LOCALVAR DragReceiveHandlerUPP gGlobalReceiveHandler = NULL;
+
+LOCALPROC UnPrepareForDragging(void)
+{
+	if (NULL != gGlobalReceiveHandler) {
+		RemoveReceiveHandler(gGlobalReceiveHandler, gMyMainWindow);
+		DisposeDragReceiveHandlerUPP(gGlobalReceiveHandler);
+		gGlobalReceiveHandler = NULL;
+	}
+	if (NULL != gGlobalTrackingHandler) {
+		RemoveTrackingHandler(gGlobalTrackingHandler, gMyMainWindow);
+		DisposeDragTrackingHandlerUPP(gGlobalTrackingHandler);
+		gGlobalTrackingHandler = NULL;
+	}
+}
+
+LOCALFUNC blnr PrepareForDragging(void)
+{
+	blnr IsOk = falseblnr;
+
+	gGlobalTrackingHandler = NewDragTrackingHandlerUPP(
+		GlobalTrackingHandler);
+	if (gGlobalTrackingHandler != NULL) {
+		gGlobalReceiveHandler = NewDragReceiveHandlerUPP(
+			GlobalReceiveHandler);
+		if (gGlobalReceiveHandler != NULL) {
+			if (noErr == InstallTrackingHandler(gGlobalTrackingHandler,
+				gMyMainWindow, nil))
+			{
+				if (noErr == InstallReceiveHandler(
+					gGlobalReceiveHandler, gMyMainWindow, nil))
+				{
+					IsOk = trueblnr;
+				}
+			}
+		}
+	}
+
+	return IsOk;
+}
+
+LOCALPROC HandleEventLocation(EventRef theEvent)
+{
+	Point NewMousePos;
+
+	if (! gWeAreActive) {
+		return;
+	}
+
+	if (noErr == GetEventParameter(theEvent,
+		kEventParamMouseLocation,
+		typeQDPoint,
+		NULL,
+		sizeof(NewMousePos),
+		NULL,
+		&NewMousePos))
+	{
+		MousePositionNotify(NewMousePos);
+	}
+}
+
+LOCALPROC HandleEventModifiers(EventRef theEvent)
+{
+	UInt32 theModifiers;
+
+	if (gWeAreActive) {
+		GetEventParameter(theEvent, kEventParamKeyModifiers,
+			typeUInt32, NULL, sizeof(typeUInt32), NULL, &theModifiers);
+
+		MyUpdateKeyboardModifiers(theModifiers);
+	}
+}
+
+LOCALVAR blnr IsOurMouseMove;
+
+static pascal OSStatus windowEventHandler(
+	EventHandlerCallRef nextHandler, EventRef theEvent,
+	void* userData)
+{
+	OSStatus result = eventNotHandledErr;
+	UInt32 eventClass = GetEventClass(theEvent);
+	UInt32 eventKind = GetEventKind(theEvent);
+
+	UnusedParam(nextHandler);
+	UnusedParam(userData);
+	switch(eventClass) {
+		case kEventClassWindow:
+			switch(eventKind) {
+				case kEventWindowClose:
+					RequestMacOff = trueblnr;
+					result = noErr;
+					break;
+				case kEventWindowDrawContent:
+					Update_Screen();
+					result = noErr;
+					break;
+				case kEventWindowClickContentRgn:
+					MouseIsOutside = falseblnr;
+					HandleEventLocation(theEvent);
+					HandleEventModifiers(theEvent);
+					MyMouseButtonSet(trueblnr);
+					result = noErr;
+					break;
+				case kEventWindowFocusAcquired:
+					gLackFocusFlag = falseblnr;
+					result = noErr;
+					break;
+				case kEventWindowFocusRelinquish:
+					{
+						WindowRef window;
+
+						(void) GetEventParameter(theEvent,
+							kEventParamDirectObject, typeWindowRef,
+							NULL, sizeof(WindowRef), NULL, &window);
+						if ((window == gMyMainWindow)
+							&& (window != gMyOldWindow))
+						{
+							ClearWeAreActive();
+							gLackFocusFlag = trueblnr;
+						}
+					}
+					result = noErr;
+					break;
+			}
+			break;
+		case kEventClassMouse:
+			switch(eventKind) {
+				case kEventMouseMoved:
+				case kEventMouseDragged:
+					MouseIsOutside = falseblnr;
+#if 0 /* don't bother, CheckMouseState will take care of it, better */
+					HandleEventLocation(theEvent);
+					HandleEventModifiers(theEvent);
+#endif
+					IsOurMouseMove = trueblnr;
+					result = noErr;
+					break;
+			}
+			break;
+	}
+
+	return result;
+}
+
+LOCALFUNC blnr MyCreateNewWindow(Rect *Bounds, WindowPtr *theWindow)
+{
+	WindowPtr ResultWin;
+	blnr IsOk = falseblnr;
+
+	if (noErr == CreateNewWindow(
+
+#if VarFullScreen
+		UseFullScreen ?
+#endif
+#if MayFullScreen
+			/*
+				appears not to work properly with aglSetWindowRef
+				at least in OS X 10.5.5
+				also doesn't seem to be needed. maybe dates from when
+				didn't cover all screens in full screen mode.
+			*/
+			/*
+				Oops, no, kDocumentWindowClass doesn't seem to
+				work quite right if made immediately after
+				launch, title bar gets moved onscreen. At least
+				in Intel 10.5.6, doesn't happen in PowerPC 10.4.11.
+				Oddly, this problem doesn't happen if icon
+				already in dock before launch, but perhaps
+				that is just a timing issue.
+				So use kPlainWindowClass after all.
+			*/
+			kPlainWindowClass
+#endif
+#if VarFullScreen
+			:
+#endif
+#if MayNotFullScreen
+			kDocumentWindowClass
+#endif
+		,
+
+#if VarFullScreen
+		UseFullScreen ?
+#endif
+#if MayFullScreen
+			/* kWindowStandardHandlerAttribute */ 0
+#endif
+#if VarFullScreen
+			:
+#endif
+#if MayNotFullScreen
+			kWindowCloseBoxAttribute
+				| kWindowCollapseBoxAttribute
+#endif
+		,
+
+		Bounds, &ResultWin
+	))
+	{
+#if VarFullScreen
+		if (! UseFullScreen)
+#endif
+#if MayNotFullScreen
+		{
+			SetWindowTitleWithCFString(ResultWin,
+				MyAppName /* CFSTR("Mini vMac") */);
+		}
+#endif
+		InstallStandardEventHandler(GetWindowEventTarget(ResultWin));
+		{
+			static const EventTypeSpec windowEvents[] =
+				{
+					{kEventClassWindow, kEventWindowClose},
+					{kEventClassWindow, kEventWindowDrawContent},
+					{kEventClassWindow, kEventWindowClickContentRgn},
+					{kEventClassMouse, kEventMouseMoved},
+					{kEventClassMouse, kEventMouseDragged},
+					{kEventClassWindow, kEventWindowFocusAcquired},
+					{kEventClassWindow, kEventWindowFocusRelinquish}
+				};
+			InstallWindowEventHandler(ResultWin,
+				NewEventHandlerUPP(windowEventHandler),
+				GetEventTypeCount(windowEvents),
+				windowEvents, 0, NULL);
+		}
+
+		*theWindow = ResultWin;
+
+		IsOk = trueblnr;
+	}
+
+	return IsOk;
+}
+
+LOCALPROC CloseAglCurrentContext(void)
+{
+	if (ctx != NULL) {
+		/*
+			Only because MyDrawWithOpenGL doesn't
+			bother to do this. No one
+			uses the CurrentContext
+			without settting it first.
+		*/
+		if (GL_TRUE != aglSetCurrentContext(NULL)) {
+			/* err = aglReportError() */
+		}
+		ctx = NULL;
+	}
+}
+
+LOCALPROC CloseMainWindow(void)
+{
+	UnPrepareForDragging();
+
+	if (window_ctx != NULL) {
+		if (GL_TRUE != aglDestroyContext(window_ctx)) {
+			/* err = aglReportError() */
+		}
+		window_ctx = NULL;
+	}
+
+	if (window_fmt != NULL) {
+		aglDestroyPixelFormat(window_fmt);
+		window_fmt = NULL;
+	}
+
+	if (gMyMainWindow != NULL) {
+		DisposeWindow(gMyMainWindow);
+		gMyMainWindow = NULL;
+	}
+}
+
+enum {
+	kMagStateNormal,
+#if EnableMagnify
+	kMagStateMagnifgy,
+#endif
+	kNumMagStates
+};
+
+#define kMagStateAuto kNumMagStates
+
+#if MayNotFullScreen
+LOCALVAR int CurWinIndx;
+LOCALVAR blnr HavePositionWins[kNumMagStates];
+LOCALVAR Point WinPositionWins[kNumMagStates];
+#endif
+
+LOCALFUNC blnr CreateMainWindow(void)
+{
+#if MayNotFullScreen
+	int WinIndx;
+#endif
+	Rect MainScrnBounds;
+	Rect AllScrnBounds;
+	Rect NewWinRect;
+	short leftPos;
+	short topPos;
+	short NewWindowHeight = vMacScreenHeight;
+	short NewWindowWidth = vMacScreenWidth;
+	blnr IsOk = falseblnr;
+
+#if VarFullScreen
+	if (UseFullScreen) {
+		My_HideMenuBar();
+	} else {
+		My_ShowMenuBar();
+	}
+#else
+#if MayFullScreen
+	My_HideMenuBar();
+#endif
+#endif
+
+	MyGetGrayRgnBounds(&AllScrnBounds);
+	MyGetScreenBitsBounds(&MainScrnBounds);
+
+#if EnableMagnify
+	if (UseMagnify) {
+		NewWindowHeight *= MyWindowScale;
+		NewWindowWidth *= MyWindowScale;
+	}
+#endif
+
+	leftPos = MainScrnBounds.left
+		+ ((MainScrnBounds.right - MainScrnBounds.left)
+			- NewWindowWidth) / 2;
+	topPos = MainScrnBounds.top
+		+ ((MainScrnBounds.bottom - MainScrnBounds.top)
+			- NewWindowHeight) / 2;
+	if (leftPos < MainScrnBounds.left) {
+		leftPos = MainScrnBounds.left;
+	}
+	if (topPos < MainScrnBounds.top) {
+		topPos = MainScrnBounds.top;
+	}
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		ViewHSize = MainScrnBounds.right - MainScrnBounds.left;
+		ViewVSize = MainScrnBounds.bottom - MainScrnBounds.top;
+#if EnableMagnify
+		if (UseMagnify) {
+			ViewHSize /= MyWindowScale;
+			ViewVSize /= MyWindowScale;
+		}
+#endif
+		if (ViewHSize >= vMacScreenWidth) {
+			ViewHStart = 0;
+			ViewHSize = vMacScreenWidth;
+		} else {
+			ViewHSize &= ~ 1;
+		}
+		if (ViewVSize >= vMacScreenHeight) {
+			ViewVStart = 0;
+			ViewVSize = vMacScreenHeight;
+		} else {
+			ViewVSize &= ~ 1;
+		}
+	}
+#endif
+
+	/* Create window rectangle and centre it on the screen */
+	SetRect(&MainScrnBounds, 0, 0, NewWindowWidth, NewWindowHeight);
+	OffsetRect(&MainScrnBounds, leftPos, topPos);
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		NewWinRect = AllScrnBounds;
+	}
+#endif
+#if VarFullScreen
+	else
+#endif
+#if MayNotFullScreen
+	{
+#if EnableMagnify
+		if (UseMagnify) {
+			WinIndx = kMagStateMagnifgy;
+		} else
+#endif
+		{
+			WinIndx = kMagStateNormal;
+		}
+
+		if (! HavePositionWins[WinIndx]) {
+			WinPositionWins[WinIndx].h = leftPos;
+			WinPositionWins[WinIndx].v = topPos;
+			HavePositionWins[WinIndx] = trueblnr;
+			NewWinRect = MainScrnBounds;
+		} else {
+			SetRect(&NewWinRect, 0, 0, NewWindowWidth, NewWindowHeight);
+			OffsetRect(&NewWinRect,
+				WinPositionWins[WinIndx].h, WinPositionWins[WinIndx].v);
+		}
+	}
+#endif
+
+#if MayNotFullScreen
+	CurWinIndx = WinIndx;
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		hOffset = MainScrnBounds.left - AllScrnBounds.left;
+		vOffset = MainScrnBounds.top - AllScrnBounds.top;
+	}
+#endif
+
+	if (MyCreateNewWindow(&NewWinRect, &gMyMainWindow)) {
+		static const GLint window_attrib[] = {AGL_RGBA,
+#if UseAGLdoublebuff
+			AGL_DOUBLEBUFFER,
+#endif
+			/* AGL_DEPTH_SIZE, 16,  */
+			AGL_NONE};
+
+#if 0 != vMacScreenDepth
+		ColorModeWorks = trueblnr;
+#endif
+
+		window_fmt = aglChoosePixelFormat(NULL, 0, window_attrib);
+		if (NULL == window_fmt) {
+			/* err = aglReportError() */
+		} else {
+			window_ctx = aglCreateContext(window_fmt, NULL);
+			if (NULL == window_ctx) {
+				/* err = aglReportError() */
+			} else {
+
+				ShowWindow(gMyMainWindow);
+
+				if (GL_TRUE != (
+					/*
+						aglSetDrawable is deprecated, but use it anyway
+						if at all possible, because aglSetWindowRef
+						doesn't seeem to work properly on a
+						kPlainWindowClass window.
+						Should move to Cocoa.
+					*/
+					HaveMyaglSetDrawable()
+					? MyaglSetDrawable(window_ctx,
+						GetWindowPort(gMyMainWindow))
+					:
+					HaveMyaglSetWindowRef()
+					? MyaglSetWindowRef(window_ctx, gMyMainWindow)
+					:
+					GL_FALSE))
+				{
+					/* err = aglReportError() */
+				} else {
+					ctx = window_ctx;
+
+#if VarFullScreen
+					if (UseFullScreen)
+#endif
+#if MayFullScreen
+					{
+						int h = NewWinRect.right - NewWinRect.left;
+						int v = NewWinRect.bottom - NewWinRect.top;
+
+						GLhOffset = hOffset;
+						GLvOffset = v - vOffset;
+						MyAdjustGLforSize(h, v);
+					}
+#endif
+#if VarFullScreen
+					else
+#endif
+#if MayNotFullScreen
+					{
+						GLhOffset = 0;
+						GLvOffset = NewWindowHeight;
+						MyAdjustGLforSize(NewWindowWidth,
+							NewWindowHeight);
+					}
+#endif
+
+#if UseAGLdoublebuff && 1
+					{
+						GLint agSwapInterval = 1;
+						if (GL_TRUE != aglSetInteger(
+							window_ctx, AGL_SWAP_INTERVAL,
+							&agSwapInterval))
+						{
+							MacMsg("oops", "aglSetInteger failed",
+								falseblnr);
+						} else {
+							/*
+								MacMsg("good", "aglSetInteger ok",
+									falseblnr);
+							*/
+						}
+					}
+#endif
+
+#if VarFullScreen
+					if (! UseFullScreen)
+#endif
+#if MayNotFullScreen
+					{
+						/* check if window rect valid */
+						Rect tr;
+
+						if (MyGetWindowTitleBounds(gMyMainWindow, &tr))
+						{
+							if (! RectInRgn(&tr, GetGrayRgn())) {
+								MySetMacWindContRect(gMyMainWindow,
+									&MainScrnBounds);
+								if (MyGetWindowTitleBounds(
+									gMyMainWindow, &tr))
+								{
+									if (! RectInRgn(&tr, GetGrayRgn()))
+									{
+										OffsetRect(&MainScrnBounds, 0,
+											AllScrnBounds.top - tr.top);
+										MySetMacWindContRect(
+											gMyMainWindow,
+											&MainScrnBounds);
+									}
+								}
+							}
+						}
+					}
+#endif
+
+					(void) PrepareForDragging();
+
+					IsOk = trueblnr;
+				}
+			}
+		}
+	}
+
+	return IsOk;
+}
+
+#if EnableRecreateW
+LOCALPROC ZapMyWState(void)
+{
+	gMyMainWindow = NULL;
+	window_fmt = NULL;
+	window_ctx = NULL;
+	gGlobalReceiveHandler = NULL;
+	gGlobalTrackingHandler = NULL;
+}
+#endif
+
+#if EnableRecreateW
+struct MyWState {
+	WindowPtr f_MainWindow;
+	AGLPixelFormat f_fmt;
+	AGLContext f_ctx;
+#if MayFullScreen
+	short f_hOffset;
+	short f_vOffset;
+	ui4r f_ViewHSize;
+	ui4r f_ViewVSize;
+	ui4r f_ViewHStart;
+	ui4r f_ViewVStart;
+#endif
+#if VarFullScreen
+	blnr f_UseFullScreen;
+#endif
+#if EnableMagnify
+	blnr f_UseMagnify;
+#endif
+#if MayNotFullScreen
+	int f_CurWinIndx;
+#endif
+	short f_GLhOffset;
+	short f_GLvOffset;
+	DragTrackingHandlerUPP f_gGlobalTrackingHandler;
+	DragReceiveHandlerUPP f_gGlobalReceiveHandler;
+};
+typedef struct MyWState MyWState;
+#endif
+
+#if EnableRecreateW
+LOCALPROC GetMyWState(MyWState *r)
+{
+	r->f_MainWindow = gMyMainWindow;
+	r->f_fmt = window_fmt;
+	r->f_ctx = window_ctx;
+#if MayFullScreen
+	r->f_hOffset = hOffset;
+	r->f_vOffset = vOffset;
+	r->f_ViewHSize = ViewHSize;
+	r->f_ViewVSize = ViewVSize;
+	r->f_ViewHStart = ViewHStart;
+	r->f_ViewVStart = ViewVStart;
+#endif
+#if VarFullScreen
+	r->f_UseFullScreen = UseFullScreen;
+#endif
+#if EnableMagnify
+	r->f_UseMagnify = UseMagnify;
+#endif
+#if MayNotFullScreen
+	r->f_CurWinIndx = CurWinIndx;
+#endif
+	r->f_GLhOffset = GLhOffset;
+	r->f_GLvOffset = GLvOffset;
+	r->f_gGlobalTrackingHandler = gGlobalTrackingHandler;
+	r->f_gGlobalReceiveHandler = gGlobalReceiveHandler;
+}
+#endif
+
+#if EnableRecreateW
+LOCALPROC SetMyWState(MyWState *r)
+{
+	gMyMainWindow = r->f_MainWindow;
+	window_fmt = r->f_fmt;
+	window_ctx = r->f_ctx;
+#if MayFullScreen
+	hOffset = r->f_hOffset;
+	vOffset = r->f_vOffset;
+	ViewHSize = r->f_ViewHSize;
+	ViewVSize = r->f_ViewVSize;
+	ViewHStart = r->f_ViewHStart;
+	ViewVStart = r->f_ViewVStart;
+#endif
+#if VarFullScreen
+	UseFullScreen = r->f_UseFullScreen;
+#endif
+#if EnableMagnify
+	UseMagnify = r->f_UseMagnify;
+#endif
+#if MayNotFullScreen
+	CurWinIndx = r->f_CurWinIndx;
+#endif
+	GLhOffset = r->f_GLhOffset;
+	GLvOffset = r->f_GLvOffset;
+	gGlobalTrackingHandler = r->f_gGlobalTrackingHandler;
+	gGlobalReceiveHandler = r->f_gGlobalReceiveHandler;
+
+	ctx = window_ctx;
+}
+#endif
+
+#if EnableRecreateW
+LOCALFUNC blnr ReCreateMainWindow(void)
+{
+	MyWState old_state;
+	MyWState new_state;
+
+#if VarFullScreen
+	if (! UseFullScreen)
+#endif
+#if MayNotFullScreen
+	{
+		/* save old position */
+		if (gMyMainWindow != NULL) {
+			Rect r;
+
+			if (MyGetWindowContBounds(gMyMainWindow, &r)) {
+				WinPositionWins[CurWinIndx].h = r.left;
+				WinPositionWins[CurWinIndx].v = r.top;
+			}
+		}
+	}
+#endif
+
+#if MayFullScreen
+	UngrabMachine();
+#endif
+
+	CloseAglCurrentContext();
+
+	gMyOldWindow = gMyMainWindow;
+
+	GetMyWState(&old_state);
+
+	ZapMyWState();
+
+#if VarFullScreen
+	UseFullScreen = WantFullScreen;
+#endif
+#if EnableMagnify
+	UseMagnify = WantMagnify;
+#endif
+
+	if (! CreateMainWindow()) {
+		gMyOldWindow = NULL;
+		CloseMainWindow();
+		SetMyWState(&old_state);
+
+#if VarFullScreen
+		if (UseFullScreen) {
+			My_HideMenuBar();
+		} else {
+			My_ShowMenuBar();
+		}
+#endif
+
+		/* avoid retry */
+#if VarFullScreen
+		WantFullScreen = UseFullScreen;
+#endif
+#if EnableMagnify
+		WantMagnify = UseMagnify;
+#endif
+
+		return falseblnr;
+	} else {
+		GetMyWState(&new_state);
+		SetMyWState(&old_state);
+		CloseMainWindow();
+		gMyOldWindow = NULL;
+		SetMyWState(&new_state);
+
+		if (HaveCursorHidden) {
+			(void) MyMoveMouse(CurMouseH, CurMouseV);
+			WantCursorHidden = trueblnr;
+		} else {
+			MouseIsOutside = falseblnr; /* don't know */
+		}
+
+		return trueblnr;
+	}
+}
+#endif
+
+#if VarFullScreen && EnableMagnify
+enum {
+	kWinStateWindowed,
+#if EnableMagnify
+	kWinStateFullScreen,
+#endif
+	kNumWinStates
+};
+#endif
+
+#if VarFullScreen && EnableMagnify
+LOCALVAR int WinMagStates[kNumWinStates];
+#endif
+
+LOCALPROC ZapWinStateVars(void)
+{
+#if MayNotFullScreen
+	{
+		int i;
+
+		for (i = 0; i < kNumMagStates; ++i) {
+			HavePositionWins[i] = falseblnr;
+		}
+	}
+#endif
+#if VarFullScreen && EnableMagnify
+	{
+		int i;
+
+		for (i = 0; i < kNumWinStates; ++i) {
+			WinMagStates[i] = kMagStateAuto;
+		}
+	}
+#endif
+}
+
+#if VarFullScreen
+LOCALPROC ToggleWantFullScreen(void)
+{
+	WantFullScreen = ! WantFullScreen;
+
+#if EnableMagnify
+	{
+		int OldWinState =
+			UseFullScreen ? kWinStateFullScreen : kWinStateWindowed;
+		int OldMagState =
+			UseMagnify ? kMagStateMagnifgy : kMagStateNormal;
+		int NewWinState =
+			WantFullScreen ? kWinStateFullScreen : kWinStateWindowed;
+		int NewMagState = WinMagStates[NewWinState];
+
+		WinMagStates[OldWinState] = OldMagState;
+		if (kMagStateAuto != NewMagState) {
+			WantMagnify = (kMagStateMagnifgy == NewMagState);
+		} else {
+			WantMagnify = falseblnr;
+			if (WantFullScreen
+				&& HaveMyCGDisplayPixelsWide()
+				&& HaveMyCGDisplayPixelsHigh())
+			{
+				CGDirectDisplayID CurMainDisplayID = MyMainDisplayID();
+
+				if ((MyCGDisplayPixelsWide(CurMainDisplayID)
+					>= vMacScreenWidth * MyWindowScale)
+					&& (MyCGDisplayPixelsHigh(CurMainDisplayID)
+					>= vMacScreenHeight * MyWindowScale)
+					)
+				{
+					WantMagnify = trueblnr;
+				}
+			}
+		}
+	}
+#endif
+}
+#endif
+
+LOCALPROC LeaveSpeedStopped(void)
+{
+#if MySoundEnabled
+	MySound_Start();
+#endif
+
+	StartUpTimeAdjust();
+}
+
+LOCALPROC EnterSpeedStopped(void)
+{
+#if MySoundEnabled
+	MySound_Stop();
+#endif
+}
+
+LOCALPROC DoNotInBackgroundTasks(void)
+{
+#if 0
+	if (HaveMyCGCursorIsVisible()) {
+		HaveCursorHidden = ! MyCGCursorIsVisible();
+
+		/*
+			This shouldn't be needed, but have seen
+			cursor state get messed up in 10.4.
+			If the os x hide count gets off, this
+			should fix it within a few ticks.
+
+			oops, no, doesn't seem to be accurate,
+			and makes things worse. particularly if
+			cursor in obscured state after typing
+			into dialog.
+		*/
+		/* trying a different approach further below */
+	}
+#endif
+
+	if (HaveCursorHidden != (
+#if MayNotFullScreen
+		(WantCursorHidden
+#if VarFullScreen
+			|| UseFullScreen
+#endif
+		) &&
+#endif
+		gWeAreActive && ! CurSpeedStopped))
+	{
+		HaveCursorHidden = ! HaveCursorHidden;
+		if (HaveCursorHidden) {
+			MyHideCursor();
+		} else {
+			/*
+				kludge for OS X, where mouse over Dock devider
+				changes cursor, and never sets it back.
+			*/
+			SetCursorArrow();
+
+			MyShowCursor();
+		}
+	}
+
+	/* check if actual cursor visibility is what it should be */
+	if (HaveMyCGCursorIsVisible()) {
+		/* but only in OS X 10.3 and later */
+		if (MyCGCursorIsVisible()) {
+			if (HaveCursorHidden) {
+				MyHideCursor();
+				if (MyCGCursorIsVisible()) {
+					/*
+						didn't work, attempt undo so that
+						hide cursor count won't get large
+					*/
+					MyShowCursor();
+				}
+			}
+		} else {
+			if (! HaveCursorHidden) {
+				MyShowCursor();
+				/*
+					don't check if worked, assume can't decrement
+					hide cursor count below 0
+				*/
+			}
+		}
+	}
+}
+
+LOCALPROC CheckForSavedTasks(void)
+{
+	if (MyEvtQNeedRecover) {
+		MyEvtQNeedRecover = falseblnr;
+
+		/* attempt cleanup, MyEvtQNeedRecover may get set again */
+		MyEvtQTryRecoverFromFull();
+	}
+
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		MyMouseConstrain();
+	}
+#endif
+
+	if (RequestMacOff) {
+		RequestMacOff = falseblnr;
+		if (AnyDiskInserted()) {
+			MacMsgOverride(kStrQuitWarningTitle,
+				kStrQuitWarningMessage);
+		} else {
+			ForceMacOff = trueblnr;
+		}
+	}
+
+	if (! gWeAreActive) {
+		if (! (gTrueBackgroundFlag || gLackFocusFlag)) {
+			gWeAreActive = trueblnr;
+			ReconnectKeyCodes3();
+			SetCursorArrow();
+		}
+	}
+
+#if VarFullScreen
+	if (gTrueBackgroundFlag && WantFullScreen) {
+		ToggleWantFullScreen();
+	}
+#endif
+
+	if (CurSpeedStopped != (SpeedStopped ||
+		(gTrueBackgroundFlag && ! RunInBackground
+#if EnableAutoSlow && 0
+			&& (QuietSubTicks >= 4092)
+#endif
+		)))
+	{
+		CurSpeedStopped = ! CurSpeedStopped;
+		if (CurSpeedStopped) {
+			EnterSpeedStopped();
+		} else {
+			LeaveSpeedStopped();
+		}
+	}
+
+#if EnableRecreateW
+	if (gWeAreActive) {
+		if (0
+#if EnableMagnify
+			|| (UseMagnify != WantMagnify)
+#endif
+#if VarFullScreen
+			|| (UseFullScreen != WantFullScreen)
+#endif
+			)
+		{
+			(void) ReCreateMainWindow();
+		}
+	}
+#endif
+
+#if MayFullScreen
+	if (GrabMachine != (
+#if VarFullScreen
+		UseFullScreen &&
+#endif
+		gWeAreActive && ! CurSpeedStopped))
+	{
+		GrabMachine = ! GrabMachine;
+		AdjustMachineGrab();
+	}
+#endif
+
+	if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
+		MacMsgDisplayOn();
+	}
+
+	if (WantScreensChangedCheck) {
+		WantScreensChangedCheck = falseblnr;
+		MyUpdateOpenGLContext();
+	}
+
+	if (NeedWholeScreenDraw) {
+		NeedWholeScreenDraw = falseblnr;
+		ScreenChangedAll();
+	}
+
+	if (! gWeAreActive) {
+		/*
+			dialog during drag and drop hangs if in background
+				and don't want recursive dialogs
+			so wait til later to display dialog
+		*/
+	} else {
+#if IncludeSonyNew
+		if (vSonyNewDiskWanted) {
+#if IncludeSonyNameNew
+			if (vSonyNewDiskName != NotAPbuf) {
+				CFStringRef NewDiskName =
+					CFStringCreateWithPbuf(vSonyNewDiskName);
+				MakeNewDisk(vSonyNewDiskSize, NewDiskName);
+				if (NewDiskName != NULL) {
+					CFRelease(NewDiskName);
+				}
+				PbufDispose(vSonyNewDiskName);
+				vSonyNewDiskName = NotAPbuf;
+			} else
+#endif
+			{
+				MakeNewDisk(vSonyNewDiskSize, NULL);
+			}
+			vSonyNewDiskWanted = falseblnr;
+				/* must be done after may have gotten disk */
+		}
+#endif
+		if (RequestInsertDisk) {
+			RequestInsertDisk = falseblnr;
+			InsertADisk0();
+		}
+	}
+
+#if NeedRequestIthDisk
+	if (0 != RequestIthDisk) {
+		Sony_InsertIth(RequestIthDisk);
+		RequestIthDisk = 0;
+	}
+#endif
+
+	if (gWeAreActive) {
+		DoNotInBackgroundTasks();
+	}
+}
+
+#define CheckItem CheckMenuItem
+
+/* Menu Constants */
+
+#define kAppleMenu   128
+#define kFileMenu    129
+#define kSpecialMenu 130
+
+enum {
+	kCmdIdNull,
+	kCmdIdMoreCommands,
+
+	kNumCmdIds
+};
+
+LOCALFUNC OSStatus MyProcessCommand(MenuCommand inCommandID)
+{
+	OSStatus result = noErr;
+
+	switch (inCommandID) {
+		case kHICommandAbout:
+			DoAboutMsg();
+			break;
+		case kHICommandQuit:
+			RequestMacOff = trueblnr;
+			break;
+		case kHICommandOpen:
+			RequestInsertDisk = trueblnr;
+			break;
+		case kCmdIdMoreCommands:
+			DoMoreCommandsMsg();
+			break;
+		default:
+			result = eventNotHandledErr;
+			break;
+	}
+
+	return result;
+}
+
+LOCALFUNC OSStatus Keyboard_UpdateKeyMap3(EventRef theEvent, blnr down)
+{
+	UInt32 uiKeyCode;
+
+	HandleEventModifiers(theEvent);
+	GetEventParameter(theEvent, kEventParamKeyCode, typeUInt32, NULL,
+		sizeof(uiKeyCode), NULL, &uiKeyCode);
+	Keyboard_UpdateKeyMap2(Keyboard_RemapMac(uiKeyCode & 0x000000FF),
+		down);
+	return noErr;
+}
+
+static pascal OSStatus MyEventHandler(EventHandlerCallRef nextHandler,
+	EventRef theEvent, void * userData)
+{
+	OSStatus result = eventNotHandledErr;
+	UInt32 eventClass = GetEventClass(theEvent);
+	UInt32 eventKind = GetEventKind(theEvent);
+
+	UnusedParam(userData);
+
+	switch (eventClass) {
+		case kEventClassMouse:
+			switch (eventKind) {
+				case kEventMouseDown:
+#if MayFullScreen
+					if (GrabMachine) {
+						HandleEventLocation(theEvent);
+						HandleEventModifiers(theEvent);
+						MyMouseButtonSet(trueblnr);
+						result = noErr;
+					} else
+#endif
+					{
+						result = CallNextEventHandler(
+							nextHandler, theEvent);
+					}
+					break;
+				case kEventMouseUp:
+					HandleEventLocation(theEvent);
+					HandleEventModifiers(theEvent);
+					MyMouseButtonSet(falseblnr);
+#if MayFullScreen
+					if (GrabMachine) {
+						result = noErr;
+					} else
+#endif
+					{
+						result = CallNextEventHandler(
+							nextHandler, theEvent);
+					}
+					break;
+				case kEventMouseMoved:
+				case kEventMouseDragged:
+					IsOurMouseMove = falseblnr;
+					result = CallNextEventHandler(
+						nextHandler, theEvent);
+						/*
+							Actually, mousing over window does't seem
+							to go through here, it goes directly to
+							the window routine. But since not documented
+							either way, leave the check in case this
+							changes.
+						*/
+					if (! IsOurMouseMove) {
+						MouseIsOutside = trueblnr;
+#if 0 /* don't bother, CheckMouseState will take care of it, better */
+						HandleEventLocation(theEvent);
+						HandleEventModifiers(theEvent);
+#endif
+					}
+					break;
+			}
+			break;
+		case kEventClassApplication:
+			switch (eventKind) {
+				case kEventAppActivated:
+					gTrueBackgroundFlag = falseblnr;
+					result = noErr;
+					break;
+				case kEventAppDeactivated:
+					gTrueBackgroundFlag = trueblnr;
+					result = noErr;
+					ClearWeAreActive();
+					break;
+			}
+			break;
+		case kEventClassCommand:
+			switch (eventKind) {
+				case kEventProcessCommand:
+					{
+						HICommand hiCommand;
+
+						GetEventParameter(theEvent,
+							kEventParamDirectObject, typeHICommand,
+							NULL, sizeof(HICommand), NULL, &hiCommand);
+						result = MyProcessCommand(hiCommand.commandID);
+					}
+					break;
+			}
+			break;
+		case kEventClassKeyboard:
+			if (! gWeAreActive) {
+				return CallNextEventHandler(nextHandler, theEvent);
+			} else {
+				switch (eventKind) {
+					case kEventRawKeyDown:
+						result = Keyboard_UpdateKeyMap3(
+							theEvent, trueblnr);
+						break;
+					case kEventRawKeyUp:
+						result = Keyboard_UpdateKeyMap3(
+							theEvent, falseblnr);
+						break;
+					case kEventRawKeyModifiersChanged:
+						HandleEventModifiers(theEvent);
+						result = noErr;
+						break;
+					default:
+						break;
+				}
+			}
+			break;
+		default:
+			break;
+	}
+	return result;
+}
+
+LOCALPROC AppendMenuConvertCStr(
+	MenuRef menu,
+	MenuCommand inCommandID,
+	char *s)
+{
+	CFStringRef cfStr = CFStringCreateFromSubstCStr(s);
+	if (NULL != cfStr) {
+		AppendMenuItemTextWithCFString(menu, cfStr,
+			0, inCommandID, NULL);
+		CFRelease(cfStr);
+	}
+}
+
+LOCALPROC AppendMenuSep(MenuRef menu)
+{
+	AppendMenuItemTextWithCFString(menu, NULL,
+		kMenuItemAttrSeparator, 0, NULL);
+}
+
+LOCALFUNC MenuRef NewMenuFromConvertCStr(short menuID, char *s)
+{
+	MenuRef menu = NULL;
+
+	CFStringRef cfStr = CFStringCreateFromSubstCStr(s);
+	if (NULL != cfStr) {
+		OSStatus err = CreateNewMenu(menuID, 0, &menu);
+		if (err != noErr) {
+			menu = NULL;
+		} else {
+			(void) SetMenuTitleWithCFString(menu, cfStr);
+		}
+		CFRelease(cfStr);
+	}
+
+	return menu;
+}
+
+LOCALPROC RemoveCommandKeysInMenu(MenuRef theMenu)
+{
+	MenuRef outHierMenu;
+	int i;
+	UInt16 n = CountMenuItems(theMenu);
+
+	for (i = 1; i <= n; ++i) {
+		SetItemCmd(theMenu, i, 0);
+		if (noErr == GetMenuItemHierarchicalMenu(
+			theMenu, i, &outHierMenu)
+			&& (NULL != outHierMenu))
+		{
+			RemoveCommandKeysInMenu(outHierMenu);
+		}
+	}
+}
+
+LOCALFUNC blnr InstallOurMenus(void)
+{
+	MenuRef menu;
+	Str255 s;
+
+	PStrFromChar(s, (char)20);
+	menu = NewMenu(kAppleMenu, s);
+	if (menu != NULL) {
+		AppendMenuConvertCStr(menu,
+			kHICommandAbout,
+			kStrMenuItemAbout);
+		AppendMenuSep(menu);
+		InsertMenu(menu, 0);
+	}
+
+	menu = NewMenuFromConvertCStr(kFileMenu, kStrMenuFile);
+	if (menu != NULL) {
+		AppendMenuConvertCStr(menu,
+			kHICommandOpen,
+			kStrMenuItemOpen ";ll");
+		InsertMenu(menu, 0);
+	}
+
+	menu = NewMenuFromConvertCStr(kSpecialMenu, kStrMenuSpecial);
+	if (menu != NULL) {
+		AppendMenuConvertCStr(menu,
+			kCmdIdMoreCommands,
+			kStrMenuItemMore ";ll");
+		InsertMenu(menu, 0);
+	}
+
+	{
+		MenuRef outMenu;
+		MenuItemIndex outIndex;
+
+		if (noErr == GetIndMenuItemWithCommandID(
+			NULL, kHICommandQuit, 1, &outMenu, &outIndex))
+		{
+			RemoveCommandKeysInMenu(outMenu);
+		}
+	}
+
+	DrawMenuBar();
+
+	return trueblnr;
+}
+
+LOCALFUNC blnr InstallOurAppearanceClient(void)
+{
+	RegisterAppearanceClient(); /* maybe not needed ? */
+	return trueblnr;
+}
+
+LOCALVAR blnr DisplayRegistrationCallBackSuccessful = falseblnr;
+
+static void DisplayRegisterReconfigurationCallback(
+	CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags,
+	void *userInfo)
+{
+	UnusedParam(display);
+	UnusedParam(userInfo);
+
+	if (0 != (flags & kCGDisplayBeginConfigurationFlag)) {
+		/* fprintf(stderr, "kCGDisplayBeginConfigurationFlag\n"); */
+	} else {
+#if 0
+		if (0 != (flags & kCGDisplayMovedFlag)) {
+			fprintf(stderr, "kCGDisplayMovedFlag\n");
+		}
+		if (0 != (flags & kCGDisplaySetMainFlag)) {
+			fprintf(stderr, "kCGDisplaySetMainFlag\n");
+		}
+		if (0 != (flags & kCGDisplaySetModeFlag)) {
+			fprintf(stderr, "kCGDisplaySetModeFlag\n");
+		}
+
+		if (0 != (flags & kCGDisplayAddFlag)) {
+			fprintf(stderr, "kCGDisplayAddFlag\n");
+		}
+		if (0 != (flags & kCGDisplayRemoveFlag)) {
+			fprintf(stderr, "kCGDisplayRemoveFlag\n");
+		}
+
+		if (0 != (flags & kCGDisplayEnabledFlag)) {
+			fprintf(stderr, "kCGDisplayEnabledFlag\n");
+		}
+		if (0 != (flags & kCGDisplayDisabledFlag)) {
+			fprintf(stderr, "kCGDisplayDisabledFlag\n");
+		}
+
+		if (0 != (flags & kCGDisplayMirrorFlag)) {
+			fprintf(stderr, "kCGDisplayMirrorFlag\n");
+		}
+		if (0 != (flags & kCGDisplayUnMirrorFlag)) {
+			fprintf(stderr, "kCGDisplayMirrorFlag\n");
+		}
+#endif
+
+		WantScreensChangedCheck = trueblnr;
+
+#if VarFullScreen
+		if (WantFullScreen) {
+			ToggleWantFullScreen();
+		}
+#endif
+	}
+}
+
+LOCALFUNC blnr InstallOurEventHandlers(void)
+{
+	EventTypeSpec eventTypes[] = {
+		{kEventClassMouse, kEventMouseDown},
+		{kEventClassMouse, kEventMouseUp},
+		{kEventClassMouse, kEventMouseMoved},
+		{kEventClassMouse, kEventMouseDragged},
+		{kEventClassKeyboard, kEventRawKeyModifiersChanged},
+		{kEventClassKeyboard, kEventRawKeyDown},
+		{kEventClassKeyboard, kEventRawKeyUp},
+		{kEventClassApplication, kEventAppActivated},
+		{kEventClassApplication, kEventAppDeactivated},
+		{kEventClassCommand, kEventProcessCommand}
+	};
+
+	InstallApplicationEventHandler(
+		NewEventHandlerUPP(MyEventHandler),
+		GetEventTypeCount(eventTypes),
+		eventTypes, NULL, NULL);
+
+	InitKeyCodes();
+
+	InstallAppleEventHandlers();
+
+	if (HaveMyCGDisplayRegisterReconfigurationCallback()) {
+		if (kCGErrorSuccess ==
+			MyCGDisplayRegisterReconfigurationCallback(
+				DisplayRegisterReconfigurationCallback, NULL))
+		{
+			DisplayRegistrationCallBackSuccessful = trueblnr;
+		}
+	}
+
+	/* (void) SetMouseCoalescingEnabled(false, NULL); */
+
+	return trueblnr;
+}
+
+LOCALPROC UnInstallOurEventHandlers(void)
+{
+	if (DisplayRegistrationCallBackSuccessful) {
+		if (HaveMyCGDisplayRemoveReconfigurationCallback()) {
+			MyCGDisplayRemoveReconfigurationCallback(
+				DisplayRegisterReconfigurationCallback, NULL);
+		}
+	}
+}
+
+GLOBALOSGLUPROC WaitForNextTick(void)
+{
+	OSStatus err;
+	EventRef theEvent;
+	ui3r NumChecks;
+	EventTimeout inTimeout;
+	EventTargetRef theTarget = GetEventDispatcherTarget();
+
+	inTimeout = kEventDurationNoWait;
+
+label_retry:
+	NumChecks = 0;
+	while ((NumChecks < 32) && (noErr == (err =
+		ReceiveNextEvent(0, NULL, inTimeout,
+			true, &theEvent))))
+	{
+		(void) SendEventToEventTarget(theEvent, theTarget);
+		ReleaseEvent(theEvent);
+		inTimeout = kEventDurationNoWait;
+		++NumChecks;
+	}
+
+	CheckForSavedTasks();
+
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (CurSpeedStopped) {
+		DoneWithDrawingForTick();
+		inTimeout = kEventDurationForever;
+		goto label_retry;
+	}
+
+	if (ExtraTimeNotOver()) {
+		inTimeout =
+			NextTickChangeTime - GetCurrentEventTime();
+		if (inTimeout > 0.0) {
+#if 1
+			struct timespec rqt;
+			struct timespec rmt;
+
+			rqt.tv_sec = 0;
+			rqt.tv_nsec = inTimeout / kEventDurationNanosecond;
+			(void) nanosleep(&rqt, &rmt);
+			inTimeout = kEventDurationNoWait;
+			goto label_retry;
+#elif 1
+			usleep(inTimeout / kEventDurationMicrosecond);
+			inTimeout = kEventDurationNoWait;
+			goto label_retry;
+#else
+			/*
+				This has higher overhead.
+			*/
+			goto label_retry;
+#endif
+		}
+	}
+
+	if (CheckDateTime()) {
+#if MySoundEnabled
+		MySound_SecondNotify();
+#endif
+#if EnableDemoMsg
+		DemoModeSecondNotify();
+#endif
+	}
+
+	if (gWeAreActive) {
+		CheckMouseState();
+	}
+
+	OnTrueTime = TrueEmulatedTime;
+
+#if dbglog_TimeStuff
+	dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime);
+#endif
+}
+
+/* --- platform independent code can be thought of as going here --- */
+
+#include "PROGMAIN.h"
+
+LOCALPROC ReserveAllocAll(void)
+{
+#if dbglog_HAVE
+	dbglog_ReserveAlloc();
+#endif
+	ReserveAllocOneBlock(&ROM, kROM_Size, 5, falseblnr);
+	ReserveAllocOneBlock(&screencomparebuff,
+		vMacScreenNumBytes, 5, trueblnr);
+	ReserveAllocOneBlock(&CntrlDisplayBuff,
+		vMacScreenNumBytes, 5, falseblnr);
+	ReserveAllocOneBlock(&ScalingBuff, vMacScreenNumPixels
+#if 0 != vMacScreenDepth
+		* 4
+#endif
+		, 5, falseblnr);
+	ReserveAllocOneBlock(&CLUT_final, CLUT_finalsz, 5, falseblnr);
+#if MySoundEnabled
+	ReserveAllocOneBlock((ui3p *)&TheSoundBuffer,
+		dbhBufferSize, 5, falseblnr);
+#endif
+
+	EmulationReserveAlloc();
+}
+
+LOCALFUNC blnr AllocMyMemory(void)
+{
+	uimr n;
+	blnr IsOk = falseblnr;
+
+	ReserveAllocOffset = 0;
+	ReserveAllocBigBlock = nullpr;
+	ReserveAllocAll();
+	n = ReserveAllocOffset;
+	ReserveAllocBigBlock = (ui3p)calloc(1, n);
+	if (NULL == ReserveAllocBigBlock) {
+		MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr);
+	} else {
+		ReserveAllocOffset = 0;
+		ReserveAllocAll();
+		if (n != ReserveAllocOffset) {
+			/* oops, program error */
+		} else {
+			IsOk = trueblnr;
+		}
+	}
+
+	return IsOk;
+}
+
+LOCALFUNC blnr InitOSGLU(void)
+{
+	if (AllocMyMemory())
+	if (InitMyApplInfo())
+#if dbglog_HAVE
+	if (dbglog_open())
+#endif
+#if MySoundEnabled
+	if (MySound_Init())
+#endif
+	if (InstallOurAppearanceClient())
+	if (InstallOurEventHandlers())
+	if (InstallOurMenus())
+	if (CreateMainWindow())
+	if (LoadMacRom())
+	if (LoadInitialImages())
+#if UseActvCode
+	if (ActvCodeInit())
+#endif
+#if EmLocalTalk
+	if (InitLocalTalk())
+#endif
+	if (InitLocationDat())
+	if (WaitForRom())
+	{
+		return trueblnr;
+	}
+	return falseblnr;
+}
+
+#if dbglog_HAVE && 0
+IMPORTPROC DoDumpTable(void);
+#endif
+#if dbglog_HAVE && 0
+IMPORTPROC DumpRTC(void);
+#endif
+
+LOCALPROC UnInitOSGLU(void)
+{
+#if dbglog_HAVE && 0
+	DoDumpTable();
+#endif
+#if dbglog_HAVE && 0
+	DumpRTC();
+#endif
+
+	if (MacMsgDisplayed) {
+		MacMsgDisplayOff();
+	}
+
+#if MayFullScreen
+	UngrabMachine();
+#endif
+
+#if MySoundEnabled
+	MySound_Stop();
+#endif
+
+	CloseAglCurrentContext();
+	CloseMainWindow();
+
+#if MayFullScreen
+	My_ShowMenuBar();
+#endif
+
+#if IncludePbufs
+	UnInitPbufs();
+#endif
+	UnInitDrives();
+
+	if (! gTrueBackgroundFlag) {
+		CheckSavedMacMsg();
+	}
+
+	UnInstallOurEventHandlers();
+
+#if dbglog_HAVE
+	dbglog_close();
+#endif
+
+	UnInitMyApplInfo();
+
+	ForceShowCursor();
+}
+
+LOCALPROC ZapOSGLUVars(void)
+{
+	InitDrives();
+	ZapWinStateVars();
+}
+
+/* adapted from Apple "Technical Q&A QA1061" */
+
+static pascal OSStatus EventLoopEventHandler(
+	EventHandlerCallRef inHandlerCallRef, EventRef inEvent,
+	void *inUserData)
+/*
+	This code contains the standard Carbon event dispatch loop,
+	as per "Inside Macintosh: Handling Carbon Events", Listing 3-10,
+	except:
+
+	o this loop supports yielding to cooperative threads based on the
+		application maintaining the gNumberOfRunningThreads global
+		variable, and
+
+	o it also works around a problem with the Inside Macintosh code
+		which unexpectedly quits when run on traditional Mac OS 9.
+
+	See RunApplicationEventLoopWithCooperativeThreadSupport for
+	an explanation of why this is inside a Carbon event handler.
+
+	The code in Inside Mac has a problem in that it quits the
+	event loop when ReceiveNextEvent returns an error.  This is
+	wrong because ReceiveNextEvent can return eventLoopQuitErr
+	when you call WakeUpProcess on traditional Mac OS.  So, rather
+	than relying on an error from ReceiveNextEvent, this routine tracks
+	whether the application is really quitting by installing a
+	customer handler for the kEventClassApplication/kEventAppQuit
+	Carbon event.  All the custom handler does is call through
+	to the previous handler and, if it returns noErr (which indicates
+	the application is quitting, it sets quitNow so that our event
+	loop quits.
+
+	Note that this approach continues to support
+	QuitApplicationEventLoop, which is a simple wrapper that just posts
+	a kEventClassApplication/kEventAppQuit event to the event loop.
+*/
+{
+	UnusedParam(inHandlerCallRef);
+	UnusedParam(inEvent);
+	UnusedParam(inUserData);
+
+	ProgramMain();
+	QuitApplicationEventLoop();
+
+	return noErr;
+}
+
+LOCALPROC RunApplicationEventLoopWithCooperativeThreadSupport(void)
+/*
+	A reimplementation of RunApplicationEventLoop that supports
+	yielding time to cooperative threads.
+*/
+{
+	static const EventTypeSpec eventSpec = {'KWIN', 'KWIN'};
+	EventHandlerUPP theEventLoopEventHandlerUPP = nil;
+	EventHandlerRef installedHandler = NULL;
+	EventRef dummyEvent = nil;
+
+/*
+	Install EventLoopEventHandler, create a dummy event and post it,
+	and then call RunApplicationEventLoop.  The rationale for this
+	is as follows:  We want to unravel RunApplicationEventLoop so
+	that we can can yield to cooperative threads.  In fact, the
+	core code for RunApplicationEventLoop is pretty easy (you
+	can see it above in EventLoopEventHandler).  However, if you
+	just execute this code you miss out on all the standard event
+	handlers.  These are relatively easy to reproduce (handling
+	the quit event and so on), but doing so is a pain because
+	a) it requires a bunch boilerplate code, and b) if Apple
+	extends the list of standard event handlers, your application
+	wouldn't benefit.  So, we execute our event loop from within
+	a Carbon event handler that we cause to be executed by
+	explicitly posting an event to our event loop.  Thus, the
+	standard event handlers are installed while our event loop runs.
+*/
+	if (nil == (theEventLoopEventHandlerUPP
+		= NewEventHandlerUPP(EventLoopEventHandler)))
+	{
+		/* fail */
+	} else
+	if (noErr != InstallEventHandler(GetApplicationEventTarget(),
+		theEventLoopEventHandlerUPP, 1, &eventSpec, nil,
+		&installedHandler))
+	{
+		/* fail */
+	} else
+	if (noErr != MacCreateEvent(nil, 'KWIN', 'KWIN',
+		GetCurrentEventTime(), kEventAttributeNone,
+		&dummyEvent))
+	{
+		/* fail */
+	} else
+	if (noErr != PostEventToQueue(GetMainEventQueue(),
+		dummyEvent, kEventPriorityHigh))
+	{
+		/* fail */
+	} else
+	{
+		RunApplicationEventLoop();
+	}
+
+	if (nil != dummyEvent) {
+		ReleaseEvent(dummyEvent);
+	}
+
+	if (NULL != installedHandler) {
+		(void) RemoveEventHandler(installedHandler);
+	}
+}
+
+int main(void)
+{
+	ZapOSGLUVars();
+	if (InitOSGLU()) {
+		RunApplicationEventLoopWithCooperativeThreadSupport();
+	}
+	UnInitOSGLU();
+
+	return 0;
+}
--- /dev/null
+++ b/src/OSGLUSD2.c
@@ -1,0 +1,4217 @@
+/*
+	OSGLUSD2.c
+
+	Copyright (C) 2012 Paul C. Pratt, Manuel Alfayate
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Operating System GLUe for SDl 2.0 library
+
+	All operating system dependent code for the
+	SDL Library should go here.
+*/
+
+#include "CNFGRAPI.h"
+#include "SYSDEPNS.h"
+#include "ENDIANAC.h"
+
+#include "MYOSGLUE.h"
+
+#include "STRCONST.h"
+
+/* --- some simple utilities --- */
+
+GLOBALOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount)
+{
+	(void) memcpy((char *)destPtr, (char *)srcPtr, byteCount);
+}
+
+/* --- control mode and internationalization --- */
+
+#define NeedCell2PlainAsciiMap 1
+
+#include "INTLCHAR.h"
+
+#ifndef CanGetAppPath
+#define CanGetAppPath 1
+#endif
+
+LOCALVAR char *d_arg = NULL;
+LOCALVAR char *n_arg = NULL;
+
+#if CanGetAppPath
+LOCALVAR char *app_parent = NULL;
+LOCALVAR char *pref_dir = NULL;
+#endif
+
+#ifdef _WIN32
+#define MyPathSep '\\'
+#else
+#define MyPathSep '/'
+#endif
+
+LOCALFUNC tMacErr ChildPath(char *x, char *y, char **r)
+{
+	tMacErr err = mnvm_miscErr;
+	int nx = strlen(x);
+	int ny = strlen(y);
+	{
+		if ((nx > 0) && (MyPathSep == x[nx - 1])) {
+			--nx;
+		}
+		{
+			int nr = nx + 1 + ny;
+			char *p = malloc(nr + 1);
+			if (p != NULL) {
+				char *p2 = p;
+				(void) memcpy(p2, x, nx);
+				p2 += nx;
+				*p2++ = MyPathSep;
+				(void) memcpy(p2, y, ny);
+				p2 += ny;
+				*p2 = 0;
+				*r = p;
+				err = mnvm_noErr;
+			}
+		}
+	}
+
+	return err;
+}
+
+LOCALPROC MyMayFree(char *p)
+{
+	if (NULL != p) {
+		free(p);
+	}
+}
+
+/* --- sending debugging info to file --- */
+
+#if dbglog_HAVE
+
+#ifndef dbglog_ToStdErr
+#define dbglog_ToStdErr 0
+#endif
+#ifndef dbglog_ToSDL_Log
+#define dbglog_ToSDL_Log 0
+#endif
+
+#if ! dbglog_ToStdErr
+LOCALVAR FILE *dbglog_File = NULL;
+#endif
+
+LOCALFUNC blnr dbglog_open0(void)
+{
+#if dbglog_ToStdErr || dbglog_ToSDL_Log
+	return trueblnr;
+#else
+	if (NULL == app_parent) {
+		dbglog_File = fopen("dbglog.txt", "w");
+	} else {
+		char *t;
+
+		if (mnvm_noErr == ChildPath(app_parent, "dbglog.txt", &t)) {
+			dbglog_File = fopen(t, "w");
+			free(t);
+		}
+	}
+
+	return (NULL != dbglog_File);
+#endif
+}
+
+LOCALPROC dbglog_write0(char *s, uimr L)
+{
+#if dbglog_ToStdErr
+	(void) fwrite(s, 1, L, stderr);
+#elif dbglog_ToSDL_Log
+	char t[256 + 1];
+
+	if (L > 256) {
+		L = 256;
+	}
+	(void) memcpy(t, s, L);
+	t[L] = 1;
+
+	SDL_Log("%s", t);
+#else
+	if (dbglog_File != NULL) {
+		(void) fwrite(s, 1, L, dbglog_File);
+	}
+#endif
+}
+
+LOCALPROC dbglog_close0(void)
+{
+#if ! dbglog_ToStdErr
+	if (dbglog_File != NULL) {
+		fclose(dbglog_File);
+		dbglog_File = NULL;
+	}
+#endif
+}
+
+#endif
+
+/* --- information about the environment --- */
+
+#define WantColorTransValid 0
+
+#include "COMOSGLU.h"
+
+#include "PBUFSTDC.h"
+
+#include "CONTROLM.h"
+
+/* --- text translation --- */
+
+LOCALPROC NativeStrFromCStr(char *r, char *s)
+{
+	ui3b ps[ClStrMaxLength];
+	int i;
+	int L;
+
+	ClStrFromSubstCStr(&L, ps, s);
+
+	for (i = 0; i < L; ++i) {
+		r[i] = Cell2PlainAsciiMap[ps[i]];
+	}
+
+	r[L] = 0;
+}
+
+/* --- drives --- */
+
+#define NotAfileRef NULL
+
+#ifndef UseRWops
+#define UseRWops 0
+#endif
+
+#if UseRWops
+#define MyFilePtr SDL_RWops *
+#define MySeek SDL_RWseek
+#define MySeekSet RW_SEEK_SET
+#define MySeekCur RW_SEEK_CUR
+#define MySeekEnd RW_SEEK_END
+#define MyFileRead(ptr, size, nmemb, stream) \
+	SDL_RWread(stream, ptr, size, nmemb)
+#define MyFileWrite(ptr, size, nmemb, stream) \
+	SDL_RWwrite(stream, ptr, size, nmemb)
+#define MyFileTell SDL_RWtell
+#define MyFileClose SDL_RWclose
+#define MyFileOpen SDL_RWFromFile
+#else
+#define MyFilePtr FILE *
+#define MySeek fseek
+#define MySeekSet SEEK_SET
+#define MySeekCur SEEK_CUR
+#define MySeekEnd SEEK_END
+#define MyFileRead fread
+#define MyFileWrite fwrite
+#define MyFileTell ftell
+#define MyFileClose fclose
+#define MyFileOpen fopen
+#define MyFileEof feof
+#endif
+
+LOCALVAR MyFilePtr Drives[NumDrives]; /* open disk image files */
+
+LOCALPROC InitDrives(void)
+{
+	/*
+		This isn't really needed, Drives[i] and DriveNames[i]
+		need not have valid values when not vSonyIsInserted[i].
+	*/
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		Drives[i] = NotAfileRef;
+	}
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer,
+	tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count,
+	ui5r *Sony_ActCount)
+{
+	tMacErr err = mnvm_miscErr;
+	MyFilePtr refnum = Drives[Drive_No];
+	ui5r NewSony_Count = 0;
+
+	if (MySeek(refnum, Sony_Start, MySeekSet) >= 0) {
+		if (IsWrite) {
+			NewSony_Count = MyFileWrite(Buffer, 1, Sony_Count, refnum);
+		} else {
+			NewSony_Count = MyFileRead(Buffer, 1, Sony_Count, refnum);
+		}
+
+		if (NewSony_Count == Sony_Count) {
+			err = mnvm_noErr;
+		}
+	}
+
+	if (nullpr != Sony_ActCount) {
+		*Sony_ActCount = NewSony_Count;
+	}
+
+	return err; /*& figure out what really to return &*/
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count)
+{
+	tMacErr err = mnvm_miscErr;
+	MyFilePtr refnum = Drives[Drive_No];
+	long v;
+
+	if (MySeek(refnum, 0, MySeekEnd) >= 0) {
+		v = MyFileTell(refnum);
+		if (v >= 0) {
+			*Sony_Count = v;
+			err = mnvm_noErr;
+		}
+	}
+
+	return err; /*& figure out what really to return &*/
+}
+
+LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, blnr deleteit)
+{
+	MyFilePtr refnum = Drives[Drive_No];
+
+	DiskEjectedNotify(Drive_No);
+
+	MyFileClose(refnum);
+	Drives[Drive_No] = NotAfileRef; /* not really needed */
+
+	return mnvm_noErr;
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
+{
+	return vSonyEject0(Drive_No, falseblnr);
+}
+
+LOCALPROC UnInitDrives(void)
+{
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		if (vSonyIsInserted(i)) {
+			(void) vSonyEject(i);
+		}
+	}
+}
+
+LOCALFUNC blnr Sony_Insert0(MyFilePtr refnum, blnr locked,
+	char *drivepath)
+{
+	tDrive Drive_No;
+	blnr IsOk = falseblnr;
+
+	if (! FirstFreeDisk(&Drive_No)) {
+		MacMsg(kStrTooManyImagesTitle, kStrTooManyImagesMessage,
+			falseblnr);
+	} else {
+		/* printf("Sony_Insert0 %d\n", (int)Drive_No); */
+
+		{
+			Drives[Drive_No] = refnum;
+			DiskInsertNotify(Drive_No, locked);
+
+			IsOk = trueblnr;
+		}
+	}
+
+	if (! IsOk) {
+		MyFileClose(refnum);
+	}
+
+	return IsOk;
+}
+
+LOCALFUNC blnr Sony_Insert1(char *drivepath, blnr silentfail)
+{
+	blnr locked = falseblnr;
+	/* printf("Sony_Insert1 %s\n", drivepath); */
+	MyFilePtr refnum = MyFileOpen(drivepath, "rb+");
+	if (NULL == refnum) {
+		locked = trueblnr;
+		refnum = MyFileOpen(drivepath, "rb");
+	}
+	if (NULL == refnum) {
+		if (! silentfail) {
+			MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
+		}
+	} else {
+		return Sony_Insert0(refnum, locked, drivepath);
+	}
+	return falseblnr;
+}
+
+LOCALFUNC tMacErr LoadMacRomFrom(char *path)
+{
+	tMacErr err;
+	MyFilePtr ROM_File;
+	int File_Size;
+
+	ROM_File = MyFileOpen(path, "rb");
+	if (NULL == ROM_File) {
+		err = mnvm_fnfErr;
+	} else {
+		File_Size = MyFileRead(ROM, 1, kROM_Size, ROM_File);
+		if (File_Size != kROM_Size) {
+#ifdef MyFileEof
+			if (MyFileEof(ROM_File))
+#else
+			if (File_Size > 0)
+#endif
+			{
+				MacMsgOverride(kStrShortROMTitle,
+					kStrShortROMMessage);
+				err = mnvm_eofErr;
+			} else {
+				MacMsgOverride(kStrNoReadROMTitle,
+					kStrNoReadROMMessage);
+				err = mnvm_miscErr;
+			}
+		} else {
+			err = ROM_IsValid();
+		}
+		MyFileClose(ROM_File);
+	}
+
+	return err;
+}
+
+LOCALFUNC blnr Sony_Insert1a(char *drivepath, blnr silentfail)
+{
+	blnr v;
+
+	if (! ROM_loaded) {
+		v = (mnvm_noErr == LoadMacRomFrom(drivepath));
+	} else {
+		v = Sony_Insert1(drivepath, silentfail);
+	}
+
+	return v;
+}
+
+LOCALFUNC blnr Sony_Insert2(char *s)
+{
+	char *d =
+#if CanGetAppPath
+		(NULL == d_arg) ? app_parent :
+#endif
+		d_arg;
+	blnr IsOk = falseblnr;
+
+	if (NULL == d) {
+		IsOk = Sony_Insert1(s, trueblnr);
+	} else {
+		char *t;
+
+		if (mnvm_noErr == ChildPath(d, s, &t)) {
+			IsOk = Sony_Insert1(t, trueblnr);
+			free(t);
+		}
+	}
+
+	return IsOk;
+}
+
+LOCALFUNC blnr Sony_InsertIth(int i)
+{
+	blnr v;
+
+	if ((i > 9) || ! FirstFreeDisk(nullpr)) {
+		v = falseblnr;
+	} else {
+		char s[] = "disk?.dsk";
+
+		s[4] = '0' + i;
+
+		v = Sony_Insert2(s);
+	}
+
+	return v;
+}
+
+LOCALFUNC blnr LoadInitialImages(void)
+{
+	if (! AnyDiskInserted()) {
+		int i;
+
+		for (i = 1; Sony_InsertIth(i); ++i) {
+			/* stop on first error (including file not found) */
+		}
+	}
+
+	return trueblnr;
+}
+
+/* --- ROM --- */
+
+LOCALVAR char *rom_path = NULL;
+
+#if CanGetAppPath
+LOCALFUNC tMacErr LoadMacRomFromPrefDir(void)
+{
+	tMacErr err;
+	char *t = NULL;
+	char *t2 = NULL;
+
+	if (NULL == pref_dir) {
+		err = mnvm_fnfErr;
+	} else
+	if (mnvm_noErr != (err =
+		ChildPath(pref_dir, "mnvm_rom", &t)))
+	{
+		/* fail */
+	} else
+	if (mnvm_noErr != (err =
+		ChildPath(t, RomFileName, &t2)))
+	{
+		/* fail */
+	} else
+	{
+		err = LoadMacRomFrom(t2);
+	}
+
+	MyMayFree(t2);
+	MyMayFree(t);
+
+	return err;
+}
+#endif
+
+#if CanGetAppPath
+LOCALFUNC tMacErr LoadMacRomFromAppPar(void)
+{
+	tMacErr err;
+	char *d = (NULL == d_arg) ? app_parent : d_arg;
+	char *t = NULL;
+
+	if (NULL == d) {
+		err = mnvm_fnfErr;
+	} else
+	if (mnvm_noErr != (err =
+		ChildPath(d, RomFileName, &t)))
+	{
+		/* fail */
+	} else
+	{
+		err = LoadMacRomFrom(t);
+	}
+
+	MyMayFree(t);
+
+	return err;
+}
+#endif
+
+LOCALFUNC blnr LoadMacRom(void)
+{
+	tMacErr err;
+
+	if ((NULL == rom_path)
+		|| (mnvm_fnfErr == (err = LoadMacRomFrom(rom_path))))
+#if CanGetAppPath
+	if (mnvm_fnfErr == (err = LoadMacRomFromAppPar()))
+	if (mnvm_fnfErr == (err = LoadMacRomFromPrefDir()))
+#endif
+	if (mnvm_fnfErr == (err = LoadMacRomFrom(RomFileName)))
+	{
+	}
+
+	return trueblnr; /* keep launching Mini vMac, regardless */
+}
+
+/* --- video out --- */
+
+#if MayFullScreen
+LOCALVAR int hOffset;
+LOCALVAR int vOffset;
+#endif
+
+#if VarFullScreen
+LOCALVAR blnr UseFullScreen = (WantInitFullScreen != 0);
+#endif
+
+#if EnableMagnify
+LOCALVAR blnr UseMagnify = (WantInitMagnify != 0);
+#endif
+
+#ifndef UseSDLscaling
+#define UseSDLscaling 0
+#endif
+
+LOCALVAR blnr gBackgroundFlag = falseblnr;
+LOCALVAR blnr gTrueBackgroundFlag = falseblnr;
+LOCALVAR blnr CurSpeedStopped = trueblnr;
+
+#if EnableMagnify && ! UseSDLscaling
+#define MaxScale MyWindowScale
+#else
+#define MaxScale 1
+#endif
+
+
+LOCALVAR SDL_Window *my_main_wind = NULL;
+LOCALVAR SDL_Renderer *my_renderer = NULL;
+LOCALVAR SDL_Texture *my_texture = NULL;
+LOCALVAR SDL_PixelFormat *my_format = NULL;
+
+LOCALVAR ui3p ScalingBuff = nullpr;
+
+LOCALVAR ui3p CLUT_final;
+
+#define CLUT_finalsz (256 * 8 * 4 * MaxScale)
+	/*
+		256 possible values of one byte
+		8 pixels per byte maximum (when black and white)
+		4 bytes per destination pixel maximum
+			multiplied by MyWindowScale if EnableMagnify
+	*/
+
+#define ScrnMapr_DoMap UpdateBWDepth3Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 3
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateBWDepth4Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 4
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateBWDepth5Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#if EnableMagnify && ! UseSDLscaling
+
+#define ScrnMapr_DoMap UpdateBWDepth3ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 3
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateBWDepth4ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 4
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateBWDepth5ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#endif /* EnableMagnify && ! UseSDLscaling */
+
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+
+#define ScrnMapr_DoMap UpdateColorDepth3Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 3
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateColorDepth4Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 4
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateColorDepth5Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#if EnableMagnify && ! UseSDLscaling
+
+#define ScrnMapr_DoMap UpdateColorDepth3ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 3
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateColorDepth4ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 4
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateColorDepth5ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#endif /* EnableMagnify && ! UseSDLscaling */
+
+#endif
+
+
+LOCALPROC HaveChangedScreenBuff(ui4r top, ui4r left,
+	ui4r bottom, ui4r right)
+{
+	int i;
+	int j;
+	ui3b *p;
+	Uint32 pixel;
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+	Uint32 CLUT_pixel[CLUT_size];
+#endif
+	Uint32 BWLUT_pixel[2];
+	ui5r top2;
+	ui5r left2;
+	ui5r bottom2;
+	ui5r right2;
+	void *pixels;
+	int pitch;
+	SDL_Rect src_rect;
+	SDL_Rect dst_rect;
+	int XDest;
+	int YDest;
+	int DestWidth;
+	int DestHeight;
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		if (top < ViewVStart) {
+			top = ViewVStart;
+		}
+		if (left < ViewHStart) {
+			left = ViewHStart;
+		}
+		if (bottom > ViewVStart + ViewVSize) {
+			bottom = ViewVStart + ViewVSize;
+		}
+		if (right > ViewHStart + ViewHSize) {
+			right = ViewHStart + ViewHSize;
+		}
+
+		if ((top >= bottom) || (left >= right)) {
+			goto label_exit;
+		}
+	}
+#endif
+
+	XDest = left;
+	YDest = top;
+	DestWidth = (right - left);
+	DestHeight = (bottom - top);
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		XDest -= ViewHStart;
+		YDest -= ViewVStart;
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+		XDest *= MyWindowScale;
+		YDest *= MyWindowScale;
+		DestWidth *= MyWindowScale;
+		DestHeight *= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		XDest += hOffset;
+		YDest += vOffset;
+	}
+#endif
+
+	top2 = top;
+	left2 = left;
+	bottom2 = bottom;
+	right2 = right;
+
+#if EnableMagnify && ! UseSDLscaling
+	if (UseMagnify) {
+		top2 *= MyWindowScale;
+		left2 *= MyWindowScale;
+		bottom2 *= MyWindowScale;
+		right2 *= MyWindowScale;
+	}
+#endif
+
+	if (0 != SDL_LockTexture(my_texture, NULL, &pixels, &pitch)) {
+		return;
+	}
+
+	{
+
+	int bpp = my_format->BytesPerPixel;
+	ui5r ExpectedPitch = vMacScreenWidth * bpp;
+
+#if EnableMagnify && ! UseSDLscaling
+	if (UseMagnify) {
+		ExpectedPitch *= MyWindowScale;
+	}
+#endif
+
+#if 0 != vMacScreenDepth
+	if (UseColorMode) {
+#if vMacScreenDepth < 4
+		for (i = 0; i < CLUT_size; ++i) {
+			CLUT_pixel[i] = SDL_MapRGB(my_format,
+				CLUT_reds[i] >> 8,
+				CLUT_greens[i] >> 8,
+				CLUT_blues[i] >> 8);
+		}
+#endif
+	} else
+#endif
+	{
+		BWLUT_pixel[1] = SDL_MapRGB(my_format, 0, 0, 0);
+			/* black */
+		BWLUT_pixel[0] = SDL_MapRGB(my_format, 255, 255, 255);
+			/* white */
+	}
+
+	if ((0 == ((bpp - 1) & bpp)) /* a power of 2 */
+		&& (pitch == ExpectedPitch)
+#if (vMacScreenDepth > 3)
+		&& ! UseColorMode
+#endif
+		)
+	{
+		int k;
+		Uint32 v;
+#if EnableMagnify && ! UseSDLscaling
+		int a;
+#endif
+		int PixPerByte =
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+			UseColorMode ? (1 << (3 - vMacScreenDepth)) :
+#endif
+			8;
+		Uint8 *p4 = (Uint8 *)CLUT_final;
+
+		for (i = 0; i < 256; ++i) {
+			for (k = PixPerByte; --k >= 0; ) {
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+				if (UseColorMode) {
+					v = CLUT_pixel[
+#if 3 == vMacScreenDepth
+						i
+#else
+						(i >> (k << vMacScreenDepth))
+							& (CLUT_size - 1)
+#endif
+						];
+				} else
+#endif
+				{
+					v = BWLUT_pixel[(i >> k) & 1];
+				}
+
+#if EnableMagnify && ! UseSDLscaling
+				for (a = UseMagnify ? MyWindowScale : 1; --a >= 0; )
+#endif
+				{
+					switch (bpp) {
+						case 1: /* Assuming 8-bpp */
+							*p4++ = v;
+							break;
+						case 2: /* Probably 15-bpp or 16-bpp */
+							*(Uint16 *)p4 = v;
+							p4 += 2;
+							break;
+						case 4: /* Probably 32-bpp */
+							*(Uint32 *)p4 = v;
+							p4 += 4;
+							break;
+					}
+				}
+			}
+		}
+
+		ScalingBuff = (ui3p)pixels;
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+		if (UseColorMode) {
+#if EnableMagnify && ! UseSDLscaling
+			if (UseMagnify) {
+				switch (bpp) {
+					case 1:
+						UpdateColorDepth3ScaledCopy(
+							top, left, bottom, right);
+						break;
+					case 2:
+						UpdateColorDepth4ScaledCopy(
+							top, left, bottom, right);
+						break;
+					case 4:
+						UpdateColorDepth5ScaledCopy(
+							top, left, bottom, right);
+						break;
+				}
+			} else
+#endif
+			{
+				switch (bpp) {
+					case 1:
+						UpdateColorDepth3Copy(top, left, bottom, right);
+						break;
+					case 2:
+						UpdateColorDepth4Copy(top, left, bottom, right);
+						break;
+					case 4:
+						UpdateColorDepth5Copy(top, left, bottom, right);
+						break;
+				}
+			}
+		} else
+#endif
+		{
+#if EnableMagnify && ! UseSDLscaling
+			if (UseMagnify) {
+				switch (bpp) {
+					case 1:
+						UpdateBWDepth3ScaledCopy(
+							top, left, bottom, right);
+						break;
+					case 2:
+						UpdateBWDepth4ScaledCopy(
+							top, left, bottom, right);
+						break;
+					case 4:
+						UpdateBWDepth5ScaledCopy(
+							top, left, bottom, right);
+						break;
+				}
+			} else
+#endif
+			{
+				switch (bpp) {
+					case 1:
+						UpdateBWDepth3Copy(top, left, bottom, right);
+						break;
+					case 2:
+						UpdateBWDepth4Copy(top, left, bottom, right);
+						break;
+					case 4:
+						UpdateBWDepth5Copy(top, left, bottom, right);
+						break;
+				}
+			}
+		}
+
+	} else {
+		ui3b *the_data = (ui3b *)GetCurDrawBuff();
+
+		/* adapted from putpixel in SDL documentation */
+
+		for (i = top2; i < bottom2; ++i) {
+			for (j = left2; j < right2; ++j) {
+				int i0 = i;
+				int j0 = j;
+				Uint8 *bufp = (Uint8 *)pixels
+					+ i * pitch + j * bpp;
+
+#if EnableMagnify && ! UseSDLscaling
+				if (UseMagnify) {
+					i0 /= MyWindowScale;
+					j0 /= MyWindowScale;
+				}
+#endif
+
+#if 0 != vMacScreenDepth
+				if (UseColorMode) {
+#if vMacScreenDepth < 4
+					p = the_data + ((i0 * vMacScreenWidth + j0)
+						>> (3 - vMacScreenDepth));
+					{
+						ui3r k = (*p >> (((~ j0)
+								& ((1 << (3 - vMacScreenDepth)) - 1))
+							<< vMacScreenDepth))
+							& (CLUT_size - 1);
+						pixel = CLUT_pixel[k];
+					}
+#elif 4 == vMacScreenDepth
+					p = the_data + ((i0 * vMacScreenWidth + j0) << 1);
+					{
+						ui4r t0 = do_get_mem_word(p);
+						pixel = SDL_MapRGB(my_format,
+							((t0 & 0x7C00) >> 7)
+								| ((t0 & 0x7000) >> 12),
+							((t0 & 0x03E0) >> 2)
+								| ((t0 & 0x0380) >> 7),
+							((t0 & 0x001F) << 3)
+								| ((t0 & 0x001C) >> 2));
+					}
+#elif 5 == vMacScreenDepth
+					p = the_data + ((i0 * vMacScreenWidth + j0) << 2);
+					pixel = SDL_MapRGB(my_format,
+						p[1],
+						p[2],
+						p[3]);
+#endif
+				} else
+#endif
+				{
+					p = the_data + ((i0 * vMacScreenWidth + j0) / 8);
+					pixel = BWLUT_pixel[(*p >> ((~ j0) & 0x7)) & 1];
+				}
+
+				switch (bpp) {
+					case 1: /* Assuming 8-bpp */
+						*bufp = pixel;
+						break;
+					case 2: /* Probably 15-bpp or 16-bpp */
+						*(Uint16 *)bufp = pixel;
+						break;
+					case 3:
+						/* Slow 24-bpp mode, usually not used */
+						if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
+							bufp[0] = (pixel >> 16) & 0xff;
+							bufp[1] = (pixel >> 8) & 0xff;
+							bufp[2] = pixel & 0xff;
+						} else {
+							bufp[0] = pixel & 0xff;
+							bufp[1] = (pixel >> 8) & 0xff;
+							bufp[2] = (pixel >> 16) & 0xff;
+						}
+						break;
+					case 4: /* Probably 32-bpp */
+						*(Uint32 *)bufp = pixel;
+						break;
+				}
+			}
+		}
+	}
+
+	}
+
+	SDL_UnlockTexture(my_texture);
+
+	src_rect.x = left2;
+	src_rect.y = top2;
+	src_rect.w = right2 - left2;
+	src_rect.h = bottom2 - top2;
+
+	dst_rect.x = XDest;
+	dst_rect.y = YDest;
+	dst_rect.w = DestWidth;
+	dst_rect.h = DestHeight;
+
+	/* SDL_RenderClear(my_renderer); */
+	SDL_RenderCopy(my_renderer, my_texture, &src_rect, &dst_rect);
+	SDL_RenderPresent(my_renderer);
+
+#if MayFullScreen
+label_exit:
+	;
+#endif
+}
+
+LOCALPROC MyDrawChangesAndClear(void)
+{
+	if (ScreenChangedBottom > ScreenChangedTop) {
+		HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft,
+			ScreenChangedBottom, ScreenChangedRight);
+		ScreenClearChanges();
+	}
+}
+
+GLOBALOSGLUPROC DoneWithDrawingForTick(void)
+{
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		AutoScrollScreen();
+	}
+#endif
+	MyDrawChangesAndClear();
+}
+
+/* --- mouse --- */
+
+/* cursor hiding */
+
+LOCALVAR blnr HaveCursorHidden = falseblnr;
+LOCALVAR blnr WantCursorHidden = falseblnr;
+
+LOCALPROC ForceShowCursor(void)
+{
+	if (HaveCursorHidden) {
+		HaveCursorHidden = falseblnr;
+		(void) SDL_ShowCursor(SDL_ENABLE);
+	}
+}
+
+/* cursor moving */
+
+#ifndef HaveWorkingWarp
+#define HaveWorkingWarp 1
+#endif
+
+#if EnableMoveMouse && HaveWorkingWarp
+LOCALFUNC blnr MyMoveMouse(si4b h, si4b v)
+{
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		h -= ViewHStart;
+		v -= ViewVStart;
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+		h *= MyWindowScale;
+		v *= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		h += hOffset;
+		v += vOffset;
+	}
+#endif
+
+	SDL_WarpMouseInWindow(my_main_wind, h, v);
+
+	return trueblnr;
+}
+#endif
+
+/* cursor state */
+
+LOCALPROC MousePositionNotify(int NewMousePosh, int NewMousePosv)
+{
+	blnr ShouldHaveCursorHidden = trueblnr;
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		NewMousePosh -= hOffset;
+		NewMousePosv -= vOffset;
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+		NewMousePosh /= MyWindowScale;
+		NewMousePosv /= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		NewMousePosh += ViewHStart;
+		NewMousePosv += ViewVStart;
+	}
+#endif
+
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		MyMousePositionSetDelta(NewMousePosh - SavedMouseH,
+			NewMousePosv - SavedMouseV);
+		SavedMouseH = NewMousePosh;
+		SavedMouseV = NewMousePosv;
+	} else
+#endif
+	{
+		if (NewMousePosh < 0) {
+			NewMousePosh = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePosh >= vMacScreenWidth) {
+			NewMousePosh = vMacScreenWidth - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+		if (NewMousePosv < 0) {
+			NewMousePosv = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePosv >= vMacScreenHeight) {
+			NewMousePosv = vMacScreenHeight - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+
+#if VarFullScreen
+		if (UseFullScreen)
+#endif
+#if MayFullScreen
+		{
+			ShouldHaveCursorHidden = trueblnr;
+		}
+#endif
+
+		/* if (ShouldHaveCursorHidden || CurMouseButton) */
+		/*
+			for a game like arkanoid, would like mouse to still
+			move even when outside window in one direction
+		*/
+		MyMousePositionSet(NewMousePosh, NewMousePosv);
+	}
+
+	WantCursorHidden = ShouldHaveCursorHidden;
+}
+
+#if EnableFSMouseMotion && ! HaveWorkingWarp
+LOCALPROC MousePositionNotifyRelative(int deltah, int deltav)
+{
+	blnr ShouldHaveCursorHidden = trueblnr;
+
+#if EnableMagnify
+	if (UseMagnify) {
+		/*
+			This is not really right. If only move one pixel
+			each time, emulated mouse doesn't move at all.
+		*/
+		deltah /= MyWindowScale;
+		deltav /= MyWindowScale;
+	}
+#endif
+
+	MyMousePositionSetDelta(deltah,
+		deltav);
+
+	WantCursorHidden = ShouldHaveCursorHidden;
+}
+#endif
+
+LOCALPROC CheckMouseState(void)
+{
+	/*
+		this doesn't work as desired, doesn't get mouse movements
+		when outside of our window.
+	*/
+	int x;
+	int y;
+
+	(void) SDL_GetMouseState(&x, &y);
+	MousePositionNotify(x, y);
+}
+
+/* --- keyboard input --- */
+
+LOCALFUNC ui3r SDLScan2MacKeyCode(SDL_Scancode i)
+{
+	ui3r v = MKC_None;
+
+	switch (i) {
+		case SDL_SCANCODE_BACKSPACE: v = MKC_BackSpace; break;
+		case SDL_SCANCODE_TAB: v = MKC_Tab; break;
+		case SDL_SCANCODE_CLEAR: v = MKC_Clear; break;
+		case SDL_SCANCODE_RETURN: v = MKC_Return; break;
+		case SDL_SCANCODE_PAUSE: v = MKC_Pause; break;
+		case SDL_SCANCODE_ESCAPE: v = MKC_formac_Escape; break;
+		case SDL_SCANCODE_SPACE: v = MKC_Space; break;
+		case SDL_SCANCODE_APOSTROPHE: v = MKC_SingleQuote; break;
+		case SDL_SCANCODE_COMMA: v = MKC_Comma; break;
+		case SDL_SCANCODE_MINUS: v = MKC_Minus; break;
+		case SDL_SCANCODE_PERIOD: v = MKC_Period; break;
+		case SDL_SCANCODE_SLASH: v = MKC_formac_Slash; break;
+		case SDL_SCANCODE_0: v = MKC_0; break;
+		case SDL_SCANCODE_1: v = MKC_1; break;
+		case SDL_SCANCODE_2: v = MKC_2; break;
+		case SDL_SCANCODE_3: v = MKC_3; break;
+		case SDL_SCANCODE_4: v = MKC_4; break;
+		case SDL_SCANCODE_5: v = MKC_5; break;
+		case SDL_SCANCODE_6: v = MKC_6; break;
+		case SDL_SCANCODE_7: v = MKC_7; break;
+		case SDL_SCANCODE_8: v = MKC_8; break;
+		case SDL_SCANCODE_9: v = MKC_9; break;
+		case SDL_SCANCODE_SEMICOLON: v = MKC_SemiColon; break;
+		case SDL_SCANCODE_EQUALS: v = MKC_Equal; break;
+
+		case SDL_SCANCODE_LEFTBRACKET: v = MKC_LeftBracket; break;
+		case SDL_SCANCODE_BACKSLASH: v = MKC_formac_BackSlash; break;
+		case SDL_SCANCODE_RIGHTBRACKET: v = MKC_RightBracket; break;
+		case SDL_SCANCODE_GRAVE: v = MKC_formac_Grave; break;
+
+		case SDL_SCANCODE_A: v = MKC_A; break;
+		case SDL_SCANCODE_B: v = MKC_B; break;
+		case SDL_SCANCODE_C: v = MKC_C; break;
+		case SDL_SCANCODE_D: v = MKC_D; break;
+		case SDL_SCANCODE_E: v = MKC_E; break;
+		case SDL_SCANCODE_F: v = MKC_F; break;
+		case SDL_SCANCODE_G: v = MKC_G; break;
+		case SDL_SCANCODE_H: v = MKC_H; break;
+		case SDL_SCANCODE_I: v = MKC_I; break;
+		case SDL_SCANCODE_J: v = MKC_J; break;
+		case SDL_SCANCODE_K: v = MKC_K; break;
+		case SDL_SCANCODE_L: v = MKC_L; break;
+		case SDL_SCANCODE_M: v = MKC_M; break;
+		case SDL_SCANCODE_N: v = MKC_N; break;
+		case SDL_SCANCODE_O: v = MKC_O; break;
+		case SDL_SCANCODE_P: v = MKC_P; break;
+		case SDL_SCANCODE_Q: v = MKC_Q; break;
+		case SDL_SCANCODE_R: v = MKC_R; break;
+		case SDL_SCANCODE_S: v = MKC_S; break;
+		case SDL_SCANCODE_T: v = MKC_T; break;
+		case SDL_SCANCODE_U: v = MKC_U; break;
+		case SDL_SCANCODE_V: v = MKC_V; break;
+		case SDL_SCANCODE_W: v = MKC_W; break;
+		case SDL_SCANCODE_X: v = MKC_X; break;
+		case SDL_SCANCODE_Y: v = MKC_Y; break;
+		case SDL_SCANCODE_Z: v = MKC_Z; break;
+
+		case SDL_SCANCODE_KP_0: v = MKC_KP0; break;
+		case SDL_SCANCODE_KP_1: v = MKC_KP1; break;
+		case SDL_SCANCODE_KP_2: v = MKC_KP2; break;
+		case SDL_SCANCODE_KP_3: v = MKC_KP3; break;
+		case SDL_SCANCODE_KP_4: v = MKC_KP4; break;
+		case SDL_SCANCODE_KP_5: v = MKC_KP5; break;
+		case SDL_SCANCODE_KP_6: v = MKC_KP6; break;
+		case SDL_SCANCODE_KP_7: v = MKC_KP7; break;
+		case SDL_SCANCODE_KP_8: v = MKC_KP8; break;
+		case SDL_SCANCODE_KP_9: v = MKC_KP9; break;
+
+		case SDL_SCANCODE_KP_PERIOD: v = MKC_Decimal; break;
+		case SDL_SCANCODE_KP_DIVIDE: v = MKC_KPDevide; break;
+		case SDL_SCANCODE_KP_MULTIPLY: v = MKC_KPMultiply; break;
+		case SDL_SCANCODE_KP_MINUS: v = MKC_KPSubtract; break;
+		case SDL_SCANCODE_KP_PLUS: v = MKC_KPAdd; break;
+		case SDL_SCANCODE_KP_ENTER: v = MKC_formac_Enter; break;
+		case SDL_SCANCODE_KP_EQUALS: v = MKC_KPEqual; break;
+
+		case SDL_SCANCODE_UP: v = MKC_Up; break;
+		case SDL_SCANCODE_DOWN: v = MKC_Down; break;
+		case SDL_SCANCODE_RIGHT: v = MKC_Right; break;
+		case SDL_SCANCODE_LEFT: v = MKC_Left; break;
+		case SDL_SCANCODE_INSERT: v = MKC_formac_Help; break;
+		case SDL_SCANCODE_HOME: v = MKC_formac_Home; break;
+		case SDL_SCANCODE_END: v = MKC_formac_End; break;
+		case SDL_SCANCODE_PAGEUP: v = MKC_formac_PageUp; break;
+		case SDL_SCANCODE_PAGEDOWN: v = MKC_formac_PageDown; break;
+
+		case SDL_SCANCODE_F1: v = MKC_formac_F1; break;
+		case SDL_SCANCODE_F2: v = MKC_formac_F2; break;
+		case SDL_SCANCODE_F3: v = MKC_formac_F3; break;
+		case SDL_SCANCODE_F4: v = MKC_formac_F4; break;
+		case SDL_SCANCODE_F5: v = MKC_formac_F5; break;
+		case SDL_SCANCODE_F6: v = MKC_F6; break;
+		case SDL_SCANCODE_F7: v = MKC_F7; break;
+		case SDL_SCANCODE_F8: v = MKC_F8; break;
+		case SDL_SCANCODE_F9: v = MKC_F9; break;
+		case SDL_SCANCODE_F10: v = MKC_F10; break;
+		case SDL_SCANCODE_F11: v = MKC_F11; break;
+		case SDL_SCANCODE_F12: v = MKC_F12; break;
+
+		case SDL_SCANCODE_NUMLOCKCLEAR:
+			v = MKC_formac_ForwardDel; break;
+		case SDL_SCANCODE_CAPSLOCK: v = MKC_formac_CapsLock; break;
+		case SDL_SCANCODE_SCROLLLOCK: v = MKC_ScrollLock; break;
+		case SDL_SCANCODE_RSHIFT: v = MKC_formac_RShift; break;
+		case SDL_SCANCODE_LSHIFT: v = MKC_formac_Shift; break;
+		case SDL_SCANCODE_RCTRL: v = MKC_formac_RControl; break;
+		case SDL_SCANCODE_LCTRL: v = MKC_formac_Control; break;
+		case SDL_SCANCODE_RALT: v = MKC_formac_ROption; break;
+		case SDL_SCANCODE_LALT: v = MKC_formac_Option; break;
+		case SDL_SCANCODE_RGUI: v = MKC_formac_RCommand; break;
+		case SDL_SCANCODE_LGUI: v = MKC_formac_Command; break;
+		/* case SDLK_LSUPER: v = MKC_formac_Option; break; */
+		/* case SDLK_RSUPER: v = MKC_formac_ROption; break; */
+
+		case SDL_SCANCODE_HELP: v = MKC_formac_Help; break;
+		case SDL_SCANCODE_PRINTSCREEN: v = MKC_Print; break;
+
+		case SDL_SCANCODE_UNDO: v = MKC_formac_F1; break;
+		case SDL_SCANCODE_CUT: v = MKC_formac_F2; break;
+		case SDL_SCANCODE_COPY: v = MKC_formac_F3; break;
+		case SDL_SCANCODE_PASTE: v = MKC_formac_F4; break;
+
+		case SDL_SCANCODE_AC_HOME: v = MKC_formac_Home; break;
+
+		case SDL_SCANCODE_KP_A: v = MKC_A; break;
+		case SDL_SCANCODE_KP_B: v = MKC_B; break;
+		case SDL_SCANCODE_KP_C: v = MKC_C; break;
+		case SDL_SCANCODE_KP_D: v = MKC_D; break;
+		case SDL_SCANCODE_KP_E: v = MKC_E; break;
+		case SDL_SCANCODE_KP_F: v = MKC_F; break;
+
+		case SDL_SCANCODE_KP_BACKSPACE: v = MKC_BackSpace; break;
+		case SDL_SCANCODE_KP_CLEAR: v = MKC_Clear; break;
+		case SDL_SCANCODE_KP_COMMA: v = MKC_Comma; break;
+		case SDL_SCANCODE_KP_DECIMAL: v = MKC_Decimal; break;
+
+		default:
+			break;
+	}
+
+	return v;
+}
+
+LOCALPROC DoKeyCode(SDL_Keysym *r, blnr down)
+{
+	ui3r v = SDLScan2MacKeyCode(r->scancode);
+	if (MKC_None != v) {
+		Keyboard_UpdateKeyMap2(v, down);
+	}
+}
+
+LOCALPROC DisableKeyRepeat(void)
+{
+}
+
+LOCALPROC RestoreKeyRepeat(void)
+{
+}
+
+LOCALPROC ReconnectKeyCodes3(void)
+{
+}
+
+LOCALPROC DisconnectKeyCodes3(void)
+{
+	DisconnectKeyCodes2();
+	MyMouseButtonSet(falseblnr);
+}
+
+/* --- time, date, location --- */
+
+#define dbglog_TimeStuff (0 && dbglog_HAVE)
+
+LOCALVAR ui5b TrueEmulatedTime = 0;
+
+#define MyInvTimeDivPow 16
+#define MyInvTimeDiv (1 << MyInvTimeDivPow)
+#define MyInvTimeDivMask (MyInvTimeDiv - 1)
+#define MyInvTimeStep 1089590 /* 1000 / 60.14742 * MyInvTimeDiv */
+
+LOCALVAR Uint32 LastTime;
+
+LOCALVAR Uint32 NextIntTime;
+LOCALVAR ui5b NextFracTime;
+
+LOCALPROC IncrNextTime(void)
+{
+	NextFracTime += MyInvTimeStep;
+	NextIntTime += (NextFracTime >> MyInvTimeDivPow);
+	NextFracTime &= MyInvTimeDivMask;
+}
+
+LOCALPROC InitNextTime(void)
+{
+	NextIntTime = LastTime;
+	NextFracTime = 0;
+	IncrNextTime();
+}
+
+LOCALVAR ui5b NewMacDateInSeconds;
+
+LOCALFUNC blnr UpdateTrueEmulatedTime(void)
+{
+	Uint32 LatestTime;
+	si5b TimeDiff;
+
+	LatestTime = SDL_GetTicks();
+	if (LatestTime != LastTime) {
+
+		NewMacDateInSeconds = LatestTime / 1000;
+			/* no date and time api in SDL */
+
+		LastTime = LatestTime;
+		TimeDiff = (LatestTime - NextIntTime);
+			/* this should work even when time wraps */
+		if (TimeDiff >= 0) {
+			if (TimeDiff > 256) {
+				/* emulation interrupted, forget it */
+				++TrueEmulatedTime;
+				InitNextTime();
+
+#if dbglog_TimeStuff
+				dbglog_writelnNum("emulation interrupted",
+					TrueEmulatedTime);
+#endif
+			} else {
+				do {
+					++TrueEmulatedTime;
+					IncrNextTime();
+					TimeDiff = (LatestTime - NextIntTime);
+				} while (TimeDiff >= 0);
+			}
+			return trueblnr;
+		} else {
+			if (TimeDiff < -256) {
+#if dbglog_TimeStuff
+				dbglog_writeln("clock set back");
+#endif
+				/* clock goofed if ever get here, reset */
+				InitNextTime();
+			}
+		}
+	}
+	return falseblnr;
+}
+
+
+LOCALFUNC blnr CheckDateTime(void)
+{
+	if (CurMacDateInSeconds != NewMacDateInSeconds) {
+		CurMacDateInSeconds = NewMacDateInSeconds;
+		return trueblnr;
+	} else {
+		return falseblnr;
+	}
+}
+
+LOCALPROC StartUpTimeAdjust(void)
+{
+	LastTime = SDL_GetTicks();
+	InitNextTime();
+}
+
+LOCALFUNC blnr InitLocationDat(void)
+{
+	LastTime = SDL_GetTicks();
+	InitNextTime();
+	NewMacDateInSeconds = LastTime / 1000;
+	CurMacDateInSeconds = NewMacDateInSeconds;
+
+	return trueblnr;
+}
+
+/* --- sound --- */
+
+#if MySoundEnabled
+
+#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */
+#define kSoundBuffers (1 << kLn2SoundBuffers)
+#define kSoundBuffMask (kSoundBuffers - 1)
+
+#define DesiredMinFilledSoundBuffs 3
+	/*
+		if too big then sound lags behind emulation.
+		if too small then sound will have pauses.
+	*/
+
+#define kLnOneBuffLen 9
+#define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen)
+#define kOneBuffLen (1UL << kLnOneBuffLen)
+#define kAllBuffLen (1UL << kLnAllBuffLen)
+#define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3)
+#define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3)
+#define kOneBuffSz (1UL << kLnOneBuffSz)
+#define kAllBuffSz (1UL << kLnAllBuffSz)
+#define kOneBuffMask (kOneBuffLen - 1)
+#define kAllBuffMask (kAllBuffLen - 1)
+#define dbhBufferSize (kAllBuffSz + kOneBuffSz)
+
+#define dbglog_SoundStuff (0 && dbglog_HAVE)
+#define dbglog_SoundBuffStats (0 && dbglog_HAVE)
+
+LOCALVAR tpSoundSamp TheSoundBuffer = nullpr;
+volatile static ui4b ThePlayOffset;
+volatile static ui4b TheFillOffset;
+volatile static ui4b MinFilledSoundBuffs;
+#if dbglog_SoundBuffStats
+LOCALVAR ui4b MaxFilledSoundBuffs;
+#endif
+LOCALVAR ui4b TheWriteOffset;
+
+LOCALPROC MySound_Init0(void)
+{
+	ThePlayOffset = 0;
+	TheFillOffset = 0;
+	TheWriteOffset = 0;
+}
+
+LOCALPROC MySound_Start0(void)
+{
+	/* Reset variables */
+	MinFilledSoundBuffs = kSoundBuffers + 1;
+#if dbglog_SoundBuffStats
+	MaxFilledSoundBuffs = 0;
+#endif
+}
+
+GLOBALOSGLUFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL)
+{
+	ui4b ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset);
+	ui4b WriteBuffContig =
+		kOneBuffLen - (TheWriteOffset & kOneBuffMask);
+
+	if (WriteBuffContig < n) {
+		n = WriteBuffContig;
+	}
+	if (ToFillLen < n) {
+		/* overwrite previous buffer */
+#if dbglog_SoundStuff
+		dbglog_writeln("sound buffer over flow");
+#endif
+		TheWriteOffset -= kOneBuffLen;
+	}
+
+	*actL = n;
+	return TheSoundBuffer + (TheWriteOffset & kAllBuffMask);
+}
+
+#if 4 == kLn2SoundSampSz
+LOCALPROC ConvertSoundBlockToNative(tpSoundSamp p)
+{
+	int i;
+
+	for (i = kOneBuffLen; --i >= 0; ) {
+		*p++ -= 0x8000;
+	}
+}
+#else
+#define ConvertSoundBlockToNative(p)
+#endif
+
+LOCALPROC MySound_WroteABlock(void)
+{
+#if (4 == kLn2SoundSampSz)
+	ui4b PrevWriteOffset = TheWriteOffset - kOneBuffLen;
+	tpSoundSamp p = TheSoundBuffer + (PrevWriteOffset & kAllBuffMask);
+#endif
+
+#if dbglog_SoundStuff
+	dbglog_writeln("enter MySound_WroteABlock");
+#endif
+
+	ConvertSoundBlockToNative(p);
+
+	TheFillOffset = TheWriteOffset;
+
+#if dbglog_SoundBuffStats
+	{
+		ui4b ToPlayLen = TheFillOffset
+			- ThePlayOffset;
+		ui4b ToPlayBuffs = ToPlayLen >> kLnOneBuffLen;
+
+		if (ToPlayBuffs > MaxFilledSoundBuffs) {
+			MaxFilledSoundBuffs = ToPlayBuffs;
+		}
+	}
+#endif
+}
+
+LOCALFUNC blnr MySound_EndWrite0(ui4r actL)
+{
+	blnr v;
+
+	TheWriteOffset += actL;
+
+	if (0 != (TheWriteOffset & kOneBuffMask)) {
+		v = falseblnr;
+	} else {
+		/* just finished a block */
+
+		MySound_WroteABlock();
+
+		v = trueblnr;
+	}
+
+	return v;
+}
+
+LOCALPROC MySound_SecondNotify0(void)
+{
+	if (MinFilledSoundBuffs <= kSoundBuffers) {
+		if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) {
+#if dbglog_SoundStuff
+			dbglog_writeln("MinFilledSoundBuffs too high");
+#endif
+			IncrNextTime();
+		} else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) {
+#if dbglog_SoundStuff
+			dbglog_writeln("MinFilledSoundBuffs too low");
+#endif
+			++TrueEmulatedTime;
+		}
+#if dbglog_SoundBuffStats
+		dbglog_writelnNum("MinFilledSoundBuffs",
+			MinFilledSoundBuffs);
+		dbglog_writelnNum("MaxFilledSoundBuffs",
+			MaxFilledSoundBuffs);
+		MaxFilledSoundBuffs = 0;
+#endif
+		MinFilledSoundBuffs = kSoundBuffers + 1;
+	}
+}
+
+typedef ui4r trSoundTemp;
+
+#define kCenterTempSound 0x8000
+
+#define AudioStepVal 0x0040
+
+#if 3 == kLn2SoundSampSz
+#define ConvertTempSoundSampleFromNative(v) ((v) << 8)
+#elif 4 == kLn2SoundSampSz
+#define ConvertTempSoundSampleFromNative(v) ((v) + kCenterSound)
+#else
+#error "unsupported kLn2SoundSampSz"
+#endif
+
+#if 3 == kLn2SoundSampSz
+#define ConvertTempSoundSampleToNative(v) ((v) >> 8)
+#elif 4 == kLn2SoundSampSz
+#define ConvertTempSoundSampleToNative(v) ((v) - kCenterSound)
+#else
+#error "unsupported kLn2SoundSampSz"
+#endif
+
+LOCALPROC SoundRampTo(trSoundTemp *last_val, trSoundTemp dst_val,
+	tpSoundSamp *stream, int *len)
+{
+	trSoundTemp diff;
+	tpSoundSamp p = *stream;
+	int n = *len;
+	trSoundTemp v1 = *last_val;
+
+	while ((v1 != dst_val) && (0 != n)) {
+		if (v1 > dst_val) {
+			diff = v1 - dst_val;
+			if (diff > AudioStepVal) {
+				v1 -= AudioStepVal;
+			} else {
+				v1 = dst_val;
+			}
+		} else {
+			diff = dst_val - v1;
+			if (diff > AudioStepVal) {
+				v1 += AudioStepVal;
+			} else {
+				v1 = dst_val;
+			}
+		}
+
+		--n;
+		*p++ = ConvertTempSoundSampleToNative(v1);
+	}
+
+	*stream = p;
+	*len = n;
+	*last_val = v1;
+}
+
+struct MySoundR {
+	tpSoundSamp fTheSoundBuffer;
+	volatile ui4b (*fPlayOffset);
+	volatile ui4b (*fFillOffset);
+	volatile ui4b (*fMinFilledSoundBuffs);
+
+	volatile trSoundTemp lastv;
+
+	blnr wantplaying;
+	blnr HaveStartedPlaying;
+};
+typedef struct MySoundR MySoundR;
+
+static void my_audio_callback(void *udata, Uint8 *stream, int len)
+{
+	ui4b ToPlayLen;
+	ui4b FilledSoundBuffs;
+	int i;
+	MySoundR *datp = (MySoundR *)udata;
+	tpSoundSamp CurSoundBuffer = datp->fTheSoundBuffer;
+	ui4b CurPlayOffset = *datp->fPlayOffset;
+	trSoundTemp v0 = datp->lastv;
+	trSoundTemp v1 = v0;
+	tpSoundSamp dst = (tpSoundSamp)stream;
+
+#if kLn2SoundSampSz > 3
+	len >>= (kLn2SoundSampSz - 3);
+#endif
+
+#if dbglog_SoundStuff
+	dbglog_writeln("Enter my_audio_callback");
+	dbglog_writelnNum("len", len);
+#endif
+
+label_retry:
+	ToPlayLen = *datp->fFillOffset - CurPlayOffset;
+	FilledSoundBuffs = ToPlayLen >> kLnOneBuffLen;
+
+	if (! datp->wantplaying) {
+#if dbglog_SoundStuff
+		dbglog_writeln("playing end transistion");
+#endif
+
+		SoundRampTo(&v1, kCenterTempSound, &dst, &len);
+
+		ToPlayLen = 0;
+	} else if (! datp->HaveStartedPlaying) {
+#if dbglog_SoundStuff
+		dbglog_writeln("playing start block");
+#endif
+
+		if ((ToPlayLen >> kLnOneBuffLen) < 8) {
+			ToPlayLen = 0;
+		} else {
+			tpSoundSamp p = datp->fTheSoundBuffer
+				+ (CurPlayOffset & kAllBuffMask);
+			trSoundTemp v2 = ConvertTempSoundSampleFromNative(*p);
+
+#if dbglog_SoundStuff
+			dbglog_writeln("have enough samples to start");
+#endif
+
+			SoundRampTo(&v1, v2, &dst, &len);
+
+			if (v1 == v2) {
+#if dbglog_SoundStuff
+				dbglog_writeln("finished start transition");
+#endif
+
+				datp->HaveStartedPlaying = trueblnr;
+			}
+		}
+	}
+
+	if (0 == len) {
+		/* done */
+
+		if (FilledSoundBuffs < *datp->fMinFilledSoundBuffs) {
+			*datp->fMinFilledSoundBuffs = FilledSoundBuffs;
+		}
+	} else if (0 == ToPlayLen) {
+
+#if dbglog_SoundStuff
+		dbglog_writeln("under run");
+#endif
+
+		for (i = 0; i < len; ++i) {
+			*dst++ = ConvertTempSoundSampleToNative(v1);
+		}
+		*datp->fMinFilledSoundBuffs = 0;
+	} else {
+		ui4b PlayBuffContig = kAllBuffLen
+			- (CurPlayOffset & kAllBuffMask);
+		tpSoundSamp p = CurSoundBuffer
+			+ (CurPlayOffset & kAllBuffMask);
+
+		if (ToPlayLen > PlayBuffContig) {
+			ToPlayLen = PlayBuffContig;
+		}
+		if (ToPlayLen > len) {
+			ToPlayLen = len;
+		}
+
+		for (i = 0; i < ToPlayLen; ++i) {
+			*dst++ = *p++;
+		}
+		v1 = ConvertTempSoundSampleFromNative(p[-1]);
+
+		CurPlayOffset += ToPlayLen;
+		len -= ToPlayLen;
+
+		*datp->fPlayOffset = CurPlayOffset;
+
+		goto label_retry;
+	}
+
+	datp->lastv = v1;
+}
+
+LOCALVAR MySoundR cur_audio;
+
+LOCALVAR blnr HaveSoundOut = falseblnr;
+
+LOCALPROC MySound_Stop(void)
+{
+#if dbglog_SoundStuff
+	dbglog_writeln("enter MySound_Stop");
+#endif
+
+	if (cur_audio.wantplaying && HaveSoundOut) {
+		ui4r retry_limit = 50; /* half of a second */
+
+		cur_audio.wantplaying = falseblnr;
+
+label_retry:
+		if (kCenterTempSound == cur_audio.lastv) {
+#if dbglog_SoundStuff
+			dbglog_writeln("reached kCenterTempSound");
+#endif
+
+			/* done */
+		} else if (0 == --retry_limit) {
+#if dbglog_SoundStuff
+			dbglog_writeln("retry limit reached");
+#endif
+			/* done */
+		} else
+		{
+			/*
+				give time back, particularly important
+				if got here on a suspend event.
+			*/
+
+#if dbglog_SoundStuff
+			dbglog_writeln("busy, so sleep");
+#endif
+
+			(void) SDL_Delay(10);
+
+			goto label_retry;
+		}
+
+		SDL_PauseAudio(1);
+	}
+
+#if dbglog_SoundStuff
+	dbglog_writeln("leave MySound_Stop");
+#endif
+}
+
+LOCALPROC MySound_Start(void)
+{
+	if ((! cur_audio.wantplaying) && HaveSoundOut) {
+		MySound_Start0();
+		cur_audio.lastv = kCenterTempSound;
+		cur_audio.HaveStartedPlaying = falseblnr;
+		cur_audio.wantplaying = trueblnr;
+
+		SDL_PauseAudio(0);
+	}
+}
+
+LOCALPROC MySound_UnInit(void)
+{
+	if (HaveSoundOut) {
+		SDL_CloseAudio();
+	}
+}
+
+#define SOUND_SAMPLERATE 22255 /* = round(7833600 * 2 / 704) */
+
+LOCALFUNC blnr MySound_Init(void)
+{
+	SDL_AudioSpec desired;
+
+	MySound_Init0();
+
+	cur_audio.fTheSoundBuffer = TheSoundBuffer;
+	cur_audio.fPlayOffset = &ThePlayOffset;
+	cur_audio.fFillOffset = &TheFillOffset;
+	cur_audio.fMinFilledSoundBuffs = &MinFilledSoundBuffs;
+	cur_audio.wantplaying = falseblnr;
+
+	desired.freq = SOUND_SAMPLERATE;
+
+#if 3 == kLn2SoundSampSz
+	desired.format = AUDIO_U8;
+#elif 4 == kLn2SoundSampSz
+	desired.format = AUDIO_S16SYS;
+#else
+#error "unsupported audio format"
+#endif
+
+	desired.channels = 1;
+	desired.samples = 1024;
+	desired.callback = my_audio_callback;
+	desired.userdata = (void *)&cur_audio;
+
+	/* Open the audio device */
+	if (SDL_OpenAudio(&desired, NULL) < 0) {
+		fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
+	} else {
+		HaveSoundOut = trueblnr;
+
+		MySound_Start();
+			/*
+				This should be taken care of by LeaveSpeedStopped,
+				but since takes a while to get going properly,
+				start early.
+			*/
+	}
+
+	return trueblnr; /* keep going, even if no sound */
+}
+
+GLOBALOSGLUPROC MySound_EndWrite(ui4r actL)
+{
+	if (MySound_EndWrite0(actL)) {
+	}
+}
+
+LOCALPROC MySound_SecondNotify(void)
+{
+	if (HaveSoundOut) {
+		MySound_SecondNotify0();
+	}
+}
+
+#endif
+
+/* --- basic dialogs --- */
+
+LOCALPROC CheckSavedMacMsg(void)
+{
+	/* called only on quit, if error saved but not yet reported */
+
+	if (nullpr != SavedBriefMsg) {
+		char briefMsg0[ClStrMaxLength + 1];
+		char longMsg0[ClStrMaxLength + 1];
+
+		NativeStrFromCStr(briefMsg0, SavedBriefMsg);
+		NativeStrFromCStr(longMsg0, SavedLongMsg);
+
+		if (0 != SDL_ShowSimpleMessageBox(
+			SDL_MESSAGEBOX_ERROR,
+			SavedBriefMsg,
+			SavedLongMsg,
+			my_main_wind
+			))
+		{
+			fprintf(stderr, "%s\n", briefMsg0);
+			fprintf(stderr, "%s\n", longMsg0);
+		}
+
+		SavedBriefMsg = nullpr;
+	}
+}
+
+/* --- clipboard --- */
+
+#if IncludeHostTextClipExchange
+LOCALFUNC uimr MacRoman2UniCodeSize(ui3b *s, uimr L)
+{
+	uimr i;
+	ui3r x;
+	uimr n;
+	uimr v = 0;
+
+	for (i = 0; i < L; ++i) {
+		x = *s++;
+		if (x < 128) {
+			n = 1;
+		} else {
+			switch (x) {
+				case 0x80: n = 2; break;
+					/* LATIN CAPITAL LETTER A WITH DIAERESIS */
+				case 0x81: n = 2; break;
+					/* LATIN CAPITAL LETTER A WITH RING ABOVE */
+				case 0x82: n = 2; break;
+					/* LATIN CAPITAL LETTER C WITH CEDILLA */
+				case 0x83: n = 2; break;
+					/* LATIN CAPITAL LETTER E WITH ACUTE */
+				case 0x84: n = 2; break;
+					/* LATIN CAPITAL LETTER N WITH TILDE */
+				case 0x85: n = 2; break;
+					/* LATIN CAPITAL LETTER O WITH DIAERESIS */
+				case 0x86: n = 2; break;
+					/* LATIN CAPITAL LETTER U WITH DIAERESIS */
+				case 0x87: n = 2; break;
+					/* LATIN SMALL LETTER A WITH ACUTE */
+				case 0x88: n = 2; break;
+					/* LATIN SMALL LETTER A WITH GRAVE */
+				case 0x89: n = 2; break;
+					/* LATIN SMALL LETTER A WITH CIRCUMFLEX */
+				case 0x8A: n = 2; break;
+					/* LATIN SMALL LETTER A WITH DIAERESIS */
+				case 0x8B: n = 2; break;
+					/* LATIN SMALL LETTER A WITH TILDE */
+				case 0x8C: n = 2; break;
+					/* LATIN SMALL LETTER A WITH RING ABOVE */
+				case 0x8D: n = 2; break;
+					/* LATIN SMALL LETTER C WITH CEDILLA */
+				case 0x8E: n = 2; break;
+					/* LATIN SMALL LETTER E WITH ACUTE */
+				case 0x8F: n = 2; break;
+					/* LATIN SMALL LETTER E WITH GRAVE */
+				case 0x90: n = 2; break;
+					/* LATIN SMALL LETTER E WITH CIRCUMFLEX */
+				case 0x91: n = 2; break;
+					/* LATIN SMALL LETTER E WITH DIAERESIS */
+				case 0x92: n = 2; break;
+					/* LATIN SMALL LETTER I WITH ACUTE */
+				case 0x93: n = 2; break;
+					/* LATIN SMALL LETTER I WITH GRAVE */
+				case 0x94: n = 2; break;
+					/* LATIN SMALL LETTER I WITH CIRCUMFLEX */
+				case 0x95: n = 2; break;
+					/* LATIN SMALL LETTER I WITH DIAERESIS */
+				case 0x96: n = 2; break;
+					/* LATIN SMALL LETTER N WITH TILDE */
+				case 0x97: n = 2; break;
+					/* LATIN SMALL LETTER O WITH ACUTE */
+				case 0x98: n = 2; break;
+					/* LATIN SMALL LETTER O WITH GRAVE */
+				case 0x99: n = 2; break;
+					/* LATIN SMALL LETTER O WITH CIRCUMFLEX */
+				case 0x9A: n = 2; break;
+					/* LATIN SMALL LETTER O WITH DIAERESIS */
+				case 0x9B: n = 2; break;
+					/* LATIN SMALL LETTER O WITH TILDE */
+				case 0x9C: n = 2; break;
+					/* LATIN SMALL LETTER U WITH ACUTE */
+				case 0x9D: n = 2; break;
+					/* LATIN SMALL LETTER U WITH GRAVE */
+				case 0x9E: n = 2; break;
+					/* LATIN SMALL LETTER U WITH CIRCUMFLEX */
+				case 0x9F: n = 2; break;
+					/* LATIN SMALL LETTER U WITH DIAERESIS */
+				case 0xA0: n = 3; break;
+					/* DAGGER */
+				case 0xA1: n = 2; break;
+					/* DEGREE SIGN */
+				case 0xA2: n = 2; break;
+					/* CENT SIGN */
+				case 0xA3: n = 2; break;
+					/* POUND SIGN */
+				case 0xA4: n = 2; break;
+					/* SECTION SIGN */
+				case 0xA5: n = 3; break;
+					/* BULLET */
+				case 0xA6: n = 2; break;
+					/* PILCROW SIGN */
+				case 0xA7: n = 2; break;
+					/* LATIN SMALL LETTER SHARP S */
+				case 0xA8: n = 2; break;
+					/* REGISTERED SIGN */
+				case 0xA9: n = 2; break;
+					/* COPYRIGHT SIGN */
+				case 0xAA: n = 3; break;
+					/* TRADE MARK SIGN */
+				case 0xAB: n = 2; break;
+					/* ACUTE ACCENT */
+				case 0xAC: n = 2; break;
+					/* DIAERESIS */
+				case 0xAD: n = 3; break;
+					/* NOT EQUAL TO */
+				case 0xAE: n = 2; break;
+					/* LATIN CAPITAL LETTER AE */
+				case 0xAF: n = 2; break;
+					/* LATIN CAPITAL LETTER O WITH STROKE */
+				case 0xB0: n = 3; break;
+					/* INFINITY */
+				case 0xB1: n = 2; break;
+					/* PLUS-MINUS SIGN */
+				case 0xB2: n = 3; break;
+					/* LESS-THAN OR EQUAL TO */
+				case 0xB3: n = 3; break;
+					/* GREATER-THAN OR EQUAL TO */
+				case 0xB4: n = 2; break;
+					/* YEN SIGN */
+				case 0xB5: n = 2; break;
+					/* MICRO SIGN */
+				case 0xB6: n = 3; break;
+					/* PARTIAL DIFFERENTIAL */
+				case 0xB7: n = 3; break;
+					/* N-ARY SUMMATION */
+				case 0xB8: n = 3; break;
+					/* N-ARY PRODUCT */
+				case 0xB9: n = 2; break;
+					/* GREEK SMALL LETTER PI */
+				case 0xBA: n = 3; break;
+					/* INTEGRAL */
+				case 0xBB: n = 2; break;
+					/* FEMININE ORDINAL INDICATOR */
+				case 0xBC: n = 2; break;
+					/* MASCULINE ORDINAL INDICATOR */
+				case 0xBD: n = 2; break;
+					/* GREEK CAPITAL LETTER OMEGA */
+				case 0xBE: n = 2; break;
+					/* LATIN SMALL LETTER AE */
+				case 0xBF: n = 2; break;
+					/* LATIN SMALL LETTER O WITH STROKE */
+				case 0xC0: n = 2; break;
+					/* INVERTED QUESTION MARK */
+				case 0xC1: n = 2; break;
+					/* INVERTED EXCLAMATION MARK */
+				case 0xC2: n = 2; break;
+					/* NOT SIGN */
+				case 0xC3: n = 3; break;
+					/* SQUARE ROOT */
+				case 0xC4: n = 2; break;
+					/* LATIN SMALL LETTER F WITH HOOK */
+				case 0xC5: n = 3; break;
+					/* ALMOST EQUAL TO */
+				case 0xC6: n = 3; break;
+					/* INCREMENT */
+				case 0xC7: n = 2; break;
+					/* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
+				case 0xC8: n = 2; break;
+					/* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
+				case 0xC9: n = 3; break;
+					/* HORIZONTAL ELLIPSIS */
+				case 0xCA: n = 2; break;
+					/* NO-BREAK SPACE */
+				case 0xCB: n = 2; break;
+					/* LATIN CAPITAL LETTER A WITH GRAVE */
+				case 0xCC: n = 2; break;
+					/* LATIN CAPITAL LETTER A WITH TILDE */
+				case 0xCD: n = 2; break;
+					/* LATIN CAPITAL LETTER O WITH TILDE */
+				case 0xCE: n = 2; break;
+					/* LATIN CAPITAL LIGATURE OE */
+				case 0xCF: n = 2; break;
+					/* LATIN SMALL LIGATURE OE */
+				case 0xD0: n = 3; break;
+					/* EN DASH */
+				case 0xD1: n = 3; break;
+					/* EM DASH */
+				case 0xD2: n = 3; break;
+					/* LEFT DOUBLE QUOTATION MARK */
+				case 0xD3: n = 3; break;
+					/* RIGHT DOUBLE QUOTATION MARK */
+				case 0xD4: n = 3; break;
+					/* LEFT SINGLE QUOTATION MARK */
+				case 0xD5: n = 3; break;
+					/* RIGHT SINGLE QUOTATION MARK */
+				case 0xD6: n = 2; break;
+					/* DIVISION SIGN */
+				case 0xD7: n = 3; break;
+					/* LOZENGE */
+				case 0xD8: n = 2; break;
+					/* LATIN SMALL LETTER Y WITH DIAERESIS */
+				case 0xD9: n = 2; break;
+					/* LATIN CAPITAL LETTER Y WITH DIAERESIS */
+				case 0xDA: n = 3; break;
+					/* FRACTION SLASH */
+				case 0xDB: n = 3; break;
+					/* EURO SIGN */
+				case 0xDC: n = 3; break;
+					/* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
+				case 0xDD: n = 3; break;
+					/* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
+				case 0xDE: n = 3; break;
+					/* LATIN SMALL LIGATURE FI */
+				case 0xDF: n = 3; break;
+					/* LATIN SMALL LIGATURE FL */
+				case 0xE0: n = 3; break;
+					/* DOUBLE DAGGER */
+				case 0xE1: n = 2; break;
+					/* MIDDLE DOT */
+				case 0xE2: n = 3; break;
+					/* SINGLE LOW-9 QUOTATION MARK */
+				case 0xE3: n = 3; break;
+					/* DOUBLE LOW-9 QUOTATION MARK */
+				case 0xE4: n = 3; break;
+					/* PER MILLE SIGN */
+				case 0xE5: n = 2; break;
+					/* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
+				case 0xE6: n = 2; break;
+					/* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
+				case 0xE7: n = 2; break;
+					/* LATIN CAPITAL LETTER A WITH ACUTE */
+				case 0xE8: n = 2; break;
+					/* LATIN CAPITAL LETTER E WITH DIAERESIS */
+				case 0xE9: n = 2; break;
+					/* LATIN CAPITAL LETTER E WITH GRAVE */
+				case 0xEA: n = 2; break;
+					/* LATIN CAPITAL LETTER I WITH ACUTE */
+				case 0xEB: n = 2; break;
+					/* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
+				case 0xEC: n = 2; break;
+					/* LATIN CAPITAL LETTER I WITH DIAERESIS */
+				case 0xED: n = 2; break;
+					/* LATIN CAPITAL LETTER I WITH GRAVE */
+				case 0xEE: n = 2; break;
+					/* LATIN CAPITAL LETTER O WITH ACUTE */
+				case 0xEF: n = 2; break;
+					/* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
+				case 0xF0: n = 3; break;
+					/* Apple logo */
+				case 0xF1: n = 2; break;
+					/* LATIN CAPITAL LETTER O WITH GRAVE */
+				case 0xF2: n = 2; break;
+					/* LATIN CAPITAL LETTER U WITH ACUTE */
+				case 0xF3: n = 2; break;
+					/* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
+				case 0xF4: n = 2; break;
+					/* LATIN CAPITAL LETTER U WITH GRAVE */
+				case 0xF5: n = 2; break;
+					/* LATIN SMALL LETTER DOTLESS I */
+				case 0xF6: n = 2; break;
+					/* MODIFIER LETTER CIRCUMFLEX ACCENT */
+				case 0xF7: n = 2; break;
+					/* SMALL TILDE */
+				case 0xF8: n = 2; break;
+					/* MACRON */
+				case 0xF9: n = 2; break;
+					/* BREVE */
+				case 0xFA: n = 2; break;
+					/* DOT ABOVE */
+				case 0xFB: n = 2; break;
+					/* RING ABOVE */
+				case 0xFC: n = 2; break;
+					/* CEDILLA */
+				case 0xFD: n = 2; break;
+					/* DOUBLE ACUTE ACCENT */
+				case 0xFE: n = 2; break;
+					/* OGONEK */
+				case 0xFF: n = 2; break;
+					/* CARON */
+				default: n = 1; break;
+					/* shouldn't get here */
+			}
+		}
+		v += n;
+	}
+
+	return v;
+}
+#endif
+
+#if IncludeHostTextClipExchange
+LOCALPROC MacRoman2UniCodeData(ui3b *s, uimr L, char *t)
+{
+	uimr i;
+	ui3r x;
+
+	for (i = 0; i < L; ++i) {
+		x = *s++;
+		if (x < 128) {
+			*t++ = x;
+		} else {
+			switch (x) {
+				case 0x80: *t++ = 0xC3; *t++ = 0x84; break;
+					/* LATIN CAPITAL LETTER A WITH DIAERESIS */
+				case 0x81: *t++ = 0xC3; *t++ = 0x85; break;
+					/* LATIN CAPITAL LETTER A WITH RING ABOVE */
+				case 0x82: *t++ = 0xC3; *t++ = 0x87; break;
+					/* LATIN CAPITAL LETTER C WITH CEDILLA */
+				case 0x83: *t++ = 0xC3; *t++ = 0x89; break;
+					/* LATIN CAPITAL LETTER E WITH ACUTE */
+				case 0x84: *t++ = 0xC3; *t++ = 0x91; break;
+					/* LATIN CAPITAL LETTER N WITH TILDE */
+				case 0x85: *t++ = 0xC3; *t++ = 0x96; break;
+					/* LATIN CAPITAL LETTER O WITH DIAERESIS */
+				case 0x86: *t++ = 0xC3; *t++ = 0x9C; break;
+					/* LATIN CAPITAL LETTER U WITH DIAERESIS */
+				case 0x87: *t++ = 0xC3; *t++ = 0xA1; break;
+					/* LATIN SMALL LETTER A WITH ACUTE */
+				case 0x88: *t++ = 0xC3; *t++ = 0xA0; break;
+					/* LATIN SMALL LETTER A WITH GRAVE */
+				case 0x89: *t++ = 0xC3; *t++ = 0xA2; break;
+					/* LATIN SMALL LETTER A WITH CIRCUMFLEX */
+				case 0x8A: *t++ = 0xC3; *t++ = 0xA4; break;
+					/* LATIN SMALL LETTER A WITH DIAERESIS */
+				case 0x8B: *t++ = 0xC3; *t++ = 0xA3; break;
+					/* LATIN SMALL LETTER A WITH TILDE */
+				case 0x8C: *t++ = 0xC3; *t++ = 0xA5; break;
+					/* LATIN SMALL LETTER A WITH RING ABOVE */
+				case 0x8D: *t++ = 0xC3; *t++ = 0xA7; break;
+					/* LATIN SMALL LETTER C WITH CEDILLA */
+				case 0x8E: *t++ = 0xC3; *t++ = 0xA9; break;
+					/* LATIN SMALL LETTER E WITH ACUTE */
+				case 0x8F: *t++ = 0xC3; *t++ = 0xA8; break;
+					/* LATIN SMALL LETTER E WITH GRAVE */
+				case 0x90: *t++ = 0xC3; *t++ = 0xAA; break;
+					/* LATIN SMALL LETTER E WITH CIRCUMFLEX */
+				case 0x91: *t++ = 0xC3; *t++ = 0xAB; break;
+					/* LATIN SMALL LETTER E WITH DIAERESIS */
+				case 0x92: *t++ = 0xC3; *t++ = 0xAD; break;
+					/* LATIN SMALL LETTER I WITH ACUTE */
+				case 0x93: *t++ = 0xC3; *t++ = 0xAC; break;
+					/* LATIN SMALL LETTER I WITH GRAVE */
+				case 0x94: *t++ = 0xC3; *t++ = 0xAE; break;
+					/* LATIN SMALL LETTER I WITH CIRCUMFLEX */
+				case 0x95: *t++ = 0xC3; *t++ = 0xAF; break;
+					/* LATIN SMALL LETTER I WITH DIAERESIS */
+				case 0x96: *t++ = 0xC3; *t++ = 0xB1; break;
+					/* LATIN SMALL LETTER N WITH TILDE */
+				case 0x97: *t++ = 0xC3; *t++ = 0xB3; break;
+					/* LATIN SMALL LETTER O WITH ACUTE */
+				case 0x98: *t++ = 0xC3; *t++ = 0xB2; break;
+					/* LATIN SMALL LETTER O WITH GRAVE */
+				case 0x99: *t++ = 0xC3; *t++ = 0xB4; break;
+					/* LATIN SMALL LETTER O WITH CIRCUMFLEX */
+				case 0x9A: *t++ = 0xC3; *t++ = 0xB6; break;
+					/* LATIN SMALL LETTER O WITH DIAERESIS */
+				case 0x9B: *t++ = 0xC3; *t++ = 0xB5; break;
+					/* LATIN SMALL LETTER O WITH TILDE */
+				case 0x9C: *t++ = 0xC3; *t++ = 0xBA; break;
+					/* LATIN SMALL LETTER U WITH ACUTE */
+				case 0x9D: *t++ = 0xC3; *t++ = 0xB9; break;
+					/* LATIN SMALL LETTER U WITH GRAVE */
+				case 0x9E: *t++ = 0xC3; *t++ = 0xBB; break;
+					/* LATIN SMALL LETTER U WITH CIRCUMFLEX */
+				case 0x9F: *t++ = 0xC3; *t++ = 0xBC; break;
+					/* LATIN SMALL LETTER U WITH DIAERESIS */
+				case 0xA0: *t++ = 0xE2; *t++ = 0x80; *t++ = 0xA0; break;
+					/* DAGGER */
+				case 0xA1: *t++ = 0xC2; *t++ = 0xB0; break;
+					/* DEGREE SIGN */
+				case 0xA2: *t++ = 0xC2; *t++ = 0xA2; break;
+					/* CENT SIGN */
+				case 0xA3: *t++ = 0xC2; *t++ = 0xA3; break;
+					/* POUND SIGN */
+				case 0xA4: *t++ = 0xC2; *t++ = 0xA7; break;
+					/* SECTION SIGN */
+				case 0xA5: *t++ = 0xE2; *t++ = 0x80; *t++ = 0xA2; break;
+					/* BULLET */
+				case 0xA6: *t++ = 0xC2; *t++ = 0xB6; break;
+					/* PILCROW SIGN */
+				case 0xA7: *t++ = 0xC3; *t++ = 0x9F; break;
+					/* LATIN SMALL LETTER SHARP S */
+				case 0xA8: *t++ = 0xC2; *t++ = 0xAE; break;
+					/* REGISTERED SIGN */
+				case 0xA9: *t++ = 0xC2; *t++ = 0xA9; break;
+					/* COPYRIGHT SIGN */
+				case 0xAA: *t++ = 0xE2; *t++ = 0x84; *t++ = 0xA2; break;
+					/* TRADE MARK SIGN */
+				case 0xAB: *t++ = 0xC2; *t++ = 0xB4; break;
+					/* ACUTE ACCENT */
+				case 0xAC: *t++ = 0xC2; *t++ = 0xA8; break;
+					/* DIAERESIS */
+				case 0xAD: *t++ = 0xE2; *t++ = 0x89; *t++ = 0xA0; break;
+					/* NOT EQUAL TO */
+				case 0xAE: *t++ = 0xC3; *t++ = 0x86; break;
+					/* LATIN CAPITAL LETTER AE */
+				case 0xAF: *t++ = 0xC3; *t++ = 0x98; break;
+					/* LATIN CAPITAL LETTER O WITH STROKE */
+				case 0xB0: *t++ = 0xE2; *t++ = 0x88; *t++ = 0x9E; break;
+					/* INFINITY */
+				case 0xB1: *t++ = 0xC2; *t++ = 0xB1; break;
+					/* PLUS-MINUS SIGN */
+				case 0xB2: *t++ = 0xE2; *t++ = 0x89; *t++ = 0xA4; break;
+					/* LESS-THAN OR EQUAL TO */
+				case 0xB3: *t++ = 0xE2; *t++ = 0x89; *t++ = 0xA5; break;
+					/* GREATER-THAN OR EQUAL TO */
+				case 0xB4: *t++ = 0xC2; *t++ = 0xA5; break;
+					/* YEN SIGN */
+				case 0xB5: *t++ = 0xC2; *t++ = 0xB5; break;
+					/* MICRO SIGN */
+				case 0xB6: *t++ = 0xE2; *t++ = 0x88; *t++ = 0x82; break;
+					/* PARTIAL DIFFERENTIAL */
+				case 0xB7: *t++ = 0xE2; *t++ = 0x88; *t++ = 0x91; break;
+					/* N-ARY SUMMATION */
+				case 0xB8: *t++ = 0xE2; *t++ = 0x88; *t++ = 0x8F; break;
+					/* N-ARY PRODUCT */
+				case 0xB9: *t++ = 0xCF; *t++ = 0x80; break;
+					/* GREEK SMALL LETTER PI */
+				case 0xBA: *t++ = 0xE2; *t++ = 0x88; *t++ = 0xAB; break;
+					/* INTEGRAL */
+				case 0xBB: *t++ = 0xC2; *t++ = 0xAA; break;
+					/* FEMININE ORDINAL INDICATOR */
+				case 0xBC: *t++ = 0xC2; *t++ = 0xBA; break;
+					/* MASCULINE ORDINAL INDICATOR */
+				case 0xBD: *t++ = 0xCE; *t++ = 0xA9; break;
+					/* GREEK CAPITAL LETTER OMEGA */
+				case 0xBE: *t++ = 0xC3; *t++ = 0xA6; break;
+					/* LATIN SMALL LETTER AE */
+				case 0xBF: *t++ = 0xC3; *t++ = 0xB8; break;
+					/* LATIN SMALL LETTER O WITH STROKE */
+				case 0xC0: *t++ = 0xC2; *t++ = 0xBF; break;
+					/* INVERTED QUESTION MARK */
+				case 0xC1: *t++ = 0xC2; *t++ = 0xA1; break;
+					/* INVERTED EXCLAMATION MARK */
+				case 0xC2: *t++ = 0xC2; *t++ = 0xAC; break;
+					/* NOT SIGN */
+				case 0xC3: *t++ = 0xE2; *t++ = 0x88; *t++ = 0x9A; break;
+					/* SQUARE ROOT */
+				case 0xC4: *t++ = 0xC6; *t++ = 0x92; break;
+					/* LATIN SMALL LETTER F WITH HOOK */
+				case 0xC5: *t++ = 0xE2; *t++ = 0x89; *t++ = 0x88; break;
+					/* ALMOST EQUAL TO */
+				case 0xC6: *t++ = 0xE2; *t++ = 0x88; *t++ = 0x86; break;
+					/* INCREMENT */
+				case 0xC7: *t++ = 0xC2; *t++ = 0xAB; break;
+					/* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
+				case 0xC8: *t++ = 0xC2; *t++ = 0xBB; break;
+					/* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
+				case 0xC9: *t++ = 0xE2; *t++ = 0x80; *t++ = 0xA6; break;
+					/* HORIZONTAL ELLIPSIS */
+				case 0xCA: *t++ = 0xC2; *t++ = 0xA0; break;
+					/* NO-BREAK SPACE */
+				case 0xCB: *t++ = 0xC3; *t++ = 0x80; break;
+					/* LATIN CAPITAL LETTER A WITH GRAVE */
+				case 0xCC: *t++ = 0xC3; *t++ = 0x83; break;
+					/* LATIN CAPITAL LETTER A WITH TILDE */
+				case 0xCD: *t++ = 0xC3; *t++ = 0x95; break;
+					/* LATIN CAPITAL LETTER O WITH TILDE */
+				case 0xCE: *t++ = 0xC5; *t++ = 0x92; break;
+					/* LATIN CAPITAL LIGATURE OE */
+				case 0xCF: *t++ = 0xC5; *t++ = 0x93; break;
+					/* LATIN SMALL LIGATURE OE */
+				case 0xD0: *t++ = 0xE2; *t++ = 0x80; *t++ = 0x93; break;
+					/* EN DASH */
+				case 0xD1: *t++ = 0xE2; *t++ = 0x80; *t++ = 0x94; break;
+					/* EM DASH */
+				case 0xD2: *t++ = 0xE2; *t++ = 0x80; *t++ = 0x9C; break;
+					/* LEFT DOUBLE QUOTATION MARK */
+				case 0xD3: *t++ = 0xE2; *t++ = 0x80; *t++ = 0x9D; break;
+					/* RIGHT DOUBLE QUOTATION MARK */
+				case 0xD4: *t++ = 0xE2; *t++ = 0x80; *t++ = 0x98; break;
+					/* LEFT SINGLE QUOTATION MARK */
+				case 0xD5: *t++ = 0xE2; *t++ = 0x80; *t++ = 0x99; break;
+					/* RIGHT SINGLE QUOTATION MARK */
+				case 0xD6: *t++ = 0xC3; *t++ = 0xB7; break;
+					/* DIVISION SIGN */
+				case 0xD7: *t++ = 0xE2; *t++ = 0x97; *t++ = 0x8A; break;
+					/* LOZENGE */
+				case 0xD8: *t++ = 0xC3; *t++ = 0xBF; break;
+					/* LATIN SMALL LETTER Y WITH DIAERESIS */
+				case 0xD9: *t++ = 0xC5; *t++ = 0xB8; break;
+					/* LATIN CAPITAL LETTER Y WITH DIAERESIS */
+				case 0xDA: *t++ = 0xE2; *t++ = 0x81; *t++ = 0x84; break;
+					/* FRACTION SLASH */
+				case 0xDB: *t++ = 0xE2; *t++ = 0x82; *t++ = 0xAC; break;
+					/* EURO SIGN */
+				case 0xDC: *t++ = 0xE2; *t++ = 0x80; *t++ = 0xB9; break;
+					/* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
+				case 0xDD: *t++ = 0xE2; *t++ = 0x80; *t++ = 0xBA; break;
+					/* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
+				case 0xDE: *t++ = 0xEF; *t++ = 0xAC; *t++ = 0x81; break;
+					/* LATIN SMALL LIGATURE FI */
+				case 0xDF: *t++ = 0xEF; *t++ = 0xAC; *t++ = 0x82; break;
+					/* LATIN SMALL LIGATURE FL */
+				case 0xE0: *t++ = 0xE2; *t++ = 0x80; *t++ = 0xA1; break;
+					/* DOUBLE DAGGER */
+				case 0xE1: *t++ = 0xC2; *t++ = 0xB7; break;
+					/* MIDDLE DOT */
+				case 0xE2: *t++ = 0xE2; *t++ = 0x80; *t++ = 0x9A; break;
+					/* SINGLE LOW-9 QUOTATION MARK */
+				case 0xE3: *t++ = 0xE2; *t++ = 0x80; *t++ = 0x9E; break;
+					/* DOUBLE LOW-9 QUOTATION MARK */
+				case 0xE4: *t++ = 0xE2; *t++ = 0x80; *t++ = 0xB0; break;
+					/* PER MILLE SIGN */
+				case 0xE5: *t++ = 0xC3; *t++ = 0x82; break;
+					/* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
+				case 0xE6: *t++ = 0xC3; *t++ = 0x8A; break;
+					/* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
+				case 0xE7: *t++ = 0xC3; *t++ = 0x81; break;
+					/* LATIN CAPITAL LETTER A WITH ACUTE */
+				case 0xE8: *t++ = 0xC3; *t++ = 0x8B; break;
+					/* LATIN CAPITAL LETTER E WITH DIAERESIS */
+				case 0xE9: *t++ = 0xC3; *t++ = 0x88; break;
+					/* LATIN CAPITAL LETTER E WITH GRAVE */
+				case 0xEA: *t++ = 0xC3; *t++ = 0x8D; break;
+					/* LATIN CAPITAL LETTER I WITH ACUTE */
+				case 0xEB: *t++ = 0xC3; *t++ = 0x8E; break;
+					/* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
+				case 0xEC: *t++ = 0xC3; *t++ = 0x8F; break;
+					/* LATIN CAPITAL LETTER I WITH DIAERESIS */
+				case 0xED: *t++ = 0xC3; *t++ = 0x8C; break;
+					/* LATIN CAPITAL LETTER I WITH GRAVE */
+				case 0xEE: *t++ = 0xC3; *t++ = 0x93; break;
+					/* LATIN CAPITAL LETTER O WITH ACUTE */
+				case 0xEF: *t++ = 0xC3; *t++ = 0x94; break;
+					/* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
+				case 0xF0: *t++ = 0xEF; *t++ = 0xA3; *t++ = 0xBF; break;
+					/* Apple logo */
+				case 0xF1: *t++ = 0xC3; *t++ = 0x92; break;
+					/* LATIN CAPITAL LETTER O WITH GRAVE */
+				case 0xF2: *t++ = 0xC3; *t++ = 0x9A; break;
+					/* LATIN CAPITAL LETTER U WITH ACUTE */
+				case 0xF3: *t++ = 0xC3; *t++ = 0x9B; break;
+					/* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
+				case 0xF4: *t++ = 0xC3; *t++ = 0x99; break;
+					/* LATIN CAPITAL LETTER U WITH GRAVE */
+				case 0xF5: *t++ = 0xC4; *t++ = 0xB1; break;
+					/* LATIN SMALL LETTER DOTLESS I */
+				case 0xF6: *t++ = 0xCB; *t++ = 0x86; break;
+					/* MODIFIER LETTER CIRCUMFLEX ACCENT */
+				case 0xF7: *t++ = 0xCB; *t++ = 0x9C; break;
+					/* SMALL TILDE */
+				case 0xF8: *t++ = 0xC2; *t++ = 0xAF; break;
+					/* MACRON */
+				case 0xF9: *t++ = 0xCB; *t++ = 0x98; break;
+					/* BREVE */
+				case 0xFA: *t++ = 0xCB; *t++ = 0x99; break;
+					/* DOT ABOVE */
+				case 0xFB: *t++ = 0xCB; *t++ = 0x9A; break;
+					/* RING ABOVE */
+				case 0xFC: *t++ = 0xC2; *t++ = 0xB8; break;
+					/* CEDILLA */
+				case 0xFD: *t++ = 0xCB; *t++ = 0x9D; break;
+					/* DOUBLE ACUTE ACCENT */
+				case 0xFE: *t++ = 0xCB; *t++ = 0x9B; break;
+					/* OGONEK */
+				case 0xFF: *t++ = 0xCB; *t++ = 0x87; break;
+					/* CARON */
+				default: *t++ = '?'; break;
+					/* shouldn't get here */
+			}
+		}
+	}
+}
+#endif
+
+#if IncludeHostTextClipExchange
+GLOBALOSGLUFUNC tMacErr HTCEexport(tPbuf i)
+{
+	tMacErr err;
+	char *p;
+	ui3p s = PbufDat[i];
+	uimr L = PbufSize[i];
+	uimr sz = MacRoman2UniCodeSize(s, L);
+
+	if (NULL == (p = malloc(sz + 1))) {
+		err = mnvm_miscErr;
+	} else {
+		MacRoman2UniCodeData(s, L, p);
+		p[sz] = 0;
+
+		if (0 != SDL_SetClipboardText(p)) {
+			err = mnvm_miscErr;
+		} else {
+			err = mnvm_noErr;
+		}
+		free(p);
+	}
+
+	return err;
+}
+#endif
+
+#if IncludeHostTextClipExchange
+LOCALFUNC tMacErr UniCodeStrLength(char *s, uimr *r)
+{
+	tMacErr err;
+	ui3r t;
+	ui3r t2;
+	char *p = s;
+	uimr L = 0;
+
+label_retry:
+	if (0 == (t = *p++)) {
+		err = mnvm_noErr;
+		/* done */
+	} else
+	if (0 == (0x80 & t)) {
+		/* One-byte code */
+		L += 1;
+		goto label_retry;
+	} else
+	if (0 == (0x40 & t)) {
+		/* continuation code, error */
+		err = mnvm_miscErr;
+	} else
+	if (0 == (t2 = *p++)) {
+		err = mnvm_miscErr;
+	} else
+	if (0x80 != (0xC0 & t2)) {
+		/* not a continuation code, error */
+		err = mnvm_miscErr;
+	} else
+	if (0 == (0x20 & t)) {
+		/* two bytes */
+		L += 2;
+		goto label_retry;
+	} else
+	if (0 == (t2 = *p++)) {
+		err = mnvm_miscErr;
+	} else
+	if (0x80 != (0xC0 & t2)) {
+		/* not a continuation code, error */
+		err = mnvm_miscErr;
+	} else
+	if (0 == (0x10 & t)) {
+		/* three bytes */
+		L += 3;
+		goto label_retry;
+	} else
+	if (0 == (t2 = *p++)) {
+		err = mnvm_miscErr;
+	} else
+	if (0x80 != (0xC0 & t2)) {
+		/* not a continuation code, error */
+		err = mnvm_miscErr;
+	} else
+	if (0 == (0x08 & t)) {
+		/* four bytes */
+		L += 5;
+		goto label_retry;
+	} else
+	{
+		err = mnvm_miscErr;
+		/* longer code not supported yet */
+	}
+
+	*r = L;
+	return err;
+}
+#endif
+
+#if IncludeHostTextClipExchange
+LOCALFUNC ui3r UniCodePoint2MacRoman(ui5r x)
+{
+/*
+	adapted from
+		http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/ROMAN.TXT
+*/
+	ui3r y;
+
+	if (x < 128) {
+		y = x;
+	} else {
+		switch (x) {
+			case 0x00C4: y = 0x80; break;
+				/* LATIN CAPITAL LETTER A WITH DIAERESIS */
+			case 0x00C5: y = 0x81; break;
+				/* LATIN CAPITAL LETTER A WITH RING ABOVE */
+			case 0x00C7: y = 0x82; break;
+				/* LATIN CAPITAL LETTER C WITH CEDILLA */
+			case 0x00C9: y = 0x83; break;
+				/* LATIN CAPITAL LETTER E WITH ACUTE */
+			case 0x00D1: y = 0x84; break;
+				/* LATIN CAPITAL LETTER N WITH TILDE */
+			case 0x00D6: y = 0x85; break;
+				/* LATIN CAPITAL LETTER O WITH DIAERESIS */
+			case 0x00DC: y = 0x86; break;
+				/* LATIN CAPITAL LETTER U WITH DIAERESIS */
+			case 0x00E1: y = 0x87; break;
+				/* LATIN SMALL LETTER A WITH ACUTE */
+			case 0x00E0: y = 0x88; break;
+				/* LATIN SMALL LETTER A WITH GRAVE */
+			case 0x00E2: y = 0x89; break;
+				/* LATIN SMALL LETTER A WITH CIRCUMFLEX */
+			case 0x00E4: y = 0x8A; break;
+				/* LATIN SMALL LETTER A WITH DIAERESIS */
+			case 0x00E3: y = 0x8B; break;
+				/* LATIN SMALL LETTER A WITH TILDE */
+			case 0x00E5: y = 0x8C; break;
+				/* LATIN SMALL LETTER A WITH RING ABOVE */
+			case 0x00E7: y = 0x8D; break;
+				/* LATIN SMALL LETTER C WITH CEDILLA */
+			case 0x00E9: y = 0x8E; break;
+				/* LATIN SMALL LETTER E WITH ACUTE */
+			case 0x00E8: y = 0x8F; break;
+				/* LATIN SMALL LETTER E WITH GRAVE */
+			case 0x00EA: y = 0x90; break;
+				/* LATIN SMALL LETTER E WITH CIRCUMFLEX */
+			case 0x00EB: y = 0x91; break;
+				/* LATIN SMALL LETTER E WITH DIAERESIS */
+			case 0x00ED: y = 0x92; break;
+				/* LATIN SMALL LETTER I WITH ACUTE */
+			case 0x00EC: y = 0x93; break;
+				/* LATIN SMALL LETTER I WITH GRAVE */
+			case 0x00EE: y = 0x94; break;
+				/* LATIN SMALL LETTER I WITH CIRCUMFLEX */
+			case 0x00EF: y = 0x95; break;
+				/* LATIN SMALL LETTER I WITH DIAERESIS */
+			case 0x00F1: y = 0x96; break;
+				/* LATIN SMALL LETTER N WITH TILDE */
+			case 0x00F3: y = 0x97; break;
+				/* LATIN SMALL LETTER O WITH ACUTE */
+			case 0x00F2: y = 0x98; break;
+				/* LATIN SMALL LETTER O WITH GRAVE */
+			case 0x00F4: y = 0x99; break;
+				/* LATIN SMALL LETTER O WITH CIRCUMFLEX */
+			case 0x00F6: y = 0x9A; break;
+				/* LATIN SMALL LETTER O WITH DIAERESIS */
+			case 0x00F5: y = 0x9B; break;
+				/* LATIN SMALL LETTER O WITH TILDE */
+			case 0x00FA: y = 0x9C; break;
+				/* LATIN SMALL LETTER U WITH ACUTE */
+			case 0x00F9: y = 0x9D; break;
+				/* LATIN SMALL LETTER U WITH GRAVE */
+			case 0x00FB: y = 0x9E; break;
+				/* LATIN SMALL LETTER U WITH CIRCUMFLEX */
+			case 0x00FC: y = 0x9F; break;
+				/* LATIN SMALL LETTER U WITH DIAERESIS */
+			case 0x2020: y = 0xA0; break;
+				/* DAGGER */
+			case 0x00B0: y = 0xA1; break;
+				/* DEGREE SIGN */
+			case 0x00A2: y = 0xA2; break;
+				/* CENT SIGN */
+			case 0x00A3: y = 0xA3; break;
+				/* POUND SIGN */
+			case 0x00A7: y = 0xA4; break;
+				/* SECTION SIGN */
+			case 0x2022: y = 0xA5; break;
+				/* BULLET */
+			case 0x00B6: y = 0xA6; break;
+				/* PILCROW SIGN */
+			case 0x00DF: y = 0xA7; break;
+				/* LATIN SMALL LETTER SHARP S */
+			case 0x00AE: y = 0xA8; break;
+				/* REGISTERED SIGN */
+			case 0x00A9: y = 0xA9; break;
+				/* COPYRIGHT SIGN */
+			case 0x2122: y = 0xAA; break;
+				/* TRADE MARK SIGN */
+			case 0x00B4: y = 0xAB; break;
+				/* ACUTE ACCENT */
+			case 0x00A8: y = 0xAC; break;
+				/* DIAERESIS */
+			case 0x2260: y = 0xAD; break;
+				/* NOT EQUAL TO */
+			case 0x00C6: y = 0xAE; break;
+				/* LATIN CAPITAL LETTER AE */
+			case 0x00D8: y = 0xAF; break;
+				/* LATIN CAPITAL LETTER O WITH STROKE */
+			case 0x221E: y = 0xB0; break;
+				/* INFINITY */
+			case 0x00B1: y = 0xB1; break;
+				/* PLUS-MINUS SIGN */
+			case 0x2264: y = 0xB2; break;
+				/* LESS-THAN OR EQUAL TO */
+			case 0x2265: y = 0xB3; break;
+				/* GREATER-THAN OR EQUAL TO */
+			case 0x00A5: y = 0xB4; break;
+				/* YEN SIGN */
+			case 0x00B5: y = 0xB5; break;
+				/* MICRO SIGN */
+			case 0x2202: y = 0xB6; break;
+				/* PARTIAL DIFFERENTIAL */
+			case 0x2211: y = 0xB7; break;
+				/* N-ARY SUMMATION */
+			case 0x220F: y = 0xB8; break;
+				/* N-ARY PRODUCT */
+			case 0x03C0: y = 0xB9; break;
+				/* GREEK SMALL LETTER PI */
+			case 0x222B: y = 0xBA; break;
+				/* INTEGRAL */
+			case 0x00AA: y = 0xBB; break;
+				/* FEMININE ORDINAL INDICATOR */
+			case 0x00BA: y = 0xBC; break;
+				/* MASCULINE ORDINAL INDICATOR */
+			case 0x03A9: y = 0xBD; break;
+				/* GREEK CAPITAL LETTER OMEGA */
+			case 0x00E6: y = 0xBE; break;
+				/* LATIN SMALL LETTER AE */
+			case 0x00F8: y = 0xBF; break;
+				/* LATIN SMALL LETTER O WITH STROKE */
+			case 0x00BF: y = 0xC0; break;
+				/* INVERTED QUESTION MARK */
+			case 0x00A1: y = 0xC1; break;
+				/* INVERTED EXCLAMATION MARK */
+			case 0x00AC: y = 0xC2; break;
+				/* NOT SIGN */
+			case 0x221A: y = 0xC3; break;
+				/* SQUARE ROOT */
+			case 0x0192: y = 0xC4; break;
+				/* LATIN SMALL LETTER F WITH HOOK */
+			case 0x2248: y = 0xC5; break;
+				/* ALMOST EQUAL TO */
+			case 0x2206: y = 0xC6; break;
+				/* INCREMENT */
+			case 0x00AB: y = 0xC7; break;
+				/* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
+			case 0x00BB: y = 0xC8; break;
+				/* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
+			case 0x2026: y = 0xC9; break;
+				/* HORIZONTAL ELLIPSIS */
+			case 0x00A0: y = 0xCA; break;
+				/* NO-BREAK SPACE */
+			case 0x00C0: y = 0xCB; break;
+				/* LATIN CAPITAL LETTER A WITH GRAVE */
+			case 0x00C3: y = 0xCC; break;
+				/* LATIN CAPITAL LETTER A WITH TILDE */
+			case 0x00D5: y = 0xCD; break;
+				/* LATIN CAPITAL LETTER O WITH TILDE */
+			case 0x0152: y = 0xCE; break;
+				/* LATIN CAPITAL LIGATURE OE */
+			case 0x0153: y = 0xCF; break;
+				/* LATIN SMALL LIGATURE OE */
+			case 0x2013: y = 0xD0; break;
+				/* EN DASH */
+			case 0x2014: y = 0xD1; break;
+				/* EM DASH */
+			case 0x201C: y = 0xD2; break;
+				/* LEFT DOUBLE QUOTATION MARK */
+			case 0x201D: y = 0xD3; break;
+				/* RIGHT DOUBLE QUOTATION MARK */
+			case 0x2018: y = 0xD4; break;
+				/* LEFT SINGLE QUOTATION MARK */
+			case 0x2019: y = 0xD5; break;
+				/* RIGHT SINGLE QUOTATION MARK */
+			case 0x00F7: y = 0xD6; break;
+				/* DIVISION SIGN */
+			case 0x25CA: y = 0xD7; break;
+				/* LOZENGE */
+			case 0x00FF: y = 0xD8; break;
+				/* LATIN SMALL LETTER Y WITH DIAERESIS */
+			case 0x0178: y = 0xD9; break;
+				/* LATIN CAPITAL LETTER Y WITH DIAERESIS */
+			case 0x2044: y = 0xDA; break;
+				/* FRACTION SLASH */
+			case 0x20AC: y = 0xDB; break;
+				/* EURO SIGN */
+			case 0x2039: y = 0xDC; break;
+				/* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
+			case 0x203A: y = 0xDD; break;
+				/* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
+			case 0xFB01: y = 0xDE; break;
+				/* LATIN SMALL LIGATURE FI */
+			case 0xFB02: y = 0xDF; break;
+				/* LATIN SMALL LIGATURE FL */
+			case 0x2021: y = 0xE0; break;
+				/* DOUBLE DAGGER */
+			case 0x00B7: y = 0xE1; break;
+				/* MIDDLE DOT */
+			case 0x201A: y = 0xE2; break;
+				/* SINGLE LOW-9 QUOTATION MARK */
+			case 0x201E: y = 0xE3; break;
+				/* DOUBLE LOW-9 QUOTATION MARK */
+			case 0x2030: y = 0xE4; break;
+				/* PER MILLE SIGN */
+			case 0x00C2: y = 0xE5; break;
+				/* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
+			case 0x00CA: y = 0xE6; break;
+				/* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
+			case 0x00C1: y = 0xE7; break;
+				/* LATIN CAPITAL LETTER A WITH ACUTE */
+			case 0x00CB: y = 0xE8; break;
+				/* LATIN CAPITAL LETTER E WITH DIAERESIS */
+			case 0x00C8: y = 0xE9; break;
+				/* LATIN CAPITAL LETTER E WITH GRAVE */
+			case 0x00CD: y = 0xEA; break;
+				/* LATIN CAPITAL LETTER I WITH ACUTE */
+			case 0x00CE: y = 0xEB; break;
+				/* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
+			case 0x00CF: y = 0xEC; break;
+				/* LATIN CAPITAL LETTER I WITH DIAERESIS */
+			case 0x00CC: y = 0xED; break;
+				/* LATIN CAPITAL LETTER I WITH GRAVE */
+			case 0x00D3: y = 0xEE; break;
+				/* LATIN CAPITAL LETTER O WITH ACUTE */
+			case 0x00D4: y = 0xEF; break;
+				/* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
+			case 0xF8FF: y = 0xF0; break;
+				/* Apple logo */
+			case 0x00D2: y = 0xF1; break;
+				/* LATIN CAPITAL LETTER O WITH GRAVE */
+			case 0x00DA: y = 0xF2; break;
+				/* LATIN CAPITAL LETTER U WITH ACUTE */
+			case 0x00DB: y = 0xF3; break;
+				/* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
+			case 0x00D9: y = 0xF4; break;
+				/* LATIN CAPITAL LETTER U WITH GRAVE */
+			case 0x0131: y = 0xF5; break;
+				/* LATIN SMALL LETTER DOTLESS I */
+			case 0x02C6: y = 0xF6; break;
+				/* MODIFIER LETTER CIRCUMFLEX ACCENT */
+			case 0x02DC: y = 0xF7; break;
+				/* SMALL TILDE */
+			case 0x00AF: y = 0xF8; break;
+				/* MACRON */
+			case 0x02D8: y = 0xF9; break;
+				/* BREVE */
+			case 0x02D9: y = 0xFA; break;
+				/* DOT ABOVE */
+			case 0x02DA: y = 0xFB; break;
+				/* RING ABOVE */
+			case 0x00B8: y = 0xFC; break;
+				/* CEDILLA */
+			case 0x02DD: y = 0xFD; break;
+				/* DOUBLE ACUTE ACCENT */
+			case 0x02DB: y = 0xFE; break;
+				/* OGONEK */
+			case 0x02C7: y = 0xFF; break;
+				/* CARON */
+			default: y = '?'; break;
+				/* unrecognized */
+		}
+	}
+
+	return y;
+}
+#endif
+
+#if IncludeHostTextClipExchange
+LOCALPROC UniCodeStr2MacRoman(char *s, char *r)
+{
+	tMacErr err;
+	ui3r t;
+	ui3r t2;
+	ui3r t3;
+	ui3r t4;
+	ui5r v;
+	char *p = s;
+	char *q = r;
+
+label_retry:
+	if (0 == (t = *p++)) {
+		err = mnvm_noErr;
+		/* done */
+	} else
+	if (0 == (0x80 & t)) {
+		*q++ = t;
+		goto label_retry;
+	} else
+	if (0 == (0x40 & t)) {
+		/* continuation code, error */
+		err = mnvm_miscErr;
+	} else
+	if (0 == (t2 = *p++)) {
+		err = mnvm_miscErr;
+	} else
+	if (0x80 != (0xC0 & t2)) {
+		/* not a continuation code, error */
+		err = mnvm_miscErr;
+	} else
+	if (0 == (0x20 & t)) {
+		/* two bytes */
+		v = t & 0x1F;
+		v = (v << 6) | (t2 & 0x3F);
+		*q++ = UniCodePoint2MacRoman(v);
+		goto label_retry;
+	} else
+	if (0 == (t3 = *p++)) {
+		err = mnvm_miscErr;
+	} else
+	if (0x80 != (0xC0 & t3)) {
+		/* not a continuation code, error */
+		err = mnvm_miscErr;
+	} else
+	if (0 == (0x10 & t)) {
+		/* three bytes */
+		v = t & 0x0F;
+		v = (v << 6) | (t3 & 0x3F);
+		v = (v << 6) | (t2 & 0x3F);
+		*q++ = UniCodePoint2MacRoman(v);
+		goto label_retry;
+	} else
+	if (0 == (t4 = *p++)) {
+		err = mnvm_miscErr;
+	} else
+	if (0x80 != (0xC0 & t4)) {
+		/* not a continuation code, error */
+		err = mnvm_miscErr;
+	} else
+	if (0 == (0x08 & t)) {
+		/* four bytes */
+		v = t & 0x07;
+		v = (v << 6) | (t4 & 0x3F);
+		v = (v << 6) | (t3 & 0x3F);
+		v = (v << 6) | (t2 & 0x3F);
+		*q++ = UniCodePoint2MacRoman(v);
+		goto label_retry;
+	} else
+	{
+		err = mnvm_miscErr;
+		/* longer code not supported yet */
+	}
+}
+#endif
+
+#if IncludeHostTextClipExchange
+GLOBALOSGLUFUNC tMacErr HTCEimport(tPbuf *r)
+{
+	tMacErr err;
+	uimr L;
+	char *s = NULL;
+	tPbuf t = NotAPbuf;
+
+	if (NULL == (s = SDL_GetClipboardText())) {
+		err = mnvm_miscErr;
+	} else
+	if (mnvm_noErr != (err =
+		UniCodeStrLength(s, &L)))
+	{
+		/* fail */
+	} else
+	if (mnvm_noErr != (err =
+		PbufNew(L, &t)))
+	{
+		/* fail */
+	} else
+	{
+		err = mnvm_noErr;
+
+		UniCodeStr2MacRoman(s, PbufDat[t]);
+		*r = t;
+		t = NotAPbuf;
+	}
+
+	if (NotAPbuf != t) {
+		PbufDispose(t);
+	}
+	if (NULL != s) {
+		SDL_free(s);
+	}
+
+	return err;
+}
+#endif
+
+/* --- event handling for main window --- */
+
+#define UseMotionEvents 1
+
+#if UseMotionEvents
+LOCALVAR blnr CaughtMouse = falseblnr;
+#endif
+
+LOCALPROC HandleTheEvent(SDL_Event *event)
+{
+	switch (event->type) {
+		case SDL_QUIT:
+			RequestMacOff = trueblnr;
+			break;
+		case SDL_WINDOWEVENT:
+			switch (event->window.event) {
+				case SDL_WINDOWEVENT_FOCUS_GAINED:
+					gTrueBackgroundFlag = 0;
+					break;
+				case SDL_WINDOWEVENT_FOCUS_LOST:
+					gTrueBackgroundFlag = 1;
+					break;
+				case SDL_WINDOWEVENT_ENTER:
+					CaughtMouse = 1;
+					break;
+				case SDL_WINDOWEVENT_LEAVE:
+					CaughtMouse = 0;
+					break;
+			}
+			break;
+		case SDL_MOUSEMOTION:
+#if EnableFSMouseMotion && ! HaveWorkingWarp
+			if (HaveMouseMotion) {
+				MousePositionNotifyRelative(
+					event->motion.xrel, event->motion.yrel);
+			} else
+#endif
+			{
+				MousePositionNotify(
+					event->motion.x, event->motion.y);
+			}
+			break;
+		case SDL_MOUSEBUTTONDOWN:
+			/* any mouse button, we don't care which */
+#if EnableFSMouseMotion && ! HaveWorkingWarp
+			if (HaveMouseMotion) {
+				/* ignore position */
+			} else
+#endif
+			{
+				MousePositionNotify(
+					event->button.x, event->button.y);
+			}
+			MyMouseButtonSet(trueblnr);
+			break;
+		case SDL_MOUSEBUTTONUP:
+#if EnableFSMouseMotion && ! HaveWorkingWarp
+			if (HaveMouseMotion) {
+				/* ignore position */
+			} else
+#endif
+			{
+				MousePositionNotify(
+					event->button.x, event->button.y);
+			}
+			MyMouseButtonSet(falseblnr);
+			break;
+		case SDL_KEYDOWN:
+			DoKeyCode(&event->key.keysym, trueblnr);
+			break;
+		case SDL_KEYUP:
+			DoKeyCode(&event->key.keysym, falseblnr);
+			break;
+		case SDL_MOUSEWHEEL:
+			if (event->wheel.x < 0) {
+				Keyboard_UpdateKeyMap2(MKC_Left, trueblnr);
+				Keyboard_UpdateKeyMap2(MKC_Left, falseblnr);
+			} else if (event->wheel.x > 0) {
+				Keyboard_UpdateKeyMap2(MKC_Right, trueblnr);
+				Keyboard_UpdateKeyMap2(MKC_Right, falseblnr);
+			}
+			if (event->wheel.y < 0) {
+				Keyboard_UpdateKeyMap2(MKC_Down, trueblnr);
+				Keyboard_UpdateKeyMap2(MKC_Down, falseblnr);
+			} else if(event->wheel.y > 0) {
+				Keyboard_UpdateKeyMap2(MKC_Up, trueblnr);
+				Keyboard_UpdateKeyMap2(MKC_Up, falseblnr);
+			}
+			break;
+		case SDL_DROPFILE:
+			{
+				char *s = event->drop.file;
+
+				(void) Sony_Insert1a(s, falseblnr);
+				SDL_RaiseWindow(my_main_wind);
+				SDL_free(s);
+			}
+			break;
+#if 0
+		case Expose: /* SDL doesn't have an expose event */
+			int x0 = event->expose.x;
+			int y0 = event->expose.y;
+			int x1 = x0 + event->expose.width;
+			int y1 = y0 + event->expose.height;
+
+			if (x0 < 0) {
+				x0 = 0;
+			}
+			if (x1 > vMacScreenWidth) {
+				x1 = vMacScreenWidth;
+			}
+			if (y0 < 0) {
+				y0 = 0;
+			}
+			if (y1 > vMacScreenHeight) {
+				y1 = vMacScreenHeight;
+			}
+			if ((x0 < x1) && (y0 < y1)) {
+				HaveChangedScreenBuff(y0, x0, y1, x1);
+			}
+			break;
+#endif
+	}
+}
+
+/* --- main window creation and disposal --- */
+
+LOCALVAR int my_argc;
+LOCALVAR char **my_argv;
+
+LOCALFUNC blnr Screen_Init(void)
+{
+	blnr v = falseblnr;
+
+	InitKeyCodes();
+
+	if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
+	{
+		fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
+	} else {
+		v = trueblnr;
+	}
+
+	return v;
+}
+
+#if MayFullScreen
+LOCALVAR blnr GrabMachine = falseblnr;
+#endif
+
+#if MayFullScreen
+LOCALPROC GrabTheMachine(void)
+{
+#if GrabKeysFullScreen
+	SDL_SetWindowGrab(my_main_wind, SDL_TRUE);
+#endif
+
+#if EnableFSMouseMotion
+
+#if HaveWorkingWarp
+	/*
+		if magnification changes, need to reset,
+		even if HaveMouseMotion already true
+	*/
+	if (MyMoveMouse(ViewHStart + (ViewHSize / 2),
+		ViewVStart + (ViewVSize / 2)))
+	{
+		SavedMouseH = ViewHStart + (ViewHSize / 2);
+		SavedMouseV = ViewVStart + (ViewVSize / 2);
+		HaveMouseMotion = trueblnr;
+	}
+#else
+	if (0 == SDL_SetRelativeMouseMode(SDL_ENABLE)) {
+		HaveMouseMotion = trueblnr;
+	}
+#endif
+
+#endif /* EnableFSMouseMotion */
+}
+#endif
+
+#if MayFullScreen
+LOCALPROC UngrabMachine(void)
+{
+#if EnableFSMouseMotion
+
+	if (HaveMouseMotion) {
+#if HaveWorkingWarp
+		(void) MyMoveMouse(CurMouseH, CurMouseV);
+#else
+		SDL_SetRelativeMouseMode(SDL_DISABLE);
+#endif
+
+		HaveMouseMotion = falseblnr;
+	}
+
+#endif /* EnableFSMouseMotion */
+
+#if GrabKeysFullScreen
+	SDL_SetWindowGrab(my_main_wind, SDL_FALSE);
+#endif
+}
+#endif
+
+#if EnableFSMouseMotion && HaveWorkingWarp
+LOCALPROC MyMouseConstrain(void)
+{
+	si4b shiftdh;
+	si4b shiftdv;
+
+	if (SavedMouseH < ViewHStart + (ViewHSize / 4)) {
+		shiftdh = ViewHSize / 2;
+	} else if (SavedMouseH > ViewHStart + ViewHSize - (ViewHSize / 4)) {
+		shiftdh = - ViewHSize / 2;
+	} else {
+		shiftdh = 0;
+	}
+	if (SavedMouseV < ViewVStart + (ViewVSize / 4)) {
+		shiftdv = ViewVSize / 2;
+	} else if (SavedMouseV > ViewVStart + ViewVSize - (ViewVSize / 4)) {
+		shiftdv = - ViewVSize / 2;
+	} else {
+		shiftdv = 0;
+	}
+	if ((shiftdh != 0) || (shiftdv != 0)) {
+		SavedMouseH += shiftdh;
+		SavedMouseV += shiftdv;
+		if (! MyMoveMouse(SavedMouseH, SavedMouseV)) {
+			HaveMouseMotion = falseblnr;
+		}
+	}
+}
+#endif
+
+enum {
+	kMagStateNormal,
+#if EnableMagnify
+	kMagStateMagnifgy,
+#endif
+	kNumMagStates
+};
+
+#define kMagStateAuto kNumMagStates
+
+#if MayNotFullScreen
+LOCALVAR int CurWinIndx;
+LOCALVAR blnr HavePositionWins[kNumMagStates];
+LOCALVAR int WinPositionsX[kNumMagStates];
+LOCALVAR int WinPositionsY[kNumMagStates];
+#endif
+
+LOCALFUNC blnr CreateMainWindow(void)
+{
+	int NewWindowX;
+	int NewWindowY;
+	int NewWindowHeight = vMacScreenHeight;
+	int NewWindowWidth = vMacScreenWidth;
+	Uint32 flags = 0 /* SDL_WINDOW_HIDDEN */;
+	blnr v = falseblnr;
+
+#if EnableMagnify && 1
+	if (UseMagnify) {
+		NewWindowHeight *= MyWindowScale;
+		NewWindowWidth *= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		/*
+			We don't want physical screen mode to be changed in modern
+			displays, so we pass this _DESKTOP flag.
+		*/
+		flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
+
+		NewWindowX = SDL_WINDOWPOS_UNDEFINED;
+		NewWindowY = SDL_WINDOWPOS_UNDEFINED;
+	}
+#endif
+#if VarFullScreen
+	else
+#endif
+#if MayNotFullScreen
+	{
+		int WinIndx;
+
+#if EnableMagnify
+		if (UseMagnify) {
+			WinIndx = kMagStateMagnifgy;
+		} else
+#endif
+		{
+			WinIndx = kMagStateNormal;
+		}
+
+		if (! HavePositionWins[WinIndx]) {
+			NewWindowX = SDL_WINDOWPOS_CENTERED;
+			NewWindowY = SDL_WINDOWPOS_CENTERED;
+		} else {
+			NewWindowX = WinPositionsX[WinIndx];
+			NewWindowY = WinPositionsY[WinIndx];
+		}
+
+		CurWinIndx = WinIndx;
+	}
+#endif
+
+#if 0
+	SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
+#endif
+
+	if (NULL == (my_main_wind = SDL_CreateWindow(
+		(NULL != n_arg) ? n_arg : kStrAppName,
+		NewWindowX, NewWindowY,
+		NewWindowWidth, NewWindowHeight,
+		flags)))
+	{
+		fprintf(stderr, "SDL_CreateWindow fails: %s\n",
+			SDL_GetError());
+	} else
+	if (NULL == (my_renderer = SDL_CreateRenderer(
+		my_main_wind, -1,
+		0 /* SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC */
+			/*
+				SDL_RENDERER_ACCELERATED not needed
+				"no flags gives priority to available
+				SDL_RENDERER_ACCELERATED renderers"
+			*/
+			/* would rather not require vsync */
+		)))
+	{
+		fprintf(stderr, "SDL_CreateRenderer fails: %s\n",
+			SDL_GetError());
+	} else
+	if (NULL == (my_texture = SDL_CreateTexture(
+		my_renderer,
+		SDL_PIXELFORMAT_ARGB8888,
+		SDL_TEXTUREACCESS_STREAMING,
+#if UseSDLscaling
+		vMacScreenWidth, vMacScreenHeight
+#else
+		NewWindowWidth, NewWindowHeight
+#endif
+		)))
+	{
+		fprintf(stderr, "SDL_CreateTexture fails: %s\n",
+			SDL_GetError());
+	} else
+	if (NULL == (my_format = SDL_AllocFormat(SDL_PIXELFORMAT_ARGB8888)))
+	{
+		fprintf(stderr, "SDL_AllocFormat fails: %s\n",
+			SDL_GetError());
+	} else
+	{
+		/* SDL_ShowWindow(my_main_wind); */
+
+		SDL_RenderClear(my_renderer);
+
+#if 0
+		SDL_DisplayMode info;
+
+		if (0 != SDL_GetCurrentDisplayMode(0, &info)) {
+			fprintf(stderr, "SDL_GetCurrentDisplayMode fails: %s\n",
+				SDL_GetError());
+
+			return falseblnr;
+		}
+#endif
+
+#if VarFullScreen
+		if (UseFullScreen)
+#endif
+#if MayFullScreen
+		{
+			int wr;
+			int hr;
+
+			SDL_GL_GetDrawableSize(my_main_wind, &wr, &hr);
+
+			ViewHSize = wr;
+			ViewVSize = hr;
+#if EnableMagnify
+			if (UseMagnify) {
+				ViewHSize /= MyWindowScale;
+				ViewVSize /= MyWindowScale;
+			}
+#endif
+			if (ViewHSize >= vMacScreenWidth) {
+				ViewHStart = 0;
+				ViewHSize = vMacScreenWidth;
+			} else {
+				ViewHSize &= ~ 1;
+			}
+			if (ViewVSize >= vMacScreenHeight) {
+				ViewVStart = 0;
+				ViewVSize = vMacScreenHeight;
+			} else {
+				ViewVSize &= ~ 1;
+			}
+
+			if (wr > NewWindowWidth) {
+				hOffset = (wr - NewWindowWidth) / 2;
+			} else {
+				hOffset = 0;
+			}
+			if (hr > NewWindowHeight) {
+				vOffset = (hr - NewWindowHeight) / 2;
+			} else {
+				vOffset = 0;
+			}
+		}
+#endif
+
+#if 0 != vMacScreenDepth
+		ColorModeWorks = trueblnr;
+#endif
+
+		v = trueblnr;
+	}
+
+	return v;
+}
+
+LOCALPROC CloseMainWindow(void)
+{
+	if (NULL != my_format) {
+		SDL_FreeFormat(my_format);
+		my_format = NULL;
+	}
+
+	if (NULL != my_texture) {
+		SDL_DestroyTexture(my_texture);
+		my_texture = NULL;
+	}
+
+	if (NULL != my_renderer) {
+		SDL_DestroyRenderer(my_renderer);
+		my_renderer = NULL;
+	}
+
+	if (NULL != my_main_wind) {
+		SDL_DestroyWindow(my_main_wind);
+		my_main_wind = NULL;
+	}
+}
+
+#if EnableRecreateW
+LOCALPROC ZapMyWState(void)
+{
+	my_main_wind = NULL;
+	my_renderer = NULL;
+	my_texture = NULL;
+	my_format = NULL;
+}
+#endif
+
+#if EnableRecreateW
+struct MyWState {
+#if MayFullScreen
+	ui4r f_ViewHSize;
+	ui4r f_ViewVSize;
+	ui4r f_ViewHStart;
+	ui4r f_ViewVStart;
+	int f_hOffset;
+	int f_vOffset;
+#endif
+#if VarFullScreen
+	blnr f_UseFullScreen;
+#endif
+#if EnableMagnify
+	blnr f_UseMagnify;
+#endif
+#if MayNotFullScreen
+	int f_CurWinIndx;
+#endif
+	SDL_Window *f_my_main_wind;
+	SDL_Renderer *f_my_renderer;
+	SDL_Texture *f_my_texture;
+	SDL_PixelFormat *f_my_format;
+};
+typedef struct MyWState MyWState;
+#endif
+
+#if EnableRecreateW
+LOCALPROC GetMyWState(MyWState *r)
+{
+#if MayFullScreen
+	r->f_ViewHSize = ViewHSize;
+	r->f_ViewVSize = ViewVSize;
+	r->f_ViewHStart = ViewHStart;
+	r->f_ViewVStart = ViewVStart;
+	r->f_hOffset = hOffset;
+	r->f_vOffset = vOffset;
+#endif
+#if VarFullScreen
+	r->f_UseFullScreen = UseFullScreen;
+#endif
+#if EnableMagnify
+	r->f_UseMagnify = UseMagnify;
+#endif
+#if MayNotFullScreen
+	r->f_CurWinIndx = CurWinIndx;
+#endif
+	r->f_my_main_wind = my_main_wind;
+	r->f_my_renderer = my_renderer;
+	r->f_my_texture = my_texture;
+	r->f_my_format = my_format;
+}
+#endif
+
+#if EnableRecreateW
+LOCALPROC SetMyWState(MyWState *r)
+{
+#if MayFullScreen
+	ViewHSize = r->f_ViewHSize;
+	ViewVSize = r->f_ViewVSize;
+	ViewHStart = r->f_ViewHStart;
+	ViewVStart = r->f_ViewVStart;
+	hOffset = r->f_hOffset;
+	vOffset = r->f_vOffset;
+#endif
+#if VarFullScreen
+	UseFullScreen = r->f_UseFullScreen;
+#endif
+#if EnableMagnify
+	UseMagnify = r->f_UseMagnify;
+#endif
+#if MayNotFullScreen
+	CurWinIndx = r->f_CurWinIndx;
+#endif
+	my_main_wind = r->f_my_main_wind;
+	my_renderer = r->f_my_renderer;
+	my_texture = r->f_my_texture;
+	my_format = r->f_my_format;
+}
+#endif
+
+#if VarFullScreen && EnableMagnify
+enum {
+	kWinStateWindowed,
+#if EnableMagnify
+	kWinStateFullScreen,
+#endif
+	kNumWinStates
+};
+#endif
+
+#if VarFullScreen && EnableMagnify
+LOCALVAR int WinMagStates[kNumWinStates];
+#endif
+
+#if EnableRecreateW
+LOCALFUNC blnr ReCreateMainWindow(void)
+{
+	MyWState old_state;
+	MyWState new_state;
+#if HaveWorkingWarp
+	blnr HadCursorHidden = HaveCursorHidden;
+#endif
+#if VarFullScreen && EnableMagnify
+	int OldWinState =
+		UseFullScreen ? kWinStateFullScreen : kWinStateWindowed;
+	int OldMagState =
+		UseMagnify ? kMagStateMagnifgy : kMagStateNormal;
+
+	WinMagStates[OldWinState] =
+		OldMagState;
+#endif
+
+#if VarFullScreen
+	if (! UseFullScreen)
+#endif
+#if MayNotFullScreen
+	{
+		SDL_GetWindowPosition(my_main_wind,
+			&WinPositionsX[CurWinIndx],
+			&WinPositionsY[CurWinIndx]);
+		HavePositionWins[CurWinIndx] = trueblnr;
+	}
+#endif
+
+	ForceShowCursor(); /* hide/show cursor api is per window */
+
+#if MayFullScreen
+	if (GrabMachine) {
+		GrabMachine = falseblnr;
+		UngrabMachine();
+	}
+#endif
+
+	GetMyWState(&old_state);
+
+	ZapMyWState();
+
+#if EnableMagnify
+	UseMagnify = WantMagnify;
+#endif
+#if VarFullScreen
+	UseFullScreen = WantFullScreen;
+#endif
+
+	if (! CreateMainWindow()) {
+		CloseMainWindow();
+		SetMyWState(&old_state);
+
+		/* avoid retry */
+#if VarFullScreen
+		WantFullScreen = UseFullScreen;
+#endif
+#if EnableMagnify
+		WantMagnify = UseMagnify;
+#endif
+
+	} else {
+		GetMyWState(&new_state);
+		SetMyWState(&old_state);
+		CloseMainWindow();
+		SetMyWState(&new_state);
+
+#if HaveWorkingWarp
+		if (HadCursorHidden) {
+			(void) MyMoveMouse(CurMouseH, CurMouseV);
+		}
+#endif
+	}
+
+	return trueblnr;
+}
+#endif
+
+LOCALPROC ZapWinStateVars(void)
+{
+#if MayNotFullScreen
+	{
+		int i;
+
+		for (i = 0; i < kNumMagStates; ++i) {
+			HavePositionWins[i] = falseblnr;
+		}
+	}
+#endif
+#if VarFullScreen && EnableMagnify
+	{
+		int i;
+
+		for (i = 0; i < kNumWinStates; ++i) {
+			WinMagStates[i] = kMagStateAuto;
+		}
+	}
+#endif
+}
+
+#if VarFullScreen
+LOCALPROC ToggleWantFullScreen(void)
+{
+	WantFullScreen = ! WantFullScreen;
+
+#if EnableMagnify
+	{
+		int OldWinState =
+			UseFullScreen ? kWinStateFullScreen : kWinStateWindowed;
+		int OldMagState =
+			UseMagnify ? kMagStateMagnifgy : kMagStateNormal;
+		int NewWinState =
+			WantFullScreen ? kWinStateFullScreen : kWinStateWindowed;
+		int NewMagState = WinMagStates[NewWinState];
+
+		WinMagStates[OldWinState] = OldMagState;
+		if (kMagStateAuto != NewMagState) {
+			WantMagnify = (kMagStateMagnifgy == NewMagState);
+		} else {
+			WantMagnify = falseblnr;
+			if (WantFullScreen) {
+				SDL_Rect r;
+
+				if (0 == SDL_GetDisplayBounds(0, &r)) {
+					if ((r.w >= vMacScreenWidth * MyWindowScale)
+						&& (r.h >= vMacScreenHeight * MyWindowScale)
+						)
+					{
+						WantMagnify = trueblnr;
+					}
+				}
+			}
+		}
+	}
+#endif
+}
+#endif
+
+/* --- SavedTasks --- */
+
+LOCALPROC LeaveBackground(void)
+{
+	ReconnectKeyCodes3();
+	DisableKeyRepeat();
+}
+
+LOCALPROC EnterBackground(void)
+{
+	RestoreKeyRepeat();
+	DisconnectKeyCodes3();
+
+	ForceShowCursor();
+}
+
+LOCALPROC LeaveSpeedStopped(void)
+{
+#if MySoundEnabled
+	MySound_Start();
+#endif
+
+	StartUpTimeAdjust();
+}
+
+LOCALPROC EnterSpeedStopped(void)
+{
+#if MySoundEnabled
+	MySound_Stop();
+#endif
+}
+
+LOCALPROC CheckForSavedTasks(void)
+{
+	if (MyEvtQNeedRecover) {
+		MyEvtQNeedRecover = falseblnr;
+
+		/* attempt cleanup, MyEvtQNeedRecover may get set again */
+		MyEvtQTryRecoverFromFull();
+	}
+
+#if EnableFSMouseMotion && HaveWorkingWarp
+	if (HaveMouseMotion) {
+		MyMouseConstrain();
+	}
+#endif
+
+	if (RequestMacOff) {
+		RequestMacOff = falseblnr;
+		if (AnyDiskInserted()) {
+			MacMsgOverride(kStrQuitWarningTitle,
+				kStrQuitWarningMessage);
+		} else {
+			ForceMacOff = trueblnr;
+		}
+	}
+
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (gTrueBackgroundFlag != gBackgroundFlag) {
+		gBackgroundFlag = gTrueBackgroundFlag;
+		if (gTrueBackgroundFlag) {
+			EnterBackground();
+		} else {
+			LeaveBackground();
+		}
+	}
+
+	if (CurSpeedStopped != (SpeedStopped ||
+		(gBackgroundFlag && ! RunInBackground
+#if EnableAutoSlow && 0
+			&& (QuietSubTicks >= 4092)
+#endif
+		)))
+	{
+		CurSpeedStopped = ! CurSpeedStopped;
+		if (CurSpeedStopped) {
+			EnterSpeedStopped();
+		} else {
+			LeaveSpeedStopped();
+		}
+	}
+
+	if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
+		MacMsgDisplayOn();
+	}
+
+#if EnableRecreateW
+	if (0
+#if EnableMagnify
+		|| (UseMagnify != WantMagnify)
+#endif
+#if VarFullScreen
+		|| (UseFullScreen != WantFullScreen)
+#endif
+		)
+	{
+		(void) ReCreateMainWindow();
+	}
+#endif
+
+#if MayFullScreen
+	if (GrabMachine != (
+#if VarFullScreen
+		UseFullScreen &&
+#endif
+		! (gTrueBackgroundFlag || CurSpeedStopped)))
+	{
+		GrabMachine = ! GrabMachine;
+		if (GrabMachine) {
+			GrabTheMachine();
+		} else {
+			UngrabMachine();
+		}
+	}
+#endif
+
+	if (NeedWholeScreenDraw) {
+		NeedWholeScreenDraw = falseblnr;
+		ScreenChangedAll();
+	}
+
+#if NeedRequestIthDisk
+	if (0 != RequestIthDisk) {
+		Sony_InsertIth(RequestIthDisk);
+		RequestIthDisk = 0;
+	}
+#endif
+
+	if (HaveCursorHidden != (WantCursorHidden
+		&& ! (gTrueBackgroundFlag || CurSpeedStopped)))
+	{
+		HaveCursorHidden = ! HaveCursorHidden;
+		(void) SDL_ShowCursor(
+			HaveCursorHidden ? SDL_DISABLE : SDL_ENABLE);
+	}
+}
+
+/* --- command line parsing --- */
+
+LOCALFUNC blnr ScanCommandLine(void)
+{
+	char *pa;
+	int i = 1;
+
+label_retry:
+	if (i < my_argc) {
+		pa = my_argv[i++];
+		if ('-' == pa[0]) {
+			if ((0 == strcmp(pa, "--rom"))
+				|| (0 == strcmp(pa, "-r")))
+			{
+				if (i < my_argc) {
+					rom_path = my_argv[i++];
+					goto label_retry;
+				}
+			} else
+			if (0 == strcmp(pa, "-n"))
+			{
+				if (i < my_argc) {
+					n_arg = my_argv[i++];
+					goto label_retry;
+				}
+			} else
+			if (0 == strcmp(pa, "-d"))
+			{
+				if (i < my_argc) {
+					d_arg = my_argv[i++];
+					goto label_retry;
+				}
+			} else
+			if (('p' == pa[1]) && ('s' == pa[2]) && ('n' == pa[3]))
+			{
+				/* seen in OS X. ignore */
+				goto label_retry;
+			} else
+			{
+				MacMsg(kStrBadArgTitle, kStrBadArgMessage, falseblnr);
+#if dbglog_HAVE
+				dbglog_writeln("bad command line argument");
+				dbglog_writeln(pa);
+#endif
+			}
+		} else {
+			(void) Sony_Insert1(pa, falseblnr);
+			goto label_retry;
+		}
+	}
+
+	return trueblnr;
+}
+
+/* --- main program flow --- */
+
+GLOBALOSGLUFUNC blnr ExtraTimeNotOver(void)
+{
+	UpdateTrueEmulatedTime();
+	return TrueEmulatedTime == OnTrueTime;
+}
+
+LOCALPROC WaitForTheNextEvent(void)
+{
+	SDL_Event event;
+
+	if (SDL_WaitEvent(&event)) {
+		HandleTheEvent(&event);
+	}
+}
+
+LOCALPROC CheckForSystemEvents(void)
+{
+	SDL_Event event;
+	int i = 10;
+
+	while ((--i >= 0) && SDL_PollEvent(&event)) {
+		HandleTheEvent(&event);
+	}
+}
+
+GLOBALOSGLUPROC WaitForNextTick(void)
+{
+label_retry:
+	CheckForSystemEvents();
+	CheckForSavedTasks();
+
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (CurSpeedStopped) {
+		DoneWithDrawingForTick();
+		WaitForTheNextEvent();
+		goto label_retry;
+	}
+
+	if (ExtraTimeNotOver()) {
+		(void) SDL_Delay(NextIntTime - LastTime);
+		goto label_retry;
+	}
+
+	if (CheckDateTime()) {
+#if MySoundEnabled
+		MySound_SecondNotify();
+#endif
+#if EnableDemoMsg
+		DemoModeSecondNotify();
+#endif
+	}
+
+	if ((! gBackgroundFlag)
+#if UseMotionEvents
+		&& (! CaughtMouse)
+#endif
+		)
+	{
+		CheckMouseState();
+	}
+
+	OnTrueTime = TrueEmulatedTime;
+
+#if dbglog_TimeStuff
+	dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime);
+#endif
+}
+
+/* --- platform independent code can be thought of as going here --- */
+
+#include "PROGMAIN.h"
+
+LOCALPROC ZapOSGLUVars(void)
+{
+	InitDrives();
+	ZapWinStateVars();
+}
+
+LOCALPROC ReserveAllocAll(void)
+{
+#if dbglog_HAVE
+	dbglog_ReserveAlloc();
+#endif
+	ReserveAllocOneBlock(&ROM, kROM_Size, 5, falseblnr);
+
+	ReserveAllocOneBlock(&screencomparebuff,
+		vMacScreenNumBytes, 5, trueblnr);
+#if UseControlKeys
+	ReserveAllocOneBlock(&CntrlDisplayBuff,
+		vMacScreenNumBytes, 5, falseblnr);
+#endif
+
+	ReserveAllocOneBlock(&CLUT_final, CLUT_finalsz, 5, falseblnr);
+#if MySoundEnabled
+	ReserveAllocOneBlock((ui3p *)&TheSoundBuffer,
+		dbhBufferSize, 5, falseblnr);
+#endif
+
+	EmulationReserveAlloc();
+}
+
+LOCALFUNC blnr AllocMyMemory(void)
+{
+	uimr n;
+	blnr IsOk = falseblnr;
+
+	ReserveAllocOffset = 0;
+	ReserveAllocBigBlock = nullpr;
+	ReserveAllocAll();
+	n = ReserveAllocOffset;
+	ReserveAllocBigBlock = (ui3p)calloc(1, n);
+	if (NULL == ReserveAllocBigBlock) {
+		MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr);
+	} else {
+		ReserveAllocOffset = 0;
+		ReserveAllocAll();
+		if (n != ReserveAllocOffset) {
+			/* oops, program error */
+		} else {
+			IsOk = trueblnr;
+		}
+	}
+
+	return IsOk;
+}
+
+LOCALPROC UnallocMyMemory(void)
+{
+	if (nullpr != ReserveAllocBigBlock) {
+		free((char *)ReserveAllocBigBlock);
+	}
+}
+
+#if CanGetAppPath
+LOCALFUNC blnr InitWhereAmI(void)
+{
+	app_parent = SDL_GetBasePath();
+
+	pref_dir = SDL_GetPrefPath("gryphel", "minivmac");
+
+	return trueblnr; /* keep going regardless */
+}
+#endif
+
+#if CanGetAppPath
+LOCALPROC UninitWhereAmI(void)
+{
+	SDL_free(pref_dir);
+
+	SDL_free(app_parent);
+}
+#endif
+
+LOCALFUNC blnr InitOSGLU(void)
+{
+	if (AllocMyMemory())
+#if CanGetAppPath
+	if (InitWhereAmI())
+#endif
+#if dbglog_HAVE
+	if (dbglog_open())
+#endif
+	if (ScanCommandLine())
+	if (LoadMacRom())
+	if (LoadInitialImages())
+	if (InitLocationDat())
+#if MySoundEnabled
+	if (MySound_Init())
+#endif
+	if (Screen_Init())
+	if (CreateMainWindow())
+	if (WaitForRom())
+	{
+		return trueblnr;
+	}
+	return falseblnr;
+}
+
+LOCALPROC UnInitOSGLU(void)
+{
+	if (MacMsgDisplayed) {
+		MacMsgDisplayOff();
+	}
+
+	RestoreKeyRepeat();
+#if MayFullScreen
+	UngrabMachine();
+#endif
+#if MySoundEnabled
+	MySound_Stop();
+#endif
+#if MySoundEnabled
+	MySound_UnInit();
+#endif
+#if IncludePbufs
+	UnInitPbufs();
+#endif
+	UnInitDrives();
+
+	ForceShowCursor();
+
+#if dbglog_HAVE
+	dbglog_close();
+#endif
+
+#if CanGetAppPath
+	UninitWhereAmI();
+#endif
+	UnallocMyMemory();
+
+	CheckSavedMacMsg();
+
+	CloseMainWindow();
+
+	SDL_Quit();
+}
+
+int main(int argc, char **argv)
+{
+	my_argc = argc;
+	my_argv = argv;
+
+	ZapOSGLUVars();
+	if (InitOSGLU()) {
+		ProgramMain();
+	}
+	UnInitOSGLU();
+
+	return 0;
+}
--- /dev/null
+++ b/src/OSGLUSDL.c
@@ -1,0 +1,2324 @@
+/*
+	OSGLUSDL.c
+
+	Copyright (C) 2012 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Operating System GLUe for SDL library
+
+	All operating system dependent code for the
+	SDL Library should go here.
+*/
+
+#include "CNFGRAPI.h"
+#include "SYSDEPNS.h"
+#include "ENDIANAC.h"
+
+#include "MYOSGLUE.h"
+
+#include "STRCONST.h"
+
+/* --- some simple utilities --- */
+
+GLOBALOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount)
+{
+	(void) memcpy((char *)destPtr, (char *)srcPtr, byteCount);
+}
+
+/* --- control mode and internationalization --- */
+
+#define NeedCell2PlainAsciiMap 1
+
+#include "INTLCHAR.h"
+
+/* --- sending debugging info to file --- */
+
+#if dbglog_HAVE
+
+#define dbglog_ToStdErr 0
+
+#if ! dbglog_ToStdErr
+LOCALVAR FILE *dbglog_File = NULL;
+#endif
+
+LOCALFUNC blnr dbglog_open0(void)
+{
+#if dbglog_ToStdErr
+	return trueblnr;
+#else
+	dbglog_File = fopen("dbglog.txt", "w");
+	return (NULL != dbglog_File);
+#endif
+}
+
+LOCALPROC dbglog_write0(char *s, uimr L)
+{
+#if dbglog_ToStdErr
+	(void) fwrite(s, 1, L, stderr);
+#else
+	if (dbglog_File != NULL) {
+		(void) fwrite(s, 1, L, dbglog_File);
+	}
+#endif
+}
+
+LOCALPROC dbglog_close0(void)
+{
+#if ! dbglog_ToStdErr
+	if (dbglog_File != NULL) {
+		fclose(dbglog_File);
+		dbglog_File = NULL;
+	}
+#endif
+}
+
+#endif
+
+/* --- information about the environment --- */
+
+#define WantColorTransValid 0
+
+#include "COMOSGLU.h"
+
+#include "PBUFSTDC.h"
+
+#include "CONTROLM.h"
+
+/* --- text translation --- */
+
+LOCALPROC NativeStrFromCStr(char *r, char *s)
+{
+	ui3b ps[ClStrMaxLength];
+	int i;
+	int L;
+
+	ClStrFromSubstCStr(&L, ps, s);
+
+	for (i = 0; i < L; ++i) {
+		r[i] = Cell2PlainAsciiMap[ps[i]];
+	}
+
+	r[L] = 0;
+}
+
+/* --- drives --- */
+
+#define NotAfileRef NULL
+
+LOCALVAR FILE *Drives[NumDrives]; /* open disk image files */
+
+LOCALPROC InitDrives(void)
+{
+	/*
+		This isn't really needed, Drives[i] and DriveNames[i]
+		need not have valid values when not vSonyIsInserted[i].
+	*/
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		Drives[i] = NotAfileRef;
+	}
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer,
+	tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count,
+	ui5r *Sony_ActCount)
+{
+	tMacErr err = mnvm_miscErr;
+	FILE *refnum = Drives[Drive_No];
+	ui5r NewSony_Count = 0;
+
+	if (0 == fseek(refnum, Sony_Start, SEEK_SET)) {
+		if (IsWrite) {
+			NewSony_Count = fwrite(Buffer, 1, Sony_Count, refnum);
+		} else {
+			NewSony_Count = fread(Buffer, 1, Sony_Count, refnum);
+		}
+
+		if (NewSony_Count == Sony_Count) {
+			err = mnvm_noErr;
+		}
+	}
+
+	if (nullpr != Sony_ActCount) {
+		*Sony_ActCount = NewSony_Count;
+	}
+
+	return err; /*& figure out what really to return &*/
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count)
+{
+	tMacErr err = mnvm_miscErr;
+	FILE *refnum = Drives[Drive_No];
+	long v;
+
+	if (0 == fseek(refnum, 0, SEEK_END)) {
+		v = ftell(refnum);
+		if (v >= 0) {
+			*Sony_Count = v;
+			err = mnvm_noErr;
+		}
+	}
+
+	return err; /*& figure out what really to return &*/
+}
+
+LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, blnr deleteit)
+{
+	FILE *refnum = Drives[Drive_No];
+
+	DiskEjectedNotify(Drive_No);
+
+	fclose(refnum);
+	Drives[Drive_No] = NotAfileRef; /* not really needed */
+
+	return mnvm_noErr;
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
+{
+	return vSonyEject0(Drive_No, falseblnr);
+}
+
+LOCALPROC UnInitDrives(void)
+{
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		if (vSonyIsInserted(i)) {
+			(void) vSonyEject(i);
+		}
+	}
+}
+
+LOCALFUNC blnr Sony_Insert0(FILE *refnum, blnr locked,
+	char *drivepath)
+{
+	tDrive Drive_No;
+	blnr IsOk = falseblnr;
+
+	if (! FirstFreeDisk(&Drive_No)) {
+		MacMsg(kStrTooManyImagesTitle, kStrTooManyImagesMessage,
+			falseblnr);
+	} else {
+		/* printf("Sony_Insert0 %d\n", (int)Drive_No); */
+
+		{
+			Drives[Drive_No] = refnum;
+			DiskInsertNotify(Drive_No, locked);
+
+			IsOk = trueblnr;
+		}
+	}
+
+	if (! IsOk) {
+		fclose(refnum);
+	}
+
+	return IsOk;
+}
+
+LOCALFUNC blnr Sony_Insert1(char *drivepath, blnr silentfail)
+{
+	blnr locked = falseblnr;
+	/* printf("Sony_Insert1 %s\n", drivepath); */
+	FILE *refnum = fopen(drivepath, "rb+");
+	if (NULL == refnum) {
+		locked = trueblnr;
+		refnum = fopen(drivepath, "rb");
+	}
+	if (NULL == refnum) {
+		if (! silentfail) {
+			MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
+		}
+	} else {
+		return Sony_Insert0(refnum, locked, drivepath);
+	}
+	return falseblnr;
+}
+
+LOCALFUNC tMacErr LoadMacRomFrom(char *path)
+{
+	tMacErr err;
+	FILE *ROM_File;
+	int File_Size;
+
+	ROM_File = fopen(path, "rb");
+	if (NULL == ROM_File) {
+		err = mnvm_fnfErr;
+	} else {
+		File_Size = fread(ROM, 1, kROM_Size, ROM_File);
+		if (File_Size != kROM_Size) {
+			if (feof(ROM_File)) {
+				MacMsgOverride(kStrShortROMTitle,
+					kStrShortROMMessage);
+				err = mnvm_eofErr;
+			} else {
+				MacMsgOverride(kStrNoReadROMTitle,
+					kStrNoReadROMMessage);
+				err = mnvm_miscErr;
+			}
+		} else {
+			err = ROM_IsValid();
+		}
+		fclose(ROM_File);
+	}
+
+	return err;
+}
+
+#if 0 /* no drag and drop to make use of this */
+LOCALFUNC blnr Sony_Insert1a(char *drivepath, blnr silentfail)
+{
+	blnr v;
+
+	if (! ROM_loaded) {
+		v = (mnvm_noErr == LoadMacRomFrom(drivepath));
+	} else {
+		v = Sony_Insert1(drivepath, silentfail);
+	}
+
+	return v;
+}
+#endif
+
+LOCALFUNC blnr Sony_Insert2(char *s)
+{
+	return Sony_Insert1(s, trueblnr);
+}
+
+LOCALFUNC blnr Sony_InsertIth(int i)
+{
+	blnr v;
+
+	if ((i > 9) || ! FirstFreeDisk(nullpr)) {
+		v = falseblnr;
+	} else {
+		char s[] = "disk?.dsk";
+
+		s[4] = '0' + i;
+
+		v = Sony_Insert2(s);
+	}
+
+	return v;
+}
+
+LOCALFUNC blnr LoadInitialImages(void)
+{
+	if (! AnyDiskInserted()) {
+		int i;
+
+		for (i = 1; Sony_InsertIth(i); ++i) {
+			/* stop on first error (including file not found) */
+		}
+	}
+
+	return trueblnr;
+}
+
+/* --- ROM --- */
+
+LOCALVAR char *rom_path = NULL;
+
+LOCALFUNC blnr LoadMacRom(void)
+{
+	tMacErr err;
+
+	if ((NULL == rom_path)
+		|| (mnvm_fnfErr == (err = LoadMacRomFrom(rom_path))))
+	if (mnvm_fnfErr == (err = LoadMacRomFrom(RomFileName)))
+	{
+	}
+
+	return trueblnr; /* keep launching Mini vMac, regardless */
+}
+
+/* --- video out --- */
+
+#if VarFullScreen
+LOCALVAR blnr UseFullScreen = (WantInitFullScreen != 0);
+#endif
+
+#if EnableMagnify
+LOCALVAR blnr UseMagnify = (WantInitMagnify != 0);
+#endif
+
+LOCALVAR blnr gBackgroundFlag = falseblnr;
+LOCALVAR blnr gTrueBackgroundFlag = falseblnr;
+LOCALVAR blnr CurSpeedStopped = trueblnr;
+
+#if EnableMagnify
+#define MaxScale MyWindowScale
+#else
+#define MaxScale 1
+#endif
+
+
+LOCALVAR SDL_Surface *my_surface = nullpr;
+
+LOCALVAR ui3p ScalingBuff = nullpr;
+
+LOCALVAR ui3p CLUT_final;
+
+#define CLUT_finalsz (256 * 8 * 4 * MaxScale)
+	/*
+		256 possible values of one byte
+		8 pixels per byte maximum (when black and white)
+		4 bytes per destination pixel maximum
+			multiplied by MyWindowScale if EnableMagnify
+	*/
+
+#define ScrnMapr_DoMap UpdateBWDepth3Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 3
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateBWDepth4Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 4
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateBWDepth5Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateBWDepth3ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 3
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateBWDepth4ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 4
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateBWDepth5ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+
+#define ScrnMapr_DoMap UpdateColorDepth3Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 3
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateColorDepth4Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 4
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateColorDepth5Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateColorDepth3ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 3
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateColorDepth4ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 4
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateColorDepth5ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#endif
+
+
+LOCALPROC HaveChangedScreenBuff(ui4r top, ui4r left,
+	ui4r bottom, ui4r right)
+{
+	int i;
+	int j;
+	ui3b *p;
+	Uint32 pixel;
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+	Uint32 CLUT_pixel[CLUT_size];
+#endif
+	Uint32 BWLUT_pixel[2];
+	ui5r top2 = top;
+	ui5r left2 = left;
+	ui5r bottom2 = bottom;
+	ui5r right2 = right;
+
+#if EnableMagnify
+	if (UseMagnify) {
+		top2 *= MyWindowScale;
+		left2 *= MyWindowScale;
+		bottom2 *= MyWindowScale;
+		right2 *= MyWindowScale;
+	}
+#endif
+
+	if (SDL_MUSTLOCK(my_surface)) {
+		if (SDL_LockSurface(my_surface) < 0) {
+			return;
+		}
+	}
+
+	{
+
+	int bpp = my_surface->format->BytesPerPixel;
+	ui5r ExpectedPitch = vMacScreenWidth * bpp;
+
+#if EnableMagnify
+	if (UseMagnify) {
+		ExpectedPitch *= MyWindowScale;
+	}
+#endif
+
+#if 0 != vMacScreenDepth
+	if (UseColorMode) {
+#if vMacScreenDepth < 4
+		for (i = 0; i < CLUT_size; ++i) {
+			CLUT_pixel[i] = SDL_MapRGB(my_surface->format,
+				CLUT_reds[i] >> 8,
+				CLUT_greens[i] >> 8,
+				CLUT_blues[i] >> 8);
+		}
+#endif
+	} else
+#endif
+	{
+		BWLUT_pixel[1] = SDL_MapRGB(my_surface->format, 0, 0, 0);
+			/* black */
+		BWLUT_pixel[0] = SDL_MapRGB(my_surface->format, 255, 255, 255);
+			/* white */
+	}
+
+	if ((0 == ((bpp - 1) & bpp)) /* a power of 2 */
+		&& (my_surface->pitch == ExpectedPitch)
+#if (vMacScreenDepth > 3)
+		&& ! UseColorMode
+#endif
+		)
+	{
+		int k;
+		Uint32 v;
+#if EnableMagnify
+		int a;
+#endif
+		int PixPerByte =
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+			UseColorMode ? (1 << (3 - vMacScreenDepth)) :
+#endif
+			8;
+		Uint8 *p4 = (Uint8 *)CLUT_final;
+
+		for (i = 0; i < 256; ++i) {
+			for (k = PixPerByte; --k >= 0; ) {
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+				if (UseColorMode) {
+					v = CLUT_pixel[
+#if 3 == vMacScreenDepth
+						i
+#else
+						(i >> (k << vMacScreenDepth))
+							& (CLUT_size - 1)
+#endif
+						];
+				} else
+#endif
+				{
+					v = BWLUT_pixel[(i >> k) & 1];
+				}
+
+#if EnableMagnify
+				for (a = UseMagnify ? MyWindowScale : 1; --a >= 0; )
+#endif
+				{
+					switch (bpp) {
+						case 1: /* Assuming 8-bpp */
+							*p4++ = v;
+							break;
+						case 2: /* Probably 15-bpp or 16-bpp */
+							*(Uint16 *)p4 = v;
+							p4 += 2;
+							break;
+						case 4: /* Probably 32-bpp */
+							*(Uint32 *)p4 = v;
+							p4 += 4;
+							break;
+					}
+				}
+			}
+		}
+
+		ScalingBuff = (ui3p)my_surface->pixels;
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+		if (UseColorMode) {
+#if EnableMagnify
+			if (UseMagnify) {
+				switch (bpp) {
+					case 1:
+						UpdateColorDepth3ScaledCopy(
+							top, left, bottom, right);
+						break;
+					case 2:
+						UpdateColorDepth4ScaledCopy(
+							top, left, bottom, right);
+						break;
+					case 4:
+						UpdateColorDepth5ScaledCopy(
+							top, left, bottom, right);
+						break;
+				}
+			} else
+#endif
+			{
+				switch (bpp) {
+					case 1:
+						UpdateColorDepth3Copy(top, left, bottom, right);
+						break;
+					case 2:
+						UpdateColorDepth4Copy(top, left, bottom, right);
+						break;
+					case 4:
+						UpdateColorDepth5Copy(top, left, bottom, right);
+						break;
+				}
+			}
+		} else
+#endif
+		{
+#if EnableMagnify
+			if (UseMagnify) {
+				switch (bpp) {
+					case 1:
+						UpdateBWDepth3ScaledCopy(
+							top, left, bottom, right);
+						break;
+					case 2:
+						UpdateBWDepth4ScaledCopy(
+							top, left, bottom, right);
+						break;
+					case 4:
+						UpdateBWDepth5ScaledCopy(
+							top, left, bottom, right);
+						break;
+				}
+			} else
+#endif
+			{
+				switch (bpp) {
+					case 1:
+						UpdateBWDepth3Copy(top, left, bottom, right);
+						break;
+					case 2:
+						UpdateBWDepth4Copy(top, left, bottom, right);
+						break;
+					case 4:
+						UpdateBWDepth5Copy(top, left, bottom, right);
+						break;
+				}
+			}
+		}
+
+	} else {
+		ui3b *the_data = (ui3b *)GetCurDrawBuff();
+
+		/* adapted from putpixel in SDL documentation */
+
+		for (i = top2; i < bottom2; ++i) {
+			for (j = left2; j < right2; ++j) {
+				int i0 = i;
+				int j0 = j;
+				Uint8 *bufp = (Uint8 *)my_surface->pixels
+					+ i * my_surface->pitch + j * bpp;
+
+#if EnableMagnify
+				if (UseMagnify) {
+					i0 /= MyWindowScale;
+					j0 /= MyWindowScale;
+				}
+#endif
+
+#if 0 != vMacScreenDepth
+				if (UseColorMode) {
+#if vMacScreenDepth < 4
+					p = the_data + ((i0 * vMacScreenWidth + j0)
+						>> (3 - vMacScreenDepth));
+					{
+						ui3r k = (*p >> (((~ j0)
+								& ((1 << (3 - vMacScreenDepth)) - 1))
+							<< vMacScreenDepth))
+							& (CLUT_size - 1);
+						pixel = CLUT_pixel[k];
+					}
+#elif 4 == vMacScreenDepth
+					p = the_data + ((i0 * vMacScreenWidth + j0) << 1);
+					{
+						ui4r t0 = do_get_mem_word(p);
+						pixel = SDL_MapRGB(my_surface->format,
+							((t0 & 0x7C00) >> 7)
+								| ((t0 & 0x7000) >> 12),
+							((t0 & 0x03E0) >> 2)
+								| ((t0 & 0x0380) >> 7),
+							((t0 & 0x001F) << 3)
+								| ((t0 & 0x001C) >> 2));
+					}
+#elif 5 == vMacScreenDepth
+					p = the_data + ((i0 * vMacScreenWidth + j0) << 2);
+					pixel = SDL_MapRGB(my_surface->format,
+						p[1],
+						p[2],
+						p[3]);
+#endif
+				} else
+#endif
+				{
+					p = the_data + ((i0 * vMacScreenWidth + j0) / 8);
+					pixel = BWLUT_pixel[(*p >> ((~ j0) & 0x7)) & 1];
+				}
+
+				switch (bpp) {
+					case 1: /* Assuming 8-bpp */
+						*bufp = pixel;
+						break;
+					case 2: /* Probably 15-bpp or 16-bpp */
+						*(Uint16 *)bufp = pixel;
+						break;
+					case 3:
+						/* Slow 24-bpp mode, usually not used */
+						if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
+							bufp[0] = (pixel >> 16) & 0xff;
+							bufp[1] = (pixel >> 8) & 0xff;
+							bufp[2] = pixel & 0xff;
+						} else {
+							bufp[0] = pixel & 0xff;
+							bufp[1] = (pixel >> 8) & 0xff;
+							bufp[2] = (pixel >> 16) & 0xff;
+						}
+						break;
+					case 4: /* Probably 32-bpp */
+						*(Uint32 *)bufp = pixel;
+						break;
+				}
+			}
+		}
+	}
+
+	}
+
+	if (SDL_MUSTLOCK(my_surface)) {
+		SDL_UnlockSurface(my_surface);
+	}
+
+	SDL_UpdateRect(my_surface, left2, top2,
+		right2 - left2, bottom2 - top2);
+}
+
+LOCALPROC MyDrawChangesAndClear(void)
+{
+	if (ScreenChangedBottom > ScreenChangedTop) {
+		HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft,
+			ScreenChangedBottom, ScreenChangedRight);
+		ScreenClearChanges();
+	}
+}
+
+GLOBALOSGLUPROC DoneWithDrawingForTick(void)
+{
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		AutoScrollScreen();
+	}
+#endif
+	MyDrawChangesAndClear();
+}
+
+/* --- mouse --- */
+
+/* cursor hiding */
+
+LOCALVAR blnr HaveCursorHidden = falseblnr;
+LOCALVAR blnr WantCursorHidden = falseblnr;
+
+LOCALPROC ForceShowCursor(void)
+{
+	if (HaveCursorHidden) {
+		HaveCursorHidden = falseblnr;
+		(void) SDL_ShowCursor(SDL_ENABLE);
+	}
+}
+
+/* cursor moving */
+
+LOCALFUNC blnr MyMoveMouse(si4b h, si4b v)
+{
+#if EnableMagnify
+	if (UseMagnify) {
+		h *= MyWindowScale;
+		v *= MyWindowScale;
+	}
+#endif
+
+	SDL_WarpMouse(h, v);
+
+	return trueblnr;
+}
+
+/* cursor state */
+
+LOCALPROC MousePositionNotify(int NewMousePosh, int NewMousePosv)
+{
+	blnr ShouldHaveCursorHidden = trueblnr;
+
+#if EnableMagnify
+	if (UseMagnify) {
+		NewMousePosh /= MyWindowScale;
+		NewMousePosv /= MyWindowScale;
+	}
+#endif
+
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		MyMousePositionSetDelta(NewMousePosh - SavedMouseH,
+			NewMousePosv - SavedMouseV);
+		SavedMouseH = NewMousePosh;
+		SavedMouseV = NewMousePosv;
+	} else
+#endif
+	{
+		if (NewMousePosh < 0) {
+			NewMousePosh = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePosh >= vMacScreenWidth) {
+			NewMousePosh = vMacScreenWidth - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+		if (NewMousePosv < 0) {
+			NewMousePosv = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePosv >= vMacScreenHeight) {
+			NewMousePosv = vMacScreenHeight - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+
+#if VarFullScreen
+		if (UseFullScreen)
+#endif
+#if MayFullScreen
+		{
+			ShouldHaveCursorHidden = trueblnr;
+		}
+#endif
+
+		/* if (ShouldHaveCursorHidden || CurMouseButton) */
+		/*
+			for a game like arkanoid, would like mouse to still
+			move even when outside window in one direction
+		*/
+		MyMousePositionSet(NewMousePosh, NewMousePosv);
+	}
+
+	WantCursorHidden = ShouldHaveCursorHidden;
+}
+
+LOCALPROC CheckMouseState(void)
+{
+	/*
+		this doesn't work as desired, doesn't get mouse movements
+		when outside of our window.
+	*/
+	int x;
+	int y;
+
+	(void) SDL_GetMouseState(&x, &y);
+	MousePositionNotify(x, y);
+}
+
+/* --- keyboard input --- */
+
+LOCALFUNC ui3r SDLKey2MacKeyCode(SDLKey i)
+{
+	ui3r v = MKC_None;
+
+	switch (i) {
+		case SDLK_BACKSPACE: v = MKC_BackSpace; break;
+		case SDLK_TAB: v = MKC_Tab; break;
+		case SDLK_CLEAR: v = MKC_Clear; break;
+		case SDLK_RETURN: v = MKC_Return; break;
+		case SDLK_PAUSE: v = MKC_Pause; break;
+		case SDLK_ESCAPE: v = MKC_formac_Escape; break;
+		case SDLK_SPACE: v = MKC_Space; break;
+		case SDLK_EXCLAIM: /* ? */ break;
+		case SDLK_QUOTEDBL: /* ? */ break;
+		case SDLK_HASH: /* ? */ break;
+		case SDLK_DOLLAR: /* ? */ break;
+		case SDLK_AMPERSAND: /* ? */ break;
+		case SDLK_QUOTE: v = MKC_SingleQuote; break;
+		case SDLK_LEFTPAREN: /* ? */ break;
+		case SDLK_RIGHTPAREN: /* ? */ break;
+		case SDLK_ASTERISK: /* ? */ break;
+		case SDLK_PLUS: /* ? */ break;
+		case SDLK_COMMA: v = MKC_Comma; break;
+		case SDLK_MINUS: v = MKC_Minus; break;
+		case SDLK_PERIOD: v = MKC_Period; break;
+		case SDLK_SLASH: v = MKC_formac_Slash; break;
+		case SDLK_0: v = MKC_0; break;
+		case SDLK_1: v = MKC_1; break;
+		case SDLK_2: v = MKC_2; break;
+		case SDLK_3: v = MKC_3; break;
+		case SDLK_4: v = MKC_4; break;
+		case SDLK_5: v = MKC_5; break;
+		case SDLK_6: v = MKC_6; break;
+		case SDLK_7: v = MKC_7; break;
+		case SDLK_8: v = MKC_8; break;
+		case SDLK_9: v = MKC_9; break;
+		case SDLK_COLON: /* ? */ break;
+		case SDLK_SEMICOLON: v = MKC_SemiColon; break;
+		case SDLK_LESS: /* ? */ break;
+		case SDLK_EQUALS: v = MKC_Equal; break;
+		case SDLK_GREATER: /* ? */ break;
+		case SDLK_QUESTION: /* ? */ break;
+		case SDLK_AT: /* ? */ break;
+
+		case SDLK_LEFTBRACKET: v = MKC_LeftBracket; break;
+		case SDLK_BACKSLASH: v = MKC_formac_BackSlash; break;
+		case SDLK_RIGHTBRACKET: v = MKC_RightBracket; break;
+		case SDLK_CARET: /* ? */ break;
+		case SDLK_UNDERSCORE: /* ? */ break;
+		case SDLK_BACKQUOTE: v = MKC_formac_Grave; break;
+
+		case SDLK_a: v = MKC_A; break;
+		case SDLK_b: v = MKC_B; break;
+		case SDLK_c: v = MKC_C; break;
+		case SDLK_d: v = MKC_D; break;
+		case SDLK_e: v = MKC_E; break;
+		case SDLK_f: v = MKC_F; break;
+		case SDLK_g: v = MKC_G; break;
+		case SDLK_h: v = MKC_H; break;
+		case SDLK_i: v = MKC_I; break;
+		case SDLK_j: v = MKC_J; break;
+		case SDLK_k: v = MKC_K; break;
+		case SDLK_l: v = MKC_L; break;
+		case SDLK_m: v = MKC_M; break;
+		case SDLK_n: v = MKC_N; break;
+		case SDLK_o: v = MKC_O; break;
+		case SDLK_p: v = MKC_P; break;
+		case SDLK_q: v = MKC_Q; break;
+		case SDLK_r: v = MKC_R; break;
+		case SDLK_s: v = MKC_S; break;
+		case SDLK_t: v = MKC_T; break;
+		case SDLK_u: v = MKC_U; break;
+		case SDLK_v: v = MKC_V; break;
+		case SDLK_w: v = MKC_W; break;
+		case SDLK_x: v = MKC_X; break;
+		case SDLK_y: v = MKC_Y; break;
+		case SDLK_z: v = MKC_Z; break;
+
+		case SDLK_KP0: v = MKC_KP0; break;
+		case SDLK_KP1: v = MKC_KP1; break;
+		case SDLK_KP2: v = MKC_KP2; break;
+		case SDLK_KP3: v = MKC_KP3; break;
+		case SDLK_KP4: v = MKC_KP4; break;
+		case SDLK_KP5: v = MKC_KP5; break;
+		case SDLK_KP6: v = MKC_KP6; break;
+		case SDLK_KP7: v = MKC_KP7; break;
+		case SDLK_KP8: v = MKC_KP8; break;
+		case SDLK_KP9: v = MKC_KP9; break;
+
+		case SDLK_KP_PERIOD: v = MKC_Decimal; break;
+		case SDLK_KP_DIVIDE: v = MKC_KPDevide; break;
+		case SDLK_KP_MULTIPLY: v = MKC_KPMultiply; break;
+		case SDLK_KP_MINUS: v = MKC_KPSubtract; break;
+		case SDLK_KP_PLUS: v = MKC_KPAdd; break;
+		case SDLK_KP_ENTER: v = MKC_formac_Enter; break;
+		case SDLK_KP_EQUALS: v = MKC_KPEqual; break;
+
+		case SDLK_UP: v = MKC_Up; break;
+		case SDLK_DOWN: v = MKC_Down; break;
+		case SDLK_RIGHT: v = MKC_Right; break;
+		case SDLK_LEFT: v = MKC_Left; break;
+		case SDLK_INSERT: v = MKC_formac_Help; break;
+		case SDLK_HOME: v = MKC_formac_Home; break;
+		case SDLK_END: v = MKC_formac_End; break;
+		case SDLK_PAGEUP: v = MKC_formac_PageUp; break;
+		case SDLK_PAGEDOWN: v = MKC_formac_PageDown; break;
+
+		case SDLK_F1: v = MKC_formac_F1; break;
+		case SDLK_F2: v = MKC_formac_F2; break;
+		case SDLK_F3: v = MKC_formac_F3; break;
+		case SDLK_F4: v = MKC_formac_F4; break;
+		case SDLK_F5: v = MKC_formac_F5; break;
+		case SDLK_F6: v = MKC_F6; break;
+		case SDLK_F7: v = MKC_F7; break;
+		case SDLK_F8: v = MKC_F8; break;
+		case SDLK_F9: v = MKC_F9; break;
+		case SDLK_F10: v = MKC_F10; break;
+		case SDLK_F11: v = MKC_F11; break;
+		case SDLK_F12: v = MKC_F12; break;
+
+		case SDLK_F13: /* ? */ break;
+		case SDLK_F14: /* ? */ break;
+		case SDLK_F15: /* ? */ break;
+
+		case SDLK_NUMLOCK: v = MKC_formac_ForwardDel; break;
+		case SDLK_CAPSLOCK: v = MKC_formac_CapsLock; break;
+		case SDLK_SCROLLOCK: v = MKC_ScrollLock; break;
+		case SDLK_RSHIFT: v = MKC_formac_RShift; break;
+		case SDLK_LSHIFT: v = MKC_formac_Shift; break;
+		case SDLK_RCTRL: v = MKC_formac_RControl; break;
+		case SDLK_LCTRL: v = MKC_formac_Control; break;
+		case SDLK_RALT: v = MKC_formac_RCommand; break;
+		case SDLK_LALT: v = MKC_formac_Command; break;
+		case SDLK_RMETA: v = MKC_formac_RCommand; break;
+		case SDLK_LMETA: v = MKC_formac_Command; break;
+		case SDLK_LSUPER: v = MKC_formac_Option; break;
+		case SDLK_RSUPER: v = MKC_formac_ROption; break;
+
+		case SDLK_MODE: /* ? */ break;
+		case SDLK_COMPOSE: /* ? */ break;
+
+		case SDLK_HELP: v = MKC_formac_Help; break;
+		case SDLK_PRINT: v = MKC_Print; break;
+
+		case SDLK_SYSREQ: /* ? */ break;
+		case SDLK_BREAK: /* ? */ break;
+		case SDLK_MENU: /* ? */ break;
+		case SDLK_POWER: /* ? */ break;
+		case SDLK_EURO: /* ? */ break;
+		case SDLK_UNDO: /* ? */ break;
+
+		default:
+			break;
+	}
+
+	return v;
+}
+
+LOCALPROC DoKeyCode(SDL_keysym *r, blnr down)
+{
+	ui3r v = SDLKey2MacKeyCode(r->sym);
+	if (MKC_None != v) {
+		Keyboard_UpdateKeyMap2(v, down);
+	}
+}
+
+LOCALPROC DisableKeyRepeat(void)
+{
+}
+
+LOCALPROC RestoreKeyRepeat(void)
+{
+}
+
+LOCALPROC ReconnectKeyCodes3(void)
+{
+}
+
+LOCALPROC DisconnectKeyCodes3(void)
+{
+	DisconnectKeyCodes2();
+	MyMouseButtonSet(falseblnr);
+}
+
+/* --- time, date, location --- */
+
+#define dbglog_TimeStuff (0 && dbglog_HAVE)
+
+LOCALVAR ui5b TrueEmulatedTime = 0;
+
+#define MyInvTimeDivPow 16
+#define MyInvTimeDiv (1 << MyInvTimeDivPow)
+#define MyInvTimeDivMask (MyInvTimeDiv - 1)
+#define MyInvTimeStep 1089590 /* 1000 / 60.14742 * MyInvTimeDiv */
+
+LOCALVAR Uint32 LastTime;
+
+LOCALVAR Uint32 NextIntTime;
+LOCALVAR ui5b NextFracTime;
+
+LOCALPROC IncrNextTime(void)
+{
+	NextFracTime += MyInvTimeStep;
+	NextIntTime += (NextFracTime >> MyInvTimeDivPow);
+	NextFracTime &= MyInvTimeDivMask;
+}
+
+LOCALPROC InitNextTime(void)
+{
+	NextIntTime = LastTime;
+	NextFracTime = 0;
+	IncrNextTime();
+}
+
+LOCALVAR ui5b NewMacDateInSeconds;
+
+LOCALFUNC blnr UpdateTrueEmulatedTime(void)
+{
+	Uint32 LatestTime;
+	si5b TimeDiff;
+
+	LatestTime = SDL_GetTicks();
+	if (LatestTime != LastTime) {
+
+		NewMacDateInSeconds = LatestTime / 1000;
+			/* no date and time api in SDL */
+
+		LastTime = LatestTime;
+		TimeDiff = (LatestTime - NextIntTime);
+			/* this should work even when time wraps */
+		if (TimeDiff >= 0) {
+			if (TimeDiff > 256) {
+				/* emulation interrupted, forget it */
+				++TrueEmulatedTime;
+				InitNextTime();
+
+#if dbglog_TimeStuff
+				dbglog_writelnNum("emulation interrupted",
+					TrueEmulatedTime);
+#endif
+			} else {
+				do {
+					++TrueEmulatedTime;
+					IncrNextTime();
+					TimeDiff = (LatestTime - NextIntTime);
+				} while (TimeDiff >= 0);
+			}
+			return trueblnr;
+		} else {
+			if (TimeDiff < -256) {
+#if dbglog_TimeStuff
+				dbglog_writeln("clock set back");
+#endif
+				/* clock goofed if ever get here, reset */
+				InitNextTime();
+			}
+		}
+	}
+	return falseblnr;
+}
+
+
+LOCALFUNC blnr CheckDateTime(void)
+{
+	if (CurMacDateInSeconds != NewMacDateInSeconds) {
+		CurMacDateInSeconds = NewMacDateInSeconds;
+		return trueblnr;
+	} else {
+		return falseblnr;
+	}
+}
+
+LOCALPROC StartUpTimeAdjust(void)
+{
+	LastTime = SDL_GetTicks();
+	InitNextTime();
+}
+
+LOCALFUNC blnr InitLocationDat(void)
+{
+	LastTime = SDL_GetTicks();
+	InitNextTime();
+	NewMacDateInSeconds = LastTime / 1000;
+	CurMacDateInSeconds = NewMacDateInSeconds;
+
+	return trueblnr;
+}
+
+/* --- sound --- */
+
+#if MySoundEnabled
+
+#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */
+#define kSoundBuffers (1 << kLn2SoundBuffers)
+#define kSoundBuffMask (kSoundBuffers - 1)
+
+#define DesiredMinFilledSoundBuffs 3
+	/*
+		if too big then sound lags behind emulation.
+		if too small then sound will have pauses.
+	*/
+
+#define kLnOneBuffLen 9
+#define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen)
+#define kOneBuffLen (1UL << kLnOneBuffLen)
+#define kAllBuffLen (1UL << kLnAllBuffLen)
+#define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3)
+#define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3)
+#define kOneBuffSz (1UL << kLnOneBuffSz)
+#define kAllBuffSz (1UL << kLnAllBuffSz)
+#define kOneBuffMask (kOneBuffLen - 1)
+#define kAllBuffMask (kAllBuffLen - 1)
+#define dbhBufferSize (kAllBuffSz + kOneBuffSz)
+
+#define dbglog_SoundStuff (0 && dbglog_HAVE)
+#define dbglog_SoundBuffStats (0 && dbglog_HAVE)
+
+LOCALVAR tpSoundSamp TheSoundBuffer = nullpr;
+volatile static ui4b ThePlayOffset;
+volatile static ui4b TheFillOffset;
+volatile static ui4b MinFilledSoundBuffs;
+#if dbglog_SoundBuffStats
+LOCALVAR ui4b MaxFilledSoundBuffs;
+#endif
+LOCALVAR ui4b TheWriteOffset;
+
+LOCALPROC MySound_Init0(void)
+{
+	ThePlayOffset = 0;
+	TheFillOffset = 0;
+	TheWriteOffset = 0;
+}
+
+LOCALPROC MySound_Start0(void)
+{
+	/* Reset variables */
+	MinFilledSoundBuffs = kSoundBuffers + 1;
+#if dbglog_SoundBuffStats
+	MaxFilledSoundBuffs = 0;
+#endif
+}
+
+GLOBALOSGLUFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL)
+{
+	ui4b ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset);
+	ui4b WriteBuffContig =
+		kOneBuffLen - (TheWriteOffset & kOneBuffMask);
+
+	if (WriteBuffContig < n) {
+		n = WriteBuffContig;
+	}
+	if (ToFillLen < n) {
+		/* overwrite previous buffer */
+#if dbglog_SoundStuff
+		dbglog_writeln("sound buffer over flow");
+#endif
+		TheWriteOffset -= kOneBuffLen;
+	}
+
+	*actL = n;
+	return TheSoundBuffer + (TheWriteOffset & kAllBuffMask);
+}
+
+#if 4 == kLn2SoundSampSz
+LOCALPROC ConvertSoundBlockToNative(tpSoundSamp p)
+{
+	int i;
+
+	for (i = kOneBuffLen; --i >= 0; ) {
+		*p++ -= 0x8000;
+	}
+}
+#else
+#define ConvertSoundBlockToNative(p)
+#endif
+
+LOCALPROC MySound_WroteABlock(void)
+{
+#if (4 == kLn2SoundSampSz)
+	ui4b PrevWriteOffset = TheWriteOffset - kOneBuffLen;
+	tpSoundSamp p = TheSoundBuffer + (PrevWriteOffset & kAllBuffMask);
+#endif
+
+#if dbglog_SoundStuff
+	dbglog_writeln("enter MySound_WroteABlock");
+#endif
+
+	ConvertSoundBlockToNative(p);
+
+	TheFillOffset = TheWriteOffset;
+
+#if dbglog_SoundBuffStats
+	{
+		ui4b ToPlayLen = TheFillOffset
+			- ThePlayOffset;
+		ui4b ToPlayBuffs = ToPlayLen >> kLnOneBuffLen;
+
+		if (ToPlayBuffs > MaxFilledSoundBuffs) {
+			MaxFilledSoundBuffs = ToPlayBuffs;
+		}
+	}
+#endif
+}
+
+LOCALFUNC blnr MySound_EndWrite0(ui4r actL)
+{
+	blnr v;
+
+	TheWriteOffset += actL;
+
+	if (0 != (TheWriteOffset & kOneBuffMask)) {
+		v = falseblnr;
+	} else {
+		/* just finished a block */
+
+		MySound_WroteABlock();
+
+		v = trueblnr;
+	}
+
+	return v;
+}
+
+LOCALPROC MySound_SecondNotify0(void)
+{
+	if (MinFilledSoundBuffs <= kSoundBuffers) {
+		if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) {
+#if dbglog_SoundStuff
+			dbglog_writeln("MinFilledSoundBuffs too high");
+#endif
+			IncrNextTime();
+		} else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) {
+#if dbglog_SoundStuff
+			dbglog_writeln("MinFilledSoundBuffs too low");
+#endif
+			++TrueEmulatedTime;
+		}
+#if dbglog_SoundBuffStats
+		dbglog_writelnNum("MinFilledSoundBuffs",
+			MinFilledSoundBuffs);
+		dbglog_writelnNum("MaxFilledSoundBuffs",
+			MaxFilledSoundBuffs);
+		MaxFilledSoundBuffs = 0;
+#endif
+		MinFilledSoundBuffs = kSoundBuffers + 1;
+	}
+}
+
+typedef ui4r trSoundTemp;
+
+#define kCenterTempSound 0x8000
+
+#define AudioStepVal 0x0040
+
+#if 3 == kLn2SoundSampSz
+#define ConvertTempSoundSampleFromNative(v) ((v) << 8)
+#elif 4 == kLn2SoundSampSz
+#define ConvertTempSoundSampleFromNative(v) ((v) + kCenterSound)
+#else
+#error "unsupported kLn2SoundSampSz"
+#endif
+
+#if 3 == kLn2SoundSampSz
+#define ConvertTempSoundSampleToNative(v) ((v) >> 8)
+#elif 4 == kLn2SoundSampSz
+#define ConvertTempSoundSampleToNative(v) ((v) - kCenterSound)
+#else
+#error "unsupported kLn2SoundSampSz"
+#endif
+
+LOCALPROC SoundRampTo(trSoundTemp *last_val, trSoundTemp dst_val,
+	tpSoundSamp *stream, int *len)
+{
+	trSoundTemp diff;
+	tpSoundSamp p = *stream;
+	int n = *len;
+	trSoundTemp v1 = *last_val;
+
+	while ((v1 != dst_val) && (0 != n)) {
+		if (v1 > dst_val) {
+			diff = v1 - dst_val;
+			if (diff > AudioStepVal) {
+				v1 -= AudioStepVal;
+			} else {
+				v1 = dst_val;
+			}
+		} else {
+			diff = dst_val - v1;
+			if (diff > AudioStepVal) {
+				v1 += AudioStepVal;
+			} else {
+				v1 = dst_val;
+			}
+		}
+
+		--n;
+		*p++ = ConvertTempSoundSampleToNative(v1);
+	}
+
+	*stream = p;
+	*len = n;
+	*last_val = v1;
+}
+
+struct MySoundR {
+	tpSoundSamp fTheSoundBuffer;
+	volatile ui4b (*fPlayOffset);
+	volatile ui4b (*fFillOffset);
+	volatile ui4b (*fMinFilledSoundBuffs);
+
+	volatile trSoundTemp lastv;
+
+	blnr wantplaying;
+	blnr HaveStartedPlaying;
+};
+typedef struct MySoundR MySoundR;
+
+static void my_audio_callback(void *udata, Uint8 *stream, int len)
+{
+	ui4b ToPlayLen;
+	ui4b FilledSoundBuffs;
+	int i;
+	MySoundR *datp = (MySoundR *)udata;
+	tpSoundSamp CurSoundBuffer = datp->fTheSoundBuffer;
+	ui4b CurPlayOffset = *datp->fPlayOffset;
+	trSoundTemp v0 = datp->lastv;
+	trSoundTemp v1 = v0;
+	tpSoundSamp dst = (tpSoundSamp)stream;
+
+#if kLn2SoundSampSz > 3
+	len >>= (kLn2SoundSampSz - 3);
+#endif
+
+#if dbglog_SoundStuff
+	dbglog_writeln("Enter my_audio_callback");
+	dbglog_writelnNum("len", len);
+#endif
+
+label_retry:
+	ToPlayLen = *datp->fFillOffset - CurPlayOffset;
+	FilledSoundBuffs = ToPlayLen >> kLnOneBuffLen;
+
+	if (! datp->wantplaying) {
+#if dbglog_SoundStuff
+		dbglog_writeln("playing end transistion");
+#endif
+
+		SoundRampTo(&v1, kCenterTempSound, &dst, &len);
+
+		ToPlayLen = 0;
+	} else if (! datp->HaveStartedPlaying) {
+#if dbglog_SoundStuff
+		dbglog_writeln("playing start block");
+#endif
+
+		if ((ToPlayLen >> kLnOneBuffLen) < 8) {
+			ToPlayLen = 0;
+		} else {
+			tpSoundSamp p = datp->fTheSoundBuffer
+				+ (CurPlayOffset & kAllBuffMask);
+			trSoundTemp v2 = ConvertTempSoundSampleFromNative(*p);
+
+#if dbglog_SoundStuff
+			dbglog_writeln("have enough samples to start");
+#endif
+
+			SoundRampTo(&v1, v2, &dst, &len);
+
+			if (v1 == v2) {
+#if dbglog_SoundStuff
+				dbglog_writeln("finished start transition");
+#endif
+
+				datp->HaveStartedPlaying = trueblnr;
+			}
+		}
+	}
+
+	if (0 == len) {
+		/* done */
+
+		if (FilledSoundBuffs < *datp->fMinFilledSoundBuffs) {
+			*datp->fMinFilledSoundBuffs = FilledSoundBuffs;
+		}
+	} else if (0 == ToPlayLen) {
+
+#if dbglog_SoundStuff
+		dbglog_writeln("under run");
+#endif
+
+		for (i = 0; i < len; ++i) {
+			*dst++ = ConvertTempSoundSampleToNative(v1);
+		}
+		*datp->fMinFilledSoundBuffs = 0;
+	} else {
+		ui4b PlayBuffContig = kAllBuffLen
+			- (CurPlayOffset & kAllBuffMask);
+		tpSoundSamp p = CurSoundBuffer
+			+ (CurPlayOffset & kAllBuffMask);
+
+		if (ToPlayLen > PlayBuffContig) {
+			ToPlayLen = PlayBuffContig;
+		}
+		if (ToPlayLen > len) {
+			ToPlayLen = len;
+		}
+
+		for (i = 0; i < ToPlayLen; ++i) {
+			*dst++ = *p++;
+		}
+		v1 = ConvertTempSoundSampleFromNative(p[-1]);
+
+		CurPlayOffset += ToPlayLen;
+		len -= ToPlayLen;
+
+		*datp->fPlayOffset = CurPlayOffset;
+
+		goto label_retry;
+	}
+
+	datp->lastv = v1;
+}
+
+LOCALVAR MySoundR cur_audio;
+
+LOCALVAR blnr HaveSoundOut = falseblnr;
+
+LOCALPROC MySound_Stop(void)
+{
+#if dbglog_SoundStuff
+	dbglog_writeln("enter MySound_Stop");
+#endif
+
+	if (cur_audio.wantplaying && HaveSoundOut) {
+		ui4r retry_limit = 50; /* half of a second */
+
+		cur_audio.wantplaying = falseblnr;
+
+label_retry:
+		if (kCenterTempSound == cur_audio.lastv) {
+#if dbglog_SoundStuff
+			dbglog_writeln("reached kCenterTempSound");
+#endif
+
+			/* done */
+		} else if (0 == --retry_limit) {
+#if dbglog_SoundStuff
+			dbglog_writeln("retry limit reached");
+#endif
+			/* done */
+		} else
+		{
+			/*
+				give time back, particularly important
+				if got here on a suspend event.
+			*/
+
+#if dbglog_SoundStuff
+			dbglog_writeln("busy, so sleep");
+#endif
+
+			(void) SDL_Delay(10);
+
+			goto label_retry;
+		}
+
+		SDL_PauseAudio(1);
+	}
+
+#if dbglog_SoundStuff
+	dbglog_writeln("leave MySound_Stop");
+#endif
+}
+
+LOCALPROC MySound_Start(void)
+{
+	if ((! cur_audio.wantplaying) && HaveSoundOut) {
+		MySound_Start0();
+		cur_audio.lastv = kCenterTempSound;
+		cur_audio.HaveStartedPlaying = falseblnr;
+		cur_audio.wantplaying = trueblnr;
+
+		SDL_PauseAudio(0);
+	}
+}
+
+LOCALPROC MySound_UnInit(void)
+{
+	if (HaveSoundOut) {
+		SDL_CloseAudio();
+	}
+}
+
+#define SOUND_SAMPLERATE 22255 /* = round(7833600 * 2 / 704) */
+
+LOCALFUNC blnr MySound_Init(void)
+{
+	SDL_AudioSpec desired;
+
+	MySound_Init0();
+
+	cur_audio.fTheSoundBuffer = TheSoundBuffer;
+	cur_audio.fPlayOffset = &ThePlayOffset;
+	cur_audio.fFillOffset = &TheFillOffset;
+	cur_audio.fMinFilledSoundBuffs = &MinFilledSoundBuffs;
+	cur_audio.wantplaying = falseblnr;
+
+	desired.freq = SOUND_SAMPLERATE;
+
+#if 3 == kLn2SoundSampSz
+	desired.format = AUDIO_U8;
+#elif 4 == kLn2SoundSampSz
+	desired.format = AUDIO_S16SYS;
+#else
+#error "unsupported audio format"
+#endif
+
+	desired.channels = 1;
+	desired.samples = 1024;
+	desired.callback = my_audio_callback;
+	desired.userdata = (void *)&cur_audio;
+
+	/* Open the audio device */
+	if (SDL_OpenAudio(&desired, NULL) < 0) {
+		fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
+	} else {
+		HaveSoundOut = trueblnr;
+
+		MySound_Start();
+			/*
+				This should be taken care of by LeaveSpeedStopped,
+				but since takes a while to get going properly,
+				start early.
+			*/
+	}
+
+	return trueblnr; /* keep going, even if no sound */
+}
+
+GLOBALOSGLUPROC MySound_EndWrite(ui4r actL)
+{
+	if (MySound_EndWrite0(actL)) {
+	}
+}
+
+LOCALPROC MySound_SecondNotify(void)
+{
+	if (HaveSoundOut) {
+		MySound_SecondNotify0();
+	}
+}
+
+#endif
+
+/* --- basic dialogs --- */
+
+LOCALPROC CheckSavedMacMsg(void)
+{
+	/* called only on quit, if error saved but not yet reported */
+
+	if (nullpr != SavedBriefMsg) {
+		char briefMsg0[ClStrMaxLength + 1];
+		char longMsg0[ClStrMaxLength + 1];
+
+		NativeStrFromCStr(briefMsg0, SavedBriefMsg);
+		NativeStrFromCStr(longMsg0, SavedLongMsg);
+
+		fprintf(stderr, "%s\n", briefMsg0);
+		fprintf(stderr, "%s\n", longMsg0);
+
+		SavedBriefMsg = nullpr;
+	}
+}
+
+/* --- clipboard --- */
+
+#define UseMotionEvents 1
+
+#if UseMotionEvents
+LOCALVAR blnr CaughtMouse = falseblnr;
+#endif
+
+/* --- event handling for main window --- */
+
+LOCALPROC HandleTheEvent(SDL_Event *event)
+{
+	switch (event->type) {
+		case SDL_QUIT:
+			RequestMacOff = trueblnr;
+			break;
+		case SDL_ACTIVEEVENT:
+			switch (event->active.state) {
+				case SDL_APPINPUTFOCUS:
+					gTrueBackgroundFlag = (0 == event->active.gain);
+#if 0 && UseMotionEvents
+					if (! gTrueBackgroundFlag) {
+						CheckMouseState();
+					}
+#endif
+					break;
+				case SDL_APPMOUSEFOCUS:
+					CaughtMouse = (0 != event->active.gain);
+					break;
+			}
+			break;
+		case SDL_MOUSEMOTION:
+			MousePositionNotify(
+				event->motion.x, event->motion.y);
+			break;
+		case SDL_MOUSEBUTTONDOWN:
+			/* any mouse button, we don't care which */
+			MousePositionNotify(
+				event->button.x, event->button.y);
+			MyMouseButtonSet(trueblnr);
+			break;
+		case SDL_MOUSEBUTTONUP:
+			MousePositionNotify(
+				event->button.x, event->button.y);
+			MyMouseButtonSet(falseblnr);
+			break;
+		case SDL_KEYDOWN:
+			DoKeyCode(&event->key.keysym, trueblnr);
+			break;
+		case SDL_KEYUP:
+			DoKeyCode(&event->key.keysym, falseblnr);
+			break;
+#if 0
+		case Expose: /* SDL doesn't have an expose event */
+			int x0 = event->expose.x;
+			int y0 = event->expose.y;
+			int x1 = x0 + event->expose.width;
+			int y1 = y0 + event->expose.height;
+
+			if (x0 < 0) {
+				x0 = 0;
+			}
+			if (x1 > vMacScreenWidth) {
+				x1 = vMacScreenWidth;
+			}
+			if (y0 < 0) {
+				y0 = 0;
+			}
+			if (y1 > vMacScreenHeight) {
+				y1 = vMacScreenHeight;
+			}
+			if ((x0 < x1) && (y0 < y1)) {
+				HaveChangedScreenBuff(y0, x0, y1, x1);
+			}
+			break;
+#endif
+	}
+}
+
+/* --- main window creation and disposal --- */
+
+LOCALVAR int my_argc;
+LOCALVAR char **my_argv;
+
+LOCALFUNC blnr Screen_Init(void)
+{
+	blnr v = falseblnr;
+
+	InitKeyCodes();
+
+	if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
+	{
+		fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
+	} else {
+		SDL_WM_SetCaption(kStrAppName, NULL);
+		v = trueblnr;
+	}
+
+	return v;
+}
+
+#if MayFullScreen
+LOCALVAR blnr GrabMachine = falseblnr;
+#endif
+
+#if MayFullScreen
+LOCALPROC GrabTheMachine(void)
+{
+#if GrabKeysFullScreen
+	(void) SDL_WM_GrabInput(SDL_GRAB_ON);
+#endif
+
+#if EnableFSMouseMotion
+	/*
+		if magnification changes, need to reset,
+		even if HaveMouseMotion already true
+	*/
+	if (MyMoveMouse(ViewHStart + (ViewHSize / 2),
+		ViewVStart + (ViewVSize / 2)))
+	{
+		SavedMouseH = ViewHStart + (ViewHSize / 2);
+		SavedMouseV = ViewVStart + (ViewVSize / 2);
+		HaveMouseMotion = trueblnr;
+	}
+#endif
+}
+#endif
+
+#if MayFullScreen
+LOCALPROC UngrabMachine(void)
+{
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		(void) MyMoveMouse(CurMouseH, CurMouseV);
+		HaveMouseMotion = falseblnr;
+	}
+#endif
+
+#if GrabKeysFullScreen
+	(void) SDL_WM_GrabInput(SDL_GRAB_OFF);
+#endif
+}
+#endif
+
+#if EnableFSMouseMotion
+LOCALPROC MyMouseConstrain(void)
+{
+	si4b shiftdh;
+	si4b shiftdv;
+
+	if (SavedMouseH < ViewHStart + (ViewHSize / 4)) {
+		shiftdh = ViewHSize / 2;
+	} else if (SavedMouseH > ViewHStart + ViewHSize - (ViewHSize / 4)) {
+		shiftdh = - ViewHSize / 2;
+	} else {
+		shiftdh = 0;
+	}
+	if (SavedMouseV < ViewVStart + (ViewVSize / 4)) {
+		shiftdv = ViewVSize / 2;
+	} else if (SavedMouseV > ViewVStart + ViewVSize - (ViewVSize / 4)) {
+		shiftdv = - ViewVSize / 2;
+	} else {
+		shiftdv = 0;
+	}
+	if ((shiftdh != 0) || (shiftdv != 0)) {
+		SavedMouseH += shiftdh;
+		SavedMouseV += shiftdv;
+		if (! MyMoveMouse(SavedMouseH, SavedMouseV)) {
+			HaveMouseMotion = falseblnr;
+		}
+	}
+}
+#endif
+
+LOCALFUNC blnr CreateMainWindow(void)
+{
+	int NewWindowHeight = vMacScreenHeight;
+	int NewWindowWidth = vMacScreenWidth;
+	Uint32 flags = SDL_SWSURFACE;
+	blnr v = falseblnr;
+
+#if EnableMagnify && 1
+	if (UseMagnify) {
+		NewWindowHeight *= MyWindowScale;
+		NewWindowWidth *= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		flags |= SDL_FULLSCREEN;
+	}
+#endif
+
+	ViewHStart = 0;
+	ViewVStart = 0;
+	ViewHSize = vMacScreenWidth;
+	ViewVSize = vMacScreenHeight;
+
+	my_surface = SDL_SetVideoMode(NewWindowWidth, NewWindowHeight,
+#if 0 != vMacScreenDepth
+		32,
+#else
+		/* 32 */ /* 24 */ /* 16 */ 8,
+#endif
+		flags);
+	if (NULL == my_surface) {
+		fprintf(stderr, "SDL_SetVideoMode fails: %s\n",
+			SDL_GetError());
+	} else {
+#if 0 != vMacScreenDepth
+		ColorModeWorks = trueblnr;
+#endif
+		v = trueblnr;
+	}
+
+	return v;
+}
+
+#if EnableRecreateW
+LOCALFUNC blnr ReCreateMainWindow(void)
+{
+	ForceShowCursor(); /* hide/show cursor api is per window */
+
+#if MayFullScreen
+	if (GrabMachine) {
+		GrabMachine = falseblnr;
+		UngrabMachine();
+	}
+#endif
+
+#if EnableMagnify
+	UseMagnify = WantMagnify;
+#endif
+#if VarFullScreen
+	UseFullScreen = WantFullScreen;
+#endif
+
+	(void) CreateMainWindow();
+
+	if (HaveCursorHidden) {
+		(void) MyMoveMouse(CurMouseH, CurMouseV);
+	}
+
+	return trueblnr;
+}
+#endif
+
+LOCALPROC ZapWinStateVars(void)
+{
+}
+
+#if VarFullScreen
+LOCALPROC ToggleWantFullScreen(void)
+{
+	WantFullScreen = ! WantFullScreen;
+}
+#endif
+
+/* --- SavedTasks --- */
+
+LOCALPROC LeaveBackground(void)
+{
+	ReconnectKeyCodes3();
+	DisableKeyRepeat();
+}
+
+LOCALPROC EnterBackground(void)
+{
+	RestoreKeyRepeat();
+	DisconnectKeyCodes3();
+
+	ForceShowCursor();
+}
+
+LOCALPROC LeaveSpeedStopped(void)
+{
+#if MySoundEnabled
+	MySound_Start();
+#endif
+
+	StartUpTimeAdjust();
+}
+
+LOCALPROC EnterSpeedStopped(void)
+{
+#if MySoundEnabled
+	MySound_Stop();
+#endif
+}
+
+LOCALPROC CheckForSavedTasks(void)
+{
+	if (MyEvtQNeedRecover) {
+		MyEvtQNeedRecover = falseblnr;
+
+		/* attempt cleanup, MyEvtQNeedRecover may get set again */
+		MyEvtQTryRecoverFromFull();
+	}
+
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		MyMouseConstrain();
+	}
+#endif
+
+	if (RequestMacOff) {
+		RequestMacOff = falseblnr;
+		if (AnyDiskInserted()) {
+			MacMsgOverride(kStrQuitWarningTitle,
+				kStrQuitWarningMessage);
+		} else {
+			ForceMacOff = trueblnr;
+		}
+	}
+
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (gTrueBackgroundFlag != gBackgroundFlag) {
+		gBackgroundFlag = gTrueBackgroundFlag;
+		if (gTrueBackgroundFlag) {
+			EnterBackground();
+		} else {
+			LeaveBackground();
+		}
+	}
+
+	if (CurSpeedStopped != (SpeedStopped ||
+		(gBackgroundFlag && ! RunInBackground
+#if EnableAutoSlow && 0
+			&& (QuietSubTicks >= 4092)
+#endif
+		)))
+	{
+		CurSpeedStopped = ! CurSpeedStopped;
+		if (CurSpeedStopped) {
+			EnterSpeedStopped();
+		} else {
+			LeaveSpeedStopped();
+		}
+	}
+
+	if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
+		MacMsgDisplayOn();
+	}
+
+#if EnableRecreateW
+	if (0
+#if EnableMagnify
+		|| (UseMagnify != WantMagnify)
+#endif
+#if VarFullScreen
+		|| (UseFullScreen != WantFullScreen)
+#endif
+		)
+	{
+		(void) ReCreateMainWindow();
+	}
+#endif
+
+#if MayFullScreen
+	if (GrabMachine != (
+#if VarFullScreen
+		UseFullScreen &&
+#endif
+		! (gTrueBackgroundFlag || CurSpeedStopped)))
+	{
+		GrabMachine = ! GrabMachine;
+		if (GrabMachine) {
+			GrabTheMachine();
+		} else {
+			UngrabMachine();
+		}
+	}
+#endif
+
+	if (NeedWholeScreenDraw) {
+		NeedWholeScreenDraw = falseblnr;
+		ScreenChangedAll();
+	}
+
+#if NeedRequestIthDisk
+	if (0 != RequestIthDisk) {
+		Sony_InsertIth(RequestIthDisk);
+		RequestIthDisk = 0;
+	}
+#endif
+
+	if (HaveCursorHidden != (WantCursorHidden
+		&& ! (gTrueBackgroundFlag || CurSpeedStopped)))
+	{
+		HaveCursorHidden = ! HaveCursorHidden;
+		(void) SDL_ShowCursor(
+			HaveCursorHidden ? SDL_DISABLE : SDL_ENABLE);
+	}
+}
+
+/* --- command line parsing --- */
+
+LOCALFUNC blnr ScanCommandLine(void)
+{
+	char *pa;
+	int i = 1;
+
+label_retry:
+	if (i < my_argc) {
+		pa = my_argv[i++];
+		if ('-' == pa[0]) {
+			if ((0 == strcmp(pa, "--rom"))
+				|| (0 == strcmp(pa, "-r")))
+			{
+				if (i < my_argc) {
+					rom_path = my_argv[i++];
+					goto label_retry;
+				}
+			} else
+			{
+				MacMsg(kStrBadArgTitle, kStrBadArgMessage, falseblnr);
+			}
+		} else {
+			(void) Sony_Insert1(pa, falseblnr);
+			goto label_retry;
+		}
+	}
+
+	return trueblnr;
+}
+
+/* --- main program flow --- */
+
+GLOBALOSGLUFUNC blnr ExtraTimeNotOver(void)
+{
+	UpdateTrueEmulatedTime();
+	return TrueEmulatedTime == OnTrueTime;
+}
+
+LOCALPROC WaitForTheNextEvent(void)
+{
+	SDL_Event event;
+
+	if (SDL_WaitEvent(&event)) {
+		HandleTheEvent(&event);
+	}
+}
+
+LOCALPROC CheckForSystemEvents(void)
+{
+	SDL_Event event;
+	int i = 10;
+
+	while ((--i >= 0) && SDL_PollEvent(&event)) {
+		HandleTheEvent(&event);
+	}
+}
+
+GLOBALOSGLUPROC WaitForNextTick(void)
+{
+label_retry:
+	CheckForSystemEvents();
+	CheckForSavedTasks();
+
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (CurSpeedStopped) {
+		DoneWithDrawingForTick();
+		WaitForTheNextEvent();
+		goto label_retry;
+	}
+
+	if (ExtraTimeNotOver()) {
+		(void) SDL_Delay(NextIntTime - LastTime);
+		goto label_retry;
+	}
+
+	if (CheckDateTime()) {
+#if MySoundEnabled
+		MySound_SecondNotify();
+#endif
+#if EnableDemoMsg
+		DemoModeSecondNotify();
+#endif
+	}
+
+	if ((! gBackgroundFlag)
+#if UseMotionEvents
+		&& (! CaughtMouse)
+#endif
+		)
+	{
+		CheckMouseState();
+	}
+
+	OnTrueTime = TrueEmulatedTime;
+
+#if dbglog_TimeStuff
+	dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime);
+#endif
+}
+
+/* --- platform independent code can be thought of as going here --- */
+
+#include "PROGMAIN.h"
+
+LOCALPROC ZapOSGLUVars(void)
+{
+	InitDrives();
+	ZapWinStateVars();
+}
+
+LOCALPROC ReserveAllocAll(void)
+{
+#if dbglog_HAVE
+	dbglog_ReserveAlloc();
+#endif
+	ReserveAllocOneBlock(&ROM, kROM_Size, 5, falseblnr);
+
+	ReserveAllocOneBlock(&screencomparebuff,
+		vMacScreenNumBytes, 5, trueblnr);
+#if UseControlKeys
+	ReserveAllocOneBlock(&CntrlDisplayBuff,
+		vMacScreenNumBytes, 5, falseblnr);
+#endif
+
+	ReserveAllocOneBlock(&CLUT_final, CLUT_finalsz, 5, falseblnr);
+#if MySoundEnabled
+	ReserveAllocOneBlock((ui3p *)&TheSoundBuffer,
+		dbhBufferSize, 5, falseblnr);
+#endif
+
+	EmulationReserveAlloc();
+}
+
+LOCALFUNC blnr AllocMyMemory(void)
+{
+	uimr n;
+	blnr IsOk = falseblnr;
+
+	ReserveAllocOffset = 0;
+	ReserveAllocBigBlock = nullpr;
+	ReserveAllocAll();
+	n = ReserveAllocOffset;
+	ReserveAllocBigBlock = (ui3p)calloc(1, n);
+	if (NULL == ReserveAllocBigBlock) {
+		MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr);
+	} else {
+		ReserveAllocOffset = 0;
+		ReserveAllocAll();
+		if (n != ReserveAllocOffset) {
+			/* oops, program error */
+		} else {
+			IsOk = trueblnr;
+		}
+	}
+
+	return IsOk;
+}
+
+LOCALPROC UnallocMyMemory(void)
+{
+	if (nullpr != ReserveAllocBigBlock) {
+		free((char *)ReserveAllocBigBlock);
+	}
+}
+
+LOCALFUNC blnr InitOSGLU(void)
+{
+	if (AllocMyMemory())
+#if dbglog_HAVE
+	if (dbglog_open())
+#endif
+	if (ScanCommandLine())
+	if (LoadMacRom())
+	if (LoadInitialImages())
+	if (InitLocationDat())
+#if MySoundEnabled
+	if (MySound_Init())
+#endif
+	if (Screen_Init())
+	if (CreateMainWindow())
+	if (WaitForRom())
+	{
+		return trueblnr;
+	}
+	return falseblnr;
+}
+
+LOCALPROC UnInitOSGLU(void)
+{
+	if (MacMsgDisplayed) {
+		MacMsgDisplayOff();
+	}
+
+	RestoreKeyRepeat();
+#if MayFullScreen
+	UngrabMachine();
+#endif
+#if MySoundEnabled
+	MySound_Stop();
+#endif
+#if MySoundEnabled
+	MySound_UnInit();
+#endif
+#if IncludePbufs
+	UnInitPbufs();
+#endif
+	UnInitDrives();
+
+	ForceShowCursor();
+
+#if dbglog_HAVE
+	dbglog_close();
+#endif
+
+	UnallocMyMemory();
+
+	CheckSavedMacMsg();
+
+	SDL_Quit();
+}
+
+int main(int argc, char **argv)
+{
+	my_argc = argc;
+	my_argv = argv;
+
+	ZapOSGLUVars();
+	if (InitOSGLU()) {
+		ProgramMain();
+	}
+	UnInitOSGLU();
+
+	return 0;
+}
--- /dev/null
+++ b/src/OSGLUWIN.c
@@ -1,0 +1,6216 @@
+/*
+	OSGLUWIN.c
+
+	Copyright (C) 2009 Philip Cummins, Weston Pawlowski,
+	Bradford L. Barrett, Paul C. Pratt, Fabio Concas
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Operating System GLUe for microsoft WINdows
+
+	All operating system dependent code for the
+	Microsoft Windows platform should go here.
+
+	This code is descended from Weston Pawlowski's Windows
+	port of vMac, by Philip Cummins.
+	Adapted by Fabio Concas to run on Pocket PC 2003 devices.
+
+	The main entry point '_tWinMain' is at the end of this file.
+*/
+
+#include "CNFGRAPI.h"
+#include "SYSDEPNS.h"
+#include "ENDIANAC.h"
+
+#include "MYOSGLUE.h"
+
+
+/* --- adapting to API/ABI version differences --- */
+
+#ifdef UNICODE
+#define MyUseUni 1
+#else
+#define MyUseUni 0
+#endif
+
+#ifdef _WIN32_WCE
+#define UseWinCE 1
+#else
+#define UseWinCE 0
+#endif
+
+
+#define My_CSIDL_APPDATA 0x001a
+
+typedef BOOL (WINAPI *SHGetSpecialFolderPathProcPtr) (
+	HWND hwndOwner,
+	LPTSTR lpszPath,
+	int nFolder,
+	BOOL fCreate
+);
+LOCALVAR SHGetSpecialFolderPathProcPtr MySHGetSpecialFolderPath = NULL;
+LOCALVAR blnr DidSHGetSpecialFolderPath = falseblnr;
+
+LOCALFUNC blnr HaveMySHGetSpecialFolderPath(void)
+{
+	if (! DidSHGetSpecialFolderPath) {
+		HMODULE hLibModule = LoadLibrary(TEXT("shell32.dll"));
+		if (NULL != hLibModule) {
+			MySHGetSpecialFolderPath =
+				(SHGetSpecialFolderPathProcPtr)
+				GetProcAddress(hLibModule,
+#if MyUseUni
+					TEXT("SHGetSpecialFolderPathW")
+#else
+					TEXT("SHGetSpecialFolderPathA")
+#endif
+				);
+			/* FreeLibrary(hLibModule); */
+		}
+		DidSHGetSpecialFolderPath = trueblnr;
+	}
+	return (MySHGetSpecialFolderPath != NULL);
+}
+
+
+/* --- end of adapting to API/ABI version differences --- */
+
+#include "STRCONST.h"
+
+#if MyUseUni
+#define NeedCell2UnicodeMap 1
+#else
+#define NeedCell2WinAsciiMap 1
+#endif
+
+#include "INTLCHAR.h"
+
+
+LOCALPROC NativeStrFromCStr(LPTSTR r, char *s, blnr AddEllipsis)
+{
+	ui3b ps[ClStrMaxLength];
+	int i;
+	int L;
+
+	ClStrFromSubstCStr(&L, ps, s);
+
+	for (i = 0; i < L; ++i) {
+		r[i] = (TCHAR)
+#if MyUseUni
+			Cell2UnicodeMap[ps[i]];
+#else
+			Cell2WinAsciiMap[ps[i]];
+#endif
+	}
+
+	if (AddEllipsis) {
+#if MyUseUni
+		r[L] = 0x2026;
+		++L;
+#else
+		r[L] = '.';
+		++L;
+		r[L] = '.';
+		++L;
+		r[L] = '.';
+		++L;
+#endif
+	}
+
+	r[L] = 0;
+}
+
+LOCALFUNC LPTSTR FindLastTerm(LPTSTR s, TCHAR delim)
+{
+	TCHAR c;
+	LPTSTR p0 = s;
+	LPTSTR p = (LPTSTR)nullpr;
+
+	while ((c = *p0++) != (TCHAR)('\0')) {
+		if (c == delim) {
+			p = p0;
+		}
+	}
+
+	return p;
+}
+
+LOCALVAR HINSTANCE AppInstance;
+
+LOCALFUNC blnr GetAppDir(LPTSTR pathName)
+/* be sure at least _MAX_PATH long! */
+{
+	if (GetModuleFileName(AppInstance, pathName, _MAX_PATH) == 0) {
+		/* MacMsg("error", "GetModuleFileName failed", falseblnr); */
+	} else {
+		LPTSTR p = FindLastTerm(pathName,
+			(TCHAR)('\\'));
+		if (p == nullpr) {
+			/* MacMsg("error", "strrchr failed", falseblnr); */
+		} else {
+			*--p = (TCHAR)('\0');
+			return trueblnr;
+		}
+	}
+	return falseblnr;
+}
+
+/* --- sending debugging info to file --- */
+
+#if dbglog_HAVE
+
+LOCALVAR HANDLE dbglog_File = INVALID_HANDLE_VALUE;
+
+LOCALFUNC blnr dbglog_open0(void)
+{
+	TCHAR pathName[_MAX_PATH];
+	TCHAR Child0[] = TEXT("\\dbglog.txt");
+	size_t newlen;
+
+	if (GetAppDir(pathName)) {
+		newlen = _tcslen(pathName) + _tcslen(Child0);
+		if (newlen + 1 < _MAX_PATH) {
+			_tcscat(pathName, Child0);
+
+			dbglog_File = CreateFile(
+				pathName, /* pointer to name of the file */
+				GENERIC_READ + GENERIC_WRITE,
+					/* access (read-write) mode */
+				0, /* share mode */
+				NULL, /* pointer to security descriptor */
+				OPEN_ALWAYS, /* how to create */
+				FILE_ATTRIBUTE_NORMAL, /* file attributes */
+				NULL /* handle to file with attributes to copy */
+			);
+			if (INVALID_HANDLE_VALUE == dbglog_File) {
+				/* report error (how?) */
+			} else if (SetFilePointer(
+				dbglog_File, /* handle of file */
+				0, /* number of bytes to move file pointer */
+				nullpr,
+					/* address of high-order word of distance to move */
+				FILE_BEGIN /* how to move */
+				) != 0)
+			{
+				/* report error (how?) */
+			}
+		}
+	}
+
+	return (INVALID_HANDLE_VALUE != dbglog_File);
+}
+
+LOCALPROC dbglog_write0(char *s, uimr L)
+{
+	DWORD BytesWritten;
+
+	if (INVALID_HANDLE_VALUE != dbglog_File) {
+		if (! WriteFile(dbglog_File, /* handle of file to read */
+			(LPVOID)s, /* address of buffer that receives data */
+			(DWORD)L, /* number of bytes to read */
+			&BytesWritten, /* address of number of bytes read */
+			nullpr) /* address of structure for data */
+			|| ((ui5b)BytesWritten != L))
+		{
+			/* report error (how?) */
+		}
+	}
+}
+
+LOCALPROC dbglog_close0(void)
+{
+	if (INVALID_HANDLE_VALUE != dbglog_File) {
+		if (! SetEndOfFile(dbglog_File)) {
+			/* report error (how?) */
+		}
+		(void) CloseHandle(dbglog_File);
+		dbglog_File = INVALID_HANDLE_VALUE;
+	}
+}
+
+#endif
+
+#include "COMOSGLU.h"
+
+#ifndef InstallFileIcons
+#define InstallFileIcons 0
+#endif
+
+/* Resource Ids */
+
+#define IDI_VMAC      256
+#if InstallFileIcons
+#define IDI_ROM       257
+#define IDI_DISK      258
+#endif
+
+/* --- some simple utilities --- */
+
+#define TestBit(i, p) (((unsigned long)(i) & PowOf2(p)) != 0)
+
+GLOBALOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount)
+{
+/*
+	must work even if blocks overlap in memory
+*/
+	(void) memcpy((char *)destPtr, (char *)srcPtr, byteCount);
+}
+
+/* --- Parameter buffers --- */
+
+#if IncludePbufs
+LOCALVAR HGLOBAL PbufDat[NumPbufs];
+#endif
+
+#if IncludePbufs
+LOCALFUNC tMacErr PbufNewFromHandle(HGLOBAL h, ui5b count, tPbuf *r)
+{
+	tPbuf i;
+	tMacErr err;
+
+	if (! FirstFreePbuf(&i)) {
+		(void) GlobalFree(h);
+		err = mnvm_miscErr;
+	} else {
+		*r = i;
+		PbufDat[i] = h;
+		PbufNewNotify(i, count);
+		err = mnvm_noErr;
+	}
+
+	return err;
+}
+#endif
+
+#if IncludePbufs
+GLOBALOSGLUFUNC tMacErr PbufNew(ui5b count, tPbuf *r)
+{
+	HGLOBAL h;
+	tMacErr err = mnvm_miscErr;
+
+	h = GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT, count);
+	if (h != NULL) {
+		/* need to clear h */
+		err = PbufNewFromHandle(h, count, r);
+	}
+
+	return err;
+}
+#endif
+
+#if IncludePbufs
+GLOBALOSGLUPROC PbufDispose(tPbuf i)
+{
+	(void) GlobalFree(PbufDat[i]);
+	PbufDisposeNotify(i);
+}
+#endif
+
+#if IncludePbufs
+LOCALPROC UnInitPbufs(void)
+{
+	tPbuf i;
+
+	for (i = 0; i < NumPbufs; ++i) {
+		if (PbufIsAllocated(i)) {
+			PbufDispose(i);
+		}
+	}
+}
+#endif
+
+#if IncludePbufs
+#define PbufHaveLock 1
+#endif
+
+#if IncludePbufs
+LOCALFUNC ui3p PbufLock(tPbuf i)
+{
+	HGLOBAL h = PbufDat[i];
+	return (ui3p)GlobalLock(h);
+}
+#endif
+
+#if IncludePbufs
+LOCALPROC PbufUnlock(tPbuf i)
+{
+	(void) GlobalUnlock(PbufDat[i]);
+}
+#endif
+
+#if IncludePbufs
+GLOBALOSGLUPROC PbufTransfer(ui3p Buffer,
+	tPbuf i, ui5r offset, ui5r count, blnr IsWrite)
+{
+	HGLOBAL h = PbufDat[i];
+	ui3p p0 = GlobalLock(h);
+	if (p0 != NULL) {
+		void *p = p0 + offset;
+		if (IsWrite) {
+			(void) memcpy(p, Buffer, count);
+		} else {
+			(void) memcpy(Buffer, p, count);
+		}
+	}
+	(void) GlobalUnlock(h);
+}
+#endif
+
+/* --- control mode and internationalization --- */
+
+#include "CONTROLM.h"
+
+/* --- main window info --- */
+
+LOCALVAR HWND MainWnd = NULL;
+
+LOCALVAR int WndX;
+LOCALVAR int WndY;
+
+#if UseWinCE
+LOCALVAR short oldOrientation;
+LOCALVAR unsigned long oldDisplayOrientation;
+#endif
+
+#if VarFullScreen
+LOCALVAR blnr UseFullScreen = (WantInitFullScreen != 0);
+#endif
+
+#if EnableMagnify
+LOCALVAR blnr UseMagnify = (WantInitMagnify != 0);
+#endif
+
+#if MayFullScreen
+LOCALVAR short hOffset;
+LOCALVAR short vOffset;
+#endif
+
+/* cursor hiding */
+
+LOCALVAR blnr HaveCursorHidden = falseblnr;
+LOCALVAR blnr WantCursorHidden = falseblnr;
+
+LOCALPROC ForceShowCursor(void)
+{
+	if (HaveCursorHidden) {
+		HaveCursorHidden = falseblnr;
+		(void) ShowCursor(TRUE);
+		SetCursor(LoadCursor(NULL, IDC_ARROW));
+	}
+}
+
+/* cursor moving */
+
+LOCALFUNC blnr MyMoveMouse(si4b h, si4b v)
+{
+	POINT NewMousePos;
+	ui5b difftime;
+	blnr IsOk;
+	DWORD StartTime = GetTickCount();
+	LONG x = h;
+	LONG y = v;
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		x -= ViewHStart;
+		y -= ViewVStart;
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+		x *= MyWindowScale;
+		y *= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		x += hOffset;
+		y += vOffset;
+	}
+#endif
+
+	x += WndX;
+	y += WndY;
+
+	do {
+		(void) SetCursorPos(x, y);
+		if (! GetCursorPos(&NewMousePos)) {
+			IsOk = falseblnr;
+		} else {
+			IsOk = (x == NewMousePos.x) && (y == NewMousePos.y);
+		}
+		difftime = (ui5b)(GetTickCount() - StartTime);
+	} while ((! IsOk) && (difftime < 100));
+	return IsOk;
+}
+
+#if EnableFSMouseMotion
+LOCALPROC StartSaveMouseMotion(void)
+{
+	if (! HaveMouseMotion) {
+		if (MyMoveMouse(ViewHStart + (ViewHSize / 2),
+				ViewVStart + (ViewVSize / 2)))
+		{
+			SavedMouseH = ViewHStart + (ViewHSize / 2);
+			SavedMouseV = ViewVStart + (ViewVSize / 2);
+			HaveMouseMotion = trueblnr;
+		}
+	}
+}
+#endif
+
+#if EnableFSMouseMotion
+LOCALPROC StopSaveMouseMotion(void)
+{
+	if (HaveMouseMotion) {
+		(void) MyMoveMouse(CurMouseH, CurMouseV);
+		HaveMouseMotion = falseblnr;
+	}
+}
+#endif
+
+LOCALVAR blnr MyMouseCaptured = falseblnr;
+
+LOCALPROC MyMouseCaptureSet(blnr v)
+{
+	if (v != MyMouseCaptured) {
+		if (v) {
+			(void) SetCapture(MainWnd);
+		} else {
+			(void) ReleaseCapture();
+		}
+		MyMouseCaptured = v;
+	}
+}
+
+LOCALPROC SetCurMouseButton(blnr v)
+{
+	MyMouseButtonSet(v);
+	MyMouseCaptureSet(v);
+}
+
+/* keyboard */
+
+/* these constants weren't in the header files I have */
+#define myVK_Subtract 0xBD
+#define myVK_Equal 0xBB
+#define myVK_BackSlash 0xDC
+#define myVK_Comma 0xBC
+#define myVK_Period 0xBE
+#define myVK_Slash 0xBF
+#define myVK_SemiColon 0xBA
+#define myVK_SingleQuote 0xDE
+#define myVK_LeftBracket 0xDB
+#define myVK_RightBracket 0xDD
+#define myVK_Grave 0xC0
+
+/* some new ones, need to check if in all header versions */
+#define myVK_PRIOR 0x21
+#define myVK_NEXT 0x22
+#define myVK_END 0x23
+#define myVK_HOME 0x24
+#define myVK_INSERT 0x2D
+#define myVK_DELETE 0x2E
+#define myVK_HELP 0x2F
+#define myVK_SCROLL 0x91
+#define myVK_SNAPSHOT 0x2C
+#define myVK_PAUSE 0x13
+#define myVK_CLEAR 0x0C
+
+#define myVK_OEM_8 0xDF
+#define myVK_OEM_102 0xE2
+
+#ifndef ItnlKyBdFix
+#define ItnlKyBdFix 0
+#endif
+
+#if ItnlKyBdFix
+LOCALVAR ui3b MyVkMapA[256];
+#endif
+
+#if ItnlKyBdFix
+LOCALPROC MyVkSwapZY(void)
+{
+	MyVkMapA['Z'] = 'Y';
+	MyVkMapA['Y'] = 'Z';
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALPROC MyVkSwapGraveQuote(void)
+{
+	MyVkMapA[myVK_Grave] = myVK_SingleQuote;
+	MyVkMapA[myVK_SingleQuote] = myVK_Grave;
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALPROC MyVkSwapSlashSubtract(void)
+{
+	MyVkMapA[myVK_Slash] = myVK_Subtract;
+	MyVkMapA[myVK_Subtract] = myVK_Slash;
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALPROC MyVkSwapAQZWGraveQuote(void)
+{
+	MyVkSwapGraveQuote();
+	MyVkMapA['A'] = 'Q';
+	MyVkMapA['Q'] = 'A';
+	MyVkMapA['Z'] = 'W';
+	MyVkMapA['W'] = 'Z';
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALPROC MyVkMapBelgian(void)
+{
+	MyVkSwapAQZWGraveQuote();
+	MyVkMapA['M'] = myVK_SemiColon;
+	MyVkMapA[myVK_SemiColon] = myVK_RightBracket;
+	MyVkMapA[myVK_RightBracket] = myVK_LeftBracket;
+	MyVkMapA[myVK_LeftBracket] = myVK_Subtract;
+	MyVkMapA[myVK_Subtract] = myVK_Equal;
+	MyVkMapA[myVK_Equal] = myVK_Slash;
+	MyVkMapA[myVK_Slash] = myVK_Period;
+	MyVkMapA[myVK_Period] = myVK_Comma;
+	MyVkMapA[myVK_Comma] = 'M';
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALPROC MyVkMapSwiss(void)
+{
+	MyVkSwapZY();
+	MyVkMapA[myVK_OEM_8] = myVK_BackSlash;
+	MyVkMapA[myVK_BackSlash] = myVK_SingleQuote;
+	MyVkMapA[myVK_SingleQuote] = myVK_SemiColon;
+	MyVkMapA[myVK_SemiColon] = myVK_LeftBracket;
+	MyVkMapA[myVK_LeftBracket] = myVK_Subtract;
+	MyVkMapA[myVK_Subtract] = myVK_Slash;
+	MyVkMapA[myVK_Slash] = myVK_Grave;
+	MyVkMapA[myVK_Grave] = myVK_RightBracket;
+	MyVkMapA[myVK_RightBracket] = myVK_Equal;
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALPROC MyVkMapDanish(void)
+{
+	MyVkMapA[myVK_Equal] = myVK_Subtract;
+	MyVkMapA[myVK_Subtract] = myVK_Slash;
+	MyVkMapA[myVK_Slash] = myVK_BackSlash;
+	MyVkMapA[myVK_BackSlash] = myVK_Grave;
+	MyVkMapA[myVK_Grave] = myVK_SemiColon;
+	MyVkMapA[myVK_SemiColon] = myVK_RightBracket;
+	MyVkMapA[myVK_RightBracket] = myVK_LeftBracket;
+	MyVkMapA[myVK_LeftBracket] = myVK_Equal;
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALPROC MyVkMapBritish(void)
+{
+	MyVkMapA[myVK_OEM_8] = myVK_Grave;
+	MyVkMapA[myVK_Grave] = myVK_SingleQuote;
+	MyVkMapA[myVK_SingleQuote] = myVK_BackSlash;
+	MyVkMapA[myVK_BackSlash] = myVK_OEM_102;
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALPROC MyVkMapSpanish(void)
+{
+	MyVkMapA[myVK_SemiColon] = myVK_LeftBracket;
+	MyVkMapA[myVK_LeftBracket] = myVK_Subtract;
+	MyVkMapA[myVK_Subtract] = myVK_Slash;
+	MyVkMapA[myVK_Slash] = myVK_BackSlash;
+	MyVkMapA[myVK_BackSlash] = myVK_Grave;
+	MyVkMapA[myVK_Grave] = myVK_SemiColon;
+
+	MyVkMapA[myVK_RightBracket] = myVK_Equal;
+	MyVkMapA[myVK_Equal] = myVK_RightBracket;
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALPROC MyVkMapDutch(void)
+{
+	MyVkSwapGraveQuote();
+	MyVkMapA[myVK_SemiColon] = myVK_RightBracket;
+	MyVkMapA[myVK_RightBracket] = myVK_LeftBracket;
+	MyVkMapA[myVK_LeftBracket] = myVK_Subtract;
+	MyVkMapA[myVK_Subtract] = myVK_Slash;
+	MyVkMapA[myVK_Slash] = myVK_Equal;
+	MyVkMapA[myVK_Equal] = myVK_SemiColon;
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALPROC MyVkMapGreekIBM(void)
+{
+	MyVkSwapSlashSubtract();
+	MyVkMapA[myVK_LeftBracket] = myVK_Equal;
+	MyVkMapA[myVK_Equal] = myVK_LeftBracket;
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALPROC MyVkMapFrench(void)
+{
+	MyVkSwapAQZWGraveQuote();
+	MyVkMapA['M'] = myVK_SemiColon;
+	MyVkMapA[myVK_SemiColon] = myVK_RightBracket;
+	MyVkMapA[myVK_RightBracket] = myVK_LeftBracket;
+	MyVkMapA[myVK_LeftBracket] = myVK_Subtract;
+	MyVkMapA[myVK_Comma] = 'M';
+	MyVkMapA[myVK_Period] = myVK_Comma;
+	MyVkMapA[myVK_Slash] = myVK_Period;
+	MyVkMapA[myVK_OEM_8] = myVK_Slash;
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALPROC MyVkMapGerman(void)
+{
+	MyVkSwapZY();
+	MyVkMapSpanish();
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALPROC MyVkMapBosnian(void)
+{
+	MyVkSwapZY();
+	/* not in Windows 95 */
+	MyVkSwapSlashSubtract();
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALPROC MyVkMapBulgarian(void)
+{
+	MyVkMapA[myVK_OEM_8] = myVK_Comma;
+	MyVkMapA[myVK_Comma] = 'Q';
+	MyVkMapA['Q'] = myVK_Period;
+	MyVkMapA[myVK_Period] = myVK_Equal;
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALPROC MyVkMapFromLayout(uimr sv)
+{
+	int i;
+
+	for (i = 0; i < 256; ++i) {
+		MyVkMapA[i] = i;
+	}
+
+	switch (sv) {
+		case 0x00000409:
+			/* United States 101 */
+			break;
+		case 0x0000041c:
+			/* Albanian; */
+			MyVkSwapZY();
+			break;
+		case 0x0000042B:
+			/* Armenian Eastern; */
+			MyVkMapDutch();
+			break;
+		case 0x0001042B:
+			/* Armenian Western; */
+			MyVkMapDutch();
+			break;
+		case 0x0000042C:
+			/* not in Windows 95 */
+			/* Azeri Latin */
+			MyVkMapBritish();
+			break;
+		case 0x0001080C:
+			/* Belgian (comma) */
+			MyVkMapBelgian();
+			break;
+		case 0x0000080c:
+			/* Belgian French */
+			MyVkMapBelgian();
+			break;
+		case 0x00000813:
+			/* not in Windows 95 */
+			/* Belgian (period); */
+			MyVkMapBelgian();
+			break;
+		case 0x0000141A:
+			/* not in Windows 95 */
+			/* Bosnian */
+			MyVkMapBosnian();
+			break;
+		case 0x00000809:
+			/* British / United Kingdom */
+			MyVkMapBritish();
+			break;
+		case 0x00000452:
+			/* not in Windows 95 */
+			/* United Kingdom Extended */
+			MyVkMapBritish();
+			break;
+		case 0x00000402:
+			/* Bulgarian */
+			/* not same in Windows 95 */
+			MyVkMapBulgarian();
+			break;
+		case 0x00030402:
+			/* Bulgarian */
+			MyVkMapBulgarian();
+			break;
+		case 0x00020402:
+			/* Bulgarian (Phonetic) */
+			MyVkMapBosnian();
+			break;
+		case 0x00001009:
+			/* Canadian Multilingual */
+			/* not in Windows 95 */
+			MyVkSwapGraveQuote();
+			break;
+		case 0x00011009:
+			/* Canadian Standard */
+			MyVkSwapGraveQuote();
+			break;
+		case 0x0000041a:
+			/* Croatian */
+			MyVkMapBosnian();
+			break;
+		case 0x00000405:
+			/* Czech */
+			MyVkMapBosnian();
+#if 0
+			/* but Windows 7 gives */
+			MyVkSwapZY();
+			MyVkMapA[myVK_Equal] = myVK_Subtract;
+			MyVkMapA[myVK_Subtract] = myVK_Slash;
+			MyVkMapA[myVK_Slash] = myVK_Equal;
+#endif
+			break;
+		case 0x00020405:
+			/* Czech (Programmers) */
+			/* only in Windows 95 */
+			/* MyVkSwapZY(); */
+			break;
+		case 0x00010405:
+			/* Czech (Qwerty) */
+			/* only in Windows 95 */
+			/* MyVkSwapZY(); */
+			break;
+		case 0x00000406:
+			/* Danish */
+			MyVkMapDanish();
+			break;
+		case 0x00000413:
+			/* Dutch */
+			MyVkMapDutch();
+			break;
+		case 0x00000425:
+			/* Estonian */
+			MyVkMapA[myVK_Grave] = myVK_LeftBracket;
+			MyVkMapA[myVK_LeftBracket] = myVK_RightBracket;
+			MyVkMapA[myVK_RightBracket] = myVK_Slash;
+			MyVkMapA[myVK_Slash] = myVK_SingleQuote;
+			MyVkMapA[myVK_SingleQuote] = myVK_Grave;
+			/* only in Windows 95 ? */
+			/* MyVkMapA[VK_DECIMAL] = VK_DELETE; */
+			break;
+		case 0x00000438:
+			/* Faeroe Islands */
+			MyVkMapDanish();
+			break;
+		case 0x0000040b:
+			/* Finnish */
+			MyVkMapDanish();
+			break;
+		case 0x0001083B:
+			/* not in Windows 95 */
+			/* Finnish with Sami */
+			MyVkMapDanish();
+			break;
+		case 0x0000040c:
+			/* v = kMyKbdFrench; */
+			/* French */
+			MyVkMapFrench();
+			break;
+		case 0x00000c0c:
+			/* French Canadian */
+			MyVkSwapGraveQuote();
+			break;
+		case 0x00011809:
+			/* not in Windows 95 */
+			/* Gaelic */
+			MyVkMapBritish();
+			break;
+		case 0x00010407:
+			/* German (IBM) */
+			MyVkMapGerman();
+			break;
+		case 0x00000407:
+			/* German (Standard) */
+			MyVkMapGerman();
+			break;
+		case 0x00010408:
+			/* Greek IBM 220 */
+			/* not in Windows 95 */
+			MyVkMapGreekIBM();
+			break;
+		case 0x00030408:
+			/* Greek IBM 319 */
+			/* not in Windows 95 */
+			MyVkMapGreekIBM();
+			break;
+		case 0x00020408:
+			/* Greek Latin IBM 220 */
+			/* not in Windows 95 */
+			MyVkSwapSlashSubtract();
+			break;
+		case 0x00040408:
+			/* Greek Latin IBM 319 */
+			/* not in Windows 95 */
+			MyVkSwapSlashSubtract();
+			break;
+		case 0x0000040e:
+			/* Hungarian */
+			MyVkMapBosnian();
+			MyVkMapA[myVK_Grave] = '0';
+			MyVkMapA['0'] = myVK_Grave;
+			break;
+		case 0x0001040E:
+			/* Hungarian (101 Keys) */
+			MyVkMapA[myVK_Grave] = '0';
+			MyVkMapA['0'] = myVK_Grave;
+			break;
+		case 0x0000040f:
+			/* Icelandic */
+			MyVkMapDanish();
+			break;
+		case 0x00001809:
+			/* Irish */
+			MyVkMapBritish();
+			break;
+		case 0x00000410:
+			/* Italian */
+			MyVkMapSpanish();
+			break;
+		case 0x00010410:
+			/* Italian 142 */
+			MyVkMapSpanish();
+			break;
+		case 0x0000080a:
+			/* Latin American */
+			MyVkMapSpanish();
+			break;
+		case 0x0000046E:
+			/* Luxembourgish */
+			MyVkMapSwiss();
+			break;
+		case 0x00000414:
+			/* Norwegian */
+			MyVkMapDanish();
+			break;
+		case 0x0000043B:
+			/* Norwegian with Sami */
+			MyVkMapDanish();
+			break;
+		case 0x00010415:
+			/* Polish (214) */
+			MyVkSwapZY();
+			/* not in windows 95 */
+			MyVkMapA[myVK_Equal] = myVK_Subtract;
+			MyVkMapA[myVK_Subtract] = myVK_Slash;
+			MyVkMapA[myVK_Slash] = myVK_Equal;
+			break;
+		case 0x00010416:
+			/* Porguguese (Brazilian ABNT2) */
+			/* MyVkMapA[myVK_OEM_8] = ??; */
+			/* MyVkMapA[VK_SEPARATOR] = ??; */
+			break;
+		case 0x00000816:
+			/* Porguguese (Standard) */
+			MyVkMapA[myVK_SemiColon] = myVK_RightBracket;
+			MyVkMapA[myVK_RightBracket] = myVK_Equal;
+			MyVkMapA[myVK_Equal] = myVK_LeftBracket;
+			MyVkMapA[myVK_LeftBracket] = myVK_Subtract;
+			MyVkMapA[myVK_Subtract] = myVK_Slash;
+			MyVkMapA[myVK_Slash] = myVK_BackSlash;
+			MyVkMapA[myVK_BackSlash] = myVK_Grave;
+			MyVkMapA[myVK_Grave] = myVK_SemiColon;
+			break;
+		case 0x00000418:
+			/* Romanian (Legacy) */
+			MyVkSwapZY();
+			/* only in Windows 95 */
+			/* MyVkSwapSlashSubtract(); */
+			break;
+		case 0x0002083B:
+			/* Sami Extended Finland-Sweden */
+			MyVkMapDanish();
+			break;
+		case 0x0001043B:
+			/* Sami Extended Norway */
+			MyVkMapDanish();
+			break;
+		case 0x00010C1A:
+			/* in Windows 95 */
+			/* Serbian (Latin) */
+			MyVkSwapZY();
+			break;
+		case 0x0000081A:
+			/* not in Windows 95 */
+			/* Serbian (Latin) */
+			MyVkMapBosnian();
+			break;
+		case 0x0000041b:
+			/* Slovak */
+			MyVkMapBosnian();
+			/* not in Windows 95 */
+			MyVkMapA[myVK_OEM_8] = myVK_Equal;
+			break;
+		case 0x00000424:
+			/* Slovenian */
+			MyVkMapBosnian();
+			break;
+		case 0x0000040A:
+			/* Spanish, not windows 95 */
+			MyVkMapSpanish();
+			break;
+		case 0x0001040A:
+			/* Spanish Variation, not windows 95 */
+			MyVkMapA[myVK_OEM_8] = myVK_Slash;
+			MyVkMapA[myVK_Slash] = myVK_BackSlash;
+			MyVkMapA[myVK_BackSlash] = myVK_Grave;
+			MyVkMapA[myVK_Grave] = myVK_SemiColon;
+			MyVkMapA[myVK_SemiColon] = myVK_RightBracket;
+			MyVkMapA[myVK_RightBracket] = myVK_LeftBracket;
+			MyVkMapA[myVK_LeftBracket] = myVK_Equal;
+			break;
+		case 0x00000c0a:
+			/* kMyKbdSpanish; */
+			/* Spanish Modern, windows 95 */
+			MyVkMapSpanish();
+			break;
+		case 0x00000403:
+			/* Spanish Traditional */
+			MyVkMapSpanish();
+			break;
+		case 0x0000041d:
+			/* Swedish */
+			MyVkMapDanish();
+			break;
+		case 0x0000083B:
+			/* not in windows 95 */
+			/* Swedish with Sami */
+			MyVkMapDanish();
+			break;
+		case 0x0000100c:
+			/* Swiss French */
+			MyVkMapSwiss();
+			break;
+		case 0x00000807:
+			/* Swiss German */
+			MyVkMapSwiss();
+			break;
+		case 0x0000085D:
+			/* Inuktitut Latin */
+			/* in windows 7, not XP */
+			MyVkMapBritish();
+			break;
+		case 0x0001045D:
+			/* Inuktitut - Naqittaut */
+			MyVkMapBritish();
+			break;
+		case 0x0000046F:
+			/* Greenlandic */
+			MyVkMapDanish();
+			break;
+		case 0x00020427:
+			/* Lithuanian Standard */
+			MyVkMapDanish();
+			break;
+		case 0x0000042f:
+			/* Macedonian (FYROM) - Standard */
+			MyVkMapBosnian();
+			break;
+		case 0x0000042E:
+			/* Sorbian Standard (Legacy) */
+			MyVkMapGerman();
+			break;
+		case 0x0001042E:
+			/* Sorbian Extended */
+			MyVkMapGerman();
+			break;
+		case 0x0002042E:
+			/* Sorbian Standard */
+			MyVkMapGerman();
+			break;
+		case 0x00000488:
+			/* Wolof */
+			MyVkMapFrench();
+			break;
+		case 0x0000041f:
+			/* Turkish (Q type) */
+			/* windows 95 */
+			/* MyVkMapA[myVK_Equal] = myVK_Subtract; */
+			/* MyVkMapA[myVK_Subtract] = myVK_Equal; */
+			/* not windows 95 */
+			MyVkMapA[myVK_OEM_8] = myVK_Subtract;
+			MyVkMapA[myVK_Subtract] = myVK_Equal;
+
+			MyVkMapA[myVK_Comma] = myVK_BackSlash;
+			MyVkMapA[myVK_BackSlash] = myVK_Period;
+			MyVkMapA[myVK_Period] = myVK_Slash;
+			MyVkMapA[myVK_Slash] = myVK_Comma;
+			break;
+		case 0x00010409:
+			/* United States Dvorak */
+			MyVkMapA[myVK_LeftBracket] = myVK_Subtract;
+			MyVkMapA[myVK_RightBracket] = myVK_Equal;
+			MyVkMapA[myVK_SingleQuote] = 'Q';
+			MyVkMapA[myVK_Comma] = 'W';
+			MyVkMapA[myVK_Period] = 'E';
+			MyVkMapA['P'] = 'R';
+			MyVkMapA['Y'] = 'T';
+			MyVkMapA['F'] = 'Y';
+			MyVkMapA['G'] = 'U';
+			MyVkMapA['C'] = 'I';
+			MyVkMapA['R'] = 'O';
+			MyVkMapA['L'] = 'P';
+			MyVkMapA[myVK_Slash] = myVK_LeftBracket;
+			MyVkMapA[myVK_Equal] = myVK_RightBracket;
+			MyVkMapA['O'] = 'S';
+			MyVkMapA['E'] = 'D';
+			MyVkMapA['U'] = 'F';
+			MyVkMapA['I'] = 'G';
+			MyVkMapA['D'] = 'H';
+			MyVkMapA['H'] = 'J';
+			MyVkMapA['T'] = 'K';
+			MyVkMapA['N'] = 'L';
+			MyVkMapA['S'] = myVK_SemiColon;
+			MyVkMapA[myVK_Subtract] = myVK_SingleQuote;
+			MyVkMapA[myVK_SemiColon] = 'Z';
+			MyVkMapA['Q'] = 'X';
+			MyVkMapA['J'] = 'C';
+			MyVkMapA['K'] = 'V';
+			MyVkMapA['X'] = 'B';
+			MyVkMapA['B'] = 'N';
+			MyVkMapA['W'] = myVK_Comma;
+			MyVkMapA['V'] = myVK_Period;
+			MyVkMapA['Z'] = myVK_Slash;
+			break;
+#if 0
+		/* too complicated, don't bother with */
+		case 0x0x00000426:
+			/* Latvian */
+			MyVkMapA['F'] = myVK_Equal;
+			MyVkMapA['G'] = 'W';
+			MyVkMapA['J'] = 'E';
+			MyVkMapA['M'] = 'T';
+			MyVkMapA['V'] = 'Y';
+			MyVkMapA['N'] = 'U';
+			MyVkMapA['Z'] = 'I';
+			MyVkMapA['W'] = 'O';
+			MyVkMapA['X'] = 'P';
+			MyVkMapA['Y'] = myVK_LeftBracket;
+			MyVkMapA['H'] = myVK_RightBracket;
+			MyVkMapA[myVK_SemiColon] = 'A';
+			MyVkMapA['U'] = 'S';
+			MyVkMapA['S'] = 'D';
+			MyVkMapA['I'] = 'F';
+			MyVkMapA['L'] = 'G';
+			MyVkMapA['D'] = 'H';
+			MyVkMapA['A'] = 'J';
+			MyVkMapA['T'] = 'K';
+			MyVkMapA['E'] = 'L';
+			MyVkMapA['C'] = myVK_SemiColon;
+			MyVkMapA[myVK_LeftBracket] = 'Z';
+			MyVkMapA['B'] = 'X';
+			MyVkMapA[myVK_RightBracket] = 'C';
+			MyVkMapA['K'] = 'V';
+			MyVkMapA['P'] = 'B';
+			MyVkMapA['O'] = 'N';
+			MyVkMapA[myVK_OEM_8] = 'M';
+			break;
+		case 0x0001041F:
+			/* Turkish (F type) */
+
+			MyVkMapA[myVK_Equal] = myVK_Subtract;
+			MyVkMapA[myVK_Subtract] = myVK_Equal;
+			MyVkMapA['F'] = 'Q';
+			MyVkMapA['G'] = 'W';
+			MyVkMapA[myVK_SemiColon] = 'E';
+			MyVkMapA['I'] = 'R';
+			MyVkMapA['O'] = 'T';
+			MyVkMapA['D'] = 'Y';
+			MyVkMapA['R'] = 'U';
+			MyVkMapA['N'] = 'I';
+			MyVkMapA['H'] = 'O';
+			MyVkMapA['Q'] = myVK_LeftBracket;
+			MyVkMapA['W'] = myVK_RightBracket;
+			MyVkMapA['U'] = 'A';
+			MyVkMapA[myVK_LeftBracket] = 'S';
+			MyVkMapA['E'] = 'D';
+			MyVkMapA['A'] = 'F';
+			MyVkMapA[myVK_RightBracket] = 'G';
+			MyVkMapA['T'] = 'H';
+			MyVkMapA['K'] = 'J';
+			MyVkMapA['M'] = 'K';
+			MyVkMapA['Y'] = myVK_SemiColon;
+			MyVkMapA['X'] = myVK_BackSlash;
+			MyVkMapA['J'] = 'Z';
+			MyVkMapA[myVK_BackSlash] = 'X';
+			MyVkMapA['V'] = 'C';
+			MyVkMapA['C'] = 'V';
+			MyVkMapA[myVK_Slash] = 'B';
+			MyVkMapA['Z'] = 'N';
+			MyVkMapA['S'] = 'M';
+			MyVkMapA['B'] = myVK_Comma;
+			MyVkMapA[myVK_Comma] = myVK_Slash;
+			break;
+		case 0x00030409:
+			/* United States LH Dvorak */
+			MyVkMapA[myVK_LeftBracket] = '1';
+			MyVkMapA[myVK_RightBracket] = '2';
+			MyVkMapA[myVK_Slash] = '3';
+			MyVkMapA['P'] = '4';
+			MyVkMapA['F'] = '5';
+			MyVkMapA['M'] = '6';
+			MyVkMapA['L'] = '7';
+			MyVkMapA['J'] = '8';
+			MyVkMapA['4'] = '9';
+			MyVkMapA['3'] = '0';
+			MyVkMapA['2'] = myVK_Subtract;
+			MyVkMapA['1'] = myVK_Equal;
+			MyVkMapA[myVK_SemiColon] = 'Q';
+			MyVkMapA['Q'] = 'W';
+			MyVkMapA['B'] = 'E';
+			MyVkMapA['Y'] = 'R';
+			MyVkMapA['U'] = 'T';
+			MyVkMapA['R'] = 'Y';
+			MyVkMapA['S'] = 'U';
+			MyVkMapA['O'] = 'I';
+			MyVkMapA[myVK_Period] = 'O';
+			MyVkMapA['6'] = 'P';
+			MyVkMapA['5'] = myVK_LeftBracket;
+			MyVkMapA[myVK_Equal] = myVK_RightBracket;
+			MyVkMapA[myVK_Subtract] = 'A';
+			MyVkMapA['K'] = 'S';
+			MyVkMapA['C'] = 'D';
+			MyVkMapA['D'] = 'F';
+			MyVkMapA['T'] = 'G';
+			MyVkMapA['E'] = 'J';
+			MyVkMapA['A'] = 'K';
+			MyVkMapA['Z'] = 'L';
+			MyVkMapA['8'] = myVK_SemiColon;
+			MyVkMapA['7'] = myVK_SingleQuote;
+			MyVkMapA[myVK_SingleQuote] = 'Z';
+			MyVkMapA['G'] = 'C';
+			MyVkMapA['W'] = 'B';
+			MyVkMapA['I'] = 'M';
+			MyVkMapA['0'] = myVK_Period;
+			MyVkMapA['9'] = myVK_Slash;
+			break;
+		case 0x00040409:
+			/* United States RH Dvorak */
+			MyVkMapA['J'] = '5';
+			MyVkMapA['L'] = '6';
+			MyVkMapA['M'] = '7';
+			MyVkMapA['F'] = '8';
+			MyVkMapA['P'] = '9';
+			MyVkMapA[myVK_Slash] = '0';
+			MyVkMapA[myVK_LeftBracket] = myVK_Subtract;
+			MyVkMapA[myVK_RightBracket] = myVK_Equal;
+			MyVkMapA['5'] = 'Q';
+			MyVkMapA['6'] = 'W';
+			MyVkMapA['Q'] = 'E';
+			MyVkMapA[myVK_Period] = 'R';
+			MyVkMapA['O'] = 'T';
+			MyVkMapA['R'] = 'Y';
+			MyVkMapA['S'] = 'U';
+			MyVkMapA['U'] = 'I';
+			MyVkMapA['Y'] = 'O';
+			MyVkMapA['B'] = 'P';
+			MyVkMapA[myVK_SemiColon] = myVK_LeftBracket;
+			MyVkMapA[myVK_Equal] = myVK_RightBracket;
+			MyVkMapA['7'] = 'A';
+			MyVkMapA['8'] = 'S';
+			MyVkMapA['Z'] = 'D';
+			MyVkMapA['A'] = 'F';
+			MyVkMapA['E'] = 'G';
+			MyVkMapA['T'] = 'J';
+			MyVkMapA['D'] = 'K';
+			MyVkMapA['C'] = 'L';
+			MyVkMapA['K'] = myVK_SemiColon;
+			MyVkMapA[myVK_Subtract] = myVK_SingleQuote;
+			MyVkMapA['9'] = 'Z';
+			MyVkMapA['0'] = 'X';
+			MyVkMapA['X'] = 'C';
+			MyVkMapA[myVK_Comma] = 'V';
+			MyVkMapA['I'] = 'B';
+			MyVkMapA['W'] = 'M';
+			MyVkMapA['V'] = myVK_Comma;
+			MyVkMapA['G'] = myVK_Period;
+			MyVkMapA[myVK_SingleQuote] = myVK_Slash;
+			break;
+#endif
+#if 0
+		case 0x0000082C:
+			/* not in Windows 95 */
+			/* Azeri Cyrillic */
+			break;
+		case 0x00000423:
+			/* Belarusian */
+			break;
+		case 0x00000445:
+			/* not in Windows 95 */
+			/* Bengali */
+			break;
+		case 0x00010445:
+			/* not in Windows 95 */
+			/* Bengali (Inscript) */
+			break;
+		case 0x0000201A:
+			/* not in Windows 95 */
+			/* Bosnian Cyrillic*/
+			break;
+		case 0x00010402:
+			/* Bulgarian Latin */
+#if 0 /* Only in Windows 95 */
+			MyVkMapA['J'] = 'Q';
+			MyVkMapA['C'] = 'W';
+			MyVkMapA['U'] = 'E';
+			MyVkMapA['K'] = 'R';
+			MyVkMapA['E'] = 'T';
+			MyVkMapA['N'] = 'Y';
+			MyVkMapA['G'] = 'U';
+			MyVkMapA[myVK_SemiColon] = 'I';
+			MyVkMapA[myVK_OEM_102] = 'O';
+			MyVkMapA['Z'] = 'P';
+			MyVkMapA['H'] = myVK_LeftBracket;
+			MyVkMapA['F'] = 'A';
+			MyVkMapA['Y'] = 'S';
+			MyVkMapA['W'] = 'D';
+			MyVkMapA['A'] = 'F';
+			MyVkMapA['P'] = 'G';
+			MyVkMapA['R'] = 'H';
+			MyVkMapA['O'] = 'J';
+			MyVkMapA['L'] = 'K';
+			MyVkMapA['D'] = 'L';
+			MyVkMapA['V'] = myVK_SemiColon;
+			MyVkMapA[myVK_LeftBracket] = 'Z';
+			MyVkMapA['S'] = 'X';
+			MyVkMapA['M'] = 'C';
+			MyVkMapA['I'] = 'V';
+			MyVkMapA['T'] = 'B';
+			MyVkMapA['X'] = 'N';
+			MyVkMapA['B'] = 'M';
+			MyVkMapA['Q'] = myVK_OEM_102;
+#endif
+			break;
+		case 0x00000408:
+			/* Greek */
+			break;
+		case 0x00050408:
+			/* Greek Latin */
+			break;
+		case 0x00060408:
+			/* Greek Polytonic */
+			break;
+		case 0x0000043F:
+			/* Kazakh */
+			break;
+		case 0x00000440:
+			/* Kyrgyz Cyrillic */
+			break;
+		case 0x00010426:
+			/* Latvian Latin */
+			break;
+		case 0x00010427:
+			/* Lithuanian */
+			break;
+		case 0x00000427:
+			/* Lithuanian (IBM) */
+			break;
+		case 0x0000044C:
+			/* Malayalam */
+			break;
+		case 0x0000042f:
+			/* Macedonian (FYROM) */
+			break;
+		case 0x0000043A:
+			/* Maltese 47-key */
+			break;
+		case 0x0001043A:
+			/* Maltese 48-key */
+			break;
+		case 0x00000481:
+			/* Maori */
+			break;
+		case 0x00000450:
+			/* Mongolian Cyrillic */
+			break;
+		case 0x00000461:
+			/* Nepali */
+			break;
+		case 0x00000463:
+			/* Pashto */
+			break;
+		case 0x00000415:
+			/* Polish (Programmers) */
+			break;
+		case 0x00000416:
+			/* Porguguese (Brazilian standard) */
+			break;
+		case 0x00000419:
+			/* Russian */
+			break;
+		case 0x00010419:
+			/* Russian (Typewriter) */
+			break;
+		case 0x00000c1a:
+			/* Serbian */
+			break;
+		case 0x0001041B:
+			/* Slovak (Qwerty) */
+			break;
+		case 0x00000444:
+			/* Tatar */
+			break;
+		case 0x00000422:
+			/* Ukrainian */
+			break;
+		case 0x00020409:
+			/* United States International */
+			break;
+		case 0x00000843:
+			/* Uzbek Cyrillic */
+			break;
+		case 0x00010418:
+			/* Romanian (Standard) */
+			break;
+		case 0x00020418:
+			/* Romanian (Programmers) */
+			break;
+		case 0x00000401:
+			/* Arabic (101) */
+			break;
+		case 0x00010401:
+			/* Arabic (102) */
+			break;
+		case 0x0000044D:
+			/* Assamese - INSCRIPT */
+			break;
+		case 0x0000046D:
+			/* Bashkir */
+			break;
+		case 0x00040402:
+			/* Bulgarian (Phonetic Traditional) */
+			break;
+		case 0x00000404:
+			/* Chinese (Traditional) */
+			break;
+		case 0x00000804:
+			/* Chinese (Simplified) */
+			break;
+		case 0x00000C04:
+			/* Chinese (Traditional, Hong Kong S.A.R.) */
+			break;
+		case 0x00001004:
+			/* Chinese (Simplified, Singapore) */
+			break;
+		case 0x00001404:
+			/* Chinese (Traditional, Macao S.A.R.) */
+			break;
+		case 0x0000040D:
+			/* Hebrew */
+			break;
+		case 0x00000447:
+			/* Gujarati */
+			break;
+		case 0x00000468:
+			/* Hausa */
+			break;
+		case 0x00010439:
+			/* Hindi Traditional */
+			break;
+		case 0x00000439:
+			/* Devanagari - INSCRIPT */
+			break;
+		case 0x00000465:
+			/* Divehi Phonetic */
+			break;
+		case 0x00010465:
+			/* Divehi Typewriter */
+			break;
+		case 0x00000437:
+			/* Georgian */
+			break;
+		case 0x00010437:
+			/* Georgian (QWERTY) */
+			break;
+		case 0x00020437:
+			/* Georgian (Ergonomic) */
+			break;
+		case 0x00000470:
+			/* Igbo */
+			break;
+		case 0x00000411:
+			/* Japanese */
+			/* MyVkMapA[??] = ??; */
+			break;
+		case 0x00000412:
+			/* Korean */
+			/* MyVkMapA[VK_ZOOM] = ??; */
+			/* MyVkMapA[VK_HELP] = VK_ZOOM; */
+			/* MyVkMapA[??] = VK_HELP; */
+			/* MyVkMapA[??] = ??; */
+			break;
+		case 0x0000044B:
+			/* Kannada */
+			break;
+		case 0x00000453:
+			/* Khmer */
+			break;
+		case 0x00000454:
+			/* Lao */
+			break;
+		case 0x00000448:
+			/* Oriya */
+			break;
+		case 0x0000044E:
+			/* Marathi */
+			break;
+		case 0x00000850:
+			/* Mongolian (Mongolian Script) */
+			break;
+		case 0x00000429:
+			/* Persion */
+			break;
+		case 0x00000446:
+			/* Punjabi */
+			break;
+		case 0x0000046C:
+			/* Sesotho sa Leboa */
+			break;
+		case 0x00000432:
+			/* Setswana */
+			break;
+		case 0x0000045B:
+			/* Sinhala */
+			break;
+		case 0x0001045B:
+			/* Sinhala - Wij 9 */
+			break;
+		case 0x0000045A:
+			/* Syriac */
+			break;
+		case 0x0001045A:
+			/* Syriac Phonetic */
+			break;
+		case 0x00000428:
+			/* Tajik */
+			break;
+		case 0x00000449:
+			/* Tamil */
+			break;
+		case 0x0000044A:
+			/* Telugu */
+			break;
+		case 0x0000041E:
+			/* Thai Kedmanee */
+			break;
+		case 0x0001041E:
+			/* Thai Pattachote */
+			break;
+		case 0x0002041E:
+			/* Thai Kedmanee (non-ShiftLock) */
+			break;
+		case 0x0003041E:
+			/* Thai Pattachote (non-ShiftLock) */
+			break;
+		case 0x00000451:
+			/* Tibetan (PRC) */
+			break;
+		case 0x00000442:
+			/* Turkmen */
+			break;
+		case 0x00020422:
+			/* Ukrainian (Enhanced) */
+			break;
+		case 0x00000420:
+			/* Urdu */
+			break;
+		case 0x00050409:
+			/* US English Table for IBM Arabic 238_L */
+			break;
+		case 0x00000480:
+			/* Uyghur (Legacy) */
+			break;
+		case 0x00010480:
+			/* Uyghur */
+			break;
+		case 0x0000042A:
+			/* Vietnamese */
+			break;
+		case 0x00000485:
+			/* Yakut */
+			break;
+		case 0x0000046A:
+			/* Yoruba */
+			break;
+#endif
+	}
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALVAR uimr CurKyBdLytNm = 0;
+#endif
+
+#if ItnlKyBdFix
+LOCALFUNC blnr tStrIsHex(TCHAR *s, int n, uimr *r)
+{
+	short i;
+	TCHAR c1;
+	TCHAR *p = s;
+	uimr v = 0;
+
+	for (i = n; --i >= 0; ) {
+		v <<= 4;
+		c1 = *p++;
+		if ((c1 >= '0') && (c1 <= '9')) {
+			v += c1 - '0';
+		} else if ((c1 >= 'A') && (c1 <= 'F')) {
+			v += c1 - ('A' - 10);
+		} else if ((c1 >= 'a') && (c1 <= 'f')) {
+			v += c1 - ('a' - 10);
+		} else {
+			return falseblnr;
+		}
+	}
+
+	*r = v;
+	return trueblnr;
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALFUNC blnr MyGetKeyboardLayoutHex(uimr *r)
+{
+	TCHAR s[KL_NAMELENGTH];
+	blnr IsOk = falseblnr;
+
+	if (! GetKeyboardLayoutName(s)) {
+		/* ReportWinLastError(); */
+	} else {
+		size_t n = _tcslen(s);
+
+		if (8 != n) {
+			/* fail */
+		} else {
+			IsOk = tStrIsHex(s, n, r);
+		}
+	}
+
+	return IsOk;
+}
+#endif
+
+#if ItnlKyBdFix && ! UseWinCE
+LOCALPROC MyCheckKeyboardLayout(void)
+{
+	uimr sv;
+
+	if (! MyGetKeyboardLayoutHex(&sv)) {
+	} else if (sv == CurKyBdLytNm) {
+		/* no change */
+	} else {
+		CurKyBdLytNm = sv;
+
+		MyVkMapFromLayout(sv);
+	}
+}
+#endif
+
+#if ItnlKyBdFix
+LOCALPROC MyInitCheckKeyboardLayout(void)
+{
+	uimr sv;
+
+	if (! MyGetKeyboardLayoutHex(&sv)) {
+		sv = 0x00000409;
+	}
+
+	CurKyBdLytNm = sv;
+
+	MyVkMapFromLayout(sv);
+}
+#endif
+
+LOCALVAR ui3b WinKey2Mac[256];
+
+LOCALPROC AssignOneMacKey(ui3b WinKey, ui3r MacKey)
+{
+	WinKey2Mac[WinKey] = MacKey;
+}
+
+LOCALFUNC blnr InitWinKey2Mac(void)
+{
+	int i;
+
+	for (i = 0; i < 256; ++i) {
+		WinKey2Mac[i] = MKC_None;
+	}
+
+	AssignOneMacKey('A', MKC_A);
+	AssignOneMacKey('S', MKC_S);
+	AssignOneMacKey('D', MKC_D);
+	AssignOneMacKey('F', MKC_F);
+	AssignOneMacKey('H', MKC_H);
+	AssignOneMacKey('G', MKC_G);
+	AssignOneMacKey('Z', MKC_Z);
+	AssignOneMacKey('X', MKC_X);
+	AssignOneMacKey('C', MKC_C);
+	AssignOneMacKey('V', MKC_V);
+	AssignOneMacKey('B', MKC_B);
+	AssignOneMacKey('Q', MKC_Q);
+	AssignOneMacKey('W', MKC_W);
+	AssignOneMacKey('E', MKC_E);
+	AssignOneMacKey('R', MKC_R);
+	AssignOneMacKey('Y', MKC_Y);
+	AssignOneMacKey('T', MKC_T);
+	AssignOneMacKey('1', MKC_1);
+	AssignOneMacKey('2', MKC_2);
+	AssignOneMacKey('3', MKC_3);
+	AssignOneMacKey('4', MKC_4);
+	AssignOneMacKey('6', MKC_6);
+	AssignOneMacKey('5', MKC_5);
+	AssignOneMacKey(myVK_Equal, MKC_Equal);
+	AssignOneMacKey('9', MKC_9);
+	AssignOneMacKey('7', MKC_7);
+	AssignOneMacKey(myVK_Subtract, MKC_Minus);
+	AssignOneMacKey('8', MKC_8);
+	AssignOneMacKey('0', MKC_0);
+	AssignOneMacKey(myVK_RightBracket, MKC_RightBracket);
+	AssignOneMacKey('O', MKC_O);
+	AssignOneMacKey('U', MKC_U);
+	AssignOneMacKey(myVK_LeftBracket, MKC_LeftBracket);
+	AssignOneMacKey('I', MKC_I);
+	AssignOneMacKey('P', MKC_P);
+	AssignOneMacKey(VK_RETURN, MKC_Return);
+	AssignOneMacKey('L', MKC_L);
+	AssignOneMacKey('J', MKC_J);
+	AssignOneMacKey(myVK_SingleQuote, MKC_SingleQuote);
+	AssignOneMacKey('K', MKC_K);
+	AssignOneMacKey(myVK_SemiColon, MKC_SemiColon);
+	AssignOneMacKey(myVK_BackSlash, MKC_formac_BackSlash);
+	AssignOneMacKey(myVK_Comma, MKC_Comma);
+	AssignOneMacKey(myVK_Slash, MKC_formac_Slash);
+	AssignOneMacKey('N', MKC_N);
+	AssignOneMacKey('M', MKC_M);
+	AssignOneMacKey(myVK_Period, MKC_Period);
+
+	AssignOneMacKey(VK_TAB, MKC_Tab);
+	AssignOneMacKey(VK_SPACE, MKC_Space);
+	AssignOneMacKey(myVK_Grave, MKC_formac_Grave);
+	AssignOneMacKey(VK_BACK, MKC_BackSpace);
+	AssignOneMacKey(VK_ESCAPE, MKC_formac_Escape);
+
+	AssignOneMacKey(VK_MENU, MKC_formac_Command);
+
+	AssignOneMacKey(VK_LMENU, MKC_formac_Command);
+
+	AssignOneMacKey(VK_RMENU, MKC_formac_RCommand);
+
+	AssignOneMacKey(VK_SHIFT, MKC_formac_Shift);
+	AssignOneMacKey(VK_LSHIFT, MKC_formac_Shift);
+	AssignOneMacKey(VK_RSHIFT, MKC_formac_RShift);
+
+	AssignOneMacKey(VK_CAPITAL, MKC_formac_CapsLock);
+
+	AssignOneMacKey(VK_APPS, MKC_formac_ROption);
+
+	AssignOneMacKey(VK_LWIN, MKC_formac_Option);
+
+	AssignOneMacKey(VK_RWIN, MKC_formac_ROption);
+
+	AssignOneMacKey(VK_CONTROL, MKC_formac_Control);
+
+	AssignOneMacKey(VK_LCONTROL, MKC_formac_Control);
+
+	AssignOneMacKey(VK_RCONTROL, MKC_formac_RControl);
+
+	AssignOneMacKey(VK_F1, MKC_formac_F1);
+	AssignOneMacKey(VK_F2, MKC_formac_F2);
+	AssignOneMacKey(VK_F3, MKC_formac_F3);
+	AssignOneMacKey(VK_F4, MKC_formac_F4);
+	AssignOneMacKey(VK_F5, MKC_formac_F5);
+	AssignOneMacKey(VK_F6, MKC_F6);
+	AssignOneMacKey(VK_F7, MKC_F7);
+	AssignOneMacKey(VK_F8, MKC_F8);
+	AssignOneMacKey(VK_F9, MKC_F9);
+	AssignOneMacKey(VK_F10, MKC_F10);
+	AssignOneMacKey(VK_F11, MKC_F11);
+	AssignOneMacKey(VK_F12, MKC_F12);
+
+	AssignOneMacKey(VK_DECIMAL, MKC_Decimal);
+	AssignOneMacKey(VK_DELETE, MKC_Decimal);
+	/* AssignOneMacKey(VK_RIGHT, 0x42); */
+	AssignOneMacKey(VK_MULTIPLY, MKC_KPMultiply);
+	AssignOneMacKey(VK_ADD, MKC_KPAdd);
+	/* AssignOneMacKey(VK_LEFT, 0x46); */
+	AssignOneMacKey(VK_NUMLOCK, MKC_Clear);
+
+	/* AssignOneMacKey(VK_DOWN, 0x48); */
+	AssignOneMacKey(VK_DIVIDE, MKC_KPDevide);
+	/* AssignOneMacKey(VK_RETURN, MKC_formac_Enter); */
+	/* AssignOneMacKey(VK_UP, 0x4D); */
+	AssignOneMacKey(VK_DIVIDE, MKC_KPDevide);
+	AssignOneMacKey(VK_SUBTRACT, MKC_KPSubtract);
+
+	AssignOneMacKey(VK_SEPARATOR, MKC_KPEqual);
+	AssignOneMacKey(VK_NUMPAD0, MKC_KP0);
+	AssignOneMacKey(VK_NUMPAD1, MKC_KP1);
+	AssignOneMacKey(VK_NUMPAD2, MKC_KP2);
+	AssignOneMacKey(VK_NUMPAD3, MKC_KP3);
+	AssignOneMacKey(VK_NUMPAD4, MKC_KP4);
+	AssignOneMacKey(VK_NUMPAD5, MKC_KP5);
+
+	AssignOneMacKey(VK_NUMPAD6, MKC_KP6);
+	AssignOneMacKey(VK_NUMPAD7, MKC_KP7);
+	AssignOneMacKey(VK_NUMPAD8, MKC_KP8);
+	AssignOneMacKey(VK_NUMPAD9, MKC_KP9);
+
+	AssignOneMacKey(VK_LEFT, MKC_Left);
+	AssignOneMacKey(VK_RIGHT, MKC_Right);
+	AssignOneMacKey(VK_DOWN, MKC_Down);
+	AssignOneMacKey(VK_UP, MKC_Up);
+
+	AssignOneMacKey(myVK_PRIOR, MKC_formac_PageUp);
+	AssignOneMacKey(myVK_NEXT, MKC_formac_PageDown);
+	AssignOneMacKey(myVK_END, MKC_formac_End);
+	AssignOneMacKey(myVK_HOME, MKC_formac_Home);
+	AssignOneMacKey(myVK_INSERT, MKC_formac_Help);
+	AssignOneMacKey(myVK_DELETE, MKC_formac_ForwardDel);
+	AssignOneMacKey(myVK_HELP, MKC_formac_Help);
+	AssignOneMacKey(myVK_SNAPSHOT, MKC_Print);
+	AssignOneMacKey(myVK_SCROLL, MKC_ScrollLock);
+	AssignOneMacKey(myVK_PAUSE, MKC_Pause);
+
+	AssignOneMacKey(myVK_OEM_102, MKC_AngleBracket);
+
+	InitKeyCodes();
+
+#if ItnlKyBdFix
+	MyInitCheckKeyboardLayout();
+#endif
+
+	return trueblnr;
+}
+
+LOCALPROC DoKeyCode(int i, blnr down)
+{
+	ui3r key = WinKey2Mac[
+#if ItnlKyBdFix
+		MyVkMapA[i]
+#else
+		i
+#endif
+		];
+	if (MKC_None != key) {
+		Keyboard_UpdateKeyMap2(key, down);
+	}
+}
+
+#ifndef EnableGrabSpecialKeys
+#if UseWinCE
+#define EnableGrabSpecialKeys 0
+#else
+#define EnableGrabSpecialKeys (MayFullScreen && GrabKeysFullScreen)
+#endif
+#endif /* EnableGrabSpecialKeys */
+
+#if EnableGrabSpecialKeys
+LOCALVAR blnr HaveSetSysParam = falseblnr;
+#endif
+
+LOCALPROC CheckTheCapsLock(void)
+{
+	DoKeyCode(VK_CAPITAL, (GetKeyState(VK_CAPITAL) & 1) != 0);
+}
+
+#if EnableGrabSpecialKeys
+LOCALVAR blnr VK_LWIN_pressed = falseblnr;
+LOCALVAR blnr VK_RWIN_pressed = falseblnr;
+#endif
+
+#if EnableGrabSpecialKeys
+LOCALPROC CheckForLostKeyUps(void)
+{
+	if (HaveSetSysParam) {
+		/* check for lost key ups */
+		if (VK_LWIN_pressed) {
+			if ((GetAsyncKeyState(VK_LWIN) & 0x8000) == 0) {
+				DoKeyCode(VK_LWIN, falseblnr);
+				VK_LWIN_pressed = falseblnr;
+			}
+		}
+		if (VK_RWIN_pressed) {
+			if ((GetAsyncKeyState(VK_RWIN) & 0x8000) == 0) {
+				DoKeyCode(VK_RWIN, falseblnr);
+				VK_RWIN_pressed = falseblnr;
+			}
+		}
+	}
+}
+#endif
+
+LOCALPROC DoVKcode0(int i, blnr down)
+{
+#if EnableGrabSpecialKeys
+	if (HaveSetSysParam) {
+		/* will need to check for lost key ups */
+		if (VK_LWIN == i) {
+			VK_LWIN_pressed = down;
+		} else if (VK_RWIN == i) {
+			VK_RWIN_pressed = down;
+		}
+	}
+#endif
+	DoKeyCode(i, down);
+}
+
+LOCALPROC DoVKcode(int i, ui3r flags, blnr down)
+{
+	switch (i) {
+#if MKC_formac_Control != MKC_formac_RControl
+		case VK_CONTROL:
+			Keyboard_UpdateKeyMap2(TestBit(flags, 0)
+				? MKC_formac_RControl : MKC_formac_Control,
+				down);
+			break;
+#endif
+#if MKC_formac_RCommand != MKC_formac_Command
+		case VK_MENU:
+			Keyboard_UpdateKeyMap2(TestBit(flags, 0)
+				? MKC_formac_RCommand : MKC_formac_Command,
+				down);
+			break;
+#endif
+		case VK_RETURN:
+			Keyboard_UpdateKeyMap2(TestBit(flags, 0)
+				? MKC_formac_Enter : MKC_Return,
+				down);
+			break;
+		case myVK_HOME:
+			Keyboard_UpdateKeyMap2(TestBit(flags, 0)
+				? MKC_formac_Home : MKC_KP7,
+				down);
+			break;
+		case VK_UP:
+			Keyboard_UpdateKeyMap2(TestBit(flags, 0)
+				? MKC_Up : MKC_KP8,
+				down);
+			break;
+		case myVK_PRIOR:
+			Keyboard_UpdateKeyMap2(TestBit(flags, 0)
+				? MKC_formac_PageUp : MKC_KP9,
+				down);
+			break;
+		case VK_LEFT:
+			Keyboard_UpdateKeyMap2(TestBit(flags, 0)
+				? MKC_Left : MKC_KP4,
+				down);
+			break;
+		case myVK_CLEAR:
+			Keyboard_UpdateKeyMap2(TestBit(flags, 0)
+				? MKC_Clear : MKC_KP5,
+				down);
+			break;
+		case VK_RIGHT:
+			Keyboard_UpdateKeyMap2(TestBit(flags, 0)
+				? MKC_Right : MKC_KP6,
+				down);
+			break;
+		case myVK_END:
+			Keyboard_UpdateKeyMap2(TestBit(flags, 0)
+				? MKC_formac_End : MKC_KP1,
+				down);
+			break;
+		case VK_DOWN:
+			Keyboard_UpdateKeyMap2(TestBit(flags, 0)
+				? MKC_Down : MKC_KP2,
+				down);
+			break;
+		case myVK_NEXT:
+			Keyboard_UpdateKeyMap2(TestBit(flags, 0)
+				? MKC_formac_PageDown : MKC_KP3,
+				down);
+			break;
+		case myVK_INSERT:
+			Keyboard_UpdateKeyMap2(TestBit(flags, 0)
+				? MKC_formac_Help : MKC_KP0,
+				down);
+			break;
+		case myVK_DELETE:
+			Keyboard_UpdateKeyMap2(TestBit(flags, 0)
+				? MKC_formac_ForwardDel : MKC_Decimal,
+				down);
+			break;
+		case VK_CAPITAL:
+			CheckTheCapsLock();
+			break;
+		default:
+			if ((i >= 0) && (i < 256)) {
+				DoVKcode0(i, down);
+			}
+			break;
+	}
+}
+
+LOCALVAR blnr WantCmdOptOnReconnect = falseblnr;
+
+LOCALPROC ReconnectKeyCodes3(void)
+{
+	int i;
+
+	CheckTheCapsLock();
+
+	if (WantCmdOptOnReconnect) {
+		WantCmdOptOnReconnect = falseblnr;
+
+		for (i = 0; i < 256; ++i) {
+			if ((GetKeyState(i) & 0x8000) != 0) {
+				if ((VK_CAPITAL != i)
+					&& (VK_RETURN != i))
+				{
+					DoVKcode0(i, trueblnr);
+				}
+			}
+		}
+	}
+}
+
+LOCALPROC DisconnectKeyCodes3(void)
+{
+	DisconnectKeyCodes2();
+	SetCurMouseButton(falseblnr);
+}
+
+#if EnableGrabSpecialKeys
+static HHOOK hKeyHook = NULL;
+#endif
+
+#if EnableGrabSpecialKeys
+typedef struct {
+	DWORD   vkCode;
+	DWORD   scanCode;
+	DWORD   flags;
+	DWORD   time;
+	DWORD   dwExtraInfo;
+} My_KBDLLHOOKSTRUCT;
+#endif
+
+#if EnableGrabSpecialKeys
+LRESULT CALLBACK LowLevelKeyboardProc(
+	int nCode,     /* hook code */
+	WPARAM wParam, /* message identifier */
+	LPARAM lParam  /* pointer to structure with message data */
+);
+#endif
+
+#if EnableGrabSpecialKeys
+LRESULT CALLBACK LowLevelKeyboardProc(
+	int nCode,     /* hook code */
+	WPARAM wParam, /* message identifier */
+	LPARAM lParam  /* pointer to structure with message data */
+)
+{
+	if (nCode == HC_ACTION) {
+		My_KBDLLHOOKSTRUCT *p = (My_KBDLLHOOKSTRUCT *)lParam;
+		if (p->vkCode != VK_CAPITAL) {
+			switch (wParam) {
+				case WM_KEYDOWN:
+				case WM_SYSKEYDOWN:
+					DoVKcode(p->vkCode, p->flags, trueblnr);
+					return 1;
+					break;
+				case WM_KEYUP:
+				case WM_SYSKEYUP:
+					DoVKcode(p->vkCode, p->flags, falseblnr);
+					return 1;
+					break;
+			}
+		}
+	}
+	return CallNextHookEx(hKeyHook, /* handle to current hook */
+		nCode, /* hook code passed to hook procedure */
+		wParam, /* value passed to hook procedure */
+		lParam /* value passed to hook procedure */
+	);
+
+}
+#endif
+
+#if EnableGrabSpecialKeys
+#define My_WH_KEYBOARD_LL 13
+#define My_SPI_SETSCREENSAVERRUNNING 0x0061
+#endif
+
+#if EnableGrabSpecialKeys
+LOCALVAR UINT nPreviousState;
+#endif
+
+#if EnableGrabSpecialKeys
+LOCALPROC GrabSpecialKeys(void)
+{
+	if ((hKeyHook == NULL) && ! HaveSetSysParam) {
+		/* this works on Windows XP */
+		hKeyHook = SetWindowsHookEx(
+			My_WH_KEYBOARD_LL, /* type of hook to install */
+			(HOOKPROC)LowLevelKeyboardProc,
+				/* address of hook procedure */
+			AppInstance,    /* handle to application instance */
+			0   /* identity of thread to install hook for */
+		);
+		if (hKeyHook == NULL) {
+			/* this works on Windows 95/98 */
+			SystemParametersInfo(My_SPI_SETSCREENSAVERRUNNING, TRUE,
+				&nPreviousState, 0);
+			HaveSetSysParam = trueblnr;
+		}
+	}
+}
+#endif
+
+#if EnableGrabSpecialKeys
+LOCALPROC UnGrabSpecialKeys(void)
+{
+	if (hKeyHook != NULL) {
+		(void) UnhookWindowsHookEx(hKeyHook);
+		hKeyHook = NULL;
+	}
+	if (HaveSetSysParam) {
+		SystemParametersInfo(My_SPI_SETSCREENSAVERRUNNING, FALSE,
+			&nPreviousState, 0);
+		HaveSetSysParam = falseblnr;
+	}
+}
+#endif
+
+/* --- priority --- */
+
+#ifndef EnableChangePriority
+#if UseWinCE
+#define EnableChangePriority 0
+#else
+#define EnableChangePriority MayFullScreen
+#endif
+#endif /* EnableChangePriority */
+
+#if EnableChangePriority
+LOCALVAR blnr MyPriorityRaised = falseblnr;
+#endif
+
+#if EnableChangePriority
+LOCALPROC RaiseMyPriority(void)
+{
+	if (! MyPriorityRaised) {
+		if (! SetPriorityClass(
+			GetCurrentProcess(), /* handle to the process */
+			HIGH_PRIORITY_CLASS
+				/* REALTIME_PRIORITY_CLASS (not, killer) */
+				/* priority class value */
+			))
+		{
+			/*
+				not recursive:
+				MacMsg("SetPriorityClass failed",
+					"Sorry, Mini vMac encountered errors"
+					" and cannot continue.", trueblnr);
+			*/
+		}
+		MyPriorityRaised = trueblnr;
+	}
+}
+#endif
+
+#if EnableChangePriority
+LOCALPROC LowerMyPriority(void)
+{
+	if (MyPriorityRaised) {
+		if (! SetPriorityClass(
+			GetCurrentProcess(),        /* handle to the process */
+			NORMAL_PRIORITY_CLASS /* priority class value */
+			))
+		{
+			/*
+				not recursive:
+				MacMsg("SetPriorityClass failed",
+					"Sorry, Mini vMac encountered errors"
+					" and cannot continue.", trueblnr);
+			*/
+		}
+		MyPriorityRaised = falseblnr;
+	}
+}
+#endif
+
+
+/* --- time, date, location --- */
+
+#define dbglog_TimeStuff (0 && dbglog_HAVE)
+
+LOCALVAR ui5b TrueEmulatedTime = 0;
+
+#define MyInvTimeDivPow 16
+#define MyInvTimeDiv (1 << MyInvTimeDivPow)
+#define MyInvTimeDivMask (MyInvTimeDiv - 1)
+#define MyInvTimeStep 1089590 /* 1000 / 60.14742 * MyInvTimeDiv */
+
+LOCALVAR DWORD LastTime;
+
+LOCALVAR DWORD NextIntTime;
+LOCALVAR ui5b NextFracTime;
+
+LOCALPROC IncrNextTime(void)
+{
+	NextFracTime += MyInvTimeStep;
+	NextIntTime += (NextFracTime >> MyInvTimeDivPow);
+	NextFracTime &= MyInvTimeDivMask;
+}
+
+LOCALPROC InitNextTime(void)
+{
+	NextIntTime = LastTime;
+	NextFracTime = 0;
+	IncrNextTime();
+}
+
+LOCALFUNC blnr UpdateTrueEmulatedTime(void)
+{
+	DWORD LatestTime;
+	si5b TimeDiff;
+
+	LatestTime = timeGetTime();
+	if (LatestTime != LastTime) {
+		LastTime = LatestTime;
+		TimeDiff = (LatestTime - NextIntTime);
+			/* this should work even when time wraps */
+		if (TimeDiff >= 0) {
+			if (TimeDiff > 256) {
+				/* emulation interrupted, forget it */
+				++TrueEmulatedTime;
+				InitNextTime();
+
+#if dbglog_TimeStuff
+				dbglog_writelnNum("emulation interrupted",
+					TrueEmulatedTime);
+#endif
+			} else {
+				do {
+					++TrueEmulatedTime;
+					IncrNextTime();
+					TimeDiff = (LatestTime - NextIntTime);
+				} while (TimeDiff >= 0);
+			}
+			return trueblnr;
+		} else if (TimeDiff < -256) {
+			/* clock goofed if ever get here, reset */
+#if dbglog_TimeStuff
+			dbglog_writeln("clock set back");
+#endif
+
+			InitNextTime();
+		}
+	}
+	return falseblnr;
+}
+
+LOCALVAR ui5b TimeSecBase;
+LOCALVAR DWORD TimeMilliBase;
+
+#include "DATE2SEC.h"
+
+LOCALFUNC blnr CheckDateTime(void)
+{
+	ui5b NewMacDateInSecond;
+
+	NewMacDateInSecond =
+		((ui5b)(LastTime - TimeMilliBase)) / 1000 + TimeSecBase;
+	if (CurMacDateInSeconds != NewMacDateInSecond) {
+		CurMacDateInSeconds = NewMacDateInSecond;
+
+		return trueblnr;
+	} else {
+		return falseblnr;
+	}
+}
+
+LOCALFUNC blnr Init60thCheck(void)
+{
+	SYSTEMTIME s;
+#if AutoTimeZone
+	TIME_ZONE_INFORMATION r;
+	DWORD v;
+#endif
+	DWORD t;
+
+	GetLocalTime(&s);
+	t = timeGetTime();
+	TimeSecBase = Date2MacSeconds(s.wSecond, s.wMinute, s.wHour,
+		s.wDay, s.wMonth, s.wYear);
+	TimeMilliBase = t - s.wMilliseconds;
+
+#if AutoTimeZone
+	v = GetTimeZoneInformation(&r);
+	if ((v != 0xFFFFFFFF) && (v != TIME_ZONE_ID_UNKNOWN)) {
+		si5b dlsBias = (v != TIME_ZONE_ID_DAYLIGHT)
+			? r.StandardBias : r.DaylightBias;
+		CurMacDelta = (((ui5b)(- (r.Bias + dlsBias) * 60))
+			& 0x00FFFFFF)
+			| (((v != TIME_ZONE_ID_DAYLIGHT) ? 0 : 0x80)
+				<< 24);
+	}
+#endif
+
+	LastTime = timeGetTime();
+	InitNextTime();
+
+	OnTrueTime = TrueEmulatedTime;
+
+	(void) CheckDateTime();
+
+	return trueblnr;
+}
+
+#ifndef MyTimeResolution
+#define MyTimeResolution 3
+#endif
+	/*
+		Setting MyTimeResolution to 1 seems to drastically slow down
+		the clock in Virtual PC 7.0.2 for Mac. Using 3 is more polite
+		anyway, and should not cause much observable difference.
+	*/
+
+#if (MyTimeResolution != 0)
+LOCALVAR blnr HaveSetTimeResolution = falseblnr;
+#endif
+
+#if (MyTimeResolution != 0)
+LOCALPROC MyTimer_Suspend(void)
+{
+	if (HaveSetTimeResolution) {
+		(void) timeEndPeriod(MyTimeResolution);
+		HaveSetTimeResolution = falseblnr;
+	}
+}
+#endif
+
+#if (MyTimeResolution != 0)
+LOCALPROC MyTimer_Resume(void)
+{
+	TIMECAPS tc;
+
+	if (timeGetDevCaps(&tc, sizeof(TIMECAPS))
+		== TIMERR_NOERROR)
+	{
+		if ((MyTimeResolution >= tc.wPeriodMin)
+			&& (MyTimeResolution <= tc.wPeriodMax))
+		{
+			if (timeBeginPeriod(MyTimeResolution)
+				== TIMERR_NOERROR)
+			{
+				HaveSetTimeResolution = trueblnr;
+			}
+		}
+	}
+}
+#endif
+
+/* --- sound --- */
+
+#if MySoundEnabled
+
+
+#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */
+#define kSoundBuffers (1 << kLn2SoundBuffers)
+#define kSoundBuffMask (kSoundBuffers - 1)
+
+#define DesiredMinFilledSoundBuffs 3
+	/*
+		if too big then sound lags behind emulation.
+		if too small then sound will have pauses.
+	*/
+
+#define kLnOneBuffLen 9
+#define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen)
+#define kOneBuffLen (1UL << kLnOneBuffLen)
+#define kAllBuffLen (1UL << kLnAllBuffLen)
+#define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3)
+#define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3)
+#define kOneBuffSz (1UL << kLnOneBuffSz)
+#define kAllBuffSz (1UL << kLnAllBuffSz)
+#define kOneBuffMask (kOneBuffLen - 1)
+#define kAllBuffMask (kAllBuffLen - 1)
+#define dbhBufferSize (kAllBuffSz + kOneBuffSz)
+
+#define dbglog_SoundStuff (0 && dbglog_HAVE)
+#define dbglog_SoundBuffStats (0 && dbglog_HAVE)
+
+LOCALVAR tpSoundSamp TheSoundBuffer = nullpr;
+LOCALVAR ui4b ThePlayOffset;
+LOCALVAR ui4b TheFillOffset;
+LOCALVAR blnr wantplaying;
+LOCALVAR ui4b MinFilledSoundBuffs;
+LOCALVAR ui4b TheWriteOffset;
+
+#define SOUND_SAMPLERATE /* 22050 */ 22255
+	/* = round(7833600 * 2 / 704) */
+
+
+LOCALPROC FillWithSilence(tpSoundSamp p, int n, trSoundSamp v)
+{
+	int i;
+
+	for (i = n; --i >= 0; ) {
+		*p++ = v;
+	}
+}
+
+
+LOCALVAR HWAVEOUT hWaveOut = NULL;
+LOCALVAR WAVEHDR whdr[kSoundBuffers];
+
+
+LOCALPROC MySound_BeginPlaying(void)
+{
+#if dbglog_SoundStuff
+	fprintf(stderr, "MySound_BeginPlaying\n");
+#endif
+}
+
+LOCALPROC MySound_Start(void)
+{
+	if (hWaveOut == NULL) {
+		WAVEFORMATEX wfex;
+		MMRESULT mmr;
+		int i;
+		tpSoundSamp p;
+		WAVEHDR *pwh;
+
+		wfex.wFormatTag = WAVE_FORMAT_PCM;
+		wfex.nChannels = 1;
+		wfex.nSamplesPerSec = SOUND_SAMPLERATE;
+		wfex.nAvgBytesPerSec = SOUND_SAMPLERATE;
+#if 3 == kLn2SoundSampSz
+		wfex.nBlockAlign = 1;
+		wfex.wBitsPerSample = 8;
+#elif 4 == kLn2SoundSampSz
+		wfex.nBlockAlign = 2;
+		wfex.wBitsPerSample = 16;
+#else
+#error "unsupported audio format"
+#endif
+		wfex.cbSize = 0;
+		mmr = waveOutOpen(&hWaveOut, WAVE_MAPPER, &wfex, 0,
+			0 /* (DWORD) AppInstance */, CALLBACK_NULL);
+		if (mmr != MMSYSERR_NOERROR) {
+			/*
+				not recursive:
+				MacMsg("waveOutOpen failed",
+					"Sorry, Mini vMac encountered errors"
+					" and cannot continue.", trueblnr);
+			*/
+		} else {
+			p = TheSoundBuffer;
+			pwh = whdr;
+			for (i = 0; i < kSoundBuffers; ++i) {
+				pwh->lpData = (LPSTR)p;
+				pwh->dwBufferLength = kOneBuffSz;
+				pwh->dwBytesRecorded = 0;
+				pwh->dwUser = 0;
+				pwh->dwFlags = 0;
+				pwh->dwLoops = 0;
+				mmr = waveOutPrepareHeader(hWaveOut, pwh,
+					sizeof(WAVEHDR));
+				if (mmr != MMSYSERR_NOERROR) {
+					/*
+						not recursive:
+						MacMsg("waveOutPrepareHeader failed",
+							"Sorry, Mini vMac encountered errors"
+							" and cannot continue.", trueblnr);
+					*/
+				} else {
+					pwh->dwFlags |= WHDR_DONE;
+				}
+				p += kOneBuffLen;
+				++pwh;
+			}
+
+			TheFillOffset = 0;
+			ThePlayOffset = 0;
+			TheWriteOffset = 0;
+			MinFilledSoundBuffs = kSoundBuffers;
+			wantplaying = falseblnr;
+		}
+	}
+}
+
+LOCALPROC MySound_Stop(void)
+{
+	MMRESULT mmr;
+	int i;
+
+	wantplaying = falseblnr;
+	if (hWaveOut != NULL) {
+		DWORD StartTime = GetTickCount();
+		for (i = 0; i < kSoundBuffers; ++i) {
+			while (((whdr[i].dwFlags & WHDR_DONE) == 0)
+				&& ((ui5b)(GetTickCount() - StartTime) < 1000))
+			{
+				Sleep(1);
+			}
+
+			mmr = waveOutUnprepareHeader(hWaveOut, &whdr[i],
+				sizeof(WAVEHDR));
+			if (mmr != MMSYSERR_NOERROR) {
+				/*
+					not recursive:
+					MacMsg("waveOutUnprepareHeader failed",
+						"Sorry, Mini vMac encountered errors"
+						" and cannot continue.", trueblnr);
+				*/
+			}
+		}
+
+		mmr = waveOutClose(hWaveOut);
+		if (mmr != MMSYSERR_NOERROR) {
+			/*
+				MacMsg("waveOutClose failed",
+					"Sorry, Mini vMac encountered errors"
+					" and cannot continue.", trueblnr);
+			*/
+		}
+		hWaveOut = NULL;
+	}
+}
+
+LOCALPROC SoundCheckVeryOften(void)
+{
+	if ((hWaveOut != NULL) && (wantplaying)) {
+label_retry:
+		{
+			ui4b FilledSoundBuffs;
+			ui4b ToPlaySize = TheFillOffset - ThePlayOffset;
+			ui4b CurPlayBuffer =
+				(ThePlayOffset >> kLnOneBuffLen) & kSoundBuffMask;
+
+			if ((ToPlaySize > kOneBuffLen)
+				&& ((whdr[CurPlayBuffer].dwFlags & WHDR_DONE) != 0))
+			{
+				ThePlayOffset += kOneBuffLen;
+				goto label_retry;
+			}
+			FilledSoundBuffs = ToPlaySize >> kLnOneBuffLen;
+
+			if (FilledSoundBuffs < MinFilledSoundBuffs) {
+				MinFilledSoundBuffs = FilledSoundBuffs;
+			}
+
+			if (FilledSoundBuffs < 2) {
+				MMRESULT mmr;
+				ui4b PrevPlayOffset = ThePlayOffset - kOneBuffLen;
+				ui4b PrevPlayBuffer =
+					(PrevPlayOffset >> kLnOneBuffLen) & kSoundBuffMask;
+				ui4b LastPlayedOffset =
+					((TheFillOffset >> kLnOneBuffLen) << kLnOneBuffLen)
+						- 1;
+
+				FillWithSilence(
+					TheSoundBuffer + (PrevPlayOffset & kAllBuffMask),
+					kOneBuffLen,
+					*(TheSoundBuffer
+						+ (LastPlayedOffset & kAllBuffMask)));
+				mmr = waveOutWrite(
+					hWaveOut, &whdr[PrevPlayBuffer], sizeof(WAVEHDR));
+				if (mmr != MMSYSERR_NOERROR) {
+					whdr[PrevPlayBuffer].dwFlags |= WHDR_DONE;
+					/*
+						not recursive:
+						MacMsg("waveOutWrite failed",
+							"Sorry, Mini vMac encountered errors"
+							" and cannot continue.", trueblnr);
+					*/
+				}
+				ThePlayOffset = PrevPlayOffset;
+				goto label_retry;
+			}
+		}
+	}
+}
+
+#if 4 == kLn2SoundSampSz
+LOCALPROC ConvertSoundBlockToNative(tpSoundSamp p)
+{
+	int i;
+
+	for (i = kOneBuffLen; --i >= 0; ) {
+		*p++ -= 0x8000;
+	}
+}
+#else
+#define ConvertSoundBlockToNative(p)
+#endif
+
+LOCALPROC MySound_FilledBlocks(void)
+{
+	while (0 != ((TheWriteOffset - TheFillOffset) >> kLnOneBuffLen)) {
+		ui4b CurFillBuffer =
+			(TheFillOffset >> kLnOneBuffLen) & kSoundBuffMask;
+		blnr IsOk = falseblnr;
+
+		ConvertSoundBlockToNative((tpSoundSamp)
+			whdr[CurFillBuffer].lpData);
+
+		if (hWaveOut != NULL) {
+			MMRESULT mmr = waveOutWrite(hWaveOut,
+				&whdr[CurFillBuffer], sizeof(WAVEHDR));
+			if (mmr == MMSYSERR_NOERROR) {
+				IsOk = trueblnr;
+			}
+		}
+
+		if (! IsOk) {
+			/*
+				not recursive:
+				MacMsg("waveOutWrite failed",
+					"Sorry, Mini vMac encountered errors"
+					" and cannot continue.", trueblnr);
+			*/
+			whdr[CurFillBuffer].dwFlags |= WHDR_DONE;
+		}
+
+		TheFillOffset += kOneBuffLen;
+	}
+}
+
+LOCALPROC MySound_WroteABlock(void)
+{
+	if (wantplaying) {
+		MySound_FilledBlocks();
+	} else if (((TheWriteOffset - ThePlayOffset) >> kLnOneBuffLen) < 12)
+	{
+		/* just wait */
+	} else {
+		MySound_FilledBlocks();
+		wantplaying = trueblnr;
+		MySound_BeginPlaying();
+	}
+}
+
+GLOBALOSGLUPROC MySound_EndWrite(ui4r actL)
+{
+	TheWriteOffset += actL;
+
+	if (0 == (TheWriteOffset & kOneBuffMask)) {
+		/* just finished a block */
+
+		MySound_WroteABlock();
+	}
+}
+
+GLOBALOSGLUFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL)
+{
+	ui4b ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset);
+	ui4b WriteBuffContig =
+		kOneBuffLen - (TheWriteOffset & kOneBuffMask);
+
+	if (WriteBuffContig < n) {
+		n = WriteBuffContig;
+	}
+	if (ToFillLen < n) {
+		/* overwrite previous buffer */
+		TheWriteOffset -= kOneBuffLen;
+	}
+
+	*actL = n;
+	return TheSoundBuffer + (TheWriteOffset & kAllBuffMask);
+}
+
+LOCALPROC MySound_SecondNotify(void)
+{
+	if (hWaveOut != NULL) {
+		if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) {
+#if dbglog_SoundStuff
+			dbglog_writeln("MinFilledSoundBuffs too high");
+#endif
+			IncrNextTime();
+		} else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) {
+#if dbglog_SoundStuff
+			dbglog_writeln("MinFilledSoundBuffs too low");
+#endif
+			++TrueEmulatedTime;
+		}
+		MinFilledSoundBuffs = kSoundBuffers;
+	}
+}
+
+#endif
+
+/* --- overall grab --- */
+
+#if MayFullScreen
+LOCALPROC GrabTheMachine(void)
+{
+#if EnableFSMouseMotion
+	StartSaveMouseMotion();
+#endif
+#if EnableChangePriority
+	if ((ui3b) -1 == SpeedValue) {
+		RaiseMyPriority();
+	}
+#endif
+#if EnableGrabSpecialKeys
+	GrabSpecialKeys();
+#endif
+}
+#endif
+
+#if MayFullScreen
+LOCALPROC UnGrabTheMachine(void)
+{
+#if EnableGrabSpecialKeys
+	UnGrabSpecialKeys();
+#endif
+#if EnableFSMouseMotion
+	StopSaveMouseMotion();
+#endif
+#if EnableChangePriority
+	LowerMyPriority();
+#endif
+}
+#endif
+
+#if MayFullScreen
+LOCALVAR blnr GrabMachine = falseblnr;
+#endif
+
+#if MayFullScreen
+LOCALPROC AdjustMachineGrab(void)
+{
+	if (GrabMachine) {
+		if (MainWnd != NULL) {
+			GrabTheMachine();
+		}
+	} else {
+		UnGrabTheMachine();
+	}
+}
+#endif
+
+/* --- basic dialogs --- */
+
+LOCALPROC MyBeginDialog(void)
+{
+	DisconnectKeyCodes3();
+#if MayFullScreen
+	GrabMachine = falseblnr;
+	UnGrabTheMachine();
+#endif
+	ForceShowCursor();
+}
+
+LOCALPROC MyEndDialog(void)
+{
+	ReconnectKeyCodes3();
+}
+
+LOCALPROC CheckSavedMacMsg(void)
+{
+	if (nullpr != SavedBriefMsg) {
+		TCHAR briefMsg0[ClStrMaxLength + 1];
+		TCHAR longMsg0[ClStrMaxLength + 1];
+
+		NativeStrFromCStr(briefMsg0, SavedBriefMsg, falseblnr);
+		NativeStrFromCStr(longMsg0, SavedLongMsg, falseblnr);
+
+		MessageBox(MainWnd, longMsg0, briefMsg0,
+			MB_APPLMODAL | MB_OK | (SavedFatalMsg ? MB_ICONSTOP : 0));
+
+		SavedBriefMsg = nullpr;
+	}
+}
+
+/* --- main window --- */
+
+enum {
+	ID_MENU_NULL = 256,
+	ID_FILE_INSERTDISK1,
+	ID_FILE_QUIT,
+	ID_SPECIAL_MORECOMMANDS,
+	ID_HELP_ABOUT,
+
+	kNum_ID_MENU
+};
+
+
+#if (1 == vMacScreenDepth) || (vMacScreenDepth >= 4)
+#define EnableScalingBuff 1
+#else
+#define EnableScalingBuff (1 && EnableMagnify && (MyWindowScale == 2))
+#endif
+
+#if EnableScalingBuff
+LOCALVAR ui3p ScalingBuff = NULL;
+#endif
+
+LOCALVAR HDC MainWndDC = NULL;
+
+LOCALVAR si5b CmdShow;
+
+LOCALVAR TCHAR WndTitle[_MAX_PATH];
+LOCALVAR const TCHAR WndClassName[] = TEXT("minivmac");
+
+LOCALVAR blnr gBackgroundFlag = falseblnr;
+LOCALVAR blnr gTrueBackgroundFlag = falseblnr;
+LOCALVAR blnr CurSpeedStopped = trueblnr;
+
+LOCALPROC GetWndTitle(void)
+{
+	TCHAR pathName[_MAX_PATH];
+	WIN32_FIND_DATA fd;
+	blnr IsOk = falseblnr;
+
+	if (GetModuleFileName(AppInstance, pathName, _MAX_PATH) != 0) {
+		HANDLE hf = FindFirstFile(pathName, &fd);
+
+		if (hf != INVALID_HANDLE_VALUE) {
+			/* get rid of extension, presumably '.exe' */
+			LPTSTR p = FindLastTerm(fd.cFileName,
+				(TCHAR)('.'));
+			if (p != nullpr) {
+				*--p = (TCHAR)('\0');
+			}
+
+			_tcscpy(WndTitle, fd.cFileName);
+			IsOk = trueblnr;
+			FindClose(hf);
+		}
+	}
+	if (! IsOk) {
+		_tcscpy(WndTitle, TEXT(kStrAppName));
+	}
+}
+
+LOCALPROC DisposeMainWindow(void)
+{
+#if UseWinCE
+	/* Show the taskbar */
+	SHFullScreen(MainWnd, SHFS_SHOWTASKBAR);
+#endif
+
+	if (MainWndDC != NULL) {
+		ReleaseDC(MainWnd, MainWndDC);
+	}
+	if (MainWnd != NULL) {
+		DestroyWindow(MainWnd);
+		MainWnd = NULL; /* so MacMsg will still work */
+	}
+}
+
+enum {
+	kMagStateNormal,
+#if EnableMagnify
+	kMagStateMagnifgy,
+#endif
+	kNumMagStates
+};
+
+#define kMagStateAuto kNumMagStates
+
+#if MayNotFullScreen
+LOCALVAR int CurWinIndx;
+LOCALVAR blnr HavePositionWins[kNumMagStates];
+LOCALVAR POINT WinPositionWins[kNumMagStates];
+#endif
+
+#if MayNotFullScreen
+LOCALPROC MyAppendConvertMenuItem(HMENU hMenu,
+	UINT uIDNewItem, char *s, blnr AddEllipsis)
+{
+	TCHAR ts[ClStrMaxLength + 1];
+
+	NativeStrFromCStr(ts, s, AddEllipsis);
+
+	(void) AppendMenu(hMenu, MF_ENABLED + MF_STRING,
+		uIDNewItem, ts);
+}
+#endif
+
+#if MayNotFullScreen
+LOCALPROC MyAppendSubmenuConvertName(HMENU hMenu,
+	HMENU hSubMenu, char *s)
+{
+	TCHAR ts[ClStrMaxLength + 1];
+	MENUITEMINFO mii;
+
+	NativeStrFromCStr(ts, s, falseblnr);
+
+#if 0
+	(void) InsertMenu(hMenu, 0xFFFFFFFF,
+		MF_BYPOSITION + MF_POPUP + MF_STRING + MF_ENABLED,
+		(UINT)hSubMenu, ts);
+#endif
+
+	memset(&mii, 0, sizeof(MENUITEMINFO));
+	mii.cbSize = sizeof(MENUITEMINFO);
+	mii.fMask = MIIM_TYPE | MIIM_SUBMENU;
+	mii.fType = MFT_STRING;
+	mii.hSubMenu = hSubMenu;
+	mii.dwTypeData = ts;
+	mii.cch = (UINT)_tcslen(ts);
+	(void) InsertMenuItem(hMenu, (UINT) -1, TRUE,
+		&mii);
+}
+#endif
+
+#ifndef kStrMenuFile_win
+#define kStrMenuFile_win kStrMenuFile
+#endif
+
+LOCALFUNC blnr ReCreateMainWindow(void)
+{
+#if MayNotFullScreen
+	HMENU m;
+	int DfltWndX;
+	int DfltWndY;
+	int WinIndx;
+#endif
+	HMENU mb;
+	HWND NewMainWindow;
+	HDC NewMainWndDC = NULL;
+	int ScreenX = GetSystemMetrics(SM_CXSCREEN);
+	int ScreenY = GetSystemMetrics(SM_CYSCREEN);
+	short NewWindowHeight = vMacScreenHeight;
+	short NewWindowWidth = vMacScreenWidth;
+	HWND OldMainWindow = MainWnd;
+	HDC OldMainWndDC = MainWndDC;
+	RECT NewWinR;
+	DWORD MyWStyle;
+	DWORD MyWExStyle;
+
+#if VarFullScreen
+	if (! UseFullScreen)
+#endif
+#if MayNotFullScreen
+	{
+		/* save old position */
+		if (OldMainWindow != NULL) {
+			WinPositionWins[CurWinIndx].x = WndX;
+			WinPositionWins[CurWinIndx].y = WndY;
+		}
+	}
+#endif
+
+#if MayNotFullScreen
+#if EnableMagnify
+	if (WantMagnify) {
+		WinIndx = kMagStateMagnifgy;
+	} else
+#endif
+	{
+		WinIndx = kMagStateNormal;
+	}
+#endif
+
+#if EnableMagnify
+	if (WantMagnify) {
+		NewWindowHeight *= MyWindowScale;
+		NewWindowWidth *= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (WantFullScreen)
+#endif
+#if MayFullScreen
+	{
+		MyWStyle = WS_VISIBLE | WS_POPUP;
+		MyWExStyle = WS_EX_TOPMOST;
+
+		hOffset = (ScreenX - NewWindowWidth) / 2;
+		vOffset = (ScreenY - NewWindowHeight) / 2;
+		if (hOffset < 0) {
+			hOffset = 0;
+		}
+		if (vOffset < 0) {
+			vOffset = 0;
+		}
+
+		NewWinR.left = 0;
+		NewWinR.top = 0;
+		NewWinR.right = ScreenX;
+		NewWinR.bottom = ScreenY;
+	}
+#endif
+#if VarFullScreen
+	else
+#endif
+#if MayNotFullScreen
+	{
+		MyWStyle = WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
+			| WS_MINIMIZEBOX;
+		MyWExStyle = WS_EX_ACCEPTFILES;
+
+		DfltWndX = (ScreenX - NewWindowWidth) / 2;
+		DfltWndY = (ScreenY - NewWindowHeight) / 2;
+
+		if (DfltWndX < 0) {
+			DfltWndX = 0;
+		}
+		if (DfltWndY < 0) {
+			DfltWndY = 0;
+		}
+
+		if (! HavePositionWins[WinIndx]) {
+			WinPositionWins[WinIndx].x = DfltWndX;
+			WinPositionWins[WinIndx].y = DfltWndY;
+			HavePositionWins[WinIndx] = trueblnr;
+		}
+
+		NewWinR.left = WinPositionWins[WinIndx].x;
+		NewWinR.top = WinPositionWins[WinIndx].y;
+		NewWinR.right = NewWinR.left + NewWindowWidth;
+		NewWinR.bottom = NewWinR.top + NewWindowHeight;
+
+		(void) AdjustWindowRectEx(&NewWinR, MyWStyle, TRUE, MyWExStyle);
+
+		if ((NewWinR.right <= 0)
+			|| (NewWinR.left >= ScreenX)
+			|| (NewWinR.bottom <= 0)
+			|| (NewWinR.top >= ScreenY))
+		{
+			NewWinR.left = DfltWndX;
+			NewWinR.top = DfltWndY;
+			NewWinR.right = DfltWndX + NewWindowWidth;
+			NewWinR.bottom = DfltWndY + NewWindowHeight;
+
+			(void) AdjustWindowRectEx(&NewWinR,
+				MyWStyle, TRUE, MyWExStyle);
+		}
+	}
+#endif
+
+	if ((OldMainWindow == NULL)
+#if VarFullScreen
+		|| (WantFullScreen != UseFullScreen)
+#endif
+		)
+	{
+
+#if VarFullScreen
+		if (WantFullScreen)
+#endif
+#if MayFullScreen
+		{
+			mb = NULL;
+		}
+#endif
+#if VarFullScreen
+		else
+#endif
+#if MayNotFullScreen
+		{
+			mb = CreateMenu();
+			if (mb != NULL) {
+				m = CreateMenu();
+				if (m != NULL) {
+					MyAppendConvertMenuItem(m, ID_FILE_INSERTDISK1,
+						kStrMenuItemOpen, trueblnr);
+					(void) AppendMenu(m, MF_SEPARATOR, 0, NULL);
+					MyAppendConvertMenuItem(m, ID_FILE_QUIT,
+						kStrMenuItemQuit, falseblnr);
+					MyAppendSubmenuConvertName(mb, m, kStrMenuFile_win);
+				}
+				m = CreateMenu();
+				if (m != NULL) {
+					MyAppendConvertMenuItem(m, ID_SPECIAL_MORECOMMANDS,
+						kStrMenuItemMore, trueblnr);
+					MyAppendSubmenuConvertName(mb, m, kStrMenuSpecial);
+				}
+				m = CreateMenu();
+				if (m != NULL) {
+					MyAppendConvertMenuItem(m, ID_HELP_ABOUT,
+						kStrMenuItemAbout, trueblnr);
+					MyAppendSubmenuConvertName(mb, m, kStrMenuHelp);
+				}
+			}
+		}
+#endif
+
+		NewMainWindow = CreateWindowEx(
+			MyWExStyle,
+			WndClassName,
+			WndTitle,
+			MyWStyle,
+			NewWinR.left, NewWinR.top,
+			NewWinR.right - NewWinR.left, NewWinR.bottom - NewWinR.top,
+			NULL,
+			mb,
+			AppInstance, NULL);
+		if (NewMainWindow == NULL) {
+			MacMsg("CreateWindow failed",
+				"Sorry, Mini vMac encountered errors"
+				" and cannot continue.", trueblnr);
+			return falseblnr;
+		}
+
+		NewMainWndDC = GetDC(NewMainWindow);
+		if (NewMainWndDC == NULL) {
+			MacMsg("GetDC failed",
+				"Sorry, Mini vMac encountered errors"
+				" and cannot continue.", trueblnr);
+			DestroyWindow(NewMainWindow);
+			return falseblnr;
+		}
+	} else {
+		NewMainWndDC = OldMainWndDC;
+		NewMainWindow = OldMainWindow;
+		(void) MoveWindow(NewMainWindow, NewWinR.left, NewWinR.top,
+			NewWinR.right - NewWinR.left, NewWinR.bottom - NewWinR.top,
+			TRUE);
+	}
+
+#if 0 != vMacScreenDepth
+	ColorModeWorks = trueblnr;
+#endif
+
+	{
+		POINT p;
+
+		/*
+			Find out where the window really went, on
+			the off chance that the WM_MOVE message wasn't
+			called on CreateWindowEx/MoveWindow, or that
+			the window wasn't put where asked for.
+		*/
+		p.x = 0;
+		p.y = 0;
+		(void) MapWindowPoints(NewMainWindow, NULL, &p, 1);
+		WndX = (si4b)p.x;
+		WndY = (si4b)p.y;
+	}
+
+#if MayFullScreen
+	GrabMachine = falseblnr;
+	UnGrabTheMachine();
+#endif
+
+#if UseWinCE && 0
+	/* Show the taskbar */
+	SHFullScreen(MainWnd, SHFS_SHOWTASKBAR);
+#endif
+
+#if MayNotFullScreen
+	CurWinIndx = WinIndx;
+#endif
+
+	MainWnd = NewMainWindow;
+	MainWndDC = NewMainWndDC;
+	gTrueBackgroundFlag = falseblnr;
+#if VarFullScreen
+	UseFullScreen = WantFullScreen;
+#endif
+#if EnableMagnify
+	UseMagnify = WantMagnify;
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		ViewHSize = ScreenX;
+		ViewVSize = ScreenY;
+#if EnableMagnify
+		if (UseMagnify) {
+			ViewHSize /= MyWindowScale;
+			ViewVSize /= MyWindowScale;
+		}
+#endif
+		if (ViewHSize >= vMacScreenWidth) {
+			ViewHStart = 0;
+			ViewHSize = vMacScreenWidth;
+		} else {
+			ViewHSize &= ~ 1;
+		}
+		if (ViewVSize >= vMacScreenHeight) {
+			ViewVStart = 0;
+			ViewVSize = vMacScreenHeight;
+		} else {
+			ViewVSize &= ~ 1;
+		}
+	}
+#endif
+
+	if (NewMainWindow != OldMainWindow) {
+		ShowWindow(NewMainWindow, SW_SHOW /* CmdShow */);
+		if (OldMainWndDC != NULL) {
+			ReleaseDC(MainWnd, OldMainWndDC);
+		}
+		if (OldMainWindow != NULL) {
+			/* ShowWindow(OldMainWindow, SW_HIDE); */
+			DestroyWindow(OldMainWindow);
+		}
+
+		DisconnectKeyCodes3();
+			/* since key events per window */
+	} else {
+		(void) InvalidateRgn(MainWnd, NULL, FALSE);
+	}
+
+#if UseWinCE
+	/* Create and set logical palette for this window */
+	{
+		HPALETTE hpal;
+		LOGPALETTE *lppal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +
+			sizeof(PALETTEENTRY) * 2);
+
+		if (! lppal)
+		{
+			MacMsg("CreateWindow failed",
+				"Sorry, Mini vMac encountered errors"
+				" and cannot continue.", trueblnr);
+			return falseblnr;
+		}
+
+		lppal->palNumEntries = 2;
+		lppal->palVersion = 0x0300;
+		lppal->palPalEntry[0].peRed   = 255;
+		lppal->palPalEntry[0].peGreen = 255;
+		lppal->palPalEntry[0].peBlue  = 255;
+		lppal->palPalEntry[0].peFlags = 0;
+		lppal->palPalEntry[1].peRed   = 0;
+		lppal->palPalEntry[1].peGreen = 0;
+		lppal->palPalEntry[1].peBlue  = 0;
+		lppal->palPalEntry[1].peFlags = 0;
+
+		hpal = CreatePalette(lppal);
+
+		if (hpal == NULL) {
+			free(lppal);
+			MacMsg("CreateWindow failed",
+				"Sorry, Mini vMac encountered errors"
+				" and cannot continue.", trueblnr);
+			return falseblnr;
+		}
+
+		if (SelectPalette(MainWndDC, hpal, FALSE) == NULL) {
+			free(lppal);
+			MacMsg("CreateWindow failed",
+				"Sorry, Mini vMac encountered errors"
+				" and cannot continue.", trueblnr);
+			return falseblnr;
+		}
+
+		if (RealizePalette(MainWndDC) == GDI_ERROR) {
+			free(lppal);
+			MacMsg("CreateWindow failed",
+				"Sorry, Mini vMac encountered errors"
+				" and cannot continue.", trueblnr);
+			return falseblnr;
+		}
+
+		free(lppal);
+	}
+#endif
+
+#if UseWinCE
+	/* Hide the taskbar */
+	SHFullScreen(MainWnd, SHFS_HIDETASKBAR);
+	(void) MoveWindow(MainWnd, 0, 0,
+			ScreenX, ScreenY, TRUE);
+#endif
+
+	if (HaveCursorHidden) {
+		(void) MyMoveMouse(CurMouseH, CurMouseV);
+		WantCursorHidden = trueblnr;
+	}
+
+	return trueblnr;
+}
+
+#if UseWinCE
+LOCALFUNC blnr AlreadyRunningCheck(void)
+{
+	/*
+		Adapted from example program from Microsoft eMbedded Visual C++
+	*/
+
+	/* If it is already running, then focus on the window */
+	HWND hWnd = FindWindow(WndClassName, WndTitle);
+	if (hWnd == NULL) {
+		return falseblnr;
+	} else {
+		/*
+			Set focus to foremost child window.
+			The "| 0x01" is used to bring any owned
+			windows to the foreground and activate them.
+		*/
+		SetForegroundWindow((HWND)((ULONG) hWnd | 0x00000001));
+		return trueblnr;
+	}
+}
+#endif
+
+typedef struct BITMAPINFOHEADER256 {
+	BITMAPINFOHEADER bmi;
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+	RGBQUAD colors[CLUT_size];
+#else
+	RGBQUAD colors[2];
+#endif
+} BITMAPINFOHEADER256;
+
+#if EnableMagnify
+#define MyScaledHeight (MyWindowScale * vMacScreenHeight)
+#define MyScaledWidth (MyWindowScale * vMacScreenWidth)
+#endif
+
+LOCALPROC HaveChangedScreenBuff(si4b top, si4b left,
+	si4b bottom, si4b right)
+{
+	BITMAPINFOHEADER256 bmh;
+	ui3b *cdb = GetCurDrawBuff();
+	int XDest;
+	int YDest;
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		if (top < ViewVStart) {
+			top = ViewVStart;
+		}
+		if (left < ViewHStart) {
+			left = ViewHStart;
+		}
+		if (bottom > ViewVStart + ViewVSize) {
+			bottom = ViewVStart + ViewVSize;
+		}
+		if (right > ViewHStart + ViewHSize) {
+			right = ViewHStart + ViewHSize;
+		}
+
+		if ((top >= bottom) || (left >= right)) {
+			goto label_exit;
+		}
+	}
+#endif
+
+	XDest = left;
+	YDest = top;
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		XDest -= ViewHStart;
+		YDest -= ViewVStart;
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+		XDest *= MyWindowScale;
+		YDest *= MyWindowScale;
+	}
+#endif
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		XDest += hOffset;
+		YDest += vOffset;
+	}
+#endif
+
+#if 0
+	{ /* testing code */
+		if (PatBlt(MainWndDC,
+			(int)left - 1,
+			(int)top - 1,
+			(int)right - left + 2,
+			(int)bottom - top + 2, PATCOPY)) {
+		}
+	}
+#endif
+#if 0 != vMacScreenDepth
+	if (UseColorMode) {
+		int i;
+		int nDestWidth = (right - left);
+		int nDestHeight = (bottom - top);
+#if 1 == vMacScreenDepth
+		ui3b *p
+			= ScalingBuff + ((ui5r)vMacScreenWidth / 4) * top;
+#elif vMacScreenDepth >= 4
+		ui3b *p = ScalingBuff + (ui5r)vMacScreenByteWidth * top;
+#else
+		ui3b *p = cdb + (ui5r)vMacScreenByteWidth * top;
+#endif
+
+		memset(&bmh, 0, sizeof (bmh));
+		bmh.bmi.biSize = sizeof(BITMAPINFOHEADER);
+		bmh.bmi.biWidth = vMacScreenWidth;
+		bmh.bmi.biHeight = - (bottom - top);
+		bmh.bmi.biPlanes = 1;
+#if 1 == vMacScreenDepth
+		bmh.bmi.biBitCount = 4;
+#else
+		bmh.bmi.biBitCount = (1 << vMacScreenDepth);
+#endif
+		bmh.bmi.biCompression= BI_RGB;
+		bmh.bmi.biSizeImage = 0;
+		bmh.bmi.biXPelsPerMeter = 0;
+		bmh.bmi.biYPelsPerMeter = 0;
+#if 1 == vMacScreenDepth
+		bmh.bmi.biClrUsed = 4;
+#else
+		bmh.bmi.biClrUsed = 0;
+#endif
+		bmh.bmi.biClrImportant = 0;
+
+#if vMacScreenDepth < 4
+		for (i = 0; i < CLUT_size; ++i) {
+			bmh.colors[i].rgbRed = CLUT_reds[i] >> 8;
+			bmh.colors[i].rgbGreen = CLUT_greens[i] >> 8;
+			bmh.colors[i].rgbBlue = CLUT_blues[i] >> 8;
+			bmh.colors[i].rgbReserved = 0;
+		}
+#endif
+
+#if 1 == vMacScreenDepth
+		{
+			int j;
+			ui3b *p1 = (ui3b *)(cdb + (ui5r)vMacScreenByteWidth * top);
+			ui4b *p2 = (ui4b *)p;
+			for (i = bottom - top; --i >= 0; ) {
+				for (j = vMacScreenWidth / 4; --j >= 0; ) {
+					ui4r t0 = *p1++;
+					*p2 ++
+						= ((t0 & 0xC0) >> 2)
+						| ((t0 & 0x30) >> 4)
+						| ((t0 & 0x0C) << 10)
+						| ((t0 & 0x03) << 8);
+				}
+			}
+		}
+#elif 4 == vMacScreenDepth
+		{
+			int j;
+			ui4b *p1 = (ui4b *)(cdb + (ui5r)vMacScreenByteWidth * top);
+			ui4b *p2 = (ui4b *)p;
+			for (i = bottom - top; --i >= 0; ) {
+				for (j = vMacScreenWidth; --j >= 0; ) {
+					ui4r t0 = *p1++;
+					*p2 ++ =
+						((t0 & 0xFF00) >> 8) | ((t0 & 0x00FF) << 8);
+				}
+			}
+		}
+#elif 5 == vMacScreenDepth
+		{
+			int j;
+			ui5b *p1 = (ui5b *)(cdb + (ui5r)vMacScreenByteWidth * top);
+			ui5b *p2 = (ui5b *)p;
+			for (i = bottom - top; --i >= 0; ) {
+				for (j = vMacScreenWidth; --j >= 0; ) {
+					ui5r t0 = *p1++;
+					*p2++
+						= ((t0 & 0xFF000000) >> 24)
+						| ((t0 & 0x00FF0000) >> 8)
+						| ((t0 & 0x0000FF00) << 8)
+						| ((t0 & 0x000000FF) << 24);
+				}
+			}
+		}
+#endif
+
+#if EnableMagnify
+		if (UseMagnify) {
+			nDestWidth *= MyWindowScale;
+			nDestHeight *= MyWindowScale;
+		}
+#endif
+
+		if (StretchDIBits(
+			MainWndDC, /* handle of device context */
+			XDest,
+				/* x-coordinate of upper-left corner of dest. rect. */
+			YDest,
+				/* y-coordinate of upper-left corner of dest. rect. */
+			nDestWidth, /* dest. rectangle width */
+			nDestHeight, /* dest. rectangle height */
+			left,
+				/* x-coordinate of lower-left corner of source rect. */
+			0, /* y-coordinate of lower-left corner of source rect. */
+			(right - left), /* source rectangle width */
+			(bottom - top), /* source rectangle height */
+			(CONST VOID *)p, /* address of array with DIB bits */
+			(const struct tagBITMAPINFO *)&bmh,
+				/* address of structure with bitmap info. */
+			DIB_RGB_COLORS, /* RGB or palette indices */
+			SRCCOPY
+		) == 0) {
+			/* ReportWinLastError(); */
+		}
+	} else
+#endif
+	{
+		ui3b *p = cdb + (ui5r)vMacScreenMonoByteWidth * top;
+
+		memset(&bmh, 0, sizeof (bmh));
+		bmh.bmi.biSize = sizeof(BITMAPINFOHEADER);
+		bmh.bmi.biWidth = vMacScreenWidth;
+		bmh.bmi.biHeight = - (bottom - top);
+		bmh.bmi.biPlanes = 1;
+		bmh.bmi.biBitCount = 1;
+		bmh.bmi.biCompression= BI_RGB;
+		bmh.bmi.biSizeImage = 0;
+		bmh.bmi.biXPelsPerMeter = 0;
+		bmh.bmi.biYPelsPerMeter = 0;
+		bmh.bmi.biClrUsed = 0;
+		bmh.bmi.biClrImportant = 0;
+#if ! UseWinCE
+		bmh.colors[0].rgbRed = 255;
+		bmh.colors[0].rgbGreen = 255;
+		bmh.colors[0].rgbBlue = 255;
+		bmh.colors[0].rgbReserved = 0;
+		bmh.colors[1].rgbRed = 0;
+		bmh.colors[1].rgbGreen = 0;
+		bmh.colors[1].rgbBlue = 0;
+		bmh.colors[1].rgbReserved = 0;
+#endif
+
+#if EnableMagnify
+		if (UseMagnify) {
+#if EnableScalingBuff
+			if (ScalingBuff != NULL) {
+				int i;
+				int j;
+				int k;
+				ui4r left1 = left & (~ 7);
+				ui4r right1 = (right + 7) & (~ 7);
+				ui4r jn = (right1 - left1) / 8;
+				ui3b *p1 =
+					cdb + ((left1 + vMacScreenWidth * (ui5r)top) / 8);
+				ui3b *p2 = ScalingBuff
+					/*
+						+ ((left1 + vMacScreenWidth * MyWindowScale
+								* (ui5r)top)
+							* MyWindowScale / 8)
+					*/
+					;
+				ui3b *p3;
+				ui3b t0;
+				ui3b t1;
+				ui3b t2;
+				ui3b m;
+
+				for (i = bottom - top; --i >= 0; ) {
+					p3 = p2;
+					for (j = jn; --j >= 0; ) {
+						t0 = *p1++;
+						t1 = t0;
+						m = 0x80;
+						t2 = 0;
+						for (k = 4; --k >= 0; ) {
+							t2 |= t1 & m;
+							t1 >>= 1;
+							m >>= 2;
+						}
+						*p2++ = t2 | (t2 >> 1);
+
+						t1 = t0 << 4;
+						m = 0x80;
+						t2 = 0;
+						for (k = 4; --k >= 0; ) {
+							t2 |= t1 & m;
+							t1 >>= 1;
+							m >>= 2;
+						}
+						*p2++ = t2 | (t2 >> 1);
+					}
+					p1 += vMacScreenWidth / 8 - jn;
+					p2 += MyScaledWidth / 8 - (MyWindowScale * jn);
+					for (j = MyWindowScale * jn; --j >= 0; ) {
+						*p2++ = *p3++;
+					}
+					p2 += MyScaledWidth / 8 - (MyWindowScale * jn);
+				}
+
+				bmh.bmi.biWidth = vMacScreenWidth * MyWindowScale;
+				bmh.bmi.biHeight = - ((bottom - top) * MyWindowScale);
+				if (SetDIBitsToDevice(
+					MainWndDC, /* handle of device context */
+					XDest,
+						/*
+							x-coordinate of upper-left corner
+							of dest. rect.
+						*/
+					YDest,
+						/*
+							y-coordinate of upper-left corner
+							of dest. rect.
+						*/
+					(right - left) * MyWindowScale,
+						/* source rectangle width */
+					(bottom - top) * MyWindowScale,
+						/* source rectangle height */
+					(left & 7) * MyWindowScale,
+						/*
+							x-coordinate of lower-left corner
+							of source rect.
+						*/
+					0,
+						/*
+							y-coordinate of lower-left corner
+							of source rect.
+						*/
+					0, /* first scan line in array */
+					(bottom - top) * MyWindowScale,
+						/* number of scan lines */
+					(CONST VOID *)ScalingBuff,
+						/* address of array with DIB bits */
+					(const struct tagBITMAPINFO *)&bmh,
+						/* address of structure with bitmap info. */
+#if ! UseWinCE
+					DIB_RGB_COLORS /* RGB or palette indices */
+#else
+					DIB_PAL_COLORS /* palette indices */
+#endif
+				) == 0) {
+					/* ReportWinLastError(); */
+				}
+			}
+#else
+			if (StretchDIBits(
+				MainWndDC, /* handle of device context */
+				XDest,
+					/*
+						x-coordinate of upper-left corner of dest. rect.
+					*/
+				YDest,
+					/*
+						y-coordinate of upper-left corner of dest. rect.
+					*/
+				(right - left) * MyWindowScale,
+					/* dest. rectangle width */
+				(bottom - top) * MyWindowScale,
+					/* dest. rectangle height */
+				left,
+					/*
+						x-coordinate of lower-left corner
+						of source rect.
+					*/
+				0,
+					/*
+						y-coordinate of lower-left corner
+						of source rect.
+					*/
+				(right - left), /* source rectangle width */
+				(bottom - top), /* source rectangle height */
+				(CONST VOID *)p, /* address of array with DIB bits */
+				(const struct tagBITMAPINFO *)&bmh,
+					/* address of structure with bitmap info. */
+#if ! UseWinCE
+				DIB_RGB_COLORS, /* RGB or palette indices */
+#else
+				DIB_PAL_COLORS, /* palette indices */
+#endif
+				SRCCOPY
+			) == 0) {
+				/* ReportWinLastError(); */
+			}
+#endif
+		} else
+#endif
+
+		{
+			if (SetDIBitsToDevice(
+				MainWndDC, /* handle of device context */
+				XDest,
+					/*
+						x-coordinate of upper-left corner of dest. rect.
+					*/
+				YDest,
+					/*
+						y-coordinate of upper-left corner of dest. rect.
+					*/
+				(right - left), /* source rectangle width */
+				(bottom - top), /* source rectangle height */
+				left,
+					/*
+						x-coordinate of lower-left corner
+						of source rect.
+					*/
+				0,
+					/*
+						y-coordinate of lower-left corner
+						of source rect.
+					*/
+				0, /* first scan line in array */
+				(bottom - top), /* number of scan lines */
+				(CONST VOID *)p, /* address of array with DIB bits */
+				(const struct tagBITMAPINFO *)&bmh,
+					/* address of structure with bitmap info. */
+#if ! UseWinCE
+				DIB_RGB_COLORS /* RGB or palette indices */
+#else
+				DIB_PAL_COLORS /* palette indices */
+#endif
+			) == 0) {
+				/* ReportWinLastError(); */
+			}
+		}
+	}
+
+#if MayFullScreen
+label_exit:
+	;
+#endif
+}
+
+LOCALPROC Screen_DrawAll(void)
+{
+	HaveChangedScreenBuff(0, 0, vMacScreenHeight, vMacScreenWidth);
+}
+
+LOCALPROC MyDrawChangesAndClear(void)
+{
+	if (ScreenChangedBottom > ScreenChangedTop) {
+		HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft,
+			ScreenChangedBottom, ScreenChangedRight);
+		ScreenClearChanges();
+	}
+}
+
+GLOBALOSGLUPROC DoneWithDrawingForTick(void)
+{
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		AutoScrollScreen();
+	}
+#endif
+	MyDrawChangesAndClear();
+}
+
+LOCALFUNC blnr InitTheCursor(void)
+{
+	SetCursor(LoadCursor(NULL, IDC_ARROW));
+	return trueblnr;
+}
+
+#if EnableFSMouseMotion
+LOCALPROC MyMouseConstrain(void)
+{
+	si4b shiftdh;
+	si4b shiftdv;
+
+	if (SavedMouseH < ViewHStart + (ViewHSize / 4)) {
+		shiftdh = ViewHSize / 2;
+	} else if (SavedMouseH > ViewHStart + ViewHSize - (ViewHSize / 4))
+	{
+		shiftdh = - ViewHSize / 2;
+	} else {
+		shiftdh = 0;
+	}
+	if (SavedMouseV < ViewVStart + (ViewVSize / 4)) {
+		shiftdv = ViewVSize / 2;
+	} else if (SavedMouseV > ViewVStart + ViewVSize - (ViewVSize / 4))
+	{
+		shiftdv = - ViewVSize / 2;
+	} else {
+		shiftdv = 0;
+	}
+	if ((shiftdh != 0) || (shiftdv != 0)) {
+		SavedMouseH += shiftdh;
+		SavedMouseV += shiftdv;
+		if (! MyMoveMouse(SavedMouseH, SavedMouseV)) {
+			HaveMouseMotion = falseblnr;
+		}
+	}
+}
+#endif
+
+LOCALPROC MousePositionNotify(LONG NewMousePosx, LONG NewMousePosy)
+{
+	blnr ShouldHaveCursorHidden = trueblnr;
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		NewMousePosx -= hOffset;
+		NewMousePosy -= vOffset;
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+		NewMousePosx /= MyWindowScale;
+		NewMousePosy /= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		NewMousePosx += ViewHStart;
+		NewMousePosy += ViewVStart;
+	}
+#endif
+
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		MyMousePositionSetDelta(NewMousePosx - SavedMouseH,
+			NewMousePosy - SavedMouseV);
+		SavedMouseH = NewMousePosx;
+		SavedMouseV = NewMousePosy;
+	} else
+#endif
+	{
+		if (NewMousePosx < 0) {
+			NewMousePosx = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePosx > vMacScreenWidth) {
+			NewMousePosx = vMacScreenWidth - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+		if (NewMousePosy < 0) {
+			NewMousePosy = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePosy > vMacScreenHeight) {
+			NewMousePosy = vMacScreenHeight - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+
+#if VarFullScreen
+		if (UseFullScreen)
+#endif
+#if MayFullScreen
+		{
+			ShouldHaveCursorHidden = trueblnr;
+		}
+#endif
+
+#if ! UseWinCE
+		/* if (ShouldHaveCursorHidden || CurMouseButton) */
+		/*
+			for a game like arkanoid, would like mouse to still
+			move even when outside window in one direction
+		*/
+#endif
+		MyMousePositionSet(NewMousePosx, NewMousePosy);
+	}
+
+	WantCursorHidden = ShouldHaveCursorHidden;
+}
+
+#if ! UseWinCE
+LOCALPROC CheckMouseState(void)
+{
+	POINT NewMousePos;
+
+	GetCursorPos(&NewMousePos);
+	NewMousePos.x -= WndX;
+	NewMousePos.y -= WndY;
+	MousePositionNotify(NewMousePos.x, NewMousePos.y);
+}
+#endif
+
+LOCALVAR const ui3b Native2MacRomanTab[] = {
+	0xAD, 0xB0, 0xE2, 0xC4, 0xE3, 0xC9, 0xA0, 0xE0,
+	0xF6, 0xE4, 0xB6, 0xDC, 0xCE, 0xB2, 0xB3, 0xB7,
+	0xB8, 0xD4, 0xD5, 0xD2, 0xD3, 0xA5, 0xD0, 0xD1,
+	0xF7, 0xAA, 0xC5, 0xDD, 0xCF, 0xB9, 0xC3, 0xD9,
+	0xCA, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4, 0xBA, 0xA4,
+	0xAC, 0xA9, 0xBB, 0xC7, 0xC2, 0xBD, 0xA8, 0xF8,
+	0xA1, 0xB1, 0xC6, 0xD7, 0xAB, 0xB5, 0xA6, 0xE1,
+	0xFC, 0xDA, 0xBC, 0xC8, 0xDE, 0xDF, 0xF0, 0xC0,
+	0xCB, 0xE7, 0xE5, 0xCC, 0x80, 0x81, 0xAE, 0x82,
+	0xE9, 0x83, 0xE6, 0xE8, 0xED, 0xEA, 0xEB, 0xEC,
+	0xF5, 0x84, 0xF1, 0xEE, 0xEF, 0xCD, 0x85, 0xF9,
+	0xAF, 0xF4, 0xF2, 0xF3, 0x86, 0xFA, 0xFB, 0xA7,
+	0x88, 0x87, 0x89, 0x8B, 0x8A, 0x8C, 0xBE, 0x8D,
+	0x8F, 0x8E, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,
+	0xFD, 0x96, 0x98, 0x97, 0x99, 0x9B, 0x9A, 0xD6,
+	0xBF, 0x9D, 0x9C, 0x9E, 0x9F, 0xFE, 0xFF, 0xD8
+};
+
+#if IncludePbufs
+LOCALFUNC tMacErr NativeTextToMacRomanPbuf(HGLOBAL x, tPbuf *r)
+{
+#if MyUseUni
+#define MyUnsignedChar ui4b
+#else
+#define MyUnsignedChar ui3b
+#endif
+	HGLOBAL h;
+	LPTSTR p1;
+	ui5b n;
+	MyUnsignedChar v;
+	tMacErr err = mnvm_miscErr;
+
+	p1 = GlobalLock(x);
+	if (p1 != NULL) {
+		n = 0;
+		while ((v = *p1++) != 0) {
+			if (v != 10) {
+				++n;
+			}
+		}
+		(void) GlobalUnlock(x);
+
+		h = GlobalAlloc(GMEM_DDESHARE, n);
+		if (h != NULL) {
+			p1 = GlobalLock(x);
+			if (p1 != NULL) {
+				ui3b *p2 = GlobalLock(h);
+				if (p2 != NULL) {
+					while ((v = (MyUnsignedChar)*p1++) != 0) {
+						if (v >= 128) {
+							*p2++ = Native2MacRomanTab[v & 0x7F];
+								/*
+									if MyUseUni, then for gives
+									garbage for v > 256.
+								*/
+						} else if (v != 10) {
+							*p2++ = v;
+						}
+					}
+
+					err = mnvm_noErr;
+
+					(void) GlobalUnlock(h);
+				}
+				(void) GlobalUnlock(x);
+			}
+
+			if (mnvm_noErr != err) {
+				(void) GlobalFree(h);
+			} else {
+				err = PbufNewFromHandle(h, n, r);
+			}
+		}
+	}
+
+	return err;
+}
+#endif
+
+LOCALVAR const ui3b MacRoman2NativeTab[] = {
+	0xC4, 0xC5, 0xC7, 0xC9, 0xD1, 0xD6, 0xDC, 0xE1,
+	0xE0, 0xE2, 0xE4, 0xE3, 0xE5, 0xE7, 0xE9, 0xE8,
+	0xEA, 0xEB, 0xED, 0xEC, 0xEE, 0xEF, 0xF1, 0xF3,
+	0xF2, 0xF4, 0xF6, 0xF5, 0xFA, 0xF9, 0xFB, 0xFC,
+	0x86, 0xB0, 0xA2, 0xA3, 0xA7, 0x95, 0xB6, 0xDF,
+	0xAE, 0xA9, 0x99, 0xB4, 0xA8, 0x80, 0xC6, 0xD8,
+	0x81, 0xB1, 0x8D, 0x8E, 0xA5, 0xB5, 0x8A, 0x8F,
+	0x90, 0x9D, 0xA6, 0xAA, 0xBA, 0xAD, 0xE6, 0xF8,
+	0xBF, 0xA1, 0xAC, 0x9E, 0x83, 0x9A, 0xB2, 0xAB,
+	0xBB, 0x85, 0xA0, 0xC0, 0xC3, 0xD5, 0x8C, 0x9C,
+	0x96, 0x97, 0x93, 0x94, 0x91, 0x92, 0xF7, 0xB3,
+	0xFF, 0x9F, 0xB9, 0xA4, 0x8B, 0x9B, 0xBC, 0xBD,
+	0x87, 0xB7, 0x82, 0x84, 0x89, 0xC2, 0xCA, 0xC1,
+	0xCB, 0xC8, 0xCD, 0xCE, 0xCF, 0xCC, 0xD3, 0xD4,
+	0xBE, 0xD2, 0xDA, 0xDB, 0xD9, 0xD0, 0x88, 0x98,
+	0xAF, 0xD7, 0xDD, 0xDE, 0xB8, 0xF0, 0xFD, 0xFE
+};
+
+#if IncludePbufs
+LOCALFUNC blnr MacRomanTextToNativeHand(tPbuf Pbuf_no,
+	blnr IsFileName, HGLOBAL *r)
+{
+	HGLOBAL h;
+	ui5b i;
+	ui5b rn = 0;
+	HGLOBAL bh = PbufDat[Pbuf_no];
+	ui5b L = PbufSize[Pbuf_no];
+	blnr IsOk = falseblnr;
+
+	if (IsFileName) {
+		if (L > 255) {
+			L = 255;
+		}
+	} else {
+		ui3b *Buffer = (ui3b *)GlobalLock(bh);
+		if (Buffer != NULL) {
+			for (i = 0; i < L; ++i) {
+				if (Buffer[i] == 13) {
+					++rn;
+				}
+			}
+			(void) GlobalUnlock(bh);
+		}
+	}
+
+	h = GlobalAlloc(GMEM_DDESHARE, (L + rn + 1) * sizeof(TCHAR));
+	if (h != NULL) {
+		ui3b *Buffer = (ui3b *)GlobalLock(bh);
+		if (Buffer != NULL) {
+			LPTSTR p1 = GlobalLock(h);
+			if (p1 != NULL) {
+				for (i = 0; i < L; ++i) {
+					TCHAR y;
+					ui3b x = ((ui3b *)Buffer)[i];
+					if (x >= 128) {
+						y = (TCHAR)MacRoman2NativeTab[x - 128];
+					} else {
+						if (IsFileName) {
+							if ((x < 32)
+								|| ('\\' == x) || ('/' == x)
+								|| (':' == x) || ('*' == x)
+								|| ('?' == x) || ('"' == x)
+								|| ('<' == x) || ('>' == x)
+								|| ('|' == x))
+							{
+								y = (TCHAR)('-');
+							} else {
+								y = (TCHAR)x;
+							}
+						} else {
+							if (13 == x) {
+								*p1++ = (TCHAR)(13);
+								y = (TCHAR)(10);
+							} else {
+								y = (TCHAR)x;
+							}
+						}
+					}
+					*p1++ = y;
+				}
+				*p1++ = (TCHAR) 0; /* null character */
+
+				*r = h;
+				IsOk = trueblnr;
+
+				(void) GlobalUnlock(h);
+			}
+			(void) GlobalUnlock(bh);
+		}
+		if (! IsOk) {
+			(void) GlobalFree(h);
+		}
+	}
+
+	return IsOk;
+}
+#endif
+
+#if IncludeHostTextClipExchange
+GLOBALOSGLUFUNC tMacErr HTCEexport(tPbuf i)
+{
+	HGLOBAL h;
+	tMacErr err = mnvm_miscErr;
+
+	if (MacRomanTextToNativeHand(i, falseblnr, &h)) {
+		if (! OpenClipboard(MainWnd)) {
+			/* ReportGetLastError(); */
+		} else {
+			if (! EmptyClipboard()) {
+				/* ReportGetLastError(); */
+			}
+			if (SetClipboardData(CF_TEXT, h) == NULL) {
+				/* ReportGetLastError(); */
+			} else {
+				err = mnvm_noErr;
+			}
+			h = NULL;
+			if (! CloseClipboard()) {
+				/* ReportGetLastError(); */
+			}
+		}
+		if (h != NULL) {
+			(void) GlobalFree(h);
+		}
+	}
+
+	PbufDispose(i);
+
+	return err;
+}
+#endif
+
+#if IncludeHostTextClipExchange
+GLOBALOSGLUFUNC tMacErr HTCEimport(tPbuf *r)
+{
+	tMacErr err = mnvm_miscErr;
+
+	if (IsClipboardFormatAvailable(CF_TEXT)) {
+		if (! OpenClipboard(MainWnd)) {
+			/* ReportGetLastError(); */
+		} else {
+			HGLOBAL h = GetClipboardData(CF_TEXT);
+			if (h == NULL) {
+				/* ReportGetLastError(); */
+			} else {
+				err = NativeTextToMacRomanPbuf(h, r);
+			}
+			if (! CloseClipboard()) {
+				/* ReportGetLastError(); */
+			}
+		}
+	}
+
+	return err;
+}
+#endif
+
+/* --- drives --- */
+
+#define NotAfileRef INVALID_HANDLE_VALUE
+
+LOCALVAR HANDLE Drives[NumDrives]; /* open disk image files */
+
+#define NeedDriveNames (IncludeSonyGetName || IncludeSonyNew)
+
+#if NeedDriveNames
+LOCALVAR HGLOBAL DriveNames[NumDrives];
+	/*
+		It is supposed to be possible to use
+		GetMappedFileName to get name of open file,
+		but that seems ugly kludge, so instead
+		save the name on open.
+	*/
+#endif
+
+LOCALPROC InitDrives(void)
+{
+	/*
+		This isn't really needed, Drives[i] and DriveNames[i]
+		need not have valid values when not vSonyIsInserted[i].
+	*/
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		Drives[i] = NotAfileRef;
+#if NeedDriveNames
+		DriveNames[i] = NULL;
+#endif
+	}
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer,
+	tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count,
+	ui5r *Sony_ActCount)
+{
+	HANDLE refnum;
+	DWORD newL;
+	tMacErr result;
+	DWORD BytesTransferred = 0;
+
+	refnum = Drives[Drive_No];
+	newL = SetFilePointer(
+		refnum, /* handle of file */
+		Sony_Start, /* number of bytes to move file pointer */
+		nullpr, /* address of high-order word of distance to move */
+		FILE_BEGIN /* how to move */
+	);
+	if (newL == 0xFFFFFFFF) {
+		result = mnvm_miscErr; /*& figure out what really to return &*/
+	} else if (Sony_Start != (ui5b)newL) {
+		/* not supposed to get here */
+		result = mnvm_miscErr; /*& figure out what really to return &*/
+	} else {
+		if (IsWrite) {
+			if (! WriteFile(refnum, /* handle of file to read */
+				(LPVOID)Buffer
+					, /* address of buffer that receives data */
+				(DWORD)Sony_Count, /* number of bytes to read */
+				&BytesTransferred, /* address of number of bytes read */
+				nullpr)) /* address of structure for data */
+			{
+				result = mnvm_miscErr;
+					/*& figure out what really to return &*/
+			} else if ((ui5b)BytesTransferred != Sony_Count) {
+				result = mnvm_miscErr;
+					/*& figure out what really to return &*/
+			} else {
+				result = mnvm_noErr;
+			}
+		} else {
+			if (! ReadFile(refnum, /* handle of file to read */
+				(LPVOID)Buffer,
+					/* address of buffer that receives data */
+				(DWORD)Sony_Count, /* number of bytes to read */
+				&BytesTransferred,
+					/* address of number of bytes read */
+				nullpr)) /* address of structure for data */
+			{
+				result = mnvm_miscErr;
+					/*& figure out what really to return &*/
+			} else if ((ui5b)BytesTransferred != Sony_Count) {
+				result = mnvm_miscErr;
+					/*& figure out what really to return &*/
+			} else {
+				result = mnvm_noErr;
+			}
+		}
+	}
+
+	if (nullpr != Sony_ActCount) {
+		*Sony_ActCount = BytesTransferred;
+	}
+
+	return result;
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count)
+{
+	tMacErr result;
+	DWORD L;
+
+	L = GetFileSize(Drives[Drive_No], nullpr);
+	if (L == 0xFFFFFFFF) {
+		result = mnvm_miscErr; /*& figure out what really to return &*/
+	} else {
+		*Sony_Count = L;
+		result = mnvm_noErr;
+	}
+
+	return result;
+}
+
+LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, blnr deleteit)
+{
+	HANDLE refnum = Drives[Drive_No];
+
+#if ! NeedDriveNames
+	UnusedParam(deleteit);
+#endif
+
+	Drives[Drive_No] = NotAfileRef; /* not really needed */
+
+	DiskEjectedNotify(Drive_No);
+
+	(void) FlushFileBuffers(refnum);
+	(void) CloseHandle(refnum);
+
+#if NeedDriveNames
+	{
+		HGLOBAL h = DriveNames[Drive_No];
+		if (NULL != h) {
+			if (deleteit) {
+				LPTSTR drivepath = GlobalLock(h);
+				if (drivepath != NULL) {
+					(void) DeleteFile(drivepath);
+					(void) GlobalUnlock(h);
+				}
+			}
+			(void) GlobalFree(h);
+			DriveNames[Drive_No] = NULL; /* not really needed */
+		}
+	}
+#endif
+
+	return mnvm_noErr;
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
+{
+	return vSonyEject0(Drive_No, falseblnr);
+}
+
+#if IncludeSonyNew
+GLOBALOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No)
+{
+	return vSonyEject0(Drive_No, trueblnr);
+}
+#endif
+
+LOCALPROC UnInitDrives(void)
+{
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		if (vSonyIsInserted(i)) {
+			(void) vSonyEject(i);
+		}
+	}
+}
+
+#if NeedDriveNames
+LOCALFUNC blnr LPTSTRtoHand(LPTSTR s, HGLOBAL *r)
+{
+	blnr IsOk = falseblnr;
+
+	size_t L = _tcslen(s);
+	HGLOBAL h = GlobalAlloc(GMEM_DDESHARE,
+		(L + 1) * sizeof(TCHAR));
+	if (h != NULL) {
+		LPTSTR p = GlobalLock(h);
+		if (p != NULL) {
+			_tcscpy(p, s);
+			IsOk = trueblnr;
+			(void) GlobalUnlock(h);
+		}
+		if (! IsOk) {
+			(void) GlobalFree(h);
+		} else {
+			*r = h;
+		}
+	}
+
+	return IsOk;
+}
+#endif
+
+#if IncludeSonyGetName
+GLOBALOSGLUFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r)
+{
+	WIN32_FIND_DATA fd;
+	tMacErr err = mnvm_miscErr;
+	HGLOBAL ph = DriveNames[Drive_No];
+	if (NULL != ph) {
+		LPTSTR drivepath = GlobalLock(ph);
+		if (drivepath != NULL) {
+			HANDLE hf = FindFirstFile(drivepath, &fd);
+			(void) GlobalUnlock(ph);
+
+			if (hf != INVALID_HANDLE_VALUE) {
+				HGLOBAL h;
+				if (LPTSTRtoHand(fd.cFileName, &h)) {
+					err = NativeTextToMacRomanPbuf(h, r);
+				}
+				FindClose(hf);
+			}
+		}
+	}
+
+	return err;
+}
+#endif
+
+LOCALFUNC blnr Sony_Insert0(HANDLE refnum, blnr locked,
+	LPTSTR drivepath)
+{
+	tDrive Drive_No;
+
+#if ! NeedDriveNames
+	UnusedParam(drivepath);
+#endif
+
+	if (! FirstFreeDisk(&Drive_No)) {
+		(void) CloseHandle(refnum);
+		MacMsg(kStrTooManyImagesTitle,
+			kStrTooManyImagesMessage, falseblnr);
+		return falseblnr;
+	} else {
+		Drives[Drive_No] = refnum;
+		DiskInsertNotify(Drive_No, locked);
+#if NeedDriveNames
+		{
+			HGLOBAL h;
+
+			if (! LPTSTRtoHand(drivepath, &h)) {
+				h = NULL;
+			}
+
+			DriveNames[Drive_No] = h;
+		}
+#endif
+		return trueblnr;
+	}
+}
+
+LOCALFUNC blnr Sony_Insert1(LPTSTR drivepath, blnr SilentOnMissing)
+{
+	blnr locked = falseblnr;
+	HANDLE refnum = CreateFile(
+		drivepath, /* pointer to name of the file */
+		GENERIC_READ + GENERIC_WRITE, /* access (read-write) mode */
+		0, /* share mode */
+		nullpr, /* pointer to security descriptor */
+		OPEN_EXISTING, /* how to create */
+		FILE_ATTRIBUTE_NORMAL, /* file attributes */
+		nullpr /* handle to file with attributes to copy */
+	);
+	if (refnum == INVALID_HANDLE_VALUE) {
+		if (ERROR_ACCESS_DENIED == GetLastError()) {
+			locked = trueblnr;
+			refnum = CreateFile(
+				drivepath, /* pointer to name of the file */
+				GENERIC_READ, /* access (read-write) mode */
+				FILE_SHARE_READ, /* share mode */
+				nullpr, /* pointer to security descriptor */
+				OPEN_EXISTING, /* how to create */
+				FILE_ATTRIBUTE_NORMAL, /* file attributes */
+				nullpr /* handle to file with attributes to copy */
+			);
+		}
+	}
+	if (refnum == INVALID_HANDLE_VALUE) {
+		DWORD err = GetLastError();
+		if (ERROR_SHARING_VIOLATION == err) {
+			MacMsg(kStrImageInUseTitle,
+				kStrImageInUseMessage, falseblnr);
+		} else if ((ERROR_FILE_NOT_FOUND == err) && SilentOnMissing) {
+			/* ignore it */
+		} else {
+			MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
+		}
+	} else {
+		return Sony_Insert0(refnum, locked, drivepath);
+	}
+	return falseblnr;
+}
+
+LOCALFUNC blnr LoadMacRomFromPath(LPTSTR drivepath)
+{
+	HANDLE refnum = INVALID_HANDLE_VALUE;
+	blnr IsOk = falseblnr;
+
+	refnum = CreateFile(
+		drivepath, /* pointer to name of the file */
+		GENERIC_READ, /* access (read-write) mode */
+		FILE_SHARE_READ, /* share mode */
+		nullpr, /* pointer to security descriptor */
+		OPEN_EXISTING, /* how to create */
+		FILE_ATTRIBUTE_NORMAL, /* file attributes */
+		nullpr /* handle to file with attributes to copy */
+	);
+
+	if (refnum == INVALID_HANDLE_VALUE) {
+		/* MacMsg(kStrNoROMTitle, kStrNoROMMessage, trueblnr); */
+	} else {
+		DWORD BytesRead;
+
+		if (! ReadFile(refnum, /* handle of file to read */
+			(LPVOID)ROM, /* address of buffer that receives data */
+			(DWORD)kROM_Size, /* number of bytes to read */
+			&BytesRead, /* address of number of bytes read */
+			nullpr)) /* address of structure for data */
+		{
+			MacMsgOverride(kStrNoReadROMTitle, kStrNoReadROMMessage);
+		} else
+		if ((ui5b)BytesRead != kROM_Size) {
+			MacMsgOverride(kStrShortROMTitle, kStrShortROMMessage);
+		} else
+		{
+			IsOk = (mnvm_noErr == ROM_IsValid());
+		}
+		(void) CloseHandle(refnum);
+	}
+
+	return IsOk;
+}
+
+#ifndef EnableShellLinks
+#define EnableShellLinks 1
+#endif
+
+#if EnableShellLinks
+LOCALVAR blnr COMinited = falseblnr;
+LOCALVAR blnr COMinitedOK;
+#endif
+
+#if EnableShellLinks
+LOCALPROC MyUninitCOM(void)
+{
+	if (COMinited) {
+		CoUninitialize();
+	}
+}
+#endif
+
+#if EnableShellLinks
+LOCALFUNC blnr MyNeedCOM(void)
+{
+	HRESULT hres;
+
+	if (! COMinited) {
+		COMinitedOK = falseblnr;
+		hres = CoInitialize(NULL);
+		if (SUCCEEDED(hres)) {
+			COMinitedOK = trueblnr;
+		}
+
+		COMinited = trueblnr;
+	}
+	return COMinitedOK;
+}
+#endif
+
+#if EnableShellLinks
+LOCALFUNC blnr MyResolveShortcut(LPTSTR FilePath, blnr *directory)
+/* adapted from Microsoft example code */
+{
+	HRESULT hres;
+	IShellLink *psl;
+	IPersistFile* ppf;
+	TCHAR szGotPath[MAX_PATH];
+	WIN32_FIND_DATA wfd;
+	blnr IsOk = falseblnr;
+
+	if (MyNeedCOM()) {
+		hres = CoCreateInstance(&CLSID_ShellLink, NULL,
+			CLSCTX_INPROC_SERVER, &IID_IShellLink,
+			(LPVOID *)(void *)&psl);
+			/*
+				the (void *) prevents a compiler warning
+				from gcc
+			*/
+		if (SUCCEEDED(hres)) {
+			/* Get a pointer to the IPersistFile interface. */
+			hres = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile,
+				(void **)(void *)&ppf);
+			if (SUCCEEDED(hres)) {
+				/* Ensure that the string is Unicode. */
+#if MyUseUni
+#define wsz FilePath
+#else
+				WORD wsz[MAX_PATH];
+				MultiByteToWideChar(CP_ACP, 0, FilePath, -1, wsz,
+					MAX_PATH);
+#endif
+
+				/* Load the shortcut. */
+				hres = ppf->lpVtbl->Load(ppf, wsz, STGM_READ);
+				if (SUCCEEDED(hres)) {
+					/* Resolve the link. */
+					hres = psl->lpVtbl->Resolve(psl, MainWnd,
+						SLR_ANY_MATCH);
+					if (SUCCEEDED(hres)) {
+						/* Get the path to the link target. */
+						hres = psl->lpVtbl->GetPath(psl, szGotPath,
+							MAX_PATH, &wfd,
+							SLGP_SHORTPATH);
+						if (SUCCEEDED(hres)) {
+							/*
+								This is in the sample code, but doesn't
+								seem to be needed:
+								Get the description of the target.
+								char szDescription[MAX_PATH];
+								hres = psl->lpVtbl->GetDescription(psl,
+									szDescription, MAX_PATH);
+								if (SUCCEEDED(hres)) {
+								}
+							*/
+							lstrcpy(FilePath, szGotPath);
+							if (NULL != directory) {
+								*directory = (0 != (wfd.dwFileAttributes
+									& FILE_ATTRIBUTE_DIRECTORY));
+							}
+							IsOk = trueblnr;
+						}
+					}
+				}
+
+				ppf->lpVtbl->Release(ppf);
+			}
+			psl->lpVtbl->Release(psl);
+		}
+	}
+	return IsOk;
+}
+#endif
+
+#if EnableShellLinks
+LOCALFUNC blnr FileIsLink(LPTSTR drivepath)
+{
+	LPTSTR p = FindLastTerm(drivepath, (TCHAR)('.'));
+
+	if (p != nullpr) {
+		if (_tcscmp(p, TEXT("lnk")) == 0) {
+			return trueblnr;
+		}
+	}
+	return falseblnr;
+}
+#endif
+
+LOCALFUNC blnr InsertDiskOrAlias(LPTSTR drivepath,
+	blnr MaybeROM, blnr MaybeAlias)
+{
+#if EnableShellLinks
+	if (MaybeAlias && FileIsLink(drivepath)) {
+		if (! MyResolveShortcut(drivepath, NULL)) {
+			return falseblnr;
+		}
+	}
+#endif
+
+	if (MaybeROM && ! ROM_loaded) {
+		return LoadMacRomFromPath(drivepath);
+	} else {
+		return Sony_Insert1(drivepath, falseblnr);
+	}
+}
+
+LOCALFUNC blnr MyFileExists(LPTSTR pathName, blnr *directory)
+{
+	WIN32_FIND_DATA fd;
+	HANDLE hf = FindFirstFile(pathName, &fd);
+	blnr IsOk = falseblnr;
+
+	if (hf != INVALID_HANDLE_VALUE) {
+		if (NULL != directory) {
+			*directory =
+				(0 != (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
+		}
+		IsOk = trueblnr;
+		FindClose(hf);
+	}
+
+	return IsOk;
+}
+
+LOCALFUNC tMacErr ResolveNamedChild0(LPTSTR pathName,
+	LPTSTR Child, blnr *directory)
+{
+	size_t newlen;
+	size_t oldlen = _tcslen(pathName);
+	tMacErr err = mnvm_miscErr;
+
+	newlen = oldlen + 1 + _tcslen(Child);
+	if (newlen + 1 < _MAX_PATH) {
+		_tcscat(pathName, TEXT("\\"));
+		_tcscat(pathName, Child);
+
+		if (MyFileExists(pathName, directory)) {
+			err = mnvm_noErr;
+		} else {
+			err = mnvm_fnfErr;
+#if EnableShellLinks
+			if (newlen + 5 < _MAX_PATH) {
+				_tcscat(pathName, TEXT(".lnk"));
+				if (MyFileExists(pathName, NULL))
+				if (MyResolveShortcut(pathName, directory))
+				{
+					err = mnvm_noErr;
+				}
+				if (mnvm_noErr != err) {
+					pathName[newlen] = (TCHAR)('\0');
+				}
+			}
+#endif
+		}
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr ResolveNamedChild(LPTSTR pathName,
+	char *Child, blnr *directory)
+{
+	TCHAR Child0[ClStrMaxLength + 1];
+
+	NativeStrFromCStr(Child0, Child, falseblnr);
+
+	return ResolveNamedChild0(pathName, Child0, directory);
+}
+
+LOCALFUNC blnr ResolveNamedChildDir(LPTSTR pathName, char *Child)
+{
+	blnr directory;
+
+	return (mnvm_noErr == ResolveNamedChild(
+		pathName, Child, &directory))
+		&& directory;
+}
+
+LOCALFUNC blnr ResolveNamedChildFile(LPTSTR pathName, char *Child)
+{
+	blnr directory;
+
+	return (mnvm_noErr == ResolveNamedChild(
+		pathName, Child, &directory))
+		&& ! directory;
+}
+
+#if UseActvFile || (IncludeSonyNew && ! SaveDialogEnable)
+LOCALFUNC blnr MakeNamedChildDir(LPTSTR pathName, char *Child)
+{
+	blnr directory;
+	blnr IsOk = falseblnr;
+	tMacErr err = ResolveNamedChild(pathName, Child, &directory);
+
+	if (mnvm_noErr == err) {
+		IsOk = directory;
+	} else if (mnvm_fnfErr == err) {
+		if (CreateDirectory(pathName, NULL)) {
+			IsOk = trueblnr;
+		}
+	}
+
+	return IsOk;
+}
+#endif
+
+LOCALFUNC blnr MyGetAppDataPath(LPTSTR lpszPath,
+	BOOL fCreate)
+{
+	blnr IsOk = falseblnr;
+
+	if (HaveMySHGetSpecialFolderPath())
+	if (MySHGetSpecialFolderPath(
+		NULL /* HWND hwndOwner */,
+		lpszPath, My_CSIDL_APPDATA, fCreate))
+	{
+		IsOk = trueblnr;
+	}
+	/*
+		if not available, could perhaps
+		use GetWindowsDirectory.
+	*/
+	/*
+		SHGetFolderPath is more recent,
+		could perhaps check for it first.
+		might also be in "SHFolder.dll".
+
+		SHGetKnownFolderPath is even
+		more recent.
+	*/
+
+	return IsOk;
+}
+
+#if UseWinCE
+/* Are we in control mode? */
+/* Needed because you can't hold down a key with the virtual keyboard */
+LOCALVAR blnr CtrlMode = falseblnr;
+#endif
+
+LOCALPROC InsertADisk0(void)
+{
+	OPENFILENAME ofn;
+	TCHAR szDirName[256];
+	TCHAR szFile[256];
+#if ! UseWinCE
+	TCHAR szFileTitle[256];
+#endif
+	UINT i;
+	size_t cbString;
+	TCHAR chReplace;
+	TCHAR szFilter[256];
+	blnr IsOk;
+
+	szDirName[0] = (TCHAR)('\0');
+	szFile[0] = (TCHAR)('\0');
+	_tcscpy(szFilter,
+		TEXT("Disk images|*.dsk;*.HF?;*.IMG;*.IMA;*.IMAGE")
+		TEXT("|All files (*.*)|*.*|\0"));
+
+	cbString = _tcslen(szFilter);
+
+	chReplace = szFilter[cbString - 1];
+
+	for (i = 0; szFilter[i] != (TCHAR)('\0'); ++i)
+	{
+		if (szFilter[i] == chReplace) {
+			szFilter[i] = (TCHAR)('\0');
+		}
+	}
+
+	memset(&ofn, 0, sizeof(OPENFILENAME));
+
+	ofn.lStructSize = sizeof(OPENFILENAME);
+	ofn.hwndOwner = MainWnd;
+	ofn.lpstrFilter = szFilter;
+	ofn.nFilterIndex = 2;
+	ofn.lpstrFile= szFile;
+	ofn.nMaxFile = sizeof(szFile);
+#if ! UseWinCE
+	ofn.lpstrFileTitle = szFileTitle;
+	ofn.nMaxFileTitle = sizeof(szFileTitle);
+#endif
+	ofn.lpstrInitialDir = szDirName;
+	ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST
+		| OFN_HIDEREADONLY;
+
+	MyBeginDialog();
+	IsOk = GetOpenFileName(&ofn);
+	MyEndDialog();
+
+	if(! IsOk) {
+		/* report error */
+#if UseWinCE
+		if (szFile[0]) {
+			char wMsg[1024];
+			sprintf(wMsg, "Couldn't open %ls", szFile);
+			MacMsg("error", wMsg, falseblnr);
+		}
+#endif
+	} else {
+		(void) InsertDiskOrAlias(ofn.lpstrFile,
+			trueblnr, falseblnr);
+	}
+
+#if UseWinCE
+	CtrlMode = falseblnr;
+#endif
+}
+
+LOCALFUNC blnr LoadInitialImageFromName(char *ImageName)
+{
+	TCHAR ImageFile[_MAX_PATH];
+
+	if (GetAppDir(ImageFile))
+	if (ResolveNamedChildFile(ImageFile, ImageName))
+	if (Sony_Insert1(ImageFile, trueblnr))
+	{
+		return trueblnr;
+	}
+	return falseblnr;
+}
+
+LOCALFUNC blnr Sony_InsertIth(int i)
+{
+	blnr v;
+
+	if ((i > 9) || ! FirstFreeDisk(nullpr)) {
+		v = falseblnr;
+	} else {
+		char s[] = "disk?.dsk";
+
+		s[4] = '0' + i;
+
+		/* stop on first error (including file not found) */
+		v = LoadInitialImageFromName(s);
+	}
+
+	return v;
+}
+
+LOCALFUNC blnr LoadInitialImages(void)
+{
+	if (! AnyDiskInserted()) {
+		int i;
+
+		for (i = 1; Sony_InsertIth(i); ++i) {
+			/* stop on first error (including file not found) */
+		}
+	}
+
+	return trueblnr;
+}
+
+#if UseActvFile
+
+#define ActvCodeFileName "act_1"
+
+LOCALFUNC tMacErr ActvCodeFileLoad(ui3p p)
+{
+	TCHAR pathName[_MAX_PATH];
+	DWORD BytesRead;
+	HANDLE refnum = INVALID_HANDLE_VALUE;
+	blnr IsOk = falseblnr;
+
+	if (MyGetAppDataPath(pathName, FALSE))
+	if (ResolveNamedChildDir(pathName, "Gryphel"))
+	if (ResolveNamedChildDir(pathName, "mnvm_act"))
+	if (ResolveNamedChildFile(pathName, ActvCodeFileName))
+	{
+		refnum = CreateFile(
+			pathName, /* pointer to name of the file */
+			GENERIC_READ, /* access (read-write) mode */
+			FILE_SHARE_READ, /* share mode */
+			NULL, /* pointer to security descriptor */
+			OPEN_EXISTING, /* how to create */
+			FILE_ATTRIBUTE_NORMAL, /* file attributes */
+			NULL /* handle to file with attributes to copy */
+		);
+		if (INVALID_HANDLE_VALUE == refnum) {
+			/* report error */
+		} else {
+			if (SetFilePointer(
+				refnum, /* handle of file */
+				0, /* number of bytes to move file pointer */
+				nullpr,
+					/* address of high-order word of distance to move */
+				FILE_BEGIN /* how to move */
+				) != 0)
+			{
+				/* report error */
+			} else if (! ReadFile(refnum, /* handle of file to read */
+				(LPVOID)p, /* address of buffer that receives data */
+				(DWORD)ActvCodeFileLen, /* number of bytes to read */
+				&BytesRead, /* address of number of bytes read */
+				nullpr) /* address of structure for data */
+				|| ((ui5b)BytesRead != ActvCodeFileLen))
+			{
+				/* report error */
+			} else {
+				IsOk = trueblnr;
+			}
+			(void) CloseHandle(refnum);
+		}
+	}
+
+	return IsOk ? mnvm_noErr : mnvm_miscErr;
+}
+
+LOCALFUNC blnr NewNamedChildFile(LPTSTR pathName, char *Child)
+{
+	blnr directory;
+	blnr IsOk = falseblnr;
+	tMacErr err = ResolveNamedChild(pathName, Child, &directory);
+
+	if (mnvm_noErr == err) {
+		IsOk = ! directory;
+	} else if (mnvm_fnfErr == err) {
+		IsOk = trueblnr;
+	}
+
+	return IsOk;
+}
+
+LOCALFUNC tMacErr ActvCodeFileSave(ui3p p)
+{
+	TCHAR pathName[_MAX_PATH];
+	DWORD BytesWritten;
+	HANDLE refnum = INVALID_HANDLE_VALUE;
+	blnr IsOk = falseblnr;
+
+	if (MyGetAppDataPath(pathName, TRUE))
+	if (MakeNamedChildDir(pathName, "Gryphel"))
+	if (MakeNamedChildDir(pathName, "mnvm_act"))
+	if (NewNamedChildFile(pathName, ActvCodeFileName))
+	{
+		refnum = CreateFile(
+			pathName, /* pointer to name of the file */
+			GENERIC_READ + GENERIC_WRITE, /* access (read-write) mode */
+			0, /* share mode */
+			NULL, /* pointer to security descriptor */
+			CREATE_ALWAYS, /* how to create */
+			FILE_ATTRIBUTE_NORMAL, /* file attributes */
+			NULL /* handle to file with attributes to copy */
+		);
+		if (INVALID_HANDLE_VALUE == refnum) {
+			/* report error */
+		} else {
+			if (SetFilePointer(
+				refnum, /* handle of file */
+				0, /* number of bytes to move file pointer */
+				nullpr,
+					/* address of high-order word of distance to move */
+				FILE_BEGIN /* how to move */
+				) != 0)
+			{
+				/* report error */
+			} else if (! WriteFile(refnum, /* handle of file to read */
+				(LPVOID)p, /* address of buffer that receives data */
+				(DWORD)ActvCodeFileLen, /* number of bytes to read */
+				&BytesWritten, /* address of number of bytes read */
+				nullpr) /* address of structure for data */
+				|| ((ui5b)BytesWritten != ActvCodeFileLen))
+			{
+				/* report error */
+			} else {
+				IsOk = trueblnr;
+			}
+			(void) CloseHandle(refnum);
+			if (! IsOk) {
+				(void) DeleteFile(pathName);
+			}
+		}
+	}
+
+	return IsOk ? mnvm_noErr : mnvm_miscErr;
+}
+
+#endif /* UseActvFile */
+
+#if IncludeSonyNew
+LOCALFUNC blnr WriteZero(HANDLE refnum, ui5b L)
+{
+	if (SetFilePointer(
+		refnum, /* handle of file */
+		0, /* number of bytes to move file pointer */
+		nullpr, /* address of high-order word of distance to move */
+		FILE_BEGIN /* how to move */
+		) != 0)
+	{
+		return falseblnr;
+	} else {
+#define ZeroBufferSize 2048
+		ui5b i;
+		ui3b buffer[ZeroBufferSize];
+		DWORD BytesWritten;
+
+		memset(&buffer, 0, ZeroBufferSize);
+
+		while (L > 0) {
+			i = (L > ZeroBufferSize) ? ZeroBufferSize : L;
+			if (! WriteFile(refnum, /* handle of file to read */
+				(LPVOID)buffer,
+					/* address of buffer that receives data */
+				(DWORD)i, /* number of bytes to read */
+				&BytesWritten, /* address of number of bytes read */
+				nullpr) /* address of structure for data */
+				|| ((ui5b)BytesWritten != i))
+			{
+				return falseblnr;
+			}
+			L -= i;
+		}
+		return trueblnr;
+	}
+}
+#endif
+
+#define MaxSavePathSize MAX_PATH
+
+#if IncludeSonyNew
+LOCALPROC MakeNewDisk0(ui5b L, LPTSTR pathName)
+{
+	blnr IsOk = falseblnr;
+	HANDLE newrefNum;
+
+	IsOk = falseblnr;
+	newrefNum = CreateFile(
+		pathName, /* pointer to name of the file */
+		GENERIC_READ + GENERIC_WRITE, /* access (read-write) mode */
+		0, /* share mode */
+		NULL, /* pointer to security descriptor */
+		CREATE_ALWAYS, /* how to create */
+		FILE_ATTRIBUTE_NORMAL, /* file attributes */
+		NULL /* handle to file with attributes to copy */
+	);
+	if (newrefNum == INVALID_HANDLE_VALUE) {
+		/* report error */
+	} else {
+		if (SetFilePointer(
+			newrefNum, /* handle of file */
+			L, /* number of bytes to move file pointer */
+			nullpr,
+				/* address of high-order word of distance to move */
+			FILE_BEGIN /* how to move */
+			) != L)
+		{
+			/* report error */
+		} else if (! SetEndOfFile(newrefNum)) {
+			/* report error */
+		} else if (! WriteZero(newrefNum, L)) {
+			/* report error */
+		} else {
+			IsOk =
+				Sony_Insert0(newrefNum, falseblnr, pathName);
+			newrefNum = INVALID_HANDLE_VALUE;
+		}
+		if (INVALID_HANDLE_VALUE != newrefNum) {
+			(void) CloseHandle(newrefNum);
+		}
+		if (! IsOk) {
+			(void) DeleteFile(pathName);
+		}
+	}
+}
+#endif
+
+#if IncludeSonyNew
+LOCALPROC MakeNewDisk(ui5b L, HGLOBAL NewDiskNameDat)
+{
+#if SaveDialogEnable
+	OPENFILENAME ofn;
+	blnr IsOk = falseblnr;
+	TCHAR szFile[MaxSavePathSize];
+	TCHAR szFileTitle[MaxSavePathSize];
+
+	memset(&ofn, 0, sizeof(OPENFILENAME));
+	szFile[0] = 0;
+	szFileTitle[0] = 0;
+
+#if IncludeSonyGetName
+	if (NewDiskNameDat != NULL) {
+		LPTSTR p = GlobalLock(NewDiskNameDat);
+		if (p != NULL) {
+			_tcscpy(szFile, p);
+			(void) GlobalUnlock(NewDiskNameDat);
+		}
+	} else
+#endif
+	{
+		NativeStrFromCStr(szFile, "untitled", falseblnr);
+	}
+
+	ofn.lStructSize = sizeof(OPENFILENAME);
+	ofn.lpstrFile = szFile;
+	ofn.hwndOwner = MainWnd;
+	/* ofn.lpstrFilter = "All\0*.*\0Text\0*.txt\0Datafile\0*.dsk\0"; */
+	/* ofn.lpstrFilter = NULL; */ /* szFilter */
+	ofn.nMaxFile = MaxSavePathSize;
+	ofn.lpstrFileTitle = szFileTitle;
+	ofn.nMaxFileTitle = MaxSavePathSize;
+	ofn.lpstrInitialDir = NULL;
+	ofn.Flags = OFN_OVERWRITEPROMPT + OFN_HIDEREADONLY;
+		/* + OFN_SHOWHELP */
+
+	MyBeginDialog();
+	IsOk = GetSaveFileName(&ofn);
+	MyEndDialog();
+
+	if (! IsOk) {
+		/* report error */
+	} else {
+		MakeNewDisk0(L, ofn.lpstrFile);
+	}
+#else /* SaveDialogEnable */
+	TCHAR pathName[MaxSavePathSize];
+
+	if (GetAppDir(pathName))
+	if (MakeNamedChildDir(pathName, "out"))
+	{
+		blnr directory;
+		LPTSTR p = GlobalLock(NewDiskNameDat);
+
+		if (p != NULL) {
+			tMacErr err = ResolveNamedChild0(pathName, p,
+				&directory);
+
+			if (mnvm_fnfErr == err) {
+				err = mnvm_noErr;
+			} else if (mnvm_noErr == err) {
+				if (directory) {
+					err = mnvm_miscErr;
+				}
+			}
+
+			if (mnvm_noErr == err) {
+				MakeNewDisk0(L, pathName);
+			}
+
+			(void) GlobalUnlock(NewDiskNameDat);
+		}
+	}
+#endif /* SaveDialogEnable */
+}
+#endif
+
+LOCALFUNC blnr LoadMacRom(void)
+{
+	TCHAR ROMFile[_MAX_PATH];
+	blnr IsOk = falseblnr;
+
+	if (GetAppDir(ROMFile))
+	if (ResolveNamedChildFile(ROMFile, RomFileName))
+	{
+		IsOk = trueblnr;
+	}
+
+	if (! IsOk) {
+		if (MyGetAppDataPath(ROMFile, FALSE))
+		if (ResolveNamedChildDir(ROMFile, "Gryphel"))
+		if (ResolveNamedChildDir(ROMFile, "mnvm_rom"))
+		if (ResolveNamedChildFile(ROMFile, RomFileName))
+		{
+			IsOk = trueblnr;
+		}
+
+	}
+
+	if (IsOk) {
+		IsOk = LoadMacRomFromPath(ROMFile);
+	}
+
+	return trueblnr;
+}
+
+#if InstallFileIcons
+LOCALPROC MySetRegKey(HKEY hKeyRoot,
+	LPTSTR strRegKey, LPTSTR strRegValue)
+{
+	HKEY RegKey;
+	DWORD dwDisposition;
+
+	if (ERROR_SUCCESS == RegCreateKeyEx(hKeyRoot, strRegKey, 0, NULL,
+		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
+		NULL, &RegKey, &dwDisposition))
+	{
+		RegSetValueEx(RegKey, NULL, 0, REG_SZ,
+			(CONST BYTE *)strRegValue,
+			(DWORD)((_tcslen(strRegValue) + 1) * sizeof(TCHAR)));
+		RegCloseKey(RegKey);
+	}
+}
+
+LOCALPROC RegisterShellFileType(LPTSTR AppPath, LPTSTR strFilterExt,
+	LPTSTR strFileTypeId, LPTSTR strFileTypeName,
+	LPTSTR strIconId, blnr CanOpen)
+{
+	TCHAR strRegKey[_MAX_PATH];
+	TCHAR strRegValue[_MAX_PATH + 2];
+		/* extra room for ","{strIconId} */
+
+	MySetRegKey(HKEY_CLASSES_ROOT, strFileTypeId, strFileTypeName);
+	MySetRegKey(HKEY_CLASSES_ROOT, strFilterExt, strFileTypeId);
+
+	_tcscpy(strRegKey, strFileTypeId);
+	_tcscat(strRegKey, TEXT("\\DefaultIcon"));
+	_tcscpy(strRegValue, TEXT("\""));
+	_tcscat(strRegValue, AppPath);
+	_tcscat(strRegValue, TEXT("\","));
+	_tcscat(strRegValue, strIconId);
+	MySetRegKey(HKEY_CLASSES_ROOT, strRegKey, strRegValue);
+
+	if (CanOpen) {
+		_tcscpy(strRegKey, strFileTypeId);
+		_tcscat(strRegKey, TEXT("\\shell\\open\\command"));
+		_tcscpy(strRegValue, TEXT("\""));
+		_tcscat(strRegValue, AppPath);
+		_tcscat(strRegValue, TEXT("\" \"%1\""));
+		MySetRegKey(HKEY_CLASSES_ROOT, strRegKey, strRegValue);
+	}
+}
+
+LOCALFUNC blnr RegisterInRegistry(void)
+{
+	TCHAR AppPath[_MAX_PATH];
+
+	GetModuleFileName(NULL, AppPath, _MAX_PATH);
+#if 0
+	GetShortPathName(AppPath, AppPath, _MAX_PATH);
+#endif
+
+	RegisterShellFileType(AppPath, TEXT(".rom"), TEXT("minivmac.rom"),
+		TEXT("Mini vMac ROM Image"), TEXT("1"), falseblnr);
+	RegisterShellFileType(AppPath, TEXT(".dsk"), TEXT("minivmac.dsk"),
+		TEXT("Mini vMac Disk Image"), TEXT("2"), trueblnr);
+
+	return trueblnr;
+}
+#endif
+
+LOCALVAR LPTSTR CommandLine;
+
+LOCALFUNC blnr ScanCommandLine(void)
+{
+	TCHAR *p = CommandLine;
+	TCHAR *p1;
+	TCHAR *p2;
+	TCHAR v;
+	size_t L;
+
+	v = *p;
+	while (0 != v) {
+		if (' ' == v) {
+			v = *++p;
+		} else {
+			if ('\"' == v) {
+				v = *++p;
+				p1 = p;
+				while (('\"' != v) && (0 != v)) {
+					v = *++p;
+				}
+				p2 = p;
+				if ('\"' == v) {
+					v = *++p;
+				}
+			} else {
+				p1 = p;
+				while ((' ' != v) && (0 != v)) {
+					v = *++p;
+				}
+				p2 = p;
+			}
+			L = p2 - p1;
+			if (L + 1 <= _MAX_PATH) {
+				TCHAR fileName[_MAX_PATH];
+				TCHAR *filePtr = fileName;
+				size_t i = L;
+
+				while (i > 0) {
+					*filePtr++ = *p1++;
+					--i;
+				}
+				*filePtr = (char)0;
+
+				if ((L > 0)
+					&& (('/' == fileName[0]) || ('-' == fileName[0])))
+				{
+#if 0
+					TCHAR *p3 = &fileName[1];
+					if (0 == _tcscmp(p3, TEXT("l"))) {
+						SpeedValue = 0;
+					} else
+#endif
+					{
+						MacMsg(kStrBadArgTitle, kStrBadArgMessage,
+							falseblnr);
+					}
+				} else {
+					(void) InsertDiskOrAlias(fileName,
+						falseblnr, trueblnr);
+				}
+			}
+		}
+	}
+
+	return trueblnr;
+}
+
+#if EnableRecreateW
+LOCALPROC CheckMagnifyAndFullScreen(void)
+{
+	if (
+#if EnableMagnify
+		(UseMagnify != WantMagnify)
+#endif
+#if EnableMagnify && VarFullScreen
+		||
+#endif
+#if VarFullScreen
+		(UseFullScreen != WantFullScreen)
+#endif
+		)
+	{
+		(void) ReCreateMainWindow();
+	}
+}
+#endif
+
+#if VarFullScreen && EnableMagnify
+enum {
+	kWinStateWindowed,
+#if EnableMagnify
+	kWinStateFullScreen,
+#endif
+	kNumWinStates
+};
+#endif
+
+#if VarFullScreen && EnableMagnify
+LOCALVAR int WinMagStates[kNumWinStates];
+#endif
+
+LOCALPROC ZapWinStateVars(void)
+{
+#if MayNotFullScreen
+	{
+		int i;
+
+		for (i = 0; i < kNumMagStates; ++i) {
+			HavePositionWins[i] = falseblnr;
+		}
+	}
+#endif
+#if VarFullScreen && EnableMagnify
+	{
+		int i;
+
+		for (i = 0; i < kNumWinStates; ++i) {
+			WinMagStates[i] = kMagStateAuto;
+		}
+	}
+#endif
+}
+
+#if VarFullScreen
+LOCALPROC ToggleWantFullScreen(void)
+{
+	WantFullScreen = ! WantFullScreen;
+
+#if EnableMagnify
+	{
+		int OldWinState =
+			UseFullScreen ? kWinStateFullScreen : kWinStateWindowed;
+		int OldMagState =
+			UseMagnify ? kMagStateMagnifgy : kMagStateNormal;
+		int NewWinState =
+			WantFullScreen ? kWinStateFullScreen : kWinStateWindowed;
+		int NewMagState = WinMagStates[NewWinState];
+
+		WinMagStates[OldWinState] = OldMagState;
+		if (kMagStateAuto != NewMagState) {
+			WantMagnify = (kMagStateMagnifgy == NewMagState);
+		} else {
+			WantMagnify = falseblnr;
+			if (WantFullScreen) {
+				if ((GetSystemMetrics(SM_CXSCREEN)
+						>= vMacScreenWidth * MyWindowScale)
+					&& (GetSystemMetrics(SM_CYSCREEN)
+						>= vMacScreenHeight * MyWindowScale)
+					)
+				{
+					WantMagnify = trueblnr;
+				}
+			}
+		}
+	}
+#endif
+}
+#endif
+
+#if EnableDragDrop
+LOCALPROC DragFunc(HDROP hDrop)
+{
+	WORD n;
+	WORD i;
+	TCHAR a[_MAX_PATH];
+
+	n = DragQueryFile(hDrop, (UINT) -1, NULL, 0);
+	for (i = 0; i < n; ++i) {
+		if (DragQueryFile(hDrop, i, NULL, 0) < _MAX_PATH - 1) {
+			(void) DragQueryFile(hDrop, i, a, _MAX_PATH);
+			(void) InsertDiskOrAlias(a, trueblnr, trueblnr);
+		}
+	}
+
+	DragFinish(hDrop);
+
+	if (gTrueBackgroundFlag) {
+		if (! SetForegroundWindow(MainWnd)) {
+			/* error message here ? */
+		}
+
+		WantCmdOptOnReconnect = trueblnr;
+	}
+}
+#endif
+
+GLOBALOSGLUFUNC blnr ExtraTimeNotOver(void)
+{
+#if MySoundEnabled
+	SoundCheckVeryOften();
+#endif
+	(void) UpdateTrueEmulatedTime();
+	return (TrueEmulatedTime == OnTrueTime);
+}
+
+/* --- platform independent code can be thought of as going here --- */
+
+LOCALPROC LeaveBackground(void)
+{
+	ReconnectKeyCodes3();
+}
+
+LOCALPROC EnterBackground(void)
+{
+	DisconnectKeyCodes3();
+
+#if VarFullScreen
+	if (WantFullScreen) {
+		ToggleWantFullScreen();
+	}
+#endif
+}
+
+LOCALPROC LeaveSpeedStopped(void)
+{
+#if MySoundEnabled
+	MySound_Start();
+#endif
+#if (MyTimeResolution != 0)
+	MyTimer_Resume();
+#endif
+}
+
+LOCALPROC EnterSpeedStopped(void)
+{
+#if (MyTimeResolution != 0)
+	MyTimer_Suspend();
+#endif
+#if MySoundEnabled
+	MySound_Stop();
+#endif
+}
+
+LOCALPROC CheckForSavedTasks(void)
+{
+	/*
+		Check for things to do that rather wouldn't
+		have done at an awkward time.
+	*/
+
+	if (MyEvtQNeedRecover) {
+		MyEvtQNeedRecover = falseblnr;
+
+		/* attempt cleanup, MyEvtQNeedRecover may get set again */
+		MyEvtQTryRecoverFromFull();
+	}
+
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		MyMouseConstrain();
+	}
+#endif
+
+	if (RequestMacOff) {
+		RequestMacOff = falseblnr;
+		if (AnyDiskInserted()) {
+			MacMsgOverride(kStrQuitWarningTitle,
+				kStrQuitWarningMessage);
+		} else {
+			ForceMacOff = trueblnr;
+		}
+	}
+
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (gTrueBackgroundFlag != gBackgroundFlag) {
+		gBackgroundFlag = gTrueBackgroundFlag;
+		if (gTrueBackgroundFlag) {
+			EnterBackground();
+		} else {
+			LeaveBackground();
+		}
+	}
+
+	if (CurSpeedStopped != (SpeedStopped ||
+		(gBackgroundFlag && ! RunInBackground
+#if EnableAutoSlow && 0
+			&& (QuietSubTicks >= 4092)
+#endif
+		)))
+	{
+		CurSpeedStopped = ! CurSpeedStopped;
+		if (CurSpeedStopped) {
+			EnterSpeedStopped();
+		} else {
+			LeaveSpeedStopped();
+		}
+	}
+
+#if EnableRecreateW
+	if (! (gTrueBackgroundFlag)) {
+		CheckMagnifyAndFullScreen();
+	}
+#endif
+
+#if MayFullScreen
+	if (GrabMachine != (
+#if VarFullScreen
+		UseFullScreen &&
+#endif
+		! (gTrueBackgroundFlag || CurSpeedStopped)))
+	{
+		GrabMachine = ! GrabMachine;
+		AdjustMachineGrab();
+	}
+#endif
+
+	if (gTrueBackgroundFlag) {
+		/*
+			wait til later
+		*/
+	} else {
+#if IncludeSonyNew
+		if (vSonyNewDiskWanted) {
+#if IncludeSonyNameNew
+			if (vSonyNewDiskName != NotAPbuf) {
+				HGLOBAL NewDiskNameDat;
+				if (MacRomanTextToNativeHand(vSonyNewDiskName, trueblnr,
+					&NewDiskNameDat))
+				{
+					MakeNewDisk(vSonyNewDiskSize, NewDiskNameDat);
+					GlobalFree(NewDiskNameDat);
+				}
+				PbufDispose(vSonyNewDiskName);
+				vSonyNewDiskName = NotAPbuf;
+			} else
+#endif
+			{
+				MakeNewDisk(vSonyNewDiskSize, NULL);
+			}
+			vSonyNewDiskWanted = falseblnr;
+				/* must be done after may have gotten disk */
+		}
+#endif
+		if (RequestInsertDisk) {
+			RequestInsertDisk = falseblnr;
+			InsertADisk0();
+		}
+	}
+
+#if NeedRequestIthDisk
+	if (0 != RequestIthDisk) {
+		Sony_InsertIth(RequestIthDisk);
+		RequestIthDisk = 0;
+	}
+#endif
+
+	if (HaveCursorHidden != (WantCursorHidden
+		&& ! (gTrueBackgroundFlag || CurSpeedStopped)))
+	{
+		HaveCursorHidden = ! HaveCursorHidden;
+		if (HaveCursorHidden) {
+			(void) ShowCursor(FALSE);
+		} else {
+			(void) ShowCursor(TRUE);
+			SetCursor(LoadCursor(NULL, IDC_ARROW));
+		}
+	}
+
+	if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
+		MacMsgDisplayOn();
+	}
+
+	if (NeedWholeScreenDraw) {
+		NeedWholeScreenDraw = falseblnr;
+		ScreenChangedAll();
+	}
+}
+
+#if UseWinCE
+/* Sip Status ON/OFF */
+LOCALVAR blnr SipOn = falseblnr;
+#endif
+
+LRESULT CALLBACK Win32WMProc(HWND hwnd,
+	UINT uMessage, WPARAM wparam, LPARAM lparam);
+
+LRESULT CALLBACK Win32WMProc(HWND hwnd,
+	UINT uMessage, WPARAM wparam, LPARAM lparam)
+{
+	switch (uMessage)
+	{
+		case WM_PAINT:
+			{
+				PAINTSTRUCT ps;
+
+				BeginPaint(hwnd, (LPPAINTSTRUCT)&ps);
+#if VarFullScreen
+				if (UseFullScreen)
+#endif
+#if MayFullScreen
+				{
+					if (! FillRect(ps.hdc,
+						&ps.rcPaint,
+						GetStockObject(BLACK_BRUSH)))
+					{
+						/* ReportGetLastError(); */
+					}
+				}
+#endif
+				if (MainWnd == hwnd) {
+					Screen_DrawAll();
+				}
+				EndPaint(hwnd, (LPPAINTSTRUCT)&ps);
+			}
+			break;
+
+		case WM_KEYDOWN:
+		case WM_SYSKEYDOWN:
+#if UseWinCE
+			SipOn = falseblnr;
+
+			{
+				SIPINFO r;
+
+				memset(&r, 0 , sizeof(SIPINFO));
+				r.cbSize = sizeof(SIPINFO);
+				if (SipGetInfo(&r)) {
+					SipOn = 0 != (r.fdwFlags & SIPF_ON);
+				}
+			}
+
+			if (wparam == 0xAE) {
+				break;
+			} else if ((! SipOn) && (wparam == VK_RETURN)) {
+				break;
+			} else if ((! SipOn)
+				&& (wparam >= VK_LEFT) && (wparam <= VK_DOWN))
+			{
+				break;
+			} else if (wparam == VK_CONTROL && CtrlMode) {
+				DoVKcode0(wparam, falseblnr);
+				CtrlMode = falseblnr;
+				break;
+			} else if (wparam == VK_CONTROL) {
+				DoVKcode0(wparam, trueblnr);
+				CtrlMode = trueblnr;
+				break;
+			}
+#endif
+			if (! TestBit(lparam, 30)) { /* ignore repeats */
+				DoVKcode(wparam, lparam >> 24, trueblnr);
+			}
+
+#if UseWinCE
+			return TRUE;
+				/*
+					So that hardware keys won't be
+					processed by the default handler
+				*/
+#endif
+
+			break;
+		case WM_KEYUP:
+		case WM_SYSKEYUP:
+#if UseWinCE
+			SipOn = falseblnr;
+
+			{
+				SIPINFO r;
+
+				memset(&r, 0 , sizeof(SIPINFO));
+				r.cbSize = sizeof(SIPINFO);
+				if (SipGetInfo(&r)) {
+					SipOn = 0 != (r.fdwFlags & SIPF_ON);
+				}
+			}
+
+			if (wparam == 0xAE) { /* to hide SoftInput panel */
+				SipShowIM(SIPF_OFF);
+				break;
+			} else if ((! SipOn) && (wparam == VK_RETURN)) {
+				/* DPad Action to show SIP */
+				/* Show SoftInput Panel */
+				SipShowIM(SIPF_ON);
+				break;
+			} else if ((! SipOn)
+				&& (wparam >= VK_LEFT) && (wparam <= VK_DOWN))
+			{
+				switch (wparam) {
+					case VK_LEFT:
+						if (ViewHStart < (ViewHSize / 2)) {
+							ViewHStart = 0;
+						} else {
+							ViewHStart -= (ViewHSize / 2);
+						}
+						break;
+					case VK_UP:
+						if (ViewVStart < (ViewVSize / 2)) {
+							ViewVStart = 0;
+						} else {
+							ViewVStart -= (ViewVSize / 2);
+						}
+						break;
+					case VK_RIGHT:
+						ViewHStart += (ViewHSize / 2);
+						if (ViewHStart >= (vMacScreenWidth - ViewHSize))
+						{
+							ViewHStart = vMacScreenWidth - ViewHSize;
+						}
+						break;
+					case VK_DOWN:
+						ViewVStart += (ViewVSize / 2);
+						if (ViewVStart
+							>= (vMacScreenHeight - ViewVSize))
+						{
+							ViewVStart = vMacScreenHeight - ViewVSize;
+						}
+						break;
+				}
+				Screen_DrawAll();
+			} else
+			if (wparam == VK_CONTROL && CtrlMode) {
+				break;
+			}
+#endif
+			DoVKcode(wparam, lparam >> 24, falseblnr);
+
+#if UseWinCE
+			return TRUE;
+				/*
+					So that hardware keys won't be
+					processed by the default handler
+				*/
+#endif
+
+			break;
+#if ItnlKyBdFix && ! UseWinCE
+		case WM_INPUTLANGCHANGE:
+			MyCheckKeyboardLayout();
+			return TRUE;
+			break;
+#endif
+
+		case WM_CLOSE:
+			RequestMacOff = trueblnr;
+			break;
+#if ! UseWinCE
+		case WM_QUERYENDSESSION:
+			if (AnyDiskInserted()) {
+				RequestMacOff = trueblnr;
+				return FALSE;
+			} else {
+				return TRUE;
+			}
+			break;
+#endif
+		case WM_ACTIVATE:
+			if (MainWnd == hwnd) {
+				gTrueBackgroundFlag = (LOWORD(wparam) == WA_INACTIVE);
+			}
+			break;
+		case WM_COMMAND:
+			switch(LOWORD(wparam))
+			{
+				case ID_FILE_INSERTDISK1:
+					RequestInsertDisk = trueblnr;
+					break;
+				case ID_FILE_QUIT:
+					RequestMacOff = trueblnr;
+					break;
+				case ID_SPECIAL_MORECOMMANDS:
+					DoMoreCommandsMsg();
+					break;
+				case ID_HELP_ABOUT:
+					DoAboutMsg();
+					break;
+			}
+			break;
+		case WM_MOVE:
+			WndX = (si4b) LOWORD(lparam);
+			WndY = (si4b) HIWORD(lparam);
+			break;
+		case WM_SYSCHAR:
+		case WM_CHAR:
+			/* prevent any further processing */
+			break;
+		case WM_LBUTTONDOWN:
+		case WM_RBUTTONDOWN:
+			MousePositionNotify(LOWORD (lparam), HIWORD (lparam));
+			SetCurMouseButton(trueblnr);
+			break;
+		case WM_LBUTTONUP:
+		case WM_RBUTTONUP:
+			MousePositionNotify(LOWORD (lparam), HIWORD (lparam));
+			SetCurMouseButton(falseblnr);
+			break;
+		case WM_MOUSEMOVE:
+#if UseWinCE
+			MousePositionNotify(LOWORD (lparam), HIWORD (lparam));
+#endif
+			/* windows may have messed up cursor */
+			/*
+				there is no notification when the mouse moves
+				outside the window, and the cursor is automatically
+				changed
+			*/
+			if (! HaveCursorHidden) {
+				/* SetCursor(LoadCursor(NULL, IDC_ARROW)); */
+			}
+			break;
+#if EnableDragDrop
+		case WM_CREATE:
+			DragAcceptFiles(hwnd, TRUE);
+			break;
+		case WM_DROPFILES:
+			DragFunc((HDROP) wparam);
+			break;
+		case WM_DESTROY:
+			DragAcceptFiles(hwnd, FALSE);
+			break;
+#endif
+		default:
+			return DefWindowProc(hwnd, uMessage, wparam, lparam);
+	}
+	return 0;
+}
+
+LOCALFUNC blnr RegisterOurClass(void)
+{
+	WNDCLASS wc;
+
+	wc.style         = CS_HREDRAW | CS_VREDRAW
+#if ! UseWinCE
+		| CS_OWNDC
+#endif
+		;
+	wc.lpfnWndProc   = (WNDPROC)Win32WMProc;
+	wc.cbClsExtra    = 0;
+	wc.cbWndExtra    = 0;
+	wc.hInstance     = AppInstance;
+	wc.hIcon         = LoadIcon(AppInstance, MAKEINTRESOURCE(IDI_VMAC));
+	wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
+	wc.hbrBackground = GetStockObject(BLACK_BRUSH);
+	wc.lpszMenuName  = NULL;
+	wc.lpszClassName = WndClassName;
+
+	if (! RegisterClass(&wc)) {
+		MacMsg("RegisterClass failed",
+			"Sorry, Mini vMac encountered errors"
+			" and cannot continue.", trueblnr);
+		return falseblnr;
+	} else {
+		return trueblnr;
+	}
+}
+
+LOCALPROC WaitForTheNextEvent(void)
+{
+	MSG msg;
+
+	if (-1 != GetMessage(&msg, NULL, 0, 0)) {
+		DispatchMessage(&msg);
+	}
+}
+
+LOCALPROC CheckForSystemEvents(void)
+{
+	MSG msg;
+	ui3r i = 0;
+
+	while ((i < 32) && (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))) {
+		DispatchMessage(&msg);
+		++i;
+	}
+}
+
+GLOBALOSGLUPROC WaitForNextTick(void)
+{
+label_retry:
+	CheckForSystemEvents();
+	CheckForSavedTasks();
+
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (CurSpeedStopped) {
+		DoneWithDrawingForTick();
+		WaitForTheNextEvent();
+		goto label_retry;
+	}
+
+	if (ExtraTimeNotOver()) {
+		Sleep(NextIntTime - LastTime);
+		goto label_retry;
+	}
+
+	if (CheckDateTime()) {
+#if MySoundEnabled
+		MySound_SecondNotify();
+#endif
+#if EnableDemoMsg
+		DemoModeSecondNotify();
+#endif
+	}
+
+	if (! (gBackgroundFlag)) {
+#if ! UseWinCE
+		CheckMouseState();
+#endif
+
+#if EnableGrabSpecialKeys
+		CheckForLostKeyUps();
+#endif
+	}
+
+	OnTrueTime = TrueEmulatedTime;
+
+#if dbglog_TimeStuff
+	dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime);
+#endif
+}
+
+#if UseWinCE
+LOCALFUNC blnr Init_ChangeOrientation(void)
+{
+	DEVMODE dm;
+
+	/* initialize the DEVMODE structure */
+	ZeroMemory(&dm, sizeof (dm));
+	dm.dmSize = sizeof (dm);
+
+	EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
+
+	/* Backup old values */
+	oldOrientation = dm.dmOrientation;
+	oldDisplayOrientation = dm.dmDisplayOrientation;
+
+
+	/* Hide SIP (you can never tell...) */
+	SipShowIM(SIPF_OFF);
+
+	/* Switch to Landscape mode if possible */
+	dm.dmOrientation = DMORIENT_LANDSCAPE;
+	dm.dmDisplayOrientation = DMDO_90;
+	dm.dmFields = DM_ORIENTATION | DM_DISPLAYORIENTATION;
+	(void) ChangeDisplaySettingsEx(NULL, &dm, NULL, 0, 0);
+	/*
+		if (ChangeDisplaySettingsEx(NULL, &dm, NULL, 0, 0) !=
+			DISP_CHANGE_SUCCESSFUL)
+		{
+			MacMsg ("warning",
+				"Couldn't switch to Landscape mode.", falseblnr);
+		}
+	*/
+
+	return trueblnr;
+}
+#endif
+
+#if UseWinCE
+LOCALPROC Uninit_ChangeOrientation(void)
+{
+	DEVMODE dm;
+
+	/* Restore old display orientation */
+	ZeroMemory(&dm, sizeof (dm));
+	dm.dmSize = sizeof(dm);
+
+	EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm);
+
+	dm.dmOrientation = oldOrientation;
+	dm.dmDisplayOrientation = oldDisplayOrientation;
+	dm.dmFields = DM_ORIENTATION | DM_DISPLAYORIENTATION;
+
+	ChangeDisplaySettingsEx(NULL, &dm, 0, 0, 0);
+}
+#endif
+
+
+/* ** code for handling hardware keys in Pocket PC devices ** */
+
+#if UseWinCE
+typedef BOOL (__stdcall *UnregisterFunc1Proc)(UINT, UINT);
+LOCALVAR HINSTANCE hCoreDLL = NULL;
+#endif
+
+#if UseWinCE
+LOCALFUNC blnr InitHotKeys(void)
+{
+	UnregisterFunc1Proc procUndergisterFunc;
+	int i;
+
+	hCoreDLL = LoadLibrary(TEXT("coredll.dll"));
+	if (! hCoreDLL) {
+		MacMsg ("Fatal", "Could not load coredll.dll", trueblnr);
+	} else {
+		procUndergisterFunc =
+			(UnregisterFunc1Proc) GetProcAddress(hCoreDLL,
+			TEXT("UnregisterFunc1"));
+		if (! procUndergisterFunc) {
+			MacMsg ("Fatal",
+				"Could not get UnregisterFunc1 procedure", trueblnr);
+		} else {
+			for (i = 0xc1; i <= 0xcf; ++i) {
+				procUndergisterFunc(MOD_WIN, i);
+				RegisterHotKey(MainWnd, i, MOD_WIN, i);
+			}
+		}
+	}
+	return trueblnr;
+}
+#endif
+
+#if UseWinCE
+LOCALPROC UninitHotKeys(void)
+{
+	if (! hCoreDLL) {
+		FreeLibrary(hCoreDLL);
+	}
+}
+#endif
+
+#include "PROGMAIN.h"
+
+/* ************************ */
+
+LOCALPROC ZapOSGLUVars(void)
+{
+	InitDrives();
+	ZapWinStateVars();
+}
+
+LOCALPROC ReserveAllocAll(void)
+{
+#if dbglog_HAVE
+	dbglog_ReserveAlloc();
+#endif
+	ReserveAllocOneBlock(&ROM, kROM_Size, 5, falseblnr);
+	ReserveAllocOneBlock(&screencomparebuff,
+		vMacScreenNumBytes, 5, trueblnr);
+#if UseControlKeys
+	ReserveAllocOneBlock(&CntrlDisplayBuff,
+		vMacScreenNumBytes, 5, falseblnr);
+#endif
+#if EnableScalingBuff
+	{
+		ui5r n = vMacScreenMonoNumBytes
+#if EnableMagnify
+			* MyWindowScale * MyWindowScale
+#endif
+			;
+#if 1 == vMacScreenDepth
+		if (vMacScreenNumBytes * 2 > n) {
+			n = vMacScreenNumBytes * 2;
+		}
+#elif vMacScreenDepth >= 4
+		if (vMacScreenNumBytes > n) {
+			n = vMacScreenNumBytes;
+		}
+#endif
+		ReserveAllocOneBlock(&ScalingBuff, n, 5, falseblnr);
+	}
+#endif
+#if MySoundEnabled
+	ReserveAllocOneBlock((ui3p *)&TheSoundBuffer,
+		dbhBufferSize, 5, falseblnr);
+#endif
+
+	EmulationReserveAlloc();
+}
+
+LOCALFUNC blnr AllocMyMemory(void)
+{
+	uimr n;
+	blnr IsOk = falseblnr;
+
+	ReserveAllocOffset = 0;
+	ReserveAllocBigBlock = nullpr;
+	ReserveAllocAll();
+	n = ReserveAllocOffset;
+	ReserveAllocBigBlock =
+		(ui3p)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, n);
+	if (NULL == ReserveAllocBigBlock) {
+		MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr);
+	} else {
+		ReserveAllocOffset = 0;
+		ReserveAllocAll();
+		if (n != ReserveAllocOffset) {
+			/* oops, program error */
+		} else {
+			IsOk = trueblnr;
+		}
+	}
+
+	return IsOk;
+}
+
+LOCALPROC UnallocMyMemory(void)
+{
+	if (nullpr != ReserveAllocBigBlock) {
+		if (GlobalFree(ReserveAllocBigBlock) != NULL) {
+			MacMsg("error", "GlobalFree failed", falseblnr);
+		}
+	}
+}
+
+LOCALFUNC blnr InitOSGLU(void)
+{
+	if (AllocMyMemory())
+#if dbglog_HAVE
+	if (dbglog_open())
+#endif
+	if (RegisterOurClass())
+	if (ScanCommandLine())
+	if (LoadInitialImages())
+#if InstallFileIcons
+	if (RegisterInRegistry())
+#endif
+	if (LoadMacRom())
+#if UseActvCode
+	if (ActvCodeInit())
+#endif
+#if UseWinCE
+	if (Init_ChangeOrientation())
+#endif
+	if (ReCreateMainWindow())
+	if (InitWinKey2Mac())
+	if (InitTheCursor())
+#if UseWinCE
+	if (InitHotKeys())
+#endif
+	if (Init60thCheck())
+	if (WaitForRom())
+	{
+		return trueblnr;
+	}
+	return falseblnr;
+}
+
+LOCALPROC UnInitOSGLU(void)
+{
+#if (MyTimeResolution != 0)
+	MyTimer_Suspend();
+#endif
+	MyMouseCaptureSet(falseblnr);
+
+	if (MacMsgDisplayed) {
+		MacMsgDisplayOff();
+	}
+
+#if MayFullScreen
+	UnGrabTheMachine();
+#endif
+#if MySoundEnabled
+	MySound_Stop();
+#endif
+#if IncludePbufs
+	UnInitPbufs();
+#endif
+	UnInitDrives();
+
+	ForceShowCursor();
+#if UseWinCE
+	Uninit_ChangeOrientation();
+	UninitHotKeys();
+#endif
+
+#if EnableShellLinks
+	MyUninitCOM();
+#endif
+
+	if (! gTrueBackgroundFlag) {
+		CheckSavedMacMsg();
+	}
+
+	DisposeMainWindow();
+
+#if dbglog_HAVE
+	dbglog_close();
+#endif
+
+	UnallocMyMemory();
+}
+
+int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+	LPTSTR lpCmdLine, int nCmdShow)
+{
+	UnusedParam(hPrevInstance);
+	AppInstance = hInstance;
+	CmdShow = nCmdShow;
+	CommandLine = lpCmdLine;
+
+	GetWndTitle();
+#if UseWinCE
+	if (AlreadyRunningCheck()) {
+		return 0;
+	}
+#endif
+
+	ZapOSGLUVars();
+	if (InitOSGLU()) {
+		ProgramMain();
+	}
+	UnInitOSGLU();
+
+	return(0);
+}
--- /dev/null
+++ b/src/OSGLUXWN.c
@@ -1,0 +1,4839 @@
+/*
+	OSGLUXWN.c
+
+	Copyright (C) 2009 Michael Hanni, Christian Bauer,
+	Stephan Kochen, Paul C. Pratt, and others
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Operating System GLUe for X WiNdow system
+
+	All operating system dependent code for the
+	X Window System should go here.
+
+	This code is descended from Michael Hanni's X
+	port of vMac, by Philip Cummins.
+	I learned more about how X programs work by
+	looking at other programs such as Basilisk II,
+	the UAE Amiga Emulator, Bochs, QuakeForge,
+	DooM Legacy, and the FLTK. A few snippets
+	from them are used here.
+
+	Drag and Drop support is based on the specification
+	"XDND: Drag-and-Drop Protocol for the X Window System"
+	developed by John Lindal at New Planet Software, and
+	looking at included examples, one by Paul Sheer.
+*/
+
+#include "CNFGRAPI.h"
+#include "SYSDEPNS.h"
+#include "ENDIANAC.h"
+
+#include "MYOSGLUE.h"
+
+#include "STRCONST.h"
+
+/* --- some simple utilities --- */
+
+GLOBALOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount)
+{
+	(void) memcpy((char *)destPtr, (char *)srcPtr, byteCount);
+}
+
+/* --- control mode and internationalization --- */
+
+#define NeedCell2PlainAsciiMap 1
+
+#include "INTLCHAR.h"
+
+
+LOCALVAR char *d_arg = NULL;
+LOCALVAR char *n_arg = NULL;
+
+#if CanGetAppPath
+LOCALVAR char *app_parent = NULL;
+LOCALVAR char *app_name = NULL;
+#endif
+
+LOCALFUNC tMacErr ChildPath(char *x, char *y, char **r)
+{
+	tMacErr err = mnvm_miscErr;
+	int nx = strlen(x);
+	int ny = strlen(y);
+	{
+		if ((nx > 0) && ('/' == x[nx - 1])) {
+			--nx;
+		}
+		{
+			int nr = nx + 1 + ny;
+			char *p = malloc(nr + 1);
+			if (p != NULL) {
+				char *p2 = p;
+				(void) memcpy(p2, x, nx);
+				p2 += nx;
+				*p2++ = '/';
+				(void) memcpy(p2, y, ny);
+				p2 += ny;
+				*p2 = 0;
+				*r = p;
+				err = mnvm_noErr;
+			}
+		}
+	}
+
+	return err;
+}
+
+#if UseActvFile || IncludeSonyNew
+LOCALFUNC tMacErr FindOrMakeChild(char *x, char *y, char **r)
+{
+	tMacErr err;
+	struct stat folder_info;
+	char *r0;
+
+	if (mnvm_noErr == (err = ChildPath(x, y, &r0))) {
+		if (0 != stat(r0, &folder_info)) {
+			if (0 != mkdir(r0, S_IRWXU)) {
+				err = mnvm_miscErr;
+			} else {
+				*r = r0;
+				err = mnvm_noErr;
+			}
+		} else {
+			if (! S_ISDIR(folder_info.st_mode)) {
+				err = mnvm_miscErr;
+			} else {
+				*r = r0;
+				err = mnvm_noErr;
+			}
+		}
+	}
+
+	return err;
+}
+#endif
+
+LOCALPROC MyMayFree(char *p)
+{
+	if (NULL != p) {
+		free(p);
+	}
+}
+
+/* --- sending debugging info to file --- */
+
+#if dbglog_HAVE
+
+#define dbglog_ToStdErr 0
+
+#if ! dbglog_ToStdErr
+LOCALVAR FILE *dbglog_File = NULL;
+#endif
+
+LOCALFUNC blnr dbglog_open0(void)
+{
+#if dbglog_ToStdErr
+	return trueblnr;
+#else
+	dbglog_File = fopen("dbglog.txt", "w");
+	return (NULL != dbglog_File);
+#endif
+}
+
+LOCALPROC dbglog_write0(char *s, uimr L)
+{
+#if dbglog_ToStdErr
+	(void) fwrite(s, 1, L, stderr);
+#else
+	if (dbglog_File != NULL) {
+		(void) fwrite(s, 1, L, dbglog_File);
+	}
+#endif
+}
+
+LOCALPROC dbglog_close0(void)
+{
+#if ! dbglog_ToStdErr
+	if (dbglog_File != NULL) {
+		fclose(dbglog_File);
+		dbglog_File = NULL;
+	}
+#endif
+}
+
+#endif
+
+/* --- debug settings and utilities --- */
+
+#if ! dbglog_HAVE
+#define WriteExtraErr(s)
+#else
+LOCALPROC WriteExtraErr(char *s)
+{
+	dbglog_writeCStr("*** error: ");
+	dbglog_writeCStr(s);
+	dbglog_writeReturn();
+}
+#endif
+
+LOCALVAR Display *x_display = NULL;
+
+#define MyDbgEvents (dbglog_HAVE && 0)
+
+#if MyDbgEvents
+LOCALPROC WriteDbgAtom(char *s, Atom x)
+{
+	char *name = XGetAtomName(x_display, x);
+	if (name != NULL) {
+		dbglog_writeCStr("Atom ");
+		dbglog_writeCStr(s);
+		dbglog_writeCStr(": ");
+		dbglog_writeCStr(name);
+		dbglog_writeReturn();
+		XFree(name);
+	}
+}
+#endif
+
+/* --- information about the environment --- */
+
+LOCALVAR Atom MyXA_DeleteW = (Atom)0;
+#if EnableDragDrop
+LOCALVAR Atom MyXA_UriList = (Atom)0;
+LOCALVAR Atom MyXA_DndAware = (Atom)0;
+LOCALVAR Atom MyXA_DndEnter = (Atom)0;
+LOCALVAR Atom MyXA_DndLeave = (Atom)0;
+LOCALVAR Atom MyXA_DndDrop = (Atom)0;
+LOCALVAR Atom MyXA_DndPosition = (Atom)0;
+LOCALVAR Atom MyXA_DndStatus = (Atom)0;
+LOCALVAR Atom MyXA_DndActionCopy = (Atom)0;
+LOCALVAR Atom MyXA_DndActionPrivate = (Atom)0;
+LOCALVAR Atom MyXA_DndSelection = (Atom)0;
+LOCALVAR Atom MyXA_DndFinished = (Atom)0;
+LOCALVAR Atom MyXA_MinivMac_DndXchng = (Atom)0;
+LOCALVAR Atom MyXA_NetActiveWindow = (Atom)0;
+LOCALVAR Atom MyXA_NetSupported = (Atom)0;
+#endif
+#if IncludeHostTextClipExchange
+LOCALVAR Atom MyXA_CLIPBOARD = (Atom)0;
+LOCALVAR Atom MyXA_TARGETS = (Atom)0;
+LOCALVAR Atom MyXA_MinivMac_Clip = (Atom)0;
+#endif
+
+LOCALPROC LoadMyXA(void)
+{
+	MyXA_DeleteW = XInternAtom(x_display, "WM_DELETE_WINDOW", False);
+#if EnableDragDrop
+	MyXA_UriList = XInternAtom (x_display, "text/uri-list", False);
+	MyXA_DndAware = XInternAtom (x_display, "XdndAware", False);
+	MyXA_DndEnter = XInternAtom(x_display, "XdndEnter", False);
+	MyXA_DndLeave = XInternAtom(x_display, "XdndLeave", False);
+	MyXA_DndDrop = XInternAtom(x_display, "XdndDrop", False);
+	MyXA_DndPosition = XInternAtom(x_display, "XdndPosition", False);
+	MyXA_DndStatus = XInternAtom(x_display, "XdndStatus", False);
+	MyXA_DndActionCopy = XInternAtom(x_display,
+		"XdndActionCopy", False);
+	MyXA_DndActionPrivate = XInternAtom(x_display,
+		"XdndActionPrivate", False);
+	MyXA_DndSelection = XInternAtom(x_display, "XdndSelection", False);
+	MyXA_DndFinished = XInternAtom(x_display, "XdndFinished", False);
+	MyXA_MinivMac_DndXchng = XInternAtom(x_display,
+		"_MinivMac_DndXchng", False);
+	MyXA_NetActiveWindow = XInternAtom(x_display,
+		"_NET_ACTIVE_WINDOW", False);
+	MyXA_NetSupported = XInternAtom(x_display,
+		"_NET_SUPPORTED", False);
+#endif
+#if IncludeHostTextClipExchange
+	MyXA_CLIPBOARD = XInternAtom(x_display, "CLIPBOARD", False);
+	MyXA_TARGETS = XInternAtom(x_display, "TARGETS", False);
+	MyXA_MinivMac_Clip = XInternAtom(x_display,
+		"_MinivMac_Clip", False);
+#endif
+}
+
+#if EnableDragDrop
+LOCALFUNC blnr NetSupportedContains(Atom x)
+{
+	/*
+		Note that the window manager could be replaced at
+		any time, so don't cache results of this function.
+	*/
+	Atom ret_type;
+	int ret_format;
+	unsigned long ret_item;
+	unsigned long remain_byte;
+	unsigned long i;
+	unsigned char *s = 0;
+	blnr foundit = falseblnr;
+	Window rootwin = XRootWindow(x_display,
+		DefaultScreen(x_display));
+
+	if (Success != XGetWindowProperty(x_display, rootwin,
+		MyXA_NetSupported,
+		0, 65535, False, XA_ATOM, &ret_type, &ret_format,
+		&ret_item, &remain_byte, &s))
+	{
+		WriteExtraErr("XGetWindowProperty failed");
+	} else if (! s) {
+		WriteExtraErr("XGetWindowProperty failed");
+	} else if (ret_type != XA_ATOM) {
+		WriteExtraErr("XGetWindowProperty returns wrong type");
+	} else {
+		Atom *v = (Atom *)s;
+
+		for (i = 0; i < ret_item; ++i) {
+			if (v[i] == x) {
+				foundit = trueblnr;
+				/* fprintf(stderr, "found the hint\n"); */
+			}
+		}
+	}
+	if (s) {
+		XFree(s);
+	}
+	return foundit;
+}
+#endif
+
+#define WantColorTransValid 1
+
+#include "COMOSGLU.h"
+
+#include "PBUFSTDC.h"
+
+#include "CONTROLM.h"
+
+/* --- text translation --- */
+
+#if IncludePbufs
+/* this is table for Windows, any changes needed for X? */
+LOCALVAR const ui3b Native2MacRomanTab[] = {
+	0xAD, 0xB0, 0xE2, 0xC4, 0xE3, 0xC9, 0xA0, 0xE0,
+	0xF6, 0xE4, 0xB6, 0xDC, 0xCE, 0xB2, 0xB3, 0xB7,
+	0xB8, 0xD4, 0xD5, 0xD2, 0xD3, 0xA5, 0xD0, 0xD1,
+	0xF7, 0xAA, 0xC5, 0xDD, 0xCF, 0xB9, 0xC3, 0xD9,
+	0xCA, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4, 0xBA, 0xA4,
+	0xAC, 0xA9, 0xBB, 0xC7, 0xC2, 0xBD, 0xA8, 0xF8,
+	0xA1, 0xB1, 0xC6, 0xD7, 0xAB, 0xB5, 0xA6, 0xE1,
+	0xFC, 0xDA, 0xBC, 0xC8, 0xDE, 0xDF, 0xF0, 0xC0,
+	0xCB, 0xE7, 0xE5, 0xCC, 0x80, 0x81, 0xAE, 0x82,
+	0xE9, 0x83, 0xE6, 0xE8, 0xED, 0xEA, 0xEB, 0xEC,
+	0xF5, 0x84, 0xF1, 0xEE, 0xEF, 0xCD, 0x85, 0xF9,
+	0xAF, 0xF4, 0xF2, 0xF3, 0x86, 0xFA, 0xFB, 0xA7,
+	0x88, 0x87, 0x89, 0x8B, 0x8A, 0x8C, 0xBE, 0x8D,
+	0x8F, 0x8E, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,
+	0xFD, 0x96, 0x98, 0x97, 0x99, 0x9B, 0x9A, 0xD6,
+	0xBF, 0x9D, 0x9C, 0x9E, 0x9F, 0xFE, 0xFF, 0xD8
+};
+#endif
+
+#if IncludePbufs
+LOCALFUNC tMacErr NativeTextToMacRomanPbuf(char *x, tPbuf *r)
+{
+	if (NULL == x) {
+		return mnvm_miscErr;
+	} else {
+		ui3p p;
+		ui5b L = strlen(x);
+
+		p = (ui3p)malloc(L);
+		if (NULL == p) {
+			return mnvm_miscErr;
+		} else {
+			ui3b *p0 = (ui3b *)x;
+			ui3b *p1 = (ui3b *)p;
+			int i;
+
+			for (i = L; --i >= 0; ) {
+				ui3b v = *p0++;
+				if (v >= 128) {
+					v = Native2MacRomanTab[v - 128];
+				} else if (10 == v) {
+					v = 13;
+				}
+				*p1++ = v;
+			}
+
+			return PbufNewFromPtr(p, L, r);
+		}
+	}
+}
+#endif
+
+#if IncludePbufs
+/* this is table for Windows, any changes needed for X? */
+LOCALVAR const ui3b MacRoman2NativeTab[] = {
+	0xC4, 0xC5, 0xC7, 0xC9, 0xD1, 0xD6, 0xDC, 0xE1,
+	0xE0, 0xE2, 0xE4, 0xE3, 0xE5, 0xE7, 0xE9, 0xE8,
+	0xEA, 0xEB, 0xED, 0xEC, 0xEE, 0xEF, 0xF1, 0xF3,
+	0xF2, 0xF4, 0xF6, 0xF5, 0xFA, 0xF9, 0xFB, 0xFC,
+	0x86, 0xB0, 0xA2, 0xA3, 0xA7, 0x95, 0xB6, 0xDF,
+	0xAE, 0xA9, 0x99, 0xB4, 0xA8, 0x80, 0xC6, 0xD8,
+	0x81, 0xB1, 0x8D, 0x8E, 0xA5, 0xB5, 0x8A, 0x8F,
+	0x90, 0x9D, 0xA6, 0xAA, 0xBA, 0xAD, 0xE6, 0xF8,
+	0xBF, 0xA1, 0xAC, 0x9E, 0x83, 0x9A, 0xB2, 0xAB,
+	0xBB, 0x85, 0xA0, 0xC0, 0xC3, 0xD5, 0x8C, 0x9C,
+	0x96, 0x97, 0x93, 0x94, 0x91, 0x92, 0xF7, 0xB3,
+	0xFF, 0x9F, 0xB9, 0xA4, 0x8B, 0x9B, 0xBC, 0xBD,
+	0x87, 0xB7, 0x82, 0x84, 0x89, 0xC2, 0xCA, 0xC1,
+	0xCB, 0xC8, 0xCD, 0xCE, 0xCF, 0xCC, 0xD3, 0xD4,
+	0xBE, 0xD2, 0xDA, 0xDB, 0xD9, 0xD0, 0x88, 0x98,
+	0xAF, 0xD7, 0xDD, 0xDE, 0xB8, 0xF0, 0xFD, 0xFE
+};
+#endif
+
+#if IncludePbufs
+LOCALFUNC blnr MacRomanTextToNativePtr(tPbuf i, blnr IsFileName,
+	ui3p *r)
+{
+	ui3p p;
+	void *Buffer = PbufDat[i];
+	ui5b L = PbufSize[i];
+
+	p = (ui3p)malloc(L + 1);
+	if (p != NULL) {
+		ui3b *p0 = (ui3b *)Buffer;
+		ui3b *p1 = (ui3b *)p;
+		int j;
+
+		if (IsFileName) {
+			for (j = L; --j >= 0; ) {
+				ui3b x = *p0++;
+				if (x < 32) {
+					x = '-';
+				} else if (x >= 128) {
+					x = MacRoman2NativeTab[x - 128];
+				} else {
+					switch (x) {
+						case '/':
+						case '<':
+						case '>':
+						case '|':
+						case ':':
+							x = '-';
+						default:
+							break;
+					}
+				}
+				*p1++ = x;
+			}
+			if ('.' == p[0]) {
+				p[0] = '-';
+			}
+		} else {
+			for (j = L; --j >= 0; ) {
+				ui3b x = *p0++;
+				if (x >= 128) {
+					x = MacRoman2NativeTab[x - 128];
+				} else if (13 == x) {
+					x = '\n';
+				}
+				*p1++ = x;
+			}
+		}
+		*p1 = 0;
+
+		*r = p;
+		return trueblnr;
+	}
+	return falseblnr;
+}
+#endif
+
+LOCALPROC NativeStrFromCStr(char *r, char *s)
+{
+	ui3b ps[ClStrMaxLength];
+	int i;
+	int L;
+
+	ClStrFromSubstCStr(&L, ps, s);
+
+	for (i = 0; i < L; ++i) {
+		r[i] = Cell2PlainAsciiMap[ps[i]];
+	}
+
+	r[L] = 0;
+}
+
+/* --- drives --- */
+
+#define NotAfileRef NULL
+
+LOCALVAR FILE *Drives[NumDrives]; /* open disk image files */
+#if IncludeSonyGetName || IncludeSonyNew
+LOCALVAR char *DriveNames[NumDrives];
+#endif
+
+LOCALPROC InitDrives(void)
+{
+	/*
+		This isn't really needed, Drives[i] and DriveNames[i]
+		need not have valid values when not vSonyIsInserted[i].
+	*/
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		Drives[i] = NotAfileRef;
+#if IncludeSonyGetName || IncludeSonyNew
+		DriveNames[i] = NULL;
+#endif
+	}
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer,
+	tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count,
+	ui5r *Sony_ActCount)
+{
+	tMacErr err = mnvm_miscErr;
+	FILE *refnum = Drives[Drive_No];
+	ui5r NewSony_Count = 0;
+
+	if (0 == fseek(refnum, Sony_Start, SEEK_SET)) {
+		if (IsWrite) {
+			NewSony_Count = fwrite(Buffer, 1, Sony_Count, refnum);
+		} else {
+			NewSony_Count = fread(Buffer, 1, Sony_Count, refnum);
+		}
+
+		if (NewSony_Count == Sony_Count) {
+			err = mnvm_noErr;
+		}
+	}
+
+	if (nullpr != Sony_ActCount) {
+		*Sony_ActCount = NewSony_Count;
+	}
+
+	return err; /*& figure out what really to return &*/
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count)
+{
+	tMacErr err = mnvm_miscErr;
+	FILE *refnum = Drives[Drive_No];
+	long v;
+
+	if (0 == fseek(refnum, 0, SEEK_END)) {
+		v = ftell(refnum);
+		if (v >= 0) {
+			*Sony_Count = v;
+			err = mnvm_noErr;
+		}
+	}
+
+	return err; /*& figure out what really to return &*/
+}
+
+#ifndef HaveAdvisoryLocks
+#define HaveAdvisoryLocks 1
+#endif
+
+/*
+	What is the difference between fcntl(fd, F_SETLK ...
+	and flock(fd ... ?
+*/
+
+#if HaveAdvisoryLocks
+LOCALFUNC blnr MyLockFile(FILE *refnum)
+{
+	blnr IsOk = falseblnr;
+
+#if 1
+	struct flock fl;
+	int fd = fileno(refnum);
+
+	fl.l_start = 0; /* starting offset */
+	fl.l_len = 0; /* len = 0 means until end of file */
+	/* fl.pid_t l_pid; */ /* lock owner, don't need to set */
+	fl.l_type = F_WRLCK; /* lock type: read/write, etc. */
+	fl.l_whence = SEEK_SET; /* type of l_start */
+	if (-1 == fcntl(fd, F_SETLK, &fl)) {
+		MacMsg(kStrImageInUseTitle, kStrImageInUseMessage,
+			falseblnr);
+	} else {
+		IsOk = trueblnr;
+	}
+#else
+	int fd = fileno(refnum);
+
+	if (-1 == flock(fd, LOCK_EX | LOCK_NB)) {
+		MacMsg(kStrImageInUseTitle, kStrImageInUseMessage,
+			falseblnr);
+	} else {
+		IsOk = trueblnr;
+	}
+#endif
+
+	return IsOk;
+}
+#endif
+
+#if HaveAdvisoryLocks
+LOCALPROC MyUnlockFile(FILE *refnum)
+{
+#if 1
+	struct flock fl;
+	int fd = fileno(refnum);
+
+	fl.l_start = 0; /* starting offset */
+	fl.l_len = 0; /* len = 0 means until end of file */
+	/* fl.pid_t l_pid; */ /* lock owner, don't need to set */
+	fl.l_type = F_UNLCK;     /* lock type: read/write, etc. */
+	fl.l_whence = SEEK_SET;   /* type of l_start */
+	if (-1 == fcntl(fd, F_SETLK, &fl)) {
+		/* an error occurred */
+	}
+#else
+	int fd = fileno(refnum);
+
+	if (-1 == flock(fd, LOCK_UN)) {
+	}
+#endif
+}
+#endif
+
+LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, blnr deleteit)
+{
+	FILE *refnum = Drives[Drive_No];
+
+	DiskEjectedNotify(Drive_No);
+
+#if HaveAdvisoryLocks
+	MyUnlockFile(refnum);
+#endif
+
+	fclose(refnum);
+	Drives[Drive_No] = NotAfileRef; /* not really needed */
+
+#if IncludeSonyGetName || IncludeSonyNew
+	{
+		char *s = DriveNames[Drive_No];
+		if (NULL != s) {
+			if (deleteit) {
+				remove(s);
+			}
+			free(s);
+			DriveNames[Drive_No] = NULL; /* not really needed */
+		}
+	}
+#endif
+
+	return mnvm_noErr;
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
+{
+	return vSonyEject0(Drive_No, falseblnr);
+}
+
+#if IncludeSonyNew
+GLOBALOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No)
+{
+	return vSonyEject0(Drive_No, trueblnr);
+}
+#endif
+
+LOCALPROC UnInitDrives(void)
+{
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		if (vSonyIsInserted(i)) {
+			(void) vSonyEject(i);
+		}
+	}
+}
+
+#if IncludeSonyGetName
+GLOBALOSGLUFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r)
+{
+	char *drivepath = DriveNames[Drive_No];
+	if (NULL == drivepath) {
+		return mnvm_miscErr;
+	} else {
+		char *s = strrchr(drivepath, '/');
+		if (NULL == s) {
+			s = drivepath;
+		} else {
+			++s;
+		}
+		return NativeTextToMacRomanPbuf(s, r);
+	}
+}
+#endif
+
+LOCALFUNC blnr Sony_Insert0(FILE *refnum, blnr locked,
+	char *drivepath)
+{
+	tDrive Drive_No;
+	blnr IsOk = falseblnr;
+
+	if (! FirstFreeDisk(&Drive_No)) {
+		MacMsg(kStrTooManyImagesTitle, kStrTooManyImagesMessage,
+			falseblnr);
+	} else {
+		/* printf("Sony_Insert0 %d\n", (int)Drive_No); */
+
+#if HaveAdvisoryLocks
+		if (locked || MyLockFile(refnum))
+#endif
+		{
+			Drives[Drive_No] = refnum;
+			DiskInsertNotify(Drive_No, locked);
+
+#if IncludeSonyGetName || IncludeSonyNew
+			{
+				ui5b L = strlen(drivepath);
+				char *p = malloc(L + 1);
+				if (p != NULL) {
+					(void) memcpy(p, drivepath, L + 1);
+				}
+				DriveNames[Drive_No] = p;
+			}
+#endif
+
+			IsOk = trueblnr;
+		}
+	}
+
+	if (! IsOk) {
+		fclose(refnum);
+	}
+
+	return IsOk;
+}
+
+LOCALFUNC blnr Sony_Insert1(char *drivepath, blnr silentfail)
+{
+	blnr locked = falseblnr;
+	/* printf("Sony_Insert1 %s\n", drivepath); */
+	FILE *refnum = fopen(drivepath, "rb+");
+	if (NULL == refnum) {
+		locked = trueblnr;
+		refnum = fopen(drivepath, "rb");
+	}
+	if (NULL == refnum) {
+		if (! silentfail) {
+			MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
+		}
+	} else {
+		return Sony_Insert0(refnum, locked, drivepath);
+	}
+	return falseblnr;
+}
+
+LOCALFUNC tMacErr LoadMacRomFrom(char *path)
+{
+	tMacErr err;
+	FILE *ROM_File;
+	int File_Size;
+
+	ROM_File = fopen(path, "rb");
+	if (NULL == ROM_File) {
+		err = mnvm_fnfErr;
+	} else {
+		File_Size = fread(ROM, 1, kROM_Size, ROM_File);
+		if (kROM_Size != File_Size) {
+			if (feof(ROM_File)) {
+				MacMsgOverride(kStrShortROMTitle,
+					kStrShortROMMessage);
+				err = mnvm_eofErr;
+			} else {
+				MacMsgOverride(kStrNoReadROMTitle,
+					kStrNoReadROMMessage);
+				err = mnvm_miscErr;
+			}
+		} else {
+			err = ROM_IsValid();
+		}
+		fclose(ROM_File);
+	}
+
+	return err;
+}
+
+LOCALFUNC blnr Sony_Insert1a(char *drivepath, blnr silentfail)
+{
+	blnr v;
+
+	if (! ROM_loaded) {
+		v = (mnvm_noErr == LoadMacRomFrom(drivepath));
+	} else {
+		v = Sony_Insert1(drivepath, silentfail);
+	}
+
+	return v;
+}
+
+LOCALFUNC blnr Sony_Insert2(char *s)
+{
+	char *d =
+#if CanGetAppPath
+		(NULL == d_arg) ? app_parent :
+#endif
+		d_arg;
+	blnr IsOk = falseblnr;
+
+	if (NULL == d) {
+		IsOk = Sony_Insert1(s, trueblnr);
+	} else {
+		char *t;
+
+		if (mnvm_noErr == ChildPath(d, s, &t)) {
+			IsOk = Sony_Insert1(t, trueblnr);
+			free(t);
+		}
+	}
+
+	return IsOk;
+}
+
+LOCALFUNC blnr Sony_InsertIth(int i)
+{
+	blnr v;
+
+	if ((i > 9) || ! FirstFreeDisk(nullpr)) {
+		v = falseblnr;
+	} else {
+		char s[] = "disk?.dsk";
+
+		s[4] = '0' + i;
+
+		v = Sony_Insert2(s);
+	}
+
+	return v;
+}
+
+LOCALFUNC blnr LoadInitialImages(void)
+{
+	if (! AnyDiskInserted()) {
+		int i;
+
+		for (i = 1; Sony_InsertIth(i); ++i) {
+			/* stop on first error (including file not found) */
+		}
+	}
+
+	return trueblnr;
+}
+
+#if IncludeSonyNew
+LOCALFUNC blnr WriteZero(FILE *refnum, ui5b L)
+{
+#define ZeroBufferSize 2048
+	ui5b i;
+	ui3b buffer[ZeroBufferSize];
+
+	memset(&buffer, 0, ZeroBufferSize);
+
+	while (L > 0) {
+		i = (L > ZeroBufferSize) ? ZeroBufferSize : L;
+		if (fwrite(buffer, 1, i, refnum) != i) {
+			return falseblnr;
+		}
+		L -= i;
+	}
+	return trueblnr;
+}
+#endif
+
+#if IncludeSonyNew
+LOCALPROC MakeNewDisk0(ui5b L, char *drivepath)
+{
+	blnr IsOk = falseblnr;
+	FILE *refnum = fopen(drivepath, "wb+");
+	if (NULL == refnum) {
+		MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
+	} else {
+		if (WriteZero(refnum, L)) {
+			IsOk = Sony_Insert0(refnum, falseblnr, drivepath);
+			refnum = NULL;
+		}
+		if (refnum != NULL) {
+			fclose(refnum);
+		}
+		if (! IsOk) {
+			(void) remove(drivepath);
+		}
+	}
+}
+#endif
+
+#if IncludeSonyNew
+LOCALPROC MakeNewDisk(ui5b L, char *drivename)
+{
+	char *d =
+#if CanGetAppPath
+		(NULL == d_arg) ? app_parent :
+#endif
+		d_arg;
+
+	if (NULL == d) {
+		MakeNewDisk0(L, drivename); /* in current directory */
+	} else {
+		tMacErr err;
+		char *t = NULL;
+		char *t2 = NULL;
+
+		if (mnvm_noErr == (err = FindOrMakeChild(d, "out", &t)))
+		if (mnvm_noErr == (err = ChildPath(t, drivename, &t2)))
+		{
+			MakeNewDisk0(L, t2);
+		}
+
+		MyMayFree(t2);
+		MyMayFree(t);
+	}
+}
+#endif
+
+#if IncludeSonyNew
+LOCALPROC MakeNewDiskAtDefault(ui5b L)
+{
+	char s[ClStrMaxLength + 1];
+
+	NativeStrFromCStr(s, "untitled.dsk");
+	MakeNewDisk(L, s);
+}
+#endif
+
+/* --- ROM --- */
+
+LOCALVAR char *rom_path = NULL;
+
+#if 0
+#include <pwd.h>
+#include <unistd.h>
+#endif
+
+LOCALFUNC tMacErr FindUserHomeFolder(char **r)
+{
+	tMacErr err;
+	char *s;
+#if 0
+	struct passwd *user;
+#endif
+
+	if (NULL != (s = getenv("HOME"))) {
+		*r = s;
+		err = mnvm_noErr;
+	} else
+#if 0
+	if ((NULL != (user = getpwuid(getuid())))
+		&& (NULL != (s = user->pw_dir)))
+	{
+		/*
+			From getpwuid man page:
+			"An application that wants to determine its user's
+			home directory should inspect the value of HOME
+			(rather than the value getpwuid(getuid())->pw_dir)
+			since this allows the user to modify their notion of
+			"the home directory" during a login session."
+
+			But it is possible for HOME to not be set.
+			Some sources say to use getpwuid in that case.
+		*/
+		*r = s;
+		err = mnvm_noErr;
+	} else
+#endif
+	{
+		err = mnvm_fnfErr;
+	}
+
+	return err;
+}
+
+LOCALFUNC tMacErr LoadMacRomFromHome(void)
+{
+	tMacErr err;
+	char *s;
+	char *t = NULL;
+	char *t2 = NULL;
+	char *t3 = NULL;
+
+	if (mnvm_noErr == (err = FindUserHomeFolder(&s)))
+	if (mnvm_noErr == (err = ChildPath(s, ".gryphel", &t)))
+	if (mnvm_noErr == (err = ChildPath(t, "mnvm_rom", &t2)))
+	if (mnvm_noErr == (err = ChildPath(t2, RomFileName, &t3)))
+	{
+		err = LoadMacRomFrom(t3);
+	}
+
+	MyMayFree(t3);
+	MyMayFree(t2);
+	MyMayFree(t);
+
+	return err;
+}
+
+#if CanGetAppPath
+LOCALFUNC tMacErr LoadMacRomFromAppPar(void)
+{
+	tMacErr err;
+	char *d =
+#if CanGetAppPath
+		(NULL == d_arg) ? app_parent :
+#endif
+		d_arg;
+	char *t = NULL;
+
+	if (NULL == d) {
+		err = mnvm_fnfErr;
+	} else {
+		if (mnvm_noErr == (err = ChildPath(d, RomFileName,
+			&t)))
+		{
+			err = LoadMacRomFrom(t);
+		}
+	}
+
+	MyMayFree(t);
+
+	return err;
+}
+#endif
+
+LOCALFUNC blnr LoadMacRom(void)
+{
+	tMacErr err;
+
+	if ((NULL == rom_path)
+		|| (mnvm_fnfErr == (err = LoadMacRomFrom(rom_path))))
+#if CanGetAppPath
+	if (mnvm_fnfErr == (err = LoadMacRomFromAppPar()))
+#endif
+	if (mnvm_fnfErr == (err = LoadMacRomFromHome()))
+	if (mnvm_fnfErr == (err = LoadMacRomFrom(RomFileName)))
+	{
+	}
+
+	return trueblnr; /* keep launching Mini vMac, regardless */
+}
+
+#if UseActvFile
+
+#define ActvCodeFileName "act_1"
+
+LOCALFUNC tMacErr ActvCodeFileLoad(ui3p p)
+{
+	tMacErr err;
+	char *s;
+	char *t = NULL;
+	char *t2 = NULL;
+	char *t3 = NULL;
+
+	if (mnvm_noErr == (err = FindUserHomeFolder(&s)))
+	if (mnvm_noErr == (err = ChildPath(s, ".gryphel", &t)))
+	if (mnvm_noErr == (err = ChildPath(t, "mnvm_act", &t2)))
+	if (mnvm_noErr == (err = ChildPath(t2, ActvCodeFileName, &t3)))
+	{
+		FILE *Actv_File;
+		int File_Size;
+
+		Actv_File = fopen(t3, "rb");
+		if (NULL == Actv_File) {
+			err = mnvm_fnfErr;
+		} else {
+			File_Size = fread(p, 1, ActvCodeFileLen, Actv_File);
+			if (File_Size != ActvCodeFileLen) {
+				if (feof(Actv_File)) {
+					err = mnvm_eofErr;
+				} else {
+					err = mnvm_miscErr;
+				}
+			} else {
+				err = mnvm_noErr;
+			}
+			fclose(Actv_File);
+		}
+	}
+
+	MyMayFree(t3);
+	MyMayFree(t2);
+	MyMayFree(t);
+
+	return err;
+}
+
+LOCALFUNC tMacErr ActvCodeFileSave(ui3p p)
+{
+	tMacErr err;
+	char *s;
+	char *t = NULL;
+	char *t2 = NULL;
+	char *t3 = NULL;
+
+	if (mnvm_noErr == (err = FindUserHomeFolder(&s)))
+	if (mnvm_noErr == (err = FindOrMakeChild(s, ".gryphel", &t)))
+	if (mnvm_noErr == (err = FindOrMakeChild(t, "mnvm_act", &t2)))
+	if (mnvm_noErr == (err = ChildPath(t2, ActvCodeFileName, &t3)))
+	{
+		FILE *Actv_File;
+		int File_Size;
+
+		Actv_File = fopen(t3, "wb+");
+		if (NULL == Actv_File) {
+			err = mnvm_fnfErr;
+		} else {
+			File_Size = fwrite(p, 1, ActvCodeFileLen, Actv_File);
+			if (File_Size != ActvCodeFileLen) {
+				err = mnvm_miscErr;
+			} else {
+				err = mnvm_noErr;
+			}
+			fclose(Actv_File);
+		}
+	}
+
+	MyMayFree(t3);
+	MyMayFree(t2);
+	MyMayFree(t);
+
+	return err;
+}
+
+#endif /* UseActvFile */
+
+/* --- video out --- */
+
+LOCALVAR Window my_main_wind = 0;
+LOCALVAR GC my_gc = NULL;
+LOCALVAR blnr NeedFinishOpen1 = falseblnr;
+LOCALVAR blnr NeedFinishOpen2 = falseblnr;
+
+LOCALVAR XColor x_black;
+LOCALVAR XColor x_white;
+
+#if MayFullScreen
+LOCALVAR short hOffset;
+LOCALVAR short vOffset;
+#endif
+
+#if VarFullScreen
+LOCALVAR blnr UseFullScreen = (WantInitFullScreen != 0);
+#endif
+
+#if EnableMagnify
+LOCALVAR blnr UseMagnify = (WantInitMagnify != 0);
+#endif
+
+LOCALVAR blnr gBackgroundFlag = falseblnr;
+LOCALVAR blnr gTrueBackgroundFlag = falseblnr;
+LOCALVAR blnr CurSpeedStopped = trueblnr;
+
+#ifndef UseColorImage
+#define UseColorImage (0 != vMacScreenDepth)
+#endif
+
+LOCALVAR XImage *my_image = NULL;
+
+#if EnableMagnify
+LOCALVAR XImage *my_Scaled_image = NULL;
+#endif
+
+#if EnableMagnify
+#define MaxScale MyWindowScale
+#else
+#define MaxScale 1
+#endif
+
+#define WantScalingTabl (EnableMagnify || UseColorImage)
+
+#if WantScalingTabl
+
+LOCALVAR ui3p ScalingTabl = nullpr;
+
+#define ScalingTablsz1 (256 * MaxScale)
+
+#if UseColorImage
+#define ScalingTablsz (ScalingTablsz1 << 5)
+#else
+#define ScalingTablsz ScalingTablsz1
+#endif
+
+#endif /* WantScalingTabl */
+
+
+#define WantScalingBuff (EnableMagnify || UseColorImage)
+
+#if WantScalingBuff
+
+LOCALVAR ui3p ScalingBuff = nullpr;
+
+
+#if UseColorImage
+#define ScalingBuffsz \
+	(vMacScreenNumPixels * 4 * MaxScale * MaxScale)
+#else
+#define ScalingBuffsz ((long)vMacScreenMonoNumBytes \
+	* MaxScale * MaxScale)
+#endif
+
+#endif /* WantScalingBuff */
+
+
+#if EnableMagnify && ! UseColorImage
+LOCALPROC SetUpScalingTabl(void)
+{
+	ui3b *p4;
+	int i;
+	int j;
+	int k;
+	ui3r bitsRemaining;
+	ui3b t1;
+	ui3b t2;
+
+	p4 = ScalingTabl;
+	for (i = 0; i < 256; ++i) {
+		bitsRemaining = 8;
+		t2 = 0;
+		for (j = 8; --j >= 0; ) {
+			t1 = (i >> j) & 1;
+			for (k = MyWindowScale; --k >= 0; ) {
+				t2 = (t2 << 1) | t1;
+				if (--bitsRemaining == 0) {
+					*p4++ = t2;
+					bitsRemaining = 8;
+					t2 = 0;
+				}
+			}
+		}
+	}
+}
+#endif
+
+#if EnableMagnify && (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+LOCALPROC SetUpColorScalingTabl(void)
+{
+	int i;
+	int j;
+	int k;
+	int a;
+	ui5r v;
+	ui5p p4;
+
+	p4 = (ui5p)ScalingTabl;
+	for (i = 0; i < 256; ++i) {
+		for (k = 1 << (3 - vMacScreenDepth); --k >= 0; ) {
+			j = (i >> (k << vMacScreenDepth)) & (CLUT_size - 1);
+			v = (((long)CLUT_reds[j] & 0xFF00) << 8)
+				| ((long)CLUT_greens[j] & 0xFF00)
+				| (((long)CLUT_blues[j] & 0xFF00) >> 8);
+			for (a = MyWindowScale; --a >= 0; ) {
+				*p4++ = v;
+			}
+		}
+	}
+}
+#endif
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+LOCALPROC SetUpColorTabl(void)
+{
+	int i;
+	int j;
+	int k;
+	ui5p p4;
+
+	p4 = (ui5p)ScalingTabl;
+	for (i = 0; i < 256; ++i) {
+		for (k = 1 << (3 - vMacScreenDepth); --k >= 0; ) {
+			j = (i >> (k << vMacScreenDepth)) & (CLUT_size - 1);
+			*p4++ = (((long)CLUT_reds[j] & 0xFF00) << 8)
+				| ((long)CLUT_greens[j] & 0xFF00)
+				| (((long)CLUT_blues[j] & 0xFF00) >> 8);
+		}
+	}
+}
+#endif
+
+#if EnableMagnify && UseColorImage
+LOCALPROC SetUpBW2ColorScalingTabl(void)
+{
+	int i;
+	int k;
+	int a;
+	ui5r v;
+	ui5p p4;
+
+	p4 = (ui5p)ScalingTabl;
+	for (i = 0; i < 256; ++i) {
+		for (k = 8; --k >= 0; ) {
+			if (0 != ((i >> k) & 1)) {
+				v = 0;
+			} else {
+				v = 0xFFFFFF;
+			}
+
+			for (a = MyWindowScale; --a >= 0; ) {
+				*p4++ = v;
+			}
+		}
+	}
+}
+#endif
+
+#if UseColorImage
+LOCALPROC SetUpBW2ColorTabl(void)
+{
+	int i;
+	int k;
+	ui5r v;
+	ui5p p4;
+
+	p4 = (ui5p)ScalingTabl;
+	for (i = 0; i < 256; ++i) {
+		for (k = 8; --k >= 0; ) {
+			if (0 != ((i >> k) & 1)) {
+				v = 0;
+			} else {
+				v = 0xFFFFFF;
+			}
+			*p4++ = v;
+		}
+	}
+}
+#endif
+
+
+#if EnableMagnify && ! UseColorImage
+
+#define ScrnMapr_DoMap UpdateScaledBWCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 0
+#define ScrnMapr_Map ScalingTabl
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#endif
+
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+
+#define ScrnMapr_DoMap UpdateMappedColorCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map ScalingTabl
+
+#include "SCRNMAPR.h"
+
+#endif
+
+
+#if EnableMagnify && (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+
+#define ScrnMapr_DoMap UpdateMappedScaledColorCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map ScalingTabl
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#endif
+
+
+#if vMacScreenDepth >= 4
+
+#define ScrnTrns_DoTrans UpdateTransColorCopy
+#define ScrnTrns_Src GetCurDrawBuff()
+#define ScrnTrns_Dst ScalingBuff
+#define ScrnTrns_SrcDepth vMacScreenDepth
+#define ScrnTrns_DstDepth 5
+
+#include "SCRNTRNS.h"
+
+#endif
+
+#if EnableMagnify && (vMacScreenDepth >= 4)
+
+#define ScrnTrns_DoTrans UpdateTransScaledColorCopy
+#define ScrnTrns_Src GetCurDrawBuff()
+#define ScrnTrns_Dst ScalingBuff
+#define ScrnTrns_SrcDepth vMacScreenDepth
+#define ScrnTrns_DstDepth 5
+#define ScrnTrns_Scale MyWindowScale
+
+#include "SCRNTRNS.h"
+
+#endif
+
+
+#if EnableMagnify && UseColorImage
+
+#define ScrnMapr_DoMap UpdateMappedScaledBW2ColorCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map ScalingTabl
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#endif
+
+
+#if UseColorImage
+
+#define ScrnMapr_DoMap UpdateMappedBW2ColorCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map ScalingTabl
+
+#include "SCRNMAPR.h"
+
+#endif
+
+
+LOCALPROC HaveChangedScreenBuff(ui4r top, ui4r left,
+	ui4r bottom, ui4r right)
+{
+	int XDest;
+	int YDest;
+	char *the_data;
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		if (top < ViewVStart) {
+			top = ViewVStart;
+		}
+		if (left < ViewHStart) {
+			left = ViewHStart;
+		}
+		if (bottom > ViewVStart + ViewVSize) {
+			bottom = ViewVStart + ViewVSize;
+		}
+		if (right > ViewHStart + ViewHSize) {
+			right = ViewHStart + ViewHSize;
+		}
+
+		if ((top >= bottom) || (left >= right)) {
+			goto label_exit;
+		}
+	}
+#endif
+
+	XDest = left;
+	YDest = top;
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		XDest -= ViewHStart;
+		YDest -= ViewVStart;
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+		XDest *= MyWindowScale;
+		YDest *= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		XDest += hOffset;
+		YDest += vOffset;
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+#if UseColorImage
+#if 0 != vMacScreenDepth
+		if (UseColorMode) {
+#if vMacScreenDepth < 4
+			if (! ColorTransValid) {
+				SetUpColorScalingTabl();
+				ColorTransValid = trueblnr;
+			}
+
+			UpdateMappedScaledColorCopy(top, left, bottom, right);
+#else
+			UpdateTransScaledColorCopy(top, left, bottom, right);
+#endif
+		} else
+#endif /* 0 != vMacScreenDepth */
+		{
+			if (! ColorTransValid) {
+				SetUpBW2ColorScalingTabl();
+				ColorTransValid = trueblnr;
+			}
+
+			UpdateMappedScaledBW2ColorCopy(top, left, bottom, right);
+		}
+#else /* ! UseColorImage */
+		/* assume 0 == vMacScreenDepth */
+		{
+			if (! ColorTransValid) {
+				SetUpScalingTabl();
+				ColorTransValid = trueblnr;
+			}
+
+			UpdateScaledBWCopy(top, left, bottom, right);
+		}
+#endif /* UseColorImage */
+
+		{
+			char *saveData = my_Scaled_image->data;
+			my_Scaled_image->data = (char *)ScalingBuff;
+
+			XPutImage(x_display, my_main_wind, my_gc, my_Scaled_image,
+				left * MyWindowScale, top * MyWindowScale,
+				XDest, YDest,
+				(right - left) * MyWindowScale,
+				(bottom - top) * MyWindowScale);
+
+			my_Scaled_image->data = saveData;
+		}
+	} else
+#endif /* EnableMagnify */
+	{
+#if UseColorImage
+#if 0 != vMacScreenDepth
+		if (UseColorMode) {
+#if vMacScreenDepth < 4
+
+			if (! ColorTransValid) {
+				SetUpColorTabl();
+				ColorTransValid = trueblnr;
+			}
+
+			UpdateMappedColorCopy(top, left, bottom, right);
+
+			the_data = (char *)ScalingBuff;
+#else
+			/*
+				if vMacScreenDepth == 5 and MSBFirst, could
+				copy directly with the_data = (char *)GetCurDrawBuff();
+			*/
+			UpdateTransColorCopy(top, left, bottom, right);
+
+			the_data = (char *)ScalingBuff;
+#endif
+		} else
+#endif /* 0 != vMacScreenDepth */
+		{
+			if (! ColorTransValid) {
+				SetUpBW2ColorTabl();
+				ColorTransValid = trueblnr;
+			}
+
+			UpdateMappedBW2ColorCopy(top, left, bottom, right);
+
+			the_data = (char *)ScalingBuff;
+		}
+#else /* ! UseColorImage */
+		{
+			the_data = (char *)GetCurDrawBuff();
+		}
+#endif /* UseColorImage */
+
+		{
+			char *saveData = my_image->data;
+			my_image->data = the_data;
+
+			XPutImage(x_display, my_main_wind, my_gc, my_image,
+				left, top, XDest, YDest,
+				right - left, bottom - top);
+
+			my_image->data = saveData;
+		}
+	}
+
+#if MayFullScreen
+label_exit:
+	;
+#endif
+}
+
+LOCALPROC MyDrawChangesAndClear(void)
+{
+	if (ScreenChangedBottom > ScreenChangedTop) {
+		HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft,
+			ScreenChangedBottom, ScreenChangedRight);
+		ScreenClearChanges();
+	}
+}
+
+/* --- mouse --- */
+
+/* cursor hiding */
+
+LOCALVAR blnr HaveCursorHidden = falseblnr;
+LOCALVAR blnr WantCursorHidden = falseblnr;
+
+LOCALPROC ForceShowCursor(void)
+{
+	if (HaveCursorHidden) {
+		HaveCursorHidden = falseblnr;
+		if (my_main_wind) {
+			XUndefineCursor(x_display, my_main_wind);
+		}
+	}
+}
+
+LOCALVAR Cursor blankCursor = None;
+
+LOCALFUNC blnr CreateMyBlankCursor(Window rootwin)
+/*
+	adapted from X11_CreateNullCursor in context.x11.c
+	in quakeforge 0.5.5, copyright Id Software, Inc.
+	Zephaniah E. Hull, and Jeff Teunissen.
+*/
+{
+	Pixmap cursormask;
+	XGCValues xgc;
+	GC gc;
+	blnr IsOk = falseblnr;
+
+	cursormask = XCreatePixmap(x_display, rootwin, 1, 1, 1);
+	if (None == cursormask) {
+		WriteExtraErr("XCreatePixmap failed.");
+	} else {
+		xgc.function = GXclear;
+		gc = XCreateGC(x_display, cursormask, GCFunction, &xgc);
+		if (None == gc) {
+			WriteExtraErr("XCreateGC failed.");
+		} else {
+			XFillRectangle(x_display, cursormask, gc, 0, 0, 1, 1);
+			XFreeGC(x_display, gc);
+
+			blankCursor = XCreatePixmapCursor(x_display, cursormask,
+							cursormask, &x_black, &x_white, 0, 0);
+			if (None == blankCursor) {
+				WriteExtraErr("XCreatePixmapCursor failed.");
+			} else {
+				IsOk = trueblnr;
+			}
+		}
+
+		XFreePixmap(x_display, cursormask);
+		/*
+			assuming that XCreatePixmapCursor doesn't think it
+			owns the pixmaps passed to it. I've seen code that
+			assumes this, and other code that seems to assume
+			the opposite.
+		*/
+	}
+	return IsOk;
+}
+
+/* cursor moving */
+
+#if EnableMoveMouse
+LOCALFUNC blnr MyMoveMouse(si4b h, si4b v)
+{
+	int NewMousePosh;
+	int NewMousePosv;
+	int root_x_return;
+	int root_y_return;
+	Window root_return;
+	Window child_return;
+	unsigned int mask_return;
+	blnr IsOk;
+	int attempts = 0;
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		h -= ViewHStart;
+		v -= ViewVStart;
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+		h *= MyWindowScale;
+		v *= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		h += hOffset;
+		v += vOffset;
+	}
+#endif
+
+	do {
+		XWarpPointer(x_display, None, my_main_wind, 0, 0, 0, 0, h, v);
+		XQueryPointer(x_display, my_main_wind,
+			&root_return, &child_return,
+			&root_x_return, &root_y_return,
+			&NewMousePosh, &NewMousePosv,
+			&mask_return);
+		IsOk = (h == NewMousePosh) && (v == NewMousePosv);
+		++attempts;
+	} while ((! IsOk) && (attempts < 10));
+	return IsOk;
+}
+#endif
+
+#if EnableFSMouseMotion
+LOCALPROC StartSaveMouseMotion(void)
+{
+	if (! HaveMouseMotion) {
+		if (MyMoveMouse(ViewHStart + (ViewHSize / 2),
+			ViewVStart + (ViewVSize / 2)))
+		{
+			SavedMouseH = ViewHStart + (ViewHSize / 2);
+			SavedMouseV = ViewVStart + (ViewVSize / 2);
+			HaveMouseMotion = trueblnr;
+		}
+	}
+}
+#endif
+
+#if EnableFSMouseMotion
+LOCALPROC StopSaveMouseMotion(void)
+{
+	if (HaveMouseMotion) {
+		(void) MyMoveMouse(CurMouseH, CurMouseV);
+		HaveMouseMotion = falseblnr;
+	}
+}
+#endif
+
+/* cursor state */
+
+#if EnableFSMouseMotion
+LOCALPROC MyMouseConstrain(void)
+{
+	si4b shiftdh;
+	si4b shiftdv;
+
+	if (SavedMouseH < ViewHStart + (ViewHSize / 4)) {
+		shiftdh = ViewHSize / 2;
+	} else if (SavedMouseH > ViewHStart + ViewHSize - (ViewHSize / 4)) {
+		shiftdh = - ViewHSize / 2;
+	} else {
+		shiftdh = 0;
+	}
+	if (SavedMouseV < ViewVStart + (ViewVSize / 4)) {
+		shiftdv = ViewVSize / 2;
+	} else if (SavedMouseV > ViewVStart + ViewVSize - (ViewVSize / 4)) {
+		shiftdv = - ViewVSize / 2;
+	} else {
+		shiftdv = 0;
+	}
+	if ((shiftdh != 0) || (shiftdv != 0)) {
+		SavedMouseH += shiftdh;
+		SavedMouseV += shiftdv;
+		if (! MyMoveMouse(SavedMouseH, SavedMouseV)) {
+			HaveMouseMotion = falseblnr;
+		}
+	}
+}
+#endif
+
+LOCALPROC MousePositionNotify(int NewMousePosh, int NewMousePosv)
+{
+	blnr ShouldHaveCursorHidden = trueblnr;
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		NewMousePosh -= hOffset;
+		NewMousePosv -= vOffset;
+	}
+#endif
+
+#if EnableMagnify
+	if (UseMagnify) {
+		NewMousePosh /= MyWindowScale;
+		NewMousePosv /= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		NewMousePosh += ViewHStart;
+		NewMousePosv += ViewVStart;
+	}
+#endif
+
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		MyMousePositionSetDelta(NewMousePosh - SavedMouseH,
+			NewMousePosv - SavedMouseV);
+		SavedMouseH = NewMousePosh;
+		SavedMouseV = NewMousePosv;
+	} else
+#endif
+	{
+		if (NewMousePosh < 0) {
+			NewMousePosh = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePosh >= vMacScreenWidth) {
+			NewMousePosh = vMacScreenWidth - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+		if (NewMousePosv < 0) {
+			NewMousePosv = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePosv >= vMacScreenHeight) {
+			NewMousePosv = vMacScreenHeight - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+
+#if VarFullScreen
+		if (UseFullScreen)
+#endif
+#if MayFullScreen
+		{
+			ShouldHaveCursorHidden = trueblnr;
+		}
+#endif
+
+		/* if (ShouldHaveCursorHidden || CurMouseButton) */
+		/*
+			for a game like arkanoid, would like mouse to still
+			move even when outside window in one direction
+		*/
+		MyMousePositionSet(NewMousePosh, NewMousePosv);
+	}
+
+	WantCursorHidden = ShouldHaveCursorHidden;
+}
+
+LOCALPROC CheckMouseState(void)
+{
+	int NewMousePosh;
+	int NewMousePosv;
+	int root_x_return;
+	int root_y_return;
+	Window root_return;
+	Window child_return;
+	unsigned int mask_return;
+
+	XQueryPointer(x_display, my_main_wind,
+		&root_return, &child_return,
+		&root_x_return, &root_y_return,
+		&NewMousePosh, &NewMousePosv,
+		&mask_return);
+	MousePositionNotify(NewMousePosh, NewMousePosv);
+}
+
+/* --- keyboard input --- */
+
+LOCALVAR KeyCode TheCapsLockCode;
+
+LOCALVAR ui3b KC2MKC[256];
+
+LOCALPROC KC2MKCAssignOne(KeySym ks, ui3r key)
+{
+	KeyCode code = XKeysymToKeycode(x_display, ks);
+	if (code != NoSymbol) {
+		KC2MKC[code] = key;
+	}
+#if 0
+	fprintf(stderr, "%d %d %d\n", (int)ks, key, (int)code);
+#endif
+}
+
+LOCALFUNC blnr KC2MKCInit(void)
+{
+	int i;
+
+	for (i = 0; i < 256; ++i) {
+		KC2MKC[i] = MKC_None;
+	}
+
+#if 0 /* find Keysym for a code */
+	for (i = 0; i < 64 * 1024; ++i) {
+		KeyCode code = XKeysymToKeycode(x_display, i);
+		if (115 == code) {
+			fprintf(stderr, "i %d\n", i);
+		}
+	}
+#endif
+
+	/*
+	start with redundant mappings, should get overwritten
+	by main mappings but define them just in case
+	*/
+
+#ifdef XK_KP_Insert
+	KC2MKCAssignOne(XK_KP_Insert, MKC_KP0);
+#endif
+#ifdef XK_KP_End
+	KC2MKCAssignOne(XK_KP_End, MKC_KP1);
+#endif
+#ifdef XK_KP_Down
+	KC2MKCAssignOne(XK_KP_Down, MKC_KP2);
+#endif
+#ifdef XK_KP_Next
+	KC2MKCAssignOne(XK_KP_Next, MKC_KP3);
+#endif
+#ifdef XK_KP_Left
+	KC2MKCAssignOne(XK_KP_Left, MKC_KP4);
+#endif
+#ifdef XK_KP_Begin
+	KC2MKCAssignOne(XK_KP_Begin, MKC_KP5);
+#endif
+#ifdef XK_KP_Right
+	KC2MKCAssignOne(XK_KP_Right, MKC_KP6);
+#endif
+#ifdef XK_KP_Home
+	KC2MKCAssignOne(XK_KP_Home, MKC_KP7);
+#endif
+#ifdef XK_KP_Up
+	KC2MKCAssignOne(XK_KP_Up, MKC_KP8);
+#endif
+#ifdef XK_KP_Prior
+	KC2MKCAssignOne(XK_KP_Prior, MKC_KP9);
+#endif
+#ifdef XK_KP_Delete
+	KC2MKCAssignOne(XK_KP_Delete, MKC_Decimal);
+#endif
+
+	KC2MKCAssignOne(XK_asciitilde, MKC_formac_Grave);
+	KC2MKCAssignOne(XK_underscore, MKC_Minus);
+	KC2MKCAssignOne(XK_plus, MKC_Equal);
+	KC2MKCAssignOne(XK_braceleft, MKC_LeftBracket);
+	KC2MKCAssignOne(XK_braceright, MKC_RightBracket);
+	KC2MKCAssignOne(XK_bar, MKC_formac_BackSlash);
+	KC2MKCAssignOne(XK_colon, MKC_SemiColon);
+	KC2MKCAssignOne(XK_quotedbl, MKC_SingleQuote);
+	KC2MKCAssignOne(XK_less, MKC_Comma);
+	KC2MKCAssignOne(XK_greater, MKC_Period);
+	KC2MKCAssignOne(XK_question, MKC_formac_Slash);
+
+	KC2MKCAssignOne(XK_a, MKC_A);
+	KC2MKCAssignOne(XK_b, MKC_B);
+	KC2MKCAssignOne(XK_c, MKC_C);
+	KC2MKCAssignOne(XK_d, MKC_D);
+	KC2MKCAssignOne(XK_e, MKC_E);
+	KC2MKCAssignOne(XK_f, MKC_F);
+	KC2MKCAssignOne(XK_g, MKC_G);
+	KC2MKCAssignOne(XK_h, MKC_H);
+	KC2MKCAssignOne(XK_i, MKC_I);
+	KC2MKCAssignOne(XK_j, MKC_J);
+	KC2MKCAssignOne(XK_k, MKC_K);
+	KC2MKCAssignOne(XK_l, MKC_L);
+	KC2MKCAssignOne(XK_m, MKC_M);
+	KC2MKCAssignOne(XK_n, MKC_N);
+	KC2MKCAssignOne(XK_o, MKC_O);
+	KC2MKCAssignOne(XK_p, MKC_P);
+	KC2MKCAssignOne(XK_q, MKC_Q);
+	KC2MKCAssignOne(XK_r, MKC_R);
+	KC2MKCAssignOne(XK_s, MKC_S);
+	KC2MKCAssignOne(XK_t, MKC_T);
+	KC2MKCAssignOne(XK_u, MKC_U);
+	KC2MKCAssignOne(XK_v, MKC_V);
+	KC2MKCAssignOne(XK_w, MKC_W);
+	KC2MKCAssignOne(XK_x, MKC_X);
+	KC2MKCAssignOne(XK_y, MKC_Y);
+	KC2MKCAssignOne(XK_z, MKC_Z);
+
+	/*
+	main mappings
+	*/
+
+	KC2MKCAssignOne(XK_F1, MKC_formac_F1);
+	KC2MKCAssignOne(XK_F2, MKC_formac_F2);
+	KC2MKCAssignOne(XK_F3, MKC_formac_F3);
+	KC2MKCAssignOne(XK_F4, MKC_formac_F4);
+	KC2MKCAssignOne(XK_F5, MKC_formac_F5);
+	KC2MKCAssignOne(XK_F6, MKC_F6);
+	KC2MKCAssignOne(XK_F7, MKC_F7);
+	KC2MKCAssignOne(XK_F8, MKC_F8);
+	KC2MKCAssignOne(XK_F9, MKC_F9);
+	KC2MKCAssignOne(XK_F10, MKC_F10);
+	KC2MKCAssignOne(XK_F11, MKC_F11);
+	KC2MKCAssignOne(XK_F12, MKC_F12);
+
+#ifdef XK_Delete
+	KC2MKCAssignOne(XK_Delete, MKC_formac_ForwardDel);
+#endif
+#ifdef XK_Insert
+	KC2MKCAssignOne(XK_Insert, MKC_formac_Help);
+#endif
+#ifdef XK_Help
+	KC2MKCAssignOne(XK_Help, MKC_formac_Help);
+#endif
+#ifdef XK_Home
+	KC2MKCAssignOne(XK_Home, MKC_formac_Home);
+#endif
+#ifdef XK_End
+	KC2MKCAssignOne(XK_End, MKC_formac_End);
+#endif
+
+#ifdef XK_Page_Up
+	KC2MKCAssignOne(XK_Page_Up, MKC_formac_PageUp);
+#else
+#ifdef XK_Prior
+	KC2MKCAssignOne(XK_Prior, MKC_formac_PageUp);
+#endif
+#endif
+
+#ifdef XK_Page_Down
+	KC2MKCAssignOne(XK_Page_Down, MKC_formac_PageDown);
+#else
+#ifdef XK_Next
+	KC2MKCAssignOne(XK_Next, MKC_formac_PageDown);
+#endif
+#endif
+
+#ifdef XK_Print
+	KC2MKCAssignOne(XK_Print, MKC_Print);
+#endif
+#ifdef XK_Scroll_Lock
+	KC2MKCAssignOne(XK_Scroll_Lock, MKC_ScrollLock);
+#endif
+#ifdef XK_Pause
+	KC2MKCAssignOne(XK_Pause, MKC_Pause);
+#endif
+
+	KC2MKCAssignOne(XK_KP_Add, MKC_KPAdd);
+	KC2MKCAssignOne(XK_KP_Subtract, MKC_KPSubtract);
+	KC2MKCAssignOne(XK_KP_Multiply, MKC_KPMultiply);
+	KC2MKCAssignOne(XK_KP_Divide, MKC_KPDevide);
+	KC2MKCAssignOne(XK_KP_Enter, MKC_formac_Enter);
+	KC2MKCAssignOne(XK_KP_Equal, MKC_KPEqual);
+
+	KC2MKCAssignOne(XK_KP_0, MKC_KP0);
+	KC2MKCAssignOne(XK_KP_1, MKC_KP1);
+	KC2MKCAssignOne(XK_KP_2, MKC_KP2);
+	KC2MKCAssignOne(XK_KP_3, MKC_KP3);
+	KC2MKCAssignOne(XK_KP_4, MKC_KP4);
+	KC2MKCAssignOne(XK_KP_5, MKC_KP5);
+	KC2MKCAssignOne(XK_KP_6, MKC_KP6);
+	KC2MKCAssignOne(XK_KP_7, MKC_KP7);
+	KC2MKCAssignOne(XK_KP_8, MKC_KP8);
+	KC2MKCAssignOne(XK_KP_9, MKC_KP9);
+	KC2MKCAssignOne(XK_KP_Decimal, MKC_Decimal);
+
+	KC2MKCAssignOne(XK_Left, MKC_Left);
+	KC2MKCAssignOne(XK_Right, MKC_Right);
+	KC2MKCAssignOne(XK_Up, MKC_Up);
+	KC2MKCAssignOne(XK_Down, MKC_Down);
+
+	KC2MKCAssignOne(XK_grave, MKC_formac_Grave);
+	KC2MKCAssignOne(XK_minus, MKC_Minus);
+	KC2MKCAssignOne(XK_equal, MKC_Equal);
+	KC2MKCAssignOne(XK_bracketleft, MKC_LeftBracket);
+	KC2MKCAssignOne(XK_bracketright, MKC_RightBracket);
+	KC2MKCAssignOne(XK_backslash, MKC_formac_BackSlash);
+	KC2MKCAssignOne(XK_semicolon, MKC_SemiColon);
+	KC2MKCAssignOne(XK_apostrophe, MKC_SingleQuote);
+	KC2MKCAssignOne(XK_comma, MKC_Comma);
+	KC2MKCAssignOne(XK_period, MKC_Period);
+	KC2MKCAssignOne(XK_slash, MKC_formac_Slash);
+
+	KC2MKCAssignOne(XK_Escape, MKC_formac_Escape);
+
+	KC2MKCAssignOne(XK_Tab, MKC_Tab);
+	KC2MKCAssignOne(XK_Return, MKC_Return);
+	KC2MKCAssignOne(XK_space, MKC_Space);
+	KC2MKCAssignOne(XK_BackSpace, MKC_BackSpace);
+
+	KC2MKCAssignOne(XK_Caps_Lock, MKC_formac_CapsLock);
+	KC2MKCAssignOne(XK_Num_Lock, MKC_Clear);
+
+	KC2MKCAssignOne(XK_Meta_L, MKC_formac_Command);
+
+	KC2MKCAssignOne(XK_Meta_R, MKC_formac_RCommand);
+
+	KC2MKCAssignOne(XK_Mode_switch, MKC_formac_Option);
+	KC2MKCAssignOne(XK_Menu, MKC_formac_Option);
+	KC2MKCAssignOne(XK_Super_L, MKC_formac_Option);
+	KC2MKCAssignOne(XK_Super_R, MKC_formac_ROption);
+	KC2MKCAssignOne(XK_Hyper_L, MKC_formac_Option);
+	KC2MKCAssignOne(XK_Hyper_R, MKC_formac_ROption);
+
+	KC2MKCAssignOne(XK_F13, MKC_formac_Option);
+		/*
+			seen being used in Mandrake Linux 9.2
+			for windows key
+		*/
+
+	KC2MKCAssignOne(XK_Shift_L, MKC_formac_Shift);
+	KC2MKCAssignOne(XK_Shift_R, MKC_formac_RShift);
+
+	KC2MKCAssignOne(XK_Alt_L, MKC_formac_Command);
+
+	KC2MKCAssignOne(XK_Alt_R, MKC_formac_RCommand);
+
+	KC2MKCAssignOne(XK_Control_L, MKC_formac_Control);
+
+	KC2MKCAssignOne(XK_Control_R, MKC_formac_RControl);
+
+	KC2MKCAssignOne(XK_1, MKC_1);
+	KC2MKCAssignOne(XK_2, MKC_2);
+	KC2MKCAssignOne(XK_3, MKC_3);
+	KC2MKCAssignOne(XK_4, MKC_4);
+	KC2MKCAssignOne(XK_5, MKC_5);
+	KC2MKCAssignOne(XK_6, MKC_6);
+	KC2MKCAssignOne(XK_7, MKC_7);
+	KC2MKCAssignOne(XK_8, MKC_8);
+	KC2MKCAssignOne(XK_9, MKC_9);
+	KC2MKCAssignOne(XK_0, MKC_0);
+
+	KC2MKCAssignOne(XK_A, MKC_A);
+	KC2MKCAssignOne(XK_B, MKC_B);
+	KC2MKCAssignOne(XK_C, MKC_C);
+	KC2MKCAssignOne(XK_D, MKC_D);
+	KC2MKCAssignOne(XK_E, MKC_E);
+	KC2MKCAssignOne(XK_F, MKC_F);
+	KC2MKCAssignOne(XK_G, MKC_G);
+	KC2MKCAssignOne(XK_H, MKC_H);
+	KC2MKCAssignOne(XK_I, MKC_I);
+	KC2MKCAssignOne(XK_J, MKC_J);
+	KC2MKCAssignOne(XK_K, MKC_K);
+	KC2MKCAssignOne(XK_L, MKC_L);
+	KC2MKCAssignOne(XK_M, MKC_M);
+	KC2MKCAssignOne(XK_N, MKC_N);
+	KC2MKCAssignOne(XK_O, MKC_O);
+	KC2MKCAssignOne(XK_P, MKC_P);
+	KC2MKCAssignOne(XK_Q, MKC_Q);
+	KC2MKCAssignOne(XK_R, MKC_R);
+	KC2MKCAssignOne(XK_S, MKC_S);
+	KC2MKCAssignOne(XK_T, MKC_T);
+	KC2MKCAssignOne(XK_U, MKC_U);
+	KC2MKCAssignOne(XK_V, MKC_V);
+	KC2MKCAssignOne(XK_W, MKC_W);
+	KC2MKCAssignOne(XK_X, MKC_X);
+	KC2MKCAssignOne(XK_Y, MKC_Y);
+	KC2MKCAssignOne(XK_Z, MKC_Z);
+
+	TheCapsLockCode = XKeysymToKeycode(x_display, XK_Caps_Lock);
+
+	InitKeyCodes();
+
+	return trueblnr;
+}
+
+LOCALPROC CheckTheCapsLock(void)
+{
+	int NewMousePosh;
+	int NewMousePosv;
+	int root_x_return;
+	int root_y_return;
+	Window root_return;
+	Window child_return;
+	unsigned int mask_return;
+
+	XQueryPointer(x_display, my_main_wind,
+		&root_return, &child_return,
+		&root_x_return, &root_y_return,
+		&NewMousePosh, &NewMousePosv,
+		&mask_return);
+
+	Keyboard_UpdateKeyMap2(MKC_formac_CapsLock,
+		(mask_return & LockMask) != 0);
+}
+
+LOCALPROC DoKeyCode0(int i, blnr down)
+{
+	ui3r key = KC2MKC[i];
+	if (MKC_None != key) {
+		Keyboard_UpdateKeyMap2(key, down);
+	}
+}
+
+LOCALPROC DoKeyCode(int i, blnr down)
+{
+	if (i == TheCapsLockCode) {
+		CheckTheCapsLock();
+	} else if (i >= 0 && i < 256) {
+		DoKeyCode0(i, down);
+	}
+}
+
+#if MayFullScreen && GrabKeysFullScreen
+LOCALVAR blnr KeyboardIsGrabbed = falseblnr;
+#endif
+
+#if MayFullScreen && GrabKeysFullScreen
+LOCALPROC MyGrabKeyboard(void)
+{
+	if (! KeyboardIsGrabbed) {
+		(void) XGrabKeyboard(x_display, my_main_wind,
+			False, GrabModeAsync, GrabModeAsync,
+			CurrentTime);
+		KeyboardIsGrabbed = trueblnr;
+	}
+}
+#endif
+
+#if MayFullScreen && GrabKeysFullScreen
+LOCALPROC MyUnGrabKeyboard(void)
+{
+	if (KeyboardIsGrabbed && my_main_wind) {
+		XUngrabKeyboard(x_display, CurrentTime);
+		KeyboardIsGrabbed = falseblnr;
+	}
+}
+#endif
+
+LOCALVAR blnr NoKeyRepeat = falseblnr;
+LOCALVAR int SaveKeyRepeat;
+
+LOCALPROC DisableKeyRepeat(void)
+{
+	XKeyboardState r;
+	XKeyboardControl k;
+
+	if ((! NoKeyRepeat) && (x_display != NULL)) {
+		NoKeyRepeat = trueblnr;
+
+		XGetKeyboardControl(x_display, &r);
+		SaveKeyRepeat = r.global_auto_repeat;
+
+		k.auto_repeat_mode = AutoRepeatModeOff;
+		XChangeKeyboardControl(x_display, KBAutoRepeatMode, &k);
+	}
+}
+
+LOCALPROC RestoreKeyRepeat(void)
+{
+	XKeyboardControl k;
+
+	if (NoKeyRepeat && (x_display != NULL)) {
+		NoKeyRepeat = falseblnr;
+
+		k.auto_repeat_mode = SaveKeyRepeat;
+		XChangeKeyboardControl(x_display, KBAutoRepeatMode, &k);
+	}
+}
+
+LOCALVAR blnr WantCmdOptOnReconnect = falseblnr;
+
+LOCALPROC GetTheDownKeys(void)
+{
+	char keys_return[32];
+	int i;
+	int v;
+	int j;
+
+	XQueryKeymap(x_display, keys_return);
+
+	for (i = 0; i < 32; ++i) {
+		v = keys_return[i];
+		for (j = 0; j < 8; ++j) {
+			if (0 != ((1 << j) & v)) {
+				int k = i * 8 + j;
+				if (k != TheCapsLockCode) {
+					DoKeyCode0(k, trueblnr);
+				}
+			}
+		}
+	}
+}
+
+LOCALPROC ReconnectKeyCodes3(void)
+{
+	CheckTheCapsLock();
+
+	if (WantCmdOptOnReconnect) {
+		WantCmdOptOnReconnect = falseblnr;
+
+		GetTheDownKeys();
+	}
+}
+
+LOCALPROC DisconnectKeyCodes3(void)
+{
+	DisconnectKeyCodes2();
+	MyMouseButtonSet(falseblnr);
+}
+
+/* --- time, date, location --- */
+
+#define dbglog_TimeStuff (0 && dbglog_HAVE)
+
+LOCALVAR ui5b TrueEmulatedTime = 0;
+
+#include "DATE2SEC.h"
+
+#define TicksPerSecond 1000000
+
+LOCALVAR blnr HaveTimeDelta = falseblnr;
+LOCALVAR ui5b TimeDelta;
+
+LOCALVAR ui5b NewMacDateInSeconds;
+
+LOCALVAR ui5b LastTimeSec;
+LOCALVAR ui5b LastTimeUsec;
+
+LOCALPROC GetCurrentTicks(void)
+{
+	struct timeval t;
+
+	gettimeofday(&t, NULL);
+	if (! HaveTimeDelta) {
+		time_t Current_Time;
+		struct tm *s;
+
+		(void) time(&Current_Time);
+		s = localtime(&Current_Time);
+		TimeDelta = Date2MacSeconds(s->tm_sec, s->tm_min, s->tm_hour,
+			s->tm_mday, 1 + s->tm_mon, 1900 + s->tm_year) - t.tv_sec;
+#if 0 && AutoTimeZone /* how portable is this ? */
+		CurMacDelta = ((ui5b)(s->tm_gmtoff) & 0x00FFFFFF)
+			| ((s->tm_isdst ? 0x80 : 0) << 24);
+#endif
+		HaveTimeDelta = trueblnr;
+	}
+
+	NewMacDateInSeconds = t.tv_sec + TimeDelta;
+	LastTimeSec = (ui5b)t.tv_sec;
+	LastTimeUsec = (ui5b)t.tv_usec;
+}
+
+#define MyInvTimeStep 16626 /* TicksPerSecond / 60.14742 */
+
+LOCALVAR ui5b NextTimeSec;
+LOCALVAR ui5b NextTimeUsec;
+
+LOCALPROC IncrNextTime(void)
+{
+	NextTimeUsec += MyInvTimeStep;
+	if (NextTimeUsec >= TicksPerSecond) {
+		NextTimeUsec -= TicksPerSecond;
+		NextTimeSec += 1;
+	}
+}
+
+LOCALPROC InitNextTime(void)
+{
+	NextTimeSec = LastTimeSec;
+	NextTimeUsec = LastTimeUsec;
+	IncrNextTime();
+}
+
+LOCALPROC StartUpTimeAdjust(void)
+{
+	GetCurrentTicks();
+	InitNextTime();
+}
+
+LOCALFUNC si5b GetTimeDiff(void)
+{
+	return ((si5b)(LastTimeSec - NextTimeSec)) * TicksPerSecond
+		+ ((si5b)(LastTimeUsec - NextTimeUsec));
+}
+
+LOCALPROC UpdateTrueEmulatedTime(void)
+{
+	si5b TimeDiff;
+
+	GetCurrentTicks();
+
+	TimeDiff = GetTimeDiff();
+	if (TimeDiff >= 0) {
+		if (TimeDiff > 16 * MyInvTimeStep) {
+			/* emulation interrupted, forget it */
+			++TrueEmulatedTime;
+			InitNextTime();
+
+#if dbglog_TimeStuff
+			dbglog_writelnNum("emulation interrupted",
+				TrueEmulatedTime);
+#endif
+		} else {
+			do {
+				++TrueEmulatedTime;
+				IncrNextTime();
+				TimeDiff -= TicksPerSecond;
+			} while (TimeDiff >= 0);
+		}
+	} else if (TimeDiff < - 16 * MyInvTimeStep) {
+		/* clock goofed if ever get here, reset */
+#if dbglog_TimeStuff
+		dbglog_writeln("clock set back");
+#endif
+
+		InitNextTime();
+	}
+}
+
+LOCALFUNC blnr CheckDateTime(void)
+{
+	if (CurMacDateInSeconds != NewMacDateInSeconds) {
+		CurMacDateInSeconds = NewMacDateInSeconds;
+		return trueblnr;
+	} else {
+		return falseblnr;
+	}
+}
+
+LOCALFUNC blnr InitLocationDat(void)
+{
+	GetCurrentTicks();
+	CurMacDateInSeconds = NewMacDateInSeconds;
+
+	return trueblnr;
+}
+
+/* --- sound --- */
+
+#if MySoundEnabled
+
+#define kLn2SoundBuffers 4 /* kSoundBuffers must be a power of two */
+#define kSoundBuffers (1 << kLn2SoundBuffers)
+#define kSoundBuffMask (kSoundBuffers - 1)
+
+#define DesiredMinFilledSoundBuffs 3
+	/*
+		if too big then sound lags behind emulation.
+		if too small then sound will have pauses.
+	*/
+
+#define kLnOneBuffLen 9
+#define kLnAllBuffLen (kLn2SoundBuffers + kLnOneBuffLen)
+#define kOneBuffLen (1UL << kLnOneBuffLen)
+#define kAllBuffLen (1UL << kLnAllBuffLen)
+#define kLnOneBuffSz (kLnOneBuffLen + kLn2SoundSampSz - 3)
+#define kLnAllBuffSz (kLnAllBuffLen + kLn2SoundSampSz - 3)
+#define kOneBuffSz (1UL << kLnOneBuffSz)
+#define kAllBuffSz (1UL << kLnAllBuffSz)
+#define kOneBuffMask (kOneBuffLen - 1)
+#define kAllBuffMask (kAllBuffLen - 1)
+#define dbhBufferSize (kAllBuffSz + kOneBuffSz)
+
+#define dbglog_SoundStuff (0 && dbglog_HAVE)
+#define dbglog_SoundBuffStats (0 && dbglog_HAVE)
+
+LOCALVAR tpSoundSamp TheSoundBuffer = nullpr;
+LOCALVAR ui4b ThePlayOffset;
+LOCALVAR ui4b TheFillOffset;
+LOCALVAR ui4b TheWriteOffset;
+LOCALVAR ui4b MinFilledSoundBuffs;
+
+LOCALPROC MySound_Start0(void)
+{
+	/* Reset variables */
+	ThePlayOffset = 0;
+	TheFillOffset = 0;
+	TheWriteOffset = 0;
+	MinFilledSoundBuffs = kSoundBuffers;
+}
+
+GLOBALOSGLUFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL)
+{
+	ui4b ToFillLen = kAllBuffLen - (TheWriteOffset - ThePlayOffset);
+	ui4b WriteBuffContig =
+		kOneBuffLen - (TheWriteOffset & kOneBuffMask);
+
+	if (WriteBuffContig < n) {
+		n = WriteBuffContig;
+	}
+	if (ToFillLen < n) {
+		/* overwrite previous buffer */
+#if dbglog_SoundStuff
+		dbglog_writeln("sound buffer over flow");
+#endif
+		TheWriteOffset -= kOneBuffLen;
+	}
+
+	*actL = n;
+	return TheSoundBuffer + (TheWriteOffset & kAllBuffMask);
+}
+
+LOCALFUNC blnr MySound_EndWrite0(ui4r actL)
+{
+	blnr v;
+
+	TheWriteOffset += actL;
+
+	if (0 != (TheWriteOffset & kOneBuffMask)) {
+		v = falseblnr;
+	} else {
+		/* just finished a block */
+
+		TheFillOffset = TheWriteOffset;
+
+		v = trueblnr;
+	}
+
+	return v;
+}
+
+LOCALPROC MySound_SecondNotify0(void)
+{
+	if (MinFilledSoundBuffs > DesiredMinFilledSoundBuffs) {
+#if dbglog_SoundStuff
+			dbglog_writeln("MinFilledSoundBuffs too high");
+#endif
+		IncrNextTime();
+	} else if (MinFilledSoundBuffs < DesiredMinFilledSoundBuffs) {
+#if dbglog_SoundStuff
+			dbglog_writeln("MinFilledSoundBuffs too low");
+#endif
+		++TrueEmulatedTime;
+	}
+	MinFilledSoundBuffs = kSoundBuffers;
+}
+
+#define SOUND_SAMPLERATE 22255 /* = round(7833600 * 2 / 704) */
+
+#include "SOUNDGLU.h"
+
+#endif
+
+/* --- basic dialogs --- */
+
+LOCALPROC CheckSavedMacMsg(void)
+{
+	/* called only on quit, if error saved but not yet reported */
+
+	if (nullpr != SavedBriefMsg) {
+		char briefMsg0[ClStrMaxLength + 1];
+		char longMsg0[ClStrMaxLength + 1];
+
+		NativeStrFromCStr(briefMsg0, SavedBriefMsg);
+		NativeStrFromCStr(longMsg0, SavedLongMsg);
+
+		fprintf(stderr, "%s\n", briefMsg0);
+		fprintf(stderr, "%s\n", longMsg0);
+
+		SavedBriefMsg = nullpr;
+	}
+}
+
+/* --- clipboard --- */
+
+#if IncludeHostTextClipExchange
+LOCALVAR ui3p MyClipBuffer = NULL;
+#endif
+
+#if IncludeHostTextClipExchange
+LOCALPROC FreeMyClipBuffer(void)
+{
+	if (MyClipBuffer != NULL) {
+		free(MyClipBuffer);
+		MyClipBuffer = NULL;
+	}
+}
+#endif
+
+#if IncludeHostTextClipExchange
+GLOBALOSGLUFUNC tMacErr HTCEexport(tPbuf i)
+{
+	tMacErr err = mnvm_miscErr;
+
+	FreeMyClipBuffer();
+	if (MacRomanTextToNativePtr(i, falseblnr,
+		&MyClipBuffer))
+	{
+		XSetSelectionOwner(x_display, MyXA_CLIPBOARD,
+			my_main_wind, CurrentTime);
+		err = mnvm_noErr;
+	}
+
+	PbufDispose(i);
+
+	return err;
+}
+#endif
+
+#if IncludeHostTextClipExchange
+LOCALFUNC blnr WaitForClipboardSelection(XEvent *xevent)
+{
+	struct timespec rqt;
+	struct timespec rmt;
+	int i;
+
+	for (i = 100; --i >= 0; ) {
+		while (XCheckTypedWindowEvent(x_display, my_main_wind,
+			SelectionNotify, xevent))
+		{
+			if (xevent->xselection.selection != MyXA_CLIPBOARD) {
+				/*
+					not what we were looking for. lose it.
+					(and hope it wasn't too important).
+				*/
+				WriteExtraErr("Discarding unwanted SelectionNotify");
+			} else {
+				/* this is our event */
+				return trueblnr;
+			}
+		}
+
+		rqt.tv_sec = 0;
+		rqt.tv_nsec = 10000000;
+		(void) nanosleep(&rqt, &rmt);
+	}
+	return falseblnr;
+}
+#endif
+
+#if IncludeHostTextClipExchange
+LOCALPROC HTCEimport_do(void)
+{
+	Window w = XGetSelectionOwner(x_display, MyXA_CLIPBOARD);
+
+	if (w == my_main_wind) {
+		/* We own the clipboard, already have MyClipBuffer */
+	} else {
+		FreeMyClipBuffer();
+		if (w != None) {
+			XEvent xevent;
+
+			XDeleteProperty(x_display, my_main_wind,
+				MyXA_MinivMac_Clip);
+			XConvertSelection(x_display, MyXA_CLIPBOARD, XA_STRING,
+				MyXA_MinivMac_Clip, my_main_wind, CurrentTime);
+
+			if (WaitForClipboardSelection(&xevent)) {
+				if (None == xevent.xselection.property) {
+					/* oops, target not supported */
+				} else {
+					if (xevent.xselection.property
+						!= MyXA_MinivMac_Clip)
+					{
+						/* not where we expected it */
+					} else {
+						Atom ret_type;
+						int ret_format;
+						unsigned long ret_item;
+						unsigned long remain_byte;
+						unsigned char *s = NULL;
+
+						if ((Success != XGetWindowProperty(
+							x_display, my_main_wind, MyXA_MinivMac_Clip,
+							0, 65535, False, AnyPropertyType, &ret_type,
+							&ret_format, &ret_item, &remain_byte, &s))
+							|| (ret_type != XA_STRING)
+							|| (ret_format != 8)
+							|| (NULL == s))
+						{
+							WriteExtraErr(
+								"XGetWindowProperty failed"
+								" in HTCEimport_do");
+						} else {
+							MyClipBuffer = (ui3p)malloc(ret_item + 1);
+							if (NULL == MyClipBuffer) {
+								MacMsg(kStrOutOfMemTitle,
+									kStrOutOfMemMessage, falseblnr);
+							} else {
+								MyMoveBytes((anyp)s, (anyp)MyClipBuffer,
+									ret_item);
+								MyClipBuffer[ret_item] = 0;
+							}
+							XFree(s);
+						}
+					}
+					XDeleteProperty(x_display, my_main_wind,
+						MyXA_MinivMac_Clip);
+				}
+			}
+		}
+	}
+}
+#endif
+
+#if IncludeHostTextClipExchange
+GLOBALOSGLUFUNC tMacErr HTCEimport(tPbuf *r)
+{
+	HTCEimport_do();
+
+	return NativeTextToMacRomanPbuf((char *)MyClipBuffer, r);
+}
+#endif
+
+#if IncludeHostTextClipExchange
+LOCALFUNC blnr HandleSelectionRequestClipboard(XEvent *theEvent)
+{
+	blnr RequestFilled = falseblnr;
+
+#if MyDbgEvents
+	dbglog_writeln("Requested MyXA_CLIPBOARD");
+#endif
+
+	if (NULL == MyClipBuffer) {
+		/* our clipboard is empty */
+	} else if (theEvent->xselectionrequest.target == MyXA_TARGETS) {
+		Atom a[2];
+
+		a[0] = MyXA_TARGETS;
+		a[1] = XA_STRING;
+
+		XChangeProperty(x_display,
+			theEvent->xselectionrequest.requestor,
+			theEvent->xselectionrequest.property,
+			MyXA_TARGETS,
+			32,
+				/*
+					most, but not all, other programs I've
+					look at seem to use 8 here, but that
+					can't be right. can it?
+				*/
+			PropModeReplace,
+			(unsigned char *)a,
+			sizeof(a) / sizeof(Atom));
+
+		RequestFilled = trueblnr;
+	} else if (theEvent->xselectionrequest.target == XA_STRING) {
+		XChangeProperty(x_display,
+			theEvent->xselectionrequest.requestor,
+			theEvent->xselectionrequest.property,
+			XA_STRING,
+			8,
+			PropModeReplace,
+			(unsigned char *)MyClipBuffer,
+			strlen((char *)MyClipBuffer));
+
+		RequestFilled = trueblnr;
+	}
+
+	return RequestFilled;
+}
+#endif
+
+/* --- drag and drop --- */
+
+#if EnableDragDrop
+LOCALPROC MyActivateWind(Time time)
+{
+	if (NetSupportedContains(MyXA_NetActiveWindow)) {
+		XEvent xevent;
+		Window rootwin = XRootWindow(x_display,
+			DefaultScreen(x_display));
+
+		memset(&xevent, 0, sizeof (xevent));
+
+		xevent.xany.type = ClientMessage;
+		xevent.xclient.send_event = True;
+		xevent.xclient.window = my_main_wind;
+		xevent.xclient.message_type = MyXA_NetActiveWindow;
+		xevent.xclient.format = 32;
+		xevent.xclient.data.l[0] = 1;
+		xevent.xclient.data.l[1]= time;
+
+		if (0 == XSendEvent(x_display, rootwin, 0,
+			SubstructureRedirectMask | SubstructureNotifyMask,
+			&xevent))
+		{
+			WriteExtraErr("XSendEvent failed in MyActivateWind");
+		}
+	}
+
+	XRaiseWindow(x_display, my_main_wind);
+		/*
+			In RedHat 7.1, _NET_ACTIVE_WINDOW supported,
+			but XSendEvent of _NET_ACTIVE_WINDOW
+			doesn't raise the window. So just always
+			call XRaiseWindow. Hopefully calling
+			XRaiseWindow won't do any harm on window
+			managers where it isn't needed.
+			(Such as in Ubuntu 5.10)
+		*/
+	XSetInputFocus(x_display, my_main_wind,
+		RevertToPointerRoot, time);
+		/* And call this always too, just in case */
+}
+#endif
+
+#if EnableDragDrop
+LOCALPROC ParseOneUri(char *s)
+{
+	/* printf("ParseOneUri %s\n", s); */
+	if (('f' == s[0]) && ('i' == s[1]) && ('l' == s[2])
+		&& ('e' == s[3]) && (':' == s[4]))
+	{
+		s += 5;
+		if (('/' == s[0]) && ('/' == s[1])) {
+			/* skip hostname */
+			char c;
+
+			s += 2;
+			while ((c = *s) != '/') {
+				if (0 == c) {
+					return;
+				}
+				++s;
+			}
+		}
+		(void) Sony_Insert1a(s, falseblnr);
+	}
+}
+#endif
+
+#if EnableDragDrop
+LOCALFUNC int HexChar2Nib(char x)
+{
+	if ((x >= '0') && (x <= '9')) {
+		return x - '0';
+	} else if ((x >= 'A') && (x <= 'F')) {
+		return x - 'A' + 10;
+	} else if ((x >= 'a') && (x <= 'f')) {
+		return x - 'a' + 10;
+	} else {
+		return -1;
+	}
+}
+#endif
+
+#if EnableDragDrop
+LOCALPROC ParseUriList(char *s)
+{
+	char *p1 = s;
+	char *p0 = s;
+	char *p = s;
+	char c;
+
+	/* printf("ParseUriList %s\n", s); */
+	while ((c = *p++) != 0) {
+		if ('%' == c) {
+			int a;
+			int b;
+
+			if (((a = HexChar2Nib(p[0])) >= 0) &&
+				((b = HexChar2Nib(p[1])) >= 0))
+			{
+				p += 2;
+				*p1++ = (a << 4) + b;
+			} else {
+				*p1++ = c;
+			}
+		} else if (('\n' == c) || ('\r' == c)) {
+			*p1++ = 0;
+			ParseOneUri(p0);
+			p0 = p1;
+		} else {
+			*p1++ = c;
+		}
+	}
+	*p1++ = 0;
+	ParseOneUri(p0);
+}
+#endif
+
+#if EnableDragDrop
+LOCALVAR Window PendingDragWindow = None;
+#endif
+
+#if EnableDragDrop
+LOCALPROC HandleSelectionNotifyDnd(XEvent *theEvent)
+{
+	blnr DropOk = falseblnr;
+
+#if MyDbgEvents
+	dbglog_writeln("Got MyXA_DndSelection");
+#endif
+
+	if ((theEvent->xselection.property == MyXA_MinivMac_DndXchng)
+		&& (theEvent->xselection.target == MyXA_UriList))
+	{
+		Atom ret_type;
+		int ret_format;
+		unsigned long ret_item;
+		unsigned long remain_byte;
+		unsigned char *s = NULL;
+
+		if ((Success != XGetWindowProperty(x_display, my_main_wind,
+			MyXA_MinivMac_DndXchng,
+			0, 65535, False, MyXA_UriList, &ret_type, &ret_format,
+			&ret_item, &remain_byte, &s))
+			|| (NULL == s))
+		{
+			WriteExtraErr(
+				"XGetWindowProperty failed in SelectionNotify");
+		} else {
+			ParseUriList((char *)s);
+			DropOk = trueblnr;
+			XFree(s);
+		}
+	} else {
+		WriteExtraErr("Got Unknown SelectionNotify");
+	}
+
+	XDeleteProperty(x_display, my_main_wind,
+		MyXA_MinivMac_DndXchng);
+
+	if (PendingDragWindow != None) {
+		XEvent xevent;
+
+		memset(&xevent, 0, sizeof(xevent));
+
+		xevent.xany.type = ClientMessage;
+		xevent.xany.display = x_display;
+		xevent.xclient.window = PendingDragWindow;
+		xevent.xclient.message_type = MyXA_DndFinished;
+		xevent.xclient.format = 32;
+
+		xevent.xclient.data.l[0] = my_main_wind;
+		if (DropOk) {
+			xevent.xclient.data.l[1] = 1;
+		}
+		xevent.xclient.data.l[2] = MyXA_DndActionPrivate;
+
+		if (0 == XSendEvent(x_display,
+			PendingDragWindow, 0, 0, &xevent))
+		{
+			WriteExtraErr("XSendEvent failed in SelectionNotify");
+		}
+	}
+	if (DropOk && gTrueBackgroundFlag) {
+		MyActivateWind(theEvent->xselection.time);
+
+		WantCmdOptOnReconnect = trueblnr;
+	}
+}
+#endif
+
+#if EnableDragDrop
+LOCALPROC HandleClientMessageDndPosition(XEvent *theEvent)
+{
+	XEvent xevent;
+	int xr;
+	int yr;
+	unsigned int dr;
+	unsigned int wr;
+	unsigned int hr;
+	unsigned int bwr;
+	Window rr;
+	Window srcwin = theEvent->xclient.data.l[0];
+
+#if MyDbgEvents
+	dbglog_writeln("Got XdndPosition");
+#endif
+
+	XGetGeometry(x_display, my_main_wind,
+		&rr, &xr, &yr, &wr, &hr, &bwr, &dr);
+	memset (&xevent, 0, sizeof(xevent));
+	xevent.xany.type = ClientMessage;
+	xevent.xany.display = x_display;
+	xevent.xclient.window = srcwin;
+	xevent.xclient.message_type = MyXA_DndStatus;
+	xevent.xclient.format = 32;
+
+	xevent.xclient.data.l[0] = theEvent->xclient.window;
+		/* Target Window */
+	xevent.xclient.data.l[1] = 1; /* Accept */
+	xevent.xclient.data.l[2] = ((xr) << 16) | ((yr) & 0xFFFFUL);
+	xevent.xclient.data.l[3] = ((wr) << 16) | ((hr) & 0xFFFFUL);
+	xevent.xclient.data.l[4] = MyXA_DndActionPrivate; /* Action */
+
+	if (0 == XSendEvent(x_display, srcwin, 0, 0, &xevent)) {
+		WriteExtraErr(
+			"XSendEvent failed in HandleClientMessageDndPosition");
+	}
+}
+#endif
+
+#if EnableDragDrop
+LOCALPROC HandleClientMessageDndDrop(XEvent *theEvent)
+{
+	Time timestamp = theEvent->xclient.data.l[2];
+	PendingDragWindow = (Window) theEvent->xclient.data.l[0];
+
+#if MyDbgEvents
+	dbglog_writeln("Got XdndDrop");
+#endif
+
+	XConvertSelection(x_display, MyXA_DndSelection, MyXA_UriList,
+		MyXA_MinivMac_DndXchng, my_main_wind, timestamp);
+}
+#endif
+
+#define UseMotionEvents 1
+
+#if UseMotionEvents
+LOCALVAR blnr CaughtMouse = falseblnr;
+#endif
+
+#if MayNotFullScreen
+LOCALVAR int SavedTransH;
+LOCALVAR int SavedTransV;
+#endif
+
+/* --- event handling for main window --- */
+
+LOCALPROC HandleTheEvent(XEvent *theEvent)
+{
+	if (theEvent->xany.display != x_display) {
+		WriteExtraErr("Got event for some other display");
+	} else switch(theEvent->type) {
+		case KeyPress:
+			if (theEvent->xkey.window != my_main_wind) {
+				WriteExtraErr("Got KeyPress for some other window");
+			} else {
+#if MyDbgEvents
+				dbglog_writeln("- event - KeyPress");
+#endif
+
+				MousePositionNotify(theEvent->xkey.x, theEvent->xkey.y);
+				DoKeyCode(theEvent->xkey.keycode, trueblnr);
+			}
+			break;
+		case KeyRelease:
+			if (theEvent->xkey.window != my_main_wind) {
+				WriteExtraErr("Got KeyRelease for some other window");
+			} else {
+#if MyDbgEvents
+				dbglog_writeln("- event - KeyRelease");
+#endif
+
+				MousePositionNotify(theEvent->xkey.x, theEvent->xkey.y);
+				DoKeyCode(theEvent->xkey.keycode, falseblnr);
+			}
+			break;
+		case ButtonPress:
+			/* any mouse button, we don't care which */
+			if (theEvent->xbutton.window != my_main_wind) {
+				WriteExtraErr("Got ButtonPress for some other window");
+			} else {
+				/*
+					could check some modifiers, but don't bother for now
+					Keyboard_UpdateKeyMap2(MKC_formac_CapsLock,
+						(theEvent->xbutton.state & LockMask) != 0);
+				*/
+				MousePositionNotify(
+					theEvent->xbutton.x, theEvent->xbutton.y);
+				MyMouseButtonSet(trueblnr);
+			}
+			break;
+		case ButtonRelease:
+			/* any mouse button, we don't care which */
+			if (theEvent->xbutton.window != my_main_wind) {
+				WriteExtraErr(
+					"Got ButtonRelease for some other window");
+			} else {
+				MousePositionNotify(
+					theEvent->xbutton.x, theEvent->xbutton.y);
+				MyMouseButtonSet(falseblnr);
+			}
+			break;
+#if UseMotionEvents
+		case MotionNotify:
+			if (theEvent->xmotion.window != my_main_wind) {
+				WriteExtraErr("Got MotionNotify for some other window");
+			} else {
+				MousePositionNotify(
+					theEvent->xmotion.x, theEvent->xmotion.y);
+			}
+			break;
+		case EnterNotify:
+			if (theEvent->xcrossing.window != my_main_wind) {
+				WriteExtraErr("Got EnterNotify for some other window");
+			} else {
+#if MyDbgEvents
+				dbglog_writeln("- event - EnterNotify");
+#endif
+
+				CaughtMouse = trueblnr;
+				MousePositionNotify(
+					theEvent->xcrossing.x, theEvent->xcrossing.y);
+			}
+			break;
+		case LeaveNotify:
+			if (theEvent->xcrossing.window != my_main_wind) {
+				WriteExtraErr("Got LeaveNotify for some other window");
+			} else {
+#if MyDbgEvents
+				dbglog_writeln("- event - LeaveNotify");
+#endif
+
+				MousePositionNotify(
+					theEvent->xcrossing.x, theEvent->xcrossing.y);
+				CaughtMouse = falseblnr;
+			}
+			break;
+#endif
+		case Expose:
+			if (theEvent->xexpose.window != my_main_wind) {
+				WriteExtraErr(
+					"Got SelectionRequest for some other window");
+			} else {
+				int x0 = theEvent->xexpose.x;
+				int y0 = theEvent->xexpose.y;
+				int x1 = x0 + theEvent->xexpose.width;
+				int y1 = y0 + theEvent->xexpose.height;
+
+#if 0 && MyDbgEvents
+				dbglog_writeln("- event - Expose");
+#endif
+
+#if VarFullScreen
+				if (UseFullScreen)
+#endif
+#if MayFullScreen
+				{
+					x0 -= hOffset;
+					y0 -= vOffset;
+					x1 -= hOffset;
+					y1 -= vOffset;
+				}
+#endif
+
+#if EnableMagnify
+				if (UseMagnify) {
+					x0 /= MyWindowScale;
+					y0 /= MyWindowScale;
+					x1 = (x1 + (MyWindowScale - 1)) / MyWindowScale;
+					y1 = (y1 + (MyWindowScale - 1)) / MyWindowScale;
+				}
+#endif
+
+#if VarFullScreen
+				if (UseFullScreen)
+#endif
+#if MayFullScreen
+				{
+					x0 += ViewHStart;
+					y0 += ViewVStart;
+					x1 += ViewHStart;
+					y1 += ViewVStart;
+				}
+#endif
+
+				if (x0 < 0) {
+					x0 = 0;
+				}
+				if (x1 > vMacScreenWidth) {
+					x1 = vMacScreenWidth;
+				}
+				if (y0 < 0) {
+					y0 = 0;
+				}
+				if (y1 > vMacScreenHeight) {
+					y1 = vMacScreenHeight;
+				}
+				if ((x0 < x1) && (y0 < y1)) {
+					HaveChangedScreenBuff(y0, x0, y1, x1);
+				}
+
+				NeedFinishOpen1 = falseblnr;
+			}
+			break;
+#if IncludeHostTextClipExchange
+		case SelectionRequest:
+			if (theEvent->xselectionrequest.owner != my_main_wind) {
+				WriteExtraErr(
+					"Got SelectionRequest for some other window");
+			} else {
+				XEvent xevent;
+				blnr RequestFilled = falseblnr;
+
+#if MyDbgEvents
+				dbglog_writeln("- event - SelectionRequest");
+				WriteDbgAtom("selection",
+					theEvent->xselectionrequest.selection);
+				WriteDbgAtom("target",
+					theEvent->xselectionrequest.target);
+				WriteDbgAtom("property",
+					theEvent->xselectionrequest.property);
+#endif
+
+				if (theEvent->xselectionrequest.selection ==
+					MyXA_CLIPBOARD)
+				{
+					RequestFilled =
+						HandleSelectionRequestClipboard(theEvent);
+				}
+
+
+				memset(&xevent, 0, sizeof(xevent));
+				xevent.xselection.type = SelectionNotify;
+				xevent.xselection.display = x_display;
+				xevent.xselection.requestor =
+					theEvent->xselectionrequest.requestor;
+				xevent.xselection.selection =
+					theEvent->xselectionrequest.selection;
+				xevent.xselection.target =
+					theEvent->xselectionrequest.target;
+				xevent.xselection.property = (! RequestFilled) ? None
+					: theEvent->xselectionrequest.property ;
+				xevent.xselection.time =
+					theEvent->xselectionrequest.time;
+
+				if (0 == XSendEvent(x_display,
+					xevent.xselection.requestor, False, 0, &xevent))
+				{
+					WriteExtraErr(
+						"XSendEvent failed in SelectionRequest");
+				}
+			}
+			break;
+		case SelectionClear:
+			if (theEvent->xselectionclear.window != my_main_wind) {
+				WriteExtraErr(
+					"Got SelectionClear for some other window");
+			} else {
+#if MyDbgEvents
+				dbglog_writeln("- event - SelectionClear");
+				WriteDbgAtom("selection",
+					theEvent->xselectionclear.selection);
+#endif
+
+				if (theEvent->xselectionclear.selection ==
+					MyXA_CLIPBOARD)
+				{
+					FreeMyClipBuffer();
+				}
+			}
+			break;
+#endif
+#if EnableDragDrop
+		case SelectionNotify:
+			if (theEvent->xselection.requestor != my_main_wind) {
+				WriteExtraErr(
+					"Got SelectionNotify for some other window");
+			} else {
+#if MyDbgEvents
+				dbglog_writeln("- event - SelectionNotify");
+				WriteDbgAtom("selection",
+					theEvent->xselection.selection);
+				WriteDbgAtom("target", theEvent->xselection.target);
+				WriteDbgAtom("property", theEvent->xselection.property);
+#endif
+
+				if (theEvent->xselection.selection == MyXA_DndSelection)
+				{
+					HandleSelectionNotifyDnd(theEvent);
+				} else {
+					WriteExtraErr(
+						"Got Unknown selection in SelectionNotify");
+				}
+			}
+			break;
+#endif
+		case ClientMessage:
+			if (theEvent->xclient.window != my_main_wind) {
+				WriteExtraErr(
+					"Got ClientMessage for some other window");
+			} else {
+#if MyDbgEvents
+				dbglog_writeln("- event - ClientMessage");
+				WriteDbgAtom("message_type",
+					theEvent->xclient.message_type);
+#endif
+
+#if EnableDragDrop
+				if (theEvent->xclient.message_type == MyXA_DndEnter) {
+					/* printf("Got XdndEnter\n"); */
+				} else if (theEvent->xclient.message_type ==
+					MyXA_DndLeave)
+				{
+					/* printf("Got XdndLeave\n"); */
+				} else if (theEvent->xclient.message_type ==
+					MyXA_DndPosition)
+				{
+					HandleClientMessageDndPosition(theEvent);
+				} else if (theEvent->xclient.message_type ==
+					MyXA_DndDrop)
+				{
+					HandleClientMessageDndDrop(theEvent);
+				} else
+#endif
+				{
+					if ((32 == theEvent->xclient.format) &&
+						(theEvent->xclient.data.l[0] == MyXA_DeleteW))
+					{
+						/*
+							I would think that should test that
+								WM_PROTOCOLS == message_type
+							but none of the other programs I looked
+							at did.
+						*/
+						RequestMacOff = trueblnr;
+					}
+				}
+			}
+			break;
+		case FocusIn:
+			if (theEvent->xfocus.window != my_main_wind) {
+				WriteExtraErr("Got FocusIn for some other window");
+			} else {
+#if MyDbgEvents
+				dbglog_writeln("- event - FocusIn");
+#endif
+
+				gTrueBackgroundFlag = falseblnr;
+#if UseMotionEvents
+				CheckMouseState();
+					/*
+						Doesn't help on x11 for OS X,
+						can't get new mouse position
+						in any fashion until mouse moves.
+					*/
+#endif
+			}
+			break;
+		case FocusOut:
+			if (theEvent->xfocus.window != my_main_wind) {
+				WriteExtraErr("Got FocusOut for some other window");
+			} else {
+#if MyDbgEvents
+				dbglog_writeln("- event - FocusOut");
+#endif
+
+				gTrueBackgroundFlag = trueblnr;
+			}
+			break;
+		default:
+			break;
+	}
+}
+
+/* --- main window creation and disposal --- */
+
+LOCALVAR int my_argc;
+LOCALVAR char **my_argv;
+
+LOCALVAR char *display_name = NULL;
+
+LOCALFUNC blnr Screen_Init(void)
+{
+	Window rootwin;
+	int screen;
+	Colormap Xcmap;
+	Visual *Xvisual;
+
+	x_display = XOpenDisplay(display_name);
+	if (NULL == x_display) {
+		fprintf(stderr, "Cannot connect to X server.\n");
+		return falseblnr;
+	}
+
+	screen = DefaultScreen(x_display);
+
+	rootwin = XRootWindow(x_display, screen);
+
+	Xcmap = DefaultColormap(x_display, screen);
+
+	Xvisual = DefaultVisual(x_display, screen);
+
+	LoadMyXA();
+
+	XParseColor(x_display, Xcmap, "#000000", &x_black);
+	if (! XAllocColor(x_display, Xcmap, &x_black)) {
+		WriteExtraErr("XParseColor black fails");
+	}
+	XParseColor(x_display, Xcmap, "#ffffff", &x_white);
+	if (! XAllocColor(x_display, Xcmap, &x_white)) {
+		WriteExtraErr("XParseColor white fails");
+	}
+
+	if (! CreateMyBlankCursor(rootwin)) {
+		return falseblnr;
+	}
+
+#if ! UseColorImage
+	my_image = XCreateImage(x_display, Xvisual, 1, XYBitmap, 0,
+		NULL /* (char *)image_Mem1 */,
+		vMacScreenWidth, vMacScreenHeight, 32,
+		vMacScreenMonoByteWidth);
+	if (NULL == my_image) {
+		fprintf(stderr, "XCreateImage failed.\n");
+		return falseblnr;
+	}
+
+#if 0
+	fprintf(stderr, "bitmap_bit_order = %d\n",
+		(int)my_image->bitmap_bit_order);
+	fprintf(stderr, "byte_order = %d\n", (int)my_image->byte_order);
+#endif
+
+	my_image->bitmap_bit_order = MSBFirst;
+	my_image->byte_order = MSBFirst;
+#endif
+
+#if UseColorImage
+	my_image = XCreateImage(x_display, Xvisual, 24, ZPixmap, 0,
+		NULL /* (char *)image_Mem1 */,
+		vMacScreenWidth, vMacScreenHeight, 32,
+			4 * (ui5r)vMacScreenWidth);
+	if (NULL == my_image) {
+		fprintf(stderr, "XCreateImage Color failed.\n");
+		return falseblnr;
+	}
+
+#if 0
+	fprintf(stderr, "DefaultDepth = %d\n",
+		(int)DefaultDepth(x_display, screen));
+
+	fprintf(stderr, "MSBFirst = %d\n", (int)MSBFirst);
+	fprintf(stderr, "LSBFirst = %d\n", (int)LSBFirst);
+
+	fprintf(stderr, "bitmap_bit_order = %d\n",
+		(int)my_image->bitmap_bit_order);
+	fprintf(stderr, "byte_order = %d\n",
+		(int)my_image->byte_order);
+	fprintf(stderr, "bitmap_unit = %d\n",
+		(int)my_image->bitmap_unit);
+	fprintf(stderr, "bits_per_pixel = %d\n",
+		(int)my_image->bits_per_pixel);
+	fprintf(stderr, "red_mask = %d\n",
+		(int)my_image->red_mask);
+	fprintf(stderr, "green_mask = %d\n",
+		(int)my_image->green_mask);
+	fprintf(stderr, "blue_mask = %d\n",
+		(int)my_image->blue_mask);
+#endif
+
+#endif /* UseColorImage */
+
+#if EnableMagnify && (! UseColorImage)
+	my_Scaled_image = XCreateImage(x_display, Xvisual,
+		1, XYBitmap, 0,
+		NULL /* (char *)image_Mem1 */,
+		vMacScreenWidth * MyWindowScale,
+		vMacScreenHeight * MyWindowScale,
+		32, vMacScreenMonoByteWidth * MyWindowScale);
+	if (NULL == my_Scaled_image) {
+		fprintf(stderr, "XCreateImage failed.\n");
+		return falseblnr;
+	}
+
+	my_Scaled_image->bitmap_bit_order = MSBFirst;
+	my_Scaled_image->byte_order = MSBFirst;
+#endif
+
+#if EnableMagnify && UseColorImage
+	my_Scaled_image = XCreateImage(x_display, Xvisual,
+		24, ZPixmap, 0,
+		NULL /* (char *)image_Mem1 */,
+		vMacScreenWidth * MyWindowScale,
+		vMacScreenHeight * MyWindowScale,
+		32, 4 * (ui5r)vMacScreenWidth * MyWindowScale);
+	if (NULL == my_Scaled_image) {
+		fprintf(stderr, "XCreateImage Scaled failed.\n");
+		return falseblnr;
+	}
+#endif
+
+#if 0 != vMacScreenDepth
+	ColorModeWorks = trueblnr;
+#endif
+
+	DisableKeyRepeat();
+
+	return trueblnr;
+}
+
+LOCALPROC CloseMainWindow(void)
+{
+	if (my_gc != NULL) {
+		XFreeGC(x_display, my_gc);
+		my_gc = NULL;
+	}
+	if (my_main_wind) {
+		XDestroyWindow(x_display, my_main_wind);
+		my_main_wind = 0;
+	}
+}
+
+enum {
+	kMagStateNormal,
+#if EnableMagnify
+	kMagStateMagnifgy,
+#endif
+	kNumMagStates
+};
+
+#define kMagStateAuto kNumMagStates
+
+#if MayNotFullScreen
+LOCALVAR int CurWinIndx;
+LOCALVAR blnr HavePositionWins[kNumMagStates];
+LOCALVAR int WinPositionWinsH[kNumMagStates];
+LOCALVAR int WinPositionWinsV[kNumMagStates];
+#endif
+
+#if EnableRecreateW
+LOCALPROC ZapMyWState(void)
+{
+	my_main_wind = 0;
+	my_gc = NULL;
+}
+#endif
+
+LOCALFUNC blnr CreateMainWindow(void)
+{
+	Window rootwin;
+	int screen;
+	int xr;
+	int yr;
+	unsigned int dr;
+	unsigned int wr;
+	unsigned int hr;
+	unsigned int bwr;
+	Window rr;
+	int leftPos;
+	int topPos;
+#if MayNotFullScreen
+	int WinIndx;
+#endif
+#if EnableDragDrop
+	long int xdnd_version = 5;
+#endif
+	int NewWindowHeight = vMacScreenHeight;
+	int NewWindowWidth = vMacScreenWidth;
+
+	/* Get connection to X Server */
+	screen = DefaultScreen(x_display);
+
+	rootwin = XRootWindow(x_display, screen);
+
+	XGetGeometry(x_display, rootwin,
+		&rr, &xr, &yr, &wr, &hr, &bwr, &dr);
+
+#if EnableMagnify
+	if (UseMagnify) {
+		NewWindowHeight *= MyWindowScale;
+		NewWindowWidth *= MyWindowScale;
+	}
+#endif
+
+	if (wr > NewWindowWidth) {
+		leftPos = (wr - NewWindowWidth) / 2;
+	} else {
+		leftPos = 0;
+	}
+	if (hr > NewWindowHeight) {
+		topPos = (hr - NewWindowHeight) / 2;
+	} else {
+		topPos = 0;
+	}
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		ViewHSize = wr;
+		ViewVSize = hr;
+#if EnableMagnify
+		if (UseMagnify) {
+			ViewHSize /= MyWindowScale;
+			ViewVSize /= MyWindowScale;
+		}
+#endif
+		if (ViewHSize >= vMacScreenWidth) {
+			ViewHStart = 0;
+			ViewHSize = vMacScreenWidth;
+		} else {
+			ViewHSize &= ~ 1;
+		}
+		if (ViewVSize >= vMacScreenHeight) {
+			ViewVStart = 0;
+			ViewVSize = vMacScreenHeight;
+		} else {
+			ViewVSize &= ~ 1;
+		}
+	}
+#endif
+
+#if VarFullScreen
+	if (! UseFullScreen)
+#endif
+#if MayNotFullScreen
+	{
+#if EnableMagnify
+		if (UseMagnify) {
+			WinIndx = kMagStateMagnifgy;
+		} else
+#endif
+		{
+			WinIndx = kMagStateNormal;
+		}
+
+		if (! HavePositionWins[WinIndx]) {
+			WinPositionWinsH[WinIndx] = leftPos;
+			WinPositionWinsV[WinIndx] = topPos;
+			HavePositionWins[WinIndx] = trueblnr;
+		} else {
+			leftPos = WinPositionWinsH[WinIndx];
+			topPos = WinPositionWinsV[WinIndx];
+		}
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+		XSetWindowAttributes xattr;
+		xattr.override_redirect = True;
+		xattr.background_pixel = x_black.pixel;
+		xattr.border_pixel = x_white.pixel;
+
+		my_main_wind = XCreateWindow(x_display, rr,
+			0, 0, wr, hr, 0,
+			CopyFromParent, /* depth */
+			InputOutput, /* class */
+			CopyFromParent, /* visual */
+			CWOverrideRedirect | CWBackPixel | CWBorderPixel,
+				/* valuemask */
+			&xattr /* attributes */);
+	}
+#endif
+#if VarFullScreen
+	else
+#endif
+#if MayNotFullScreen
+	{
+		my_main_wind = XCreateSimpleWindow(x_display, rootwin,
+			leftPos,
+			topPos,
+			NewWindowWidth, NewWindowHeight, 4,
+			x_white.pixel,
+			x_black.pixel);
+	}
+#endif
+
+	if (! my_main_wind) {
+		WriteExtraErr("XCreateSimpleWindow failed.");
+		return falseblnr;
+	} else {
+		char *win_name =
+			(NULL != n_arg) ? n_arg : (
+#if CanGetAppPath
+			(NULL != app_name) ? app_name :
+#endif
+			kStrAppName);
+		XSelectInput(x_display, my_main_wind,
+			ExposureMask | KeyPressMask | KeyReleaseMask
+			| ButtonPressMask | ButtonReleaseMask
+#if UseMotionEvents
+			| PointerMotionMask | EnterWindowMask | LeaveWindowMask
+#endif
+			| FocusChangeMask);
+
+		XStoreName(x_display, my_main_wind, win_name);
+		XSetIconName(x_display, my_main_wind, win_name);
+
+		{
+			XClassHint *hints = XAllocClassHint();
+			if (hints) {
+				hints->res_name = "minivmac";
+				hints->res_class = "minivmac";
+				XSetClassHint(x_display, my_main_wind, hints);
+				XFree(hints);
+			}
+		}
+
+		{
+			XWMHints *hints = XAllocWMHints();
+			if (hints) {
+				hints->input = True;
+				hints->initial_state = NormalState;
+				hints->flags = InputHint | StateHint;
+				XSetWMHints(x_display, my_main_wind, hints);
+				XFree(hints);
+			}
+
+		}
+
+		XSetCommand(x_display, my_main_wind, my_argv, my_argc);
+
+		/* let us handle a click on the close box */
+		XSetWMProtocols(x_display, my_main_wind, &MyXA_DeleteW, 1);
+
+#if EnableDragDrop
+		XChangeProperty (x_display, my_main_wind, MyXA_DndAware,
+			XA_ATOM, 32, PropModeReplace,
+			(unsigned char *) &xdnd_version, 1);
+#endif
+
+		my_gc = XCreateGC(x_display, my_main_wind, 0, NULL);
+		if (NULL == my_gc) {
+			WriteExtraErr("XCreateGC failed.");
+			return falseblnr;
+		}
+		XSetState(x_display, my_gc, x_black.pixel, x_white.pixel,
+			GXcopy, AllPlanes);
+
+#if VarFullScreen
+		if (! UseFullScreen)
+#endif
+#if MayNotFullScreen
+		{
+			XSizeHints *hints = XAllocSizeHints();
+			if (hints) {
+				hints->min_width = NewWindowWidth;
+				hints->max_width = NewWindowWidth;
+				hints->min_height = NewWindowHeight;
+				hints->max_height = NewWindowHeight;
+
+				/*
+					Try again to say where the window ought to go.
+					I've seen this described as obsolete, but it
+					seems to work on all x implementations tried
+					so far, and nothing else does.
+				*/
+				hints->x = leftPos;
+				hints->y = topPos;
+				hints->width = NewWindowWidth;
+				hints->height = NewWindowHeight;
+
+				hints->flags = PMinSize | PMaxSize | PPosition | PSize;
+				XSetWMNormalHints(x_display, my_main_wind, hints);
+				XFree(hints);
+			}
+		}
+#endif
+
+#if VarFullScreen
+		if (UseFullScreen)
+#endif
+#if MayFullScreen
+		{
+			hOffset = leftPos;
+			vOffset = topPos;
+		}
+#endif
+
+		DisconnectKeyCodes3();
+			/* since will lose keystrokes to old window */
+
+#if MayNotFullScreen
+		CurWinIndx = WinIndx;
+#endif
+
+		XMapRaised(x_display, my_main_wind);
+
+#if 0
+		XSync(x_display, 0);
+#endif
+
+#if 0
+		/*
+			This helps in Red Hat 9 to get the new window
+			activated, and I've seen other programs
+			do similar things.
+		*/
+		/*
+			In current scheme, haven't closed old window
+			yet. If old window full screen, never receive
+			expose event for new one.
+		*/
+		{
+			XEvent event;
+
+			do {
+				XNextEvent(x_display, &event);
+				HandleTheEvent(&event);
+			} while (! ((Expose == event.type)
+				&& (event.xexpose.window == my_main_wind)));
+		}
+#endif
+
+		NeedFinishOpen1 = trueblnr;
+		NeedFinishOpen2 = trueblnr;
+
+		return trueblnr;
+	}
+}
+
+#if MayFullScreen
+LOCALVAR blnr GrabMachine = falseblnr;
+#endif
+
+#if MayFullScreen
+LOCALPROC GrabTheMachine(void)
+{
+#if EnableFSMouseMotion
+	StartSaveMouseMotion();
+#endif
+#if GrabKeysFullScreen
+	MyGrabKeyboard();
+#endif
+}
+#endif
+
+#if MayFullScreen
+LOCALPROC UngrabMachine(void)
+{
+#if EnableFSMouseMotion
+	StopSaveMouseMotion();
+#endif
+#if GrabKeysFullScreen
+	MyUnGrabKeyboard();
+#endif
+}
+#endif
+
+#if EnableRecreateW
+struct MyWState {
+	Window f_my_main_wind;
+	GC f_my_gc;
+#if MayFullScreen
+	short f_hOffset;
+	short f_vOffset;
+	ui4r f_ViewHSize;
+	ui4r f_ViewVSize;
+	ui4r f_ViewHStart;
+	ui4r f_ViewVStart;
+#endif
+#if VarFullScreen
+	blnr f_UseFullScreen;
+#endif
+#if EnableMagnify
+	blnr f_UseMagnify;
+#endif
+};
+typedef struct MyWState MyWState;
+#endif
+
+#if EnableRecreateW
+LOCALPROC GetMyWState(MyWState *r)
+{
+	r->f_my_main_wind = my_main_wind;
+	r->f_my_gc = my_gc;
+#if MayFullScreen
+	r->f_hOffset = hOffset;
+	r->f_vOffset = vOffset;
+	r->f_ViewHSize = ViewHSize;
+	r->f_ViewVSize = ViewVSize;
+	r->f_ViewHStart = ViewHStart;
+	r->f_ViewVStart = ViewVStart;
+#endif
+#if VarFullScreen
+	r->f_UseFullScreen = UseFullScreen;
+#endif
+#if EnableMagnify
+	r->f_UseMagnify = UseMagnify;
+#endif
+}
+#endif
+
+#if EnableRecreateW
+LOCALPROC SetMyWState(MyWState *r)
+{
+	my_main_wind = r->f_my_main_wind;
+	my_gc = r->f_my_gc;
+#if MayFullScreen
+	hOffset = r->f_hOffset;
+	vOffset = r->f_vOffset;
+	ViewHSize = r->f_ViewHSize;
+	ViewVSize = r->f_ViewVSize;
+	ViewHStart = r->f_ViewHStart;
+	ViewVStart = r->f_ViewVStart;
+#endif
+#if VarFullScreen
+	UseFullScreen = r->f_UseFullScreen;
+#endif
+#if EnableMagnify
+	UseMagnify = r->f_UseMagnify;
+#endif
+}
+#endif
+
+#if EnableRecreateW
+LOCALVAR blnr WantRestoreCursPos = falseblnr;
+LOCALVAR ui4b RestoreMouseH;
+LOCALVAR ui4b RestoreMouseV;
+#endif
+
+#if EnableRecreateW
+LOCALFUNC blnr ReCreateMainWindow(void)
+{
+	MyWState old_state;
+	MyWState new_state;
+#if IncludeHostTextClipExchange
+	blnr OwnClipboard = falseblnr;
+#endif
+
+	if (HaveCursorHidden) {
+		WantRestoreCursPos = trueblnr;
+		RestoreMouseH = CurMouseH;
+		RestoreMouseV = CurMouseV;
+	}
+
+	ForceShowCursor(); /* hide/show cursor api is per window */
+
+#if MayNotFullScreen
+#if VarFullScreen
+	if (! UseFullScreen)
+#endif
+	if (my_main_wind)
+	if (! NeedFinishOpen2)
+	{
+		/* save old position */
+		int xr;
+		int yr;
+		unsigned int dr;
+		unsigned int wr;
+		unsigned int hr;
+		unsigned int bwr;
+		Window rr;
+		Window rr2;
+
+		/* Get connection to X Server */
+		int screen = DefaultScreen(x_display);
+
+		Window rootwin = XRootWindow(x_display, screen);
+
+		XGetGeometry(x_display, rootwin,
+			&rr, &xr, &yr, &wr, &hr, &bwr, &dr);
+
+		/*
+			Couldn't reliably find out where window
+			is now, due to what seem to be some
+			broken X implementations, and so instead
+			track how far window has moved.
+		*/
+		XSync(x_display, 0);
+		if (XTranslateCoordinates(x_display, my_main_wind, rootwin,
+			0, 0, &xr, &yr, &rr2))
+		{
+			int newposh =
+				WinPositionWinsH[CurWinIndx] + (xr - SavedTransH);
+			int newposv =
+				WinPositionWinsV[CurWinIndx] + (yr - SavedTransV);
+			if ((newposv > 0) && (newposv < hr) && (newposh < wr)) {
+				WinPositionWinsH[CurWinIndx] = newposh;
+				WinPositionWinsV[CurWinIndx] = newposv;
+				SavedTransH = xr;
+				SavedTransV = yr;
+			}
+		}
+	}
+#endif
+
+#if MayFullScreen
+	if (GrabMachine) {
+		GrabMachine = falseblnr;
+		UngrabMachine();
+	}
+#endif
+
+	GetMyWState(&old_state);
+	ZapMyWState();
+
+#if EnableMagnify
+	UseMagnify = WantMagnify;
+#endif
+#if VarFullScreen
+	UseFullScreen = WantFullScreen;
+#endif
+
+	ColorTransValid = falseblnr;
+
+	if (! CreateMainWindow()) {
+		CloseMainWindow();
+		SetMyWState(&old_state);
+
+		/* avoid retry */
+#if VarFullScreen
+		WantFullScreen = UseFullScreen;
+#endif
+#if EnableMagnify
+		WantMagnify = UseMagnify;
+#endif
+
+		return falseblnr;
+	} else {
+		GetMyWState(&new_state);
+		SetMyWState(&old_state);
+
+#if IncludeHostTextClipExchange
+		if (my_main_wind) {
+			if (XGetSelectionOwner(x_display, MyXA_CLIPBOARD) ==
+				my_main_wind)
+			{
+				OwnClipboard = trueblnr;
+			}
+		}
+#endif
+
+		CloseMainWindow();
+
+		SetMyWState(&new_state);
+
+#if IncludeHostTextClipExchange
+		if (OwnClipboard) {
+			XSetSelectionOwner(x_display, MyXA_CLIPBOARD,
+				my_main_wind, CurrentTime);
+		}
+#endif
+	}
+
+	return trueblnr;
+}
+#endif
+
+#if VarFullScreen && EnableMagnify
+enum {
+	kWinStateWindowed,
+#if EnableMagnify
+	kWinStateFullScreen,
+#endif
+	kNumWinStates
+};
+#endif
+
+#if VarFullScreen && EnableMagnify
+LOCALVAR int WinMagStates[kNumWinStates];
+#endif
+
+LOCALPROC ZapWinStateVars(void)
+{
+#if MayNotFullScreen
+	{
+		int i;
+
+		for (i = 0; i < kNumMagStates; ++i) {
+			HavePositionWins[i] = falseblnr;
+		}
+	}
+#endif
+#if VarFullScreen && EnableMagnify
+	{
+		int i;
+
+		for (i = 0; i < kNumWinStates; ++i) {
+			WinMagStates[i] = kMagStateAuto;
+		}
+	}
+#endif
+}
+
+#if VarFullScreen
+LOCALPROC ToggleWantFullScreen(void)
+{
+	WantFullScreen = ! WantFullScreen;
+
+#if EnableMagnify
+	{
+		int OldWinState =
+			UseFullScreen ? kWinStateFullScreen : kWinStateWindowed;
+		int OldMagState =
+			UseMagnify ? kMagStateMagnifgy : kMagStateNormal;
+		int NewWinState =
+			WantFullScreen ? kWinStateFullScreen : kWinStateWindowed;
+		int NewMagState = WinMagStates[NewWinState];
+
+		WinMagStates[OldWinState] = OldMagState;
+		if (kMagStateAuto != NewMagState) {
+			WantMagnify = (kMagStateMagnifgy == NewMagState);
+		} else {
+			WantMagnify = falseblnr;
+			if (WantFullScreen) {
+				Window rootwin;
+				int xr;
+				int yr;
+				unsigned int dr;
+				unsigned int wr;
+				unsigned int hr;
+				unsigned int bwr;
+				Window rr;
+
+				rootwin =
+					XRootWindow(x_display, DefaultScreen(x_display));
+				XGetGeometry(x_display, rootwin,
+					&rr, &xr, &yr, &wr, &hr, &bwr, &dr);
+				if ((wr >= vMacScreenWidth * MyWindowScale)
+					&& (hr >= vMacScreenHeight * MyWindowScale)
+					)
+				{
+					WantMagnify = trueblnr;
+				}
+			}
+		}
+	}
+#endif
+}
+#endif
+
+/* --- SavedTasks --- */
+
+LOCALPROC LeaveBackground(void)
+{
+	ReconnectKeyCodes3();
+	DisableKeyRepeat();
+}
+
+LOCALPROC EnterBackground(void)
+{
+	RestoreKeyRepeat();
+	DisconnectKeyCodes3();
+
+	ForceShowCursor();
+}
+
+LOCALPROC LeaveSpeedStopped(void)
+{
+#if MySoundEnabled
+	MySound_Start();
+#endif
+
+	StartUpTimeAdjust();
+}
+
+LOCALPROC EnterSpeedStopped(void)
+{
+#if MySoundEnabled
+	MySound_Stop();
+#endif
+}
+
+LOCALPROC CheckForSavedTasks(void)
+{
+	if (MyEvtQNeedRecover) {
+		MyEvtQNeedRecover = falseblnr;
+
+		/* attempt cleanup, MyEvtQNeedRecover may get set again */
+		MyEvtQTryRecoverFromFull();
+	}
+
+	if (NeedFinishOpen2 && ! NeedFinishOpen1) {
+		NeedFinishOpen2 = falseblnr;
+
+#if VarFullScreen
+		if (UseFullScreen)
+#endif
+#if MayFullScreen
+		{
+			XSetInputFocus(x_display, my_main_wind,
+				RevertToPointerRoot, CurrentTime);
+		}
+#endif
+#if VarFullScreen
+		else
+#endif
+#if MayNotFullScreen
+		{
+			Window rr;
+			int screen = DefaultScreen(x_display);
+			Window rootwin = XRootWindow(x_display, screen);
+#if 0
+			/*
+				This doesn't work right in Red Hat 6, and may not
+				be needed anymore, now that using PPosition hint.
+			*/
+			XMoveWindow(x_display, my_main_wind,
+				leftPos, topPos);
+				/*
+					Needed after XMapRaised, because some window
+					managers will apparently ignore where the
+					window was asked to be put.
+				*/
+#endif
+
+			XSync(x_display, 0);
+				/*
+					apparently, XTranslateCoordinates can be inaccurate
+					without this
+				*/
+			XTranslateCoordinates(x_display, my_main_wind, rootwin,
+				0, 0, &SavedTransH, &SavedTransV, &rr);
+		}
+#endif
+
+#if EnableRecreateW
+		if (WantRestoreCursPos) {
+#if EnableFSMouseMotion
+			if (! HaveMouseMotion)
+#endif
+			{
+				(void) MyMoveMouse(RestoreMouseH, RestoreMouseV);
+				WantCursorHidden = trueblnr;
+			}
+			WantRestoreCursPos = falseblnr;
+		}
+#endif
+	}
+
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		MyMouseConstrain();
+	}
+#endif
+
+	if (RequestMacOff) {
+		RequestMacOff = falseblnr;
+		if (AnyDiskInserted()) {
+			MacMsgOverride(kStrQuitWarningTitle,
+				kStrQuitWarningMessage);
+		} else {
+			ForceMacOff = trueblnr;
+		}
+	}
+
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (gTrueBackgroundFlag != gBackgroundFlag) {
+		gBackgroundFlag = gTrueBackgroundFlag;
+		if (gTrueBackgroundFlag) {
+			EnterBackground();
+		} else {
+			LeaveBackground();
+		}
+	}
+
+	if (CurSpeedStopped != (SpeedStopped ||
+		(gBackgroundFlag && ! RunInBackground
+#if EnableAutoSlow && 0
+			&& (QuietSubTicks >= 4092)
+#endif
+		)))
+	{
+		CurSpeedStopped = ! CurSpeedStopped;
+		if (CurSpeedStopped) {
+			EnterSpeedStopped();
+		} else {
+			LeaveSpeedStopped();
+		}
+	}
+
+#if MayFullScreen
+	if (gTrueBackgroundFlag
+#if VarFullScreen
+		&& WantFullScreen
+#endif
+		)
+	{
+		/*
+			Since often get here on Ubuntu Linux 5.10
+			running on a slow machine (emulated) when
+			attempt to enter full screen, don't abort
+			full screen, but try to fix it.
+		*/
+#if 0
+		ToggleWantFullScreen();
+#else
+		XRaiseWindow(x_display, my_main_wind);
+		XSetInputFocus(x_display, my_main_wind,
+			RevertToPointerRoot, CurrentTime);
+#endif
+	}
+#endif
+
+#if EnableRecreateW
+	if (0
+#if EnableMagnify
+		|| (UseMagnify != WantMagnify)
+#endif
+#if VarFullScreen
+		|| (UseFullScreen != WantFullScreen)
+#endif
+		)
+	{
+		(void) ReCreateMainWindow();
+	}
+#endif
+
+
+#if MayFullScreen
+	if (GrabMachine != (
+#if VarFullScreen
+		UseFullScreen &&
+#endif
+		! (gTrueBackgroundFlag || CurSpeedStopped)))
+	{
+		GrabMachine = ! GrabMachine;
+		if (GrabMachine) {
+			GrabTheMachine();
+		} else {
+			UngrabMachine();
+		}
+	}
+#endif
+
+#if IncludeSonyNew
+	if (vSonyNewDiskWanted) {
+#if IncludeSonyNameNew
+		if (vSonyNewDiskName != NotAPbuf) {
+			ui3p NewDiskNameDat;
+			if (MacRomanTextToNativePtr(vSonyNewDiskName, trueblnr,
+				&NewDiskNameDat))
+			{
+				MakeNewDisk(vSonyNewDiskSize, (char *)NewDiskNameDat);
+				free(NewDiskNameDat);
+			}
+			PbufDispose(vSonyNewDiskName);
+			vSonyNewDiskName = NotAPbuf;
+		} else
+#endif
+		{
+			MakeNewDiskAtDefault(vSonyNewDiskSize);
+		}
+		vSonyNewDiskWanted = falseblnr;
+			/* must be done after may have gotten disk */
+	}
+#endif
+
+	if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
+		MacMsgDisplayOn();
+	}
+
+	if (NeedWholeScreenDraw) {
+		NeedWholeScreenDraw = falseblnr;
+		ScreenChangedAll();
+	}
+
+#if NeedRequestIthDisk
+	if (0 != RequestIthDisk) {
+		Sony_InsertIth(RequestIthDisk);
+		RequestIthDisk = 0;
+	}
+#endif
+
+	if (HaveCursorHidden != (WantCursorHidden
+		&& ! (gTrueBackgroundFlag || CurSpeedStopped)))
+	{
+		HaveCursorHidden = ! HaveCursorHidden;
+		if (HaveCursorHidden) {
+			XDefineCursor(x_display, my_main_wind, blankCursor);
+		} else {
+			XUndefineCursor(x_display, my_main_wind);
+		}
+	}
+}
+
+/* --- command line parsing --- */
+
+LOCALFUNC blnr ScanCommandLine(void)
+{
+	char *pa;
+	int i = 1;
+
+label_retry:
+	if (i < my_argc) {
+		pa = my_argv[i++];
+		if ('-' == pa[0]) {
+			if ((0 == strcmp(pa, "--display"))
+				|| (0 == strcmp(pa, "-display")))
+			{
+				if (i < my_argc) {
+					display_name = my_argv[i++];
+					goto label_retry;
+				}
+			} else
+			if ((0 == strcmp(pa, "--rom"))
+				|| (0 == strcmp(pa, "-r")))
+			{
+				if (i < my_argc) {
+					rom_path = my_argv[i++];
+					goto label_retry;
+				}
+			} else
+			if (0 == strcmp(pa, "-n"))
+			{
+				if (i < my_argc) {
+					n_arg = my_argv[i++];
+					goto label_retry;
+				}
+			} else
+			if (0 == strcmp(pa, "-d"))
+			{
+				if (i < my_argc) {
+					d_arg = my_argv[i++];
+					goto label_retry;
+				}
+			} else
+#ifndef UsingAlsa
+#define UsingAlsa 0
+#endif
+
+#if UsingAlsa
+			if ((0 == strcmp(pa, "--alsadev"))
+				|| (0 == strcmp(pa, "-alsadev")))
+			{
+				if (i < my_argc) {
+					alsadev_name = my_argv[i++];
+					goto label_retry;
+				}
+			} else
+#endif
+#if 0
+			if (0 == strcmp(pa, "-l")) {
+				SpeedValue = 0;
+				goto label_retry;
+			} else
+#endif
+			{
+				MacMsg(kStrBadArgTitle, kStrBadArgMessage, falseblnr);
+			}
+		} else {
+			(void) Sony_Insert1(pa, falseblnr);
+			goto label_retry;
+		}
+	}
+
+	return trueblnr;
+}
+
+/* --- main program flow --- */
+
+GLOBALOSGLUPROC DoneWithDrawingForTick(void)
+{
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		AutoScrollScreen();
+	}
+#endif
+	MyDrawChangesAndClear();
+	XFlush(x_display);
+}
+
+GLOBALOSGLUFUNC blnr ExtraTimeNotOver(void)
+{
+	UpdateTrueEmulatedTime();
+	return TrueEmulatedTime == OnTrueTime;
+}
+
+LOCALPROC WaitForTheNextEvent(void)
+{
+	XEvent event;
+
+	XNextEvent(x_display, &event);
+	HandleTheEvent(&event);
+}
+
+LOCALPROC CheckForSystemEvents(void)
+{
+	int i = 10;
+
+	while ((XEventsQueued(x_display, QueuedAfterReading) > 0)
+		&& (--i >= 0))
+	{
+		WaitForTheNextEvent();
+	}
+}
+
+GLOBALOSGLUPROC WaitForNextTick(void)
+{
+label_retry:
+	CheckForSystemEvents();
+	CheckForSavedTasks();
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (CurSpeedStopped) {
+		DoneWithDrawingForTick();
+		WaitForTheNextEvent();
+		goto label_retry;
+	}
+
+	if (ExtraTimeNotOver()) {
+		struct timespec rqt;
+		struct timespec rmt;
+
+		si5b TimeDiff = GetTimeDiff();
+		if (TimeDiff < 0) {
+			rqt.tv_sec = 0;
+			rqt.tv_nsec = (- TimeDiff) * 1000;
+			(void) nanosleep(&rqt, &rmt);
+		}
+		goto label_retry;
+	}
+
+	if (CheckDateTime()) {
+#if MySoundEnabled
+		MySound_SecondNotify();
+#endif
+#if EnableDemoMsg
+		DemoModeSecondNotify();
+#endif
+	}
+
+	if ((! gBackgroundFlag)
+#if UseMotionEvents
+		&& (! CaughtMouse)
+#endif
+		)
+	{
+		CheckMouseState();
+	}
+
+	OnTrueTime = TrueEmulatedTime;
+
+#if dbglog_TimeStuff
+	dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime);
+#endif
+}
+
+/* --- platform independent code can be thought of as going here --- */
+
+#include "PROGMAIN.h"
+
+LOCALPROC ZapOSGLUVars(void)
+{
+	InitDrives();
+	ZapWinStateVars();
+}
+
+LOCALPROC ReserveAllocAll(void)
+{
+#if dbglog_HAVE
+	dbglog_ReserveAlloc();
+#endif
+	ReserveAllocOneBlock(&ROM, kROM_Size, 5, falseblnr);
+
+	ReserveAllocOneBlock(&screencomparebuff,
+		vMacScreenNumBytes, 5, trueblnr);
+#if UseControlKeys
+	ReserveAllocOneBlock(&CntrlDisplayBuff,
+		vMacScreenNumBytes, 5, falseblnr);
+#endif
+#if WantScalingBuff
+	ReserveAllocOneBlock(&ScalingBuff,
+		ScalingBuffsz, 5, falseblnr);
+#endif
+#if WantScalingTabl
+	ReserveAllocOneBlock(&ScalingTabl,
+		ScalingTablsz, 5, falseblnr);
+#endif
+
+#if MySoundEnabled
+	ReserveAllocOneBlock((ui3p *)&TheSoundBuffer,
+		dbhBufferSize, 5, falseblnr);
+#endif
+
+	EmulationReserveAlloc();
+}
+
+LOCALFUNC blnr AllocMyMemory(void)
+{
+	uimr n;
+	blnr IsOk = falseblnr;
+
+	ReserveAllocOffset = 0;
+	ReserveAllocBigBlock = nullpr;
+	ReserveAllocAll();
+	n = ReserveAllocOffset;
+	ReserveAllocBigBlock = (ui3p)calloc(1, n);
+	if (NULL == ReserveAllocBigBlock) {
+		MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr);
+	} else {
+		ReserveAllocOffset = 0;
+		ReserveAllocAll();
+		if (n != ReserveAllocOffset) {
+			/* oops, program error */
+		} else {
+			IsOk = trueblnr;
+		}
+	}
+
+	return IsOk;
+}
+
+LOCALPROC UnallocMyMemory(void)
+{
+	if (nullpr != ReserveAllocBigBlock) {
+		free((char *)ReserveAllocBigBlock);
+	}
+}
+
+#if HaveAppPathLink
+LOCALFUNC blnr ReadLink_Alloc(char *path, char **r)
+{
+	/*
+		This should work to find size:
+
+		struct stat r;
+
+		if (lstat(path, &r) != -1) {
+			r = r.st_size;
+			IsOk = trueblnr;
+		}
+
+		But observed to return 0 in Ubuntu 10.04 x86-64
+	*/
+
+	char *s;
+	int sz;
+	char *p;
+	blnr IsOk = falseblnr;
+	size_t s_alloc = 256;
+
+label_retry:
+	s = (char *)malloc(s_alloc);
+	if (NULL == s) {
+		fprintf(stderr, "malloc failed.\n");
+	} else {
+		sz = readlink(path, s, s_alloc);
+		if ((sz < 0) || (sz >= s_alloc)) {
+			free(s);
+			if (sz == s_alloc) {
+				s_alloc <<= 1;
+				goto label_retry;
+			} else {
+				fprintf(stderr, "readlink failed.\n");
+			}
+		} else {
+			/* ok */
+			p = (char *)malloc(sz + 1);
+			if (NULL == p) {
+				fprintf(stderr, "malloc failed.\n");
+			} else {
+				(void) memcpy(p, s, sz);
+				p[sz] = 0;
+				*r = p;
+				IsOk = trueblnr;
+			}
+			free(s);
+		}
+	}
+
+	return IsOk;
+}
+#endif
+
+#if HaveSysctlPath
+LOCALFUNC blnr ReadKernProcPathname(char **r)
+{
+	size_t s_alloc;
+	char *s;
+	int mib[] = {
+		CTL_KERN,
+		KERN_PROC,
+		KERN_PROC_PATHNAME,
+		-1
+	};
+	blnr IsOk = falseblnr;
+
+	if (0 != sysctl(mib, sizeof(mib) / sizeof(int),
+		NULL, &s_alloc, NULL, 0))
+	{
+		fprintf(stderr, "sysctl failed.\n");
+	} else {
+		s = (char *)malloc(s_alloc);
+		if (NULL == s) {
+			fprintf(stderr, "malloc failed.\n");
+		} else {
+			if (0 != sysctl(mib, sizeof(mib) / sizeof(int),
+				s, &s_alloc, NULL, 0))
+			{
+				fprintf(stderr, "sysctl 2 failed.\n");
+			} else {
+				*r = s;
+				IsOk = trueblnr;
+			}
+			if (! IsOk) {
+				free(s);
+			}
+		}
+	}
+
+	return IsOk;
+}
+#endif
+
+#if CanGetAppPath
+LOCALFUNC blnr Path2ParentAndName(char *path,
+	char **parent, char **name)
+{
+	blnr IsOk = falseblnr;
+
+	char *t = strrchr(path, '/');
+	if (NULL == t) {
+		fprintf(stderr, "no directory.\n");
+	} else {
+		int par_sz = t - path;
+		char *par = (char *)malloc(par_sz + 1);
+		if (NULL == par) {
+			fprintf(stderr, "malloc failed.\n");
+		} else {
+			(void) memcpy(par, path, par_sz);
+			par[par_sz] = 0;
+			{
+				int s_sz = strlen(path);
+				int child_sz = s_sz - par_sz - 1;
+				char *child = (char *)malloc(child_sz + 1);
+				if (NULL == child) {
+					fprintf(stderr, "malloc failed.\n");
+				} else {
+					(void) memcpy(child, t + 1, child_sz);
+					child[child_sz] = 0;
+
+					*name = child;
+					IsOk = trueblnr;
+					/* free(child); */
+				}
+			}
+			if (! IsOk) {
+				free(par);
+			} else {
+				*parent = par;
+			}
+		}
+	}
+
+	return IsOk;
+}
+#endif
+
+#if CanGetAppPath
+LOCALFUNC blnr InitWhereAmI(void)
+{
+	char *s;
+
+	if (!
+#if HaveAppPathLink
+		ReadLink_Alloc(TheAppPathLink, &s)
+#endif
+#if HaveSysctlPath
+		ReadKernProcPathname(&s)
+#endif
+		)
+	{
+		fprintf(stderr, "InitWhereAmI fails.\n");
+	} else {
+		if (! Path2ParentAndName(s, &app_parent, &app_name)) {
+			fprintf(stderr, "Path2ParentAndName fails.\n");
+		} else {
+			/* ok */
+			/*
+				fprintf(stderr, "parent = %s.\n", app_parent);
+				fprintf(stderr, "name = %s.\n", app_name);
+			*/
+		}
+
+		free(s);
+	}
+
+	return trueblnr; /* keep going regardless */
+}
+#endif
+
+#if CanGetAppPath
+LOCALPROC UninitWhereAmI(void)
+{
+	MyMayFree(app_parent);
+	MyMayFree(app_name);
+}
+#endif
+
+LOCALFUNC blnr InitOSGLU(void)
+{
+	if (AllocMyMemory())
+#if CanGetAppPath
+	if (InitWhereAmI())
+#endif
+#if dbglog_HAVE
+	if (dbglog_open())
+#endif
+	if (ScanCommandLine())
+	if (LoadMacRom())
+	if (LoadInitialImages())
+#if UseActvCode
+	if (ActvCodeInit())
+#endif
+	if (InitLocationDat())
+#if MySoundEnabled
+	if (MySound_Init())
+#endif
+	if (Screen_Init())
+	if (CreateMainWindow())
+	if (KC2MKCInit())
+	if (WaitForRom())
+	{
+		return trueblnr;
+	}
+	return falseblnr;
+}
+
+LOCALPROC UnInitOSGLU(void)
+{
+	if (MacMsgDisplayed) {
+		MacMsgDisplayOff();
+	}
+
+	RestoreKeyRepeat();
+#if MayFullScreen
+	UngrabMachine();
+#endif
+#if MySoundEnabled
+	MySound_Stop();
+#endif
+#if MySoundEnabled
+	MySound_UnInit();
+#endif
+#if IncludeHostTextClipExchange
+	FreeMyClipBuffer();
+#endif
+#if IncludePbufs
+	UnInitPbufs();
+#endif
+	UnInitDrives();
+
+	ForceShowCursor();
+	if (blankCursor != None) {
+		XFreeCursor(x_display, blankCursor);
+	}
+
+	if (my_image != NULL) {
+		XDestroyImage(my_image);
+	}
+#if EnableMagnify
+	if (my_Scaled_image != NULL) {
+		XDestroyImage(my_Scaled_image);
+	}
+#endif
+
+	CloseMainWindow();
+	if (x_display != NULL) {
+		XCloseDisplay(x_display);
+	}
+
+#if dbglog_HAVE
+	dbglog_close();
+#endif
+
+#if CanGetAppPath
+	UninitWhereAmI();
+#endif
+	UnallocMyMemory();
+
+	CheckSavedMacMsg();
+}
+
+int main(int argc, char **argv)
+{
+	my_argc = argc;
+	my_argv = argv;
+
+	ZapOSGLUVars();
+	if (InitOSGLU()) {
+		ProgramMain();
+	}
+	UnInitOSGLU();
+
+	return 0;
+}
--- /dev/null
+++ b/src/OSPLAN9.c
@@ -1,0 +1,1886 @@
+#include <u.h>
+#include <libc.h>
+#include <stdio.h>
+#include <draw.h>
+#include <mouse.h>
+#include <cursor.h>
+#include <keyboard.h>
+#include <thread.h>
+#include <plumb.h>
+#define Uint8 u8int
+#define Uint16 u16int
+#define Uint32 u32int
+#include "CNFGRAPI.h"
+#include "SYSDEPNS.h"
+#include "ENDIANAC.h"
+#include "MYOSGLUE.h"
+#include "STRCONST.h"
+
+GLOBALOSGLUPROC MyMoveBytes(anyp srcPtr, anyp destPtr, si5b byteCount)
+{
+	memmove(destPtr, srcPtr, byteCount);
+}
+
+#define NeedCell2PlainAsciiMap 1
+#include "INTLCHAR.h"
+
+#if dbglog_HAVE
+
+#define dbglog_ToStdErr 0
+
+#if ! dbglog_ToStdErr
+LOCALVAR FILE *dbglog_File = NULL;
+#endif
+
+LOCALFUNC blnr dbglog_open0(void)
+{
+#if dbglog_ToStdErr
+	return trueblnr;
+#else
+	dbglog_File = fopen("dbglog.txt", "w");
+	return (NULL != dbglog_File);
+#endif
+}
+
+LOCALPROC dbglog_write0(char *s, uimr L)
+{
+#if dbglog_ToStdErr
+	(void) fwrite(s, 1, L, stderr);
+#else
+	if (dbglog_File != NULL) {
+		(void) fwrite(s, 1, L, dbglog_File);
+	}
+#endif
+}
+
+LOCALPROC dbglog_close0(void)
+{
+#if ! dbglog_ToStdErr
+	if (dbglog_File != NULL) {
+		fclose(dbglog_File);
+		dbglog_File = NULL;
+	}
+#endif
+}
+
+#endif
+
+/* --- information about the environment --- */
+
+#define WantColorTransValid 0
+
+#include "COMOSGLU.h"
+
+#include "PBUFSTDC.h"
+
+#include "CONTROLM.h"
+
+/* --- text translation --- */
+
+LOCALPROC NativeStrFromCStr(char *r, char *s)
+{
+	ui3b ps[ClStrMaxLength];
+	int i;
+	int L;
+
+	ClStrFromSubstCStr(&L, ps, s);
+
+	for (i = 0; i < L; ++i) {
+		r[i] = Cell2PlainAsciiMap[ps[i]];
+	}
+
+	r[L] = 0;
+}
+
+/* --- drives --- */
+
+#define NotAfileRef NULL
+
+LOCALVAR FILE *Drives[NumDrives]; /* open disk image files */
+
+LOCALPROC InitDrives(void)
+{
+	/*
+		This isn't really needed, Drives[i] and DriveNames[i]
+		need not have valid values when not vSonyIsInserted[i].
+	*/
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		Drives[i] = NotAfileRef;
+	}
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyTransfer(blnr IsWrite, ui3p Buffer,
+	tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count,
+	ui5r *Sony_ActCount)
+{
+	tMacErr err = mnvm_miscErr;
+	FILE *refnum = Drives[Drive_No];
+	ui5r NewSony_Count = 0;
+
+	if (0 == fseek(refnum, Sony_Start, SEEK_SET)) {
+		if (IsWrite) {
+			NewSony_Count = fwrite(Buffer, 1, Sony_Count, refnum);
+		} else {
+			NewSony_Count = fread(Buffer, 1, Sony_Count, refnum);
+		}
+
+		if (NewSony_Count == Sony_Count) {
+			err = mnvm_noErr;
+		}
+	}
+
+	if (nullpr != Sony_ActCount) {
+		*Sony_ActCount = NewSony_Count;
+	}
+
+	return err; /*& figure out what really to return &*/
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyGetSize(tDrive Drive_No, ui5r *Sony_Count)
+{
+	tMacErr err = mnvm_miscErr;
+	FILE *refnum = Drives[Drive_No];
+	long v;
+
+	if (0 == fseek(refnum, 0, SEEK_END)) {
+		v = ftell(refnum);
+		if (v >= 0) {
+			*Sony_Count = v;
+			err = mnvm_noErr;
+		}
+	}
+
+	return err; /*& figure out what really to return &*/
+}
+
+LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, blnr deleteit)
+{
+	FILE *refnum = Drives[Drive_No];
+
+	DiskEjectedNotify(Drive_No);
+
+	fclose(refnum);
+	Drives[Drive_No] = NotAfileRef; /* not really needed */
+
+	return mnvm_noErr;
+}
+
+GLOBALOSGLUFUNC tMacErr vSonyEject(tDrive Drive_No)
+{
+	return vSonyEject0(Drive_No, falseblnr);
+}
+
+#if IncludeSonyNew
+GLOBALOSGLUFUNC tMacErr vSonyEjectDelete(tDrive Drive_No)
+{
+	return vSonyEject0(Drive_No, trueblnr);
+}
+#endif
+
+#if IncludeSonyGetName
+GLOBALOSGLUFUNC tMacErr vSonyGetName(tDrive Drive_No, tPbuf *r)
+{
+	r[0] = 0;
+	return mnvm_noErr;
+}
+#endif
+
+LOCALPROC UnInitDrives(void)
+{
+	tDrive i;
+
+	for (i = 0; i < NumDrives; ++i) {
+		if (vSonyIsInserted(i)) {
+			(void) vSonyEject(i);
+		}
+	}
+}
+
+LOCALFUNC blnr Sony_Insert0(FILE *refnum, blnr locked,
+	char *drivepath)
+{
+	tDrive Drive_No;
+	blnr IsOk = falseblnr;
+
+	if (! FirstFreeDisk(&Drive_No)) {
+		MacMsg(kStrTooManyImagesTitle, kStrTooManyImagesMessage,
+			falseblnr);
+	} else {
+		/* printf("Sony_Insert0 %d\n", (int)Drive_No); */
+
+		{
+			Drives[Drive_No] = refnum;
+			DiskInsertNotify(Drive_No, locked);
+
+			IsOk = trueblnr;
+		}
+	}
+
+	if (! IsOk) {
+		fclose(refnum);
+	}
+
+	return IsOk;
+}
+
+LOCALFUNC blnr Sony_Insert1(char *drivepath, blnr silentfail)
+{
+	blnr locked = falseblnr;
+	/* printf("Sony_Insert1 %s\n", drivepath); */
+	FILE *refnum = fopen(drivepath, "rb+");
+	if (NULL == refnum) {
+		locked = trueblnr;
+		refnum = fopen(drivepath, "rb");
+	}
+	if (NULL == refnum) {
+		if (! silentfail) {
+			MacMsg(kStrOpenFailTitle, kStrOpenFailMessage, falseblnr);
+		}
+	} else {
+		return Sony_Insert0(refnum, locked, drivepath);
+	}
+	return falseblnr;
+}
+
+LOCALFUNC tMacErr LoadMacRomFrom(char *path)
+{
+	tMacErr err;
+	FILE *ROM_File;
+	int File_Size;
+
+	ROM_File = fopen(path, "rb");
+	if (NULL == ROM_File) {
+		err = mnvm_fnfErr;
+	} else {
+		File_Size = fread(ROM, 1, kROM_Size, ROM_File);
+		if (File_Size != kROM_Size) {
+			if (feof(ROM_File)) {
+				MacMsgOverride(kStrShortROMTitle,
+					kStrShortROMMessage);
+				err = mnvm_eofErr;
+			} else {
+				MacMsgOverride(kStrNoReadROMTitle,
+					kStrNoReadROMMessage);
+				err = mnvm_miscErr;
+			}
+		} else {
+			err = ROM_IsValid();
+		}
+		fclose(ROM_File);
+	}
+
+	return err;
+}
+
+LOCALFUNC blnr Sony_Insert1a(char *drivepath, blnr silentfail)
+{
+	blnr v;
+
+	if (! ROM_loaded) {
+		v = (mnvm_noErr == LoadMacRomFrom(drivepath));
+	} else {
+		v = Sony_Insert1(drivepath, silentfail);
+	}
+
+	return v;
+}
+
+static void
+plumbproc(void *)
+{
+	int f;
+	Plumbmsg *m;
+	char tmp[1024];
+
+	threadsetname("plumb");
+	if ((f = plumbopen("minivmac", OREAD)) >= 0) {
+		while ((m = plumbrecv(f)) != nil) {
+			snprint(tmp, sizeof(tmp), "%s/%s", m->wdir, m->data);
+			Sony_Insert1a(tmp, 0);
+			plumbfree(m);
+		}
+	}
+
+	threadexits(nil);
+}
+
+LOCALFUNC blnr Sony_Insert2(char *s)
+{
+	return Sony_Insert1(s, trueblnr);
+}
+
+LOCALFUNC blnr Sony_InsertIth(int i)
+{
+	blnr v;
+
+	if ((i > 9) || ! FirstFreeDisk(nullpr)) {
+		v = falseblnr;
+	} else {
+		char s[] = "disk?.dsk";
+
+		s[4] = '0' + i;
+
+		v = Sony_Insert2(s);
+	}
+
+	return v;
+}
+
+LOCALFUNC blnr LoadInitialImages(void)
+{
+	if (! AnyDiskInserted()) {
+		int i;
+
+		for (i = 1; Sony_InsertIth(i); ++i) {
+			/* stop on first error (including file not found) */
+		}
+	}
+
+	proccreate(plumbproc, nil, mainstacksize);
+
+	return trueblnr;
+}
+
+/* --- ROM --- */
+
+LOCALVAR char *rom_path = NULL;
+
+LOCALFUNC blnr LoadMacRom(void)
+{
+	tMacErr err;
+
+	if ((NULL == rom_path)
+		|| (mnvm_fnfErr == (err = LoadMacRomFrom(rom_path))))
+	if (mnvm_fnfErr == (err = LoadMacRomFrom(RomFileName)))
+	{
+	}
+
+	return trueblnr; /* keep launching Mini vMac, regardless */
+}
+
+/* --- video out --- */
+
+#if VarFullScreen
+LOCALVAR blnr UseFullScreen = (WantInitFullScreen != 0);
+#endif
+
+#if EnableMagnify
+LOCALVAR blnr UseMagnify = (WantInitMagnify != 0);
+#endif
+
+LOCALVAR blnr gBackgroundFlag = falseblnr;
+LOCALVAR blnr gTrueBackgroundFlag = falseblnr;
+LOCALVAR blnr CurSpeedStopped = falseblnr;
+
+#if EnableMagnify
+#define MaxScale MyWindowScale
+#else
+#define MaxScale 1
+#endif
+
+
+LOCALVAR Image *my_surface = nullpr;
+LOCALVAR u8int *pixels;
+
+LOCALVAR ui3p ScalingBuff = nullpr;
+
+LOCALVAR ui3p CLUT_final;
+
+#define CLUT_finalsz (256 * 8 * 4 * MaxScale)
+	/*
+		256 possible values of one byte
+		8 pixels per byte maximum (when black and white)
+		4 bytes per destination pixel maximum
+			multiplied by MyWindowScale if EnableMagnify
+	*/
+
+#define ScrnMapr_DoMap UpdateBWDepth3Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 3
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateBWDepth4Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 4
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateBWDepth5Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateBWDepth3ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 3
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateBWDepth4ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 4
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateBWDepth5ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth 0
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+
+#define ScrnMapr_DoMap UpdateColorDepth3Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 3
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateColorDepth4Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 4
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateColorDepth5Copy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map CLUT_final
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateColorDepth3ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 3
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateColorDepth4ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 4
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#define ScrnMapr_DoMap UpdateColorDepth5ScaledCopy
+#define ScrnMapr_Src GetCurDrawBuff()
+#define ScrnMapr_Dst ScalingBuff
+#define ScrnMapr_SrcDepth vMacScreenDepth
+#define ScrnMapr_DstDepth 5
+#define ScrnMapr_Map CLUT_final
+#define ScrnMapr_Scale MyWindowScale
+
+#include "SCRNMAPR.h"
+
+#endif
+
+
+LOCALPROC HaveChangedScreenBuff(ui4r top, ui4r left,
+	ui4r bottom, ui4r right)
+{
+	int i;
+	int j;
+	ui3b *p;
+	Uint32 pixel;
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+	Uint32 CLUT_pixel[CLUT_size];
+#endif
+	Uint32 BWLUT_pixel[2];
+	ui5r top2 = top;
+	ui5r left2 = left;
+	ui5r bottom2 = bottom;
+	ui5r right2 = right;
+
+#if EnableMagnify
+	if (UseMagnify) {
+		top2 *= MyWindowScale;
+		left2 *= MyWindowScale;
+		bottom2 *= MyWindowScale;
+		right2 *= MyWindowScale;
+	}
+#endif
+
+	/* FIXME image locking here? */
+
+	{
+
+	int bpp = 4; /* FIXME RGB32 for now, make it dynamic though */
+	ui5r ExpectedPitch = vMacScreenWidth * bpp;
+
+#if EnableMagnify
+	if (UseMagnify) {
+		ExpectedPitch *= MyWindowScale;
+	}
+#endif
+
+#if 0 != vMacScreenDepth
+	if (UseColorMode) {
+#if vMacScreenDepth < 4
+		for (i = 0; i < CLUT_size; ++i) {
+			CLUT_pixel[i] = (CLUT_blues[i]>>8)<<24 | (CLUT_greens[i]>>8)<<16 | (CLUT_reds[i]>>8)<<8 | 0xff;
+		}
+#endif
+	} else
+#endif
+	{
+		BWLUT_pixel[1] = 0x000000ff;
+			/* black */
+		BWLUT_pixel[0] = 0xffffffff;
+			/* white */
+	}
+
+	if ((0 == ((bpp - 1) & bpp)) /* a power of 2 */
+#if (vMacScreenDepth > 3)
+		&& ! UseColorMode
+#endif
+		)
+	{
+		int k;
+		Uint32 v;
+#if EnableMagnify
+		int a;
+#endif
+		int PixPerByte =
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+			UseColorMode ? (1 << (3 - vMacScreenDepth)) :
+#endif
+			8;
+		Uint8 *p4 = (Uint8 *)CLUT_final;
+
+		for (i = 0; i < 256; ++i) {
+			for (k = PixPerByte; --k >= 0; ) {
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+				if (UseColorMode) {
+					v = CLUT_pixel[
+#if 3 == vMacScreenDepth
+						i
+#else
+						(i >> (k << vMacScreenDepth))
+							& (CLUT_size - 1)
+#endif
+						];
+				} else
+#endif
+				{
+					v = BWLUT_pixel[(i >> k) & 1];
+				}
+
+#if EnableMagnify
+				for (a = UseMagnify ? MyWindowScale : 1; --a >= 0; )
+#endif
+				{
+					switch (bpp) {
+						case 1: /* Assuming 8-bpp */
+							*p4++ = v;
+							break;
+						case 2: /* Probably 15-bpp or 16-bpp */
+							*(Uint16 *)p4 = v;
+							p4 += 2;
+							break;
+						case 4: /* Probably 32-bpp */
+							*(Uint32 *)p4 = v;
+							p4 += 4;
+							break;
+					}
+				}
+			}
+		}
+
+		ScalingBuff = (ui3p)pixels;
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+		if (UseColorMode) {
+#if EnableMagnify
+			if (UseMagnify) {
+				switch (bpp) {
+					case 1:
+						UpdateColorDepth3ScaledCopy(
+							top, left, bottom, right);
+						break;
+					case 2:
+						UpdateColorDepth4ScaledCopy(
+							top, left, bottom, right);
+						break;
+					case 4:
+						UpdateColorDepth5ScaledCopy(
+							top, left, bottom, right);
+						break;
+				}
+			} else
+#endif
+			{
+				switch (bpp) {
+					case 1:
+						UpdateColorDepth3Copy(top, left, bottom, right);
+						break;
+					case 2:
+						UpdateColorDepth4Copy(top, left, bottom, right);
+						break;
+					case 4:
+						UpdateColorDepth5Copy(top, left, bottom, right);
+						break;
+				}
+			}
+		} else
+#endif
+		{
+#if EnableMagnify
+			if (UseMagnify) {
+				switch (bpp) {
+					case 1:
+						UpdateBWDepth3ScaledCopy(
+							top, left, bottom, right);
+						break;
+					case 2:
+						UpdateBWDepth4ScaledCopy(
+							top, left, bottom, right);
+						break;
+					case 4:
+						UpdateBWDepth5ScaledCopy(
+							top, left, bottom, right);
+						break;
+				}
+			} else
+#endif
+			{
+				switch (bpp) {
+					case 1:
+						UpdateBWDepth3Copy(top, left, bottom, right);
+						break;
+					case 2:
+						UpdateBWDepth4Copy(top, left, bottom, right);
+						break;
+					case 4:
+						UpdateBWDepth5Copy(top, left, bottom, right);
+						break;
+				}
+			}
+		}
+
+	} else {
+		ui3b *the_data = (ui3b *)GetCurDrawBuff();
+
+		/* adapted from putpixel in SDL documentation */
+
+		for (i = top2; i < bottom2; ++i) {
+			for (j = left2; j < right2; ++j) {
+				int i0 = i;
+				int j0 = j;
+				Uint8 *bufp = (Uint8 *)pixels
+					+ i * Dx(my_surface->r)*bpp + j * bpp;
+
+#if EnableMagnify
+				if (UseMagnify) {
+					i0 /= MyWindowScale;
+					j0 /= MyWindowScale;
+				}
+#endif
+
+#if 0 != vMacScreenDepth
+				if (UseColorMode) {
+#if vMacScreenDepth < 4
+					p = the_data + ((i0 * vMacScreenWidth + j0)
+						>> (3 - vMacScreenDepth));
+					{
+						ui3r k = (*p >> (((~ j0)
+								& ((1 << (3 - vMacScreenDepth)) - 1))
+							<< vMacScreenDepth))
+							& (CLUT_size - 1);
+						pixel = CLUT_pixel[k];
+					}
+#elif 4 == vMacScreenDepth
+					p = the_data + ((i0 * vMacScreenWidth + j0) << 1);
+					{
+						ui4r t0 = do_get_mem_word(p);
+						pixel =
+							(((t0 & 0x7C00) >> 7)
+								| ((t0 & 0x7000) >> 12))<<24 |
+							(((t0 & 0x03E0) >> 2)
+								| ((t0 & 0x0380) >> 7))<<16 |
+							(((t0 & 0x001F) << 3)
+								| ((t0 & 0x001C) >> 2))<<8 |
+							0xff;
+					}
+#elif 5 == vMacScreenDepth
+					p = the_data + ((i0 * vMacScreenWidth + j0) << 2);
+					pixel = p[1]<<24 | p[2]<<16 | p[3]<<8 | 0xff;
+#endif
+				} else
+#endif
+				{
+					p = the_data + ((i0 * vMacScreenWidth + j0) / 8);
+					pixel = BWLUT_pixel[(*p >> ((~ j0) & 0x7)) & 1];
+				}
+
+				switch (bpp) {
+					case 1: /* Assuming 8-bpp */
+						*bufp = pixel;
+						break;
+					case 2: /* Probably 15-bpp or 16-bpp */
+						*(Uint16 *)bufp = pixel;
+						break;
+					case 3:
+						bufp[0] = (pixel >> 16) & 0xff;
+						bufp[1] = (pixel >> 8) & 0xff;
+						bufp[2] = pixel & 0xff;
+						break;
+					case 4: /* Probably 32-bpp */
+						*(Uint32 *)bufp = pixel;
+						break;
+				}
+			}
+		}
+	}
+
+	}
+
+	/* FIXME image unlocking? */
+	lockdisplay(display);
+	if(loadimage(my_surface, my_surface->r, pixels, 4*Dx(my_surface->r)*Dy(my_surface->r)) < 0)
+		sysfatal("%r");
+	Rectangle r = screen->r;
+	r.min.x += (Dx(r) - Dx(my_surface->r))/2;
+	r.min.y += (Dy(r) - Dy(my_surface->r))/2;
+	draw(screen, r, my_surface, nil, ZP);
+	flushimage(display, 1);
+	unlockdisplay(display);
+}
+
+LOCALPROC MyDrawChangesAndClear(void)
+{
+	if (ScreenChangedBottom > ScreenChangedTop) {
+		HaveChangedScreenBuff(ScreenChangedTop, ScreenChangedLeft,
+			ScreenChangedBottom, ScreenChangedRight);
+		ScreenClearChanges();
+	}
+}
+
+GLOBALOSGLUPROC DoneWithDrawingForTick(void)
+{
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		AutoScrollScreen();
+	}
+#endif
+	MyDrawChangesAndClear();
+}
+
+/* --- mouse --- */
+
+/* cursor hiding */
+
+LOCALVAR blnr HaveCursorHidden = falseblnr;
+LOCALVAR blnr WantCursorHidden = falseblnr;
+
+LOCALPROC ForceShowCursor(void)
+{
+	if (HaveCursorHidden) {
+		HaveCursorHidden = falseblnr;
+		// FIXME pointer toggle
+		//(void) SDL_ShowCursor(SDL_ENABLE);
+	}
+}
+
+/* cursor moving */
+
+LOCALFUNC blnr MyMoveMouse(si4b h, si4b v)
+{
+#if EnableMagnify
+	if (UseMagnify) {
+		h *= MyWindowScale;
+		v *= MyWindowScale;
+	}
+#endif
+
+	// FIXME pointer warp
+	//SDL_WarpMouse(h, v);
+
+	return trueblnr;
+}
+
+/* cursor state */
+
+LOCALPROC MousePositionNotify(int NewMousePosh, int NewMousePosv)
+{
+	blnr ShouldHaveCursorHidden = trueblnr;
+
+#if EnableMagnify
+	if (UseMagnify) {
+		NewMousePosh /= MyWindowScale;
+		NewMousePosv /= MyWindowScale;
+	}
+#endif
+
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		MyMousePositionSetDelta(NewMousePosh - SavedMouseH,
+			NewMousePosv - SavedMouseV);
+		SavedMouseH = NewMousePosh;
+		SavedMouseV = NewMousePosv;
+	} else
+#endif
+	{
+		if (NewMousePosh < 0) {
+			NewMousePosh = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePosh >= vMacScreenWidth) {
+			NewMousePosh = vMacScreenWidth - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+		if (NewMousePosv < 0) {
+			NewMousePosv = 0;
+			ShouldHaveCursorHidden = falseblnr;
+		} else if (NewMousePosv >= vMacScreenHeight) {
+			NewMousePosv = vMacScreenHeight - 1;
+			ShouldHaveCursorHidden = falseblnr;
+		}
+
+#if VarFullScreen
+		if (UseFullScreen)
+#endif
+#if MayFullScreen
+		{
+			ShouldHaveCursorHidden = trueblnr;
+		}
+#endif
+
+		/* if (ShouldHaveCursorHidden || CurMouseButton) */
+		/*
+			for a game like arkanoid, would like mouse to still
+			move even when outside window in one direction
+		*/
+		MyMousePositionSet(NewMousePosh, NewMousePosv);
+	}
+
+	WantCursorHidden = ShouldHaveCursorHidden;
+}
+
+/* --- keyboard input --- */
+
+LOCALFUNC ui3r Rune2MacKeyCode(Rune i)
+{
+	ui3r v = MKC_None;
+
+	switch (i) {
+		case Kbs: v = MKC_BackSpace; break;
+		case '\t': v = MKC_Tab; break;
+		//FIXME case clear: v = MKC_Clear; break;
+		case '\n': v = MKC_Return; break;
+		//FIXME case pause: v = MKC_Pause; break;
+		case Kesc: v = MKC_formac_Escape; break;
+		case ' ': v = MKC_Space; break;
+		case '\'': v = MKC_SingleQuote; break;
+		case ',': v = MKC_Comma; break;
+		case '-': v = MKC_Minus; break;
+		case '.': v = MKC_Period; break;
+		case '/': v = MKC_formac_Slash; break;
+		case '0': v = MKC_0; break;
+		case '1': v = MKC_1; break;
+		case '2': v = MKC_2; break;
+		case '3': v = MKC_3; break;
+		case '4': v = MKC_4; break;
+		case '5': v = MKC_5; break;
+		case '6': v = MKC_6; break;
+		case '7': v = MKC_7; break;
+		case '8': v = MKC_8; break;
+		case '9': v = MKC_9; break;
+		case ';': v = MKC_SemiColon; break;
+		case '=': v = MKC_Equal; break;
+
+		case '[': v = MKC_LeftBracket; break;
+		case '\\': v = MKC_formac_BackSlash; break;
+		case ']': v = MKC_RightBracket; break;
+		case '`': v = MKC_formac_Grave; break;
+
+		case 'a': v = MKC_A; break;
+		case 'b': v = MKC_B; break;
+		case 'c': v = MKC_C; break;
+		case 'd': v = MKC_D; break;
+		case 'e': v = MKC_E; break;
+		case 'f': v = MKC_F; break;
+		case 'g': v = MKC_G; break;
+		case 'h': v = MKC_H; break;
+		case 'i': v = MKC_I; break;
+		case 'j': v = MKC_J; break;
+		case 'k': v = MKC_K; break;
+		case 'l': v = MKC_L; break;
+		case 'm': v = MKC_M; break;
+		case 'n': v = MKC_N; break;
+		case 'o': v = MKC_O; break;
+		case 'p': v = MKC_P; break;
+		case 'q': v = MKC_Q; break;
+		case 'r': v = MKC_R; break;
+		case 's': v = MKC_S; break;
+		case 't': v = MKC_T; break;
+		case 'u': v = MKC_U; break;
+		case 'v': v = MKC_V; break;
+		case 'w': v = MKC_W; break;
+		case 'x': v = MKC_X; break;
+		case 'y': v = MKC_Y; break;
+		case 'z': v = MKC_Z; break;
+
+		case Kup: v = MKC_Up; break;
+		case Kdown: v = MKC_Down; break;
+		case Kright: v = MKC_Right; break;
+		case Kleft: v = MKC_Left; break;
+		case Kins: v = MKC_formac_Help; break;
+		case Khome: v = MKC_formac_Home; break;
+		case Kend: v = MKC_formac_End; break;
+		case Kpgup: v = MKC_formac_PageUp; break;
+		case Kpgdown: v = MKC_formac_PageDown; break;
+
+		//case KF|1: v = MKC_formac_F1; break;
+		//case KF|2: v = MKC_formac_F2; break;
+		//case KF|3: v = MKC_formac_F3; break;
+		case KF|4: v = MKC_formac_F4; break;
+		case KF|5: v = MKC_formac_F5; break;
+		case KF|6: v = MKC_F6; break;
+		case KF|7: v = MKC_F7; break;
+		case KF|8: v = MKC_F8; break;
+		case KF|9: v = MKC_F9; break;
+		case KF|10: v = MKC_F10; break;
+		case KF|11: v = MKC_F11; break;
+		case KF|12: v = MKC_F12; break;
+
+		case Kshift: v = MKC_formac_Shift; break;
+		case Kctl: v = MKC_formac_Control; break;
+		case Kalt: case KF|1: v = MKC_formac_Command; break;
+		case KF|2: v = MKC_formac_Command; break;
+		case KF|3: v = MKC_formac_Option; break;
+
+		//FIXME case SDLK_HELP: v = MKC_formac_Help; break;
+		//FIXME case SDLK_PRINT: v = MKC_Print; break;
+
+		default:
+			break;
+	}
+
+	return v;
+}
+
+LOCALPROC DoKeyCode(Rune r, blnr down)
+{
+	ui3r v = Rune2MacKeyCode(r);
+	if (MKC_None != v) {
+		Keyboard_UpdateKeyMap2(v, down);
+	}
+}
+
+LOCALPROC DisableKeyRepeat(void)
+{
+}
+
+LOCALPROC RestoreKeyRepeat(void)
+{
+}
+
+LOCALPROC ReconnectKeyCodes3(void)
+{
+}
+
+LOCALPROC DisconnectKeyCodes3(void)
+{
+	DisconnectKeyCodes2();
+	MyMouseButtonSet(falseblnr);
+}
+
+/* --- time, date, location --- */
+
+#define dbglog_TimeStuff (0 && dbglog_HAVE)
+
+LOCALVAR ui5b TrueEmulatedTime = 0;
+
+#define MyInvTimeDivPow 16
+#define MyInvTimeDiv (1 << MyInvTimeDivPow)
+#define MyInvTimeDivMask (MyInvTimeDiv - 1)
+#define MyInvTimeStep 1089590 /* 1000 / 60.14742 * MyInvTimeDiv */
+
+LOCALVAR Uint32 LastTime;
+
+LOCALVAR Uint32 NextIntTime;
+LOCALVAR ui5b NextFracTime;
+
+LOCALPROC IncrNextTime(void)
+{
+	NextFracTime += MyInvTimeStep;
+	NextIntTime += (NextFracTime >> MyInvTimeDivPow);
+	NextFracTime &= MyInvTimeDivMask;
+}
+
+LOCALPROC InitNextTime(void)
+{
+	NextIntTime = LastTime;
+	NextFracTime = 0;
+	IncrNextTime();
+}
+
+LOCALVAR ui5b NewMacDateInSeconds;
+
+static int usensec = 0;
+
+/*
+ * nsec() is wallclock and can be adjusted by timesync
+ * so need to use cycles() instead, but fall back to
+ * nsec() in case we can't
+ *
+ * "fasthz" is how many ticks there are in a second
+ * can be read from /dev/time
+ *
+ * perhaps using RDTSCP is even better
+ */
+static uvlong
+nanosec(void)
+{
+	static uvlong fasthz, xstart;
+	uvlong x, div;
+	int f, n, i;
+	char tmp[128], *e;
+
+	if (fasthz == ~0ULL)
+		return nsec() - xstart;
+
+	if (fasthz == 0) {
+		fasthz = ~0ULL;
+		xstart = nsec();
+		if (usensec)
+			return 0;
+		if ((f = open("/dev/time", OREAD)) >= 0 && (n = read(f, tmp, sizeof(tmp)-1)) > 2) {
+			tmp[n] = 0;
+			e = tmp;
+			for (i = 0; i < 3; i++)
+				strtoll(e, &e, 10);
+			if ((fasthz = strtoll(e, nil, 10)) < 1)
+				fasthz = ~0ULL;
+			else
+				cycles(&xstart);
+		}
+		close(f);
+		if (fasthz == ~0ULL) {
+			fprint(2, "couldn't get fasthz, falling back to nsec()\n");
+			fprint(2, "you might want to disable aux/timesync\n");
+			return 0;
+		}
+	}
+	cycles(&x);
+	x -= xstart;
+
+	for (div = 1000000000ULL; x < 0x1999999999999999ULL && div > 1 ; div /= 10ULL, x *= 10ULL);
+
+	return x / (fasthz / div);
+}
+
+LOCALFUNC blnr UpdateTrueEmulatedTime(void)
+{
+	Uint32 LatestTime;
+	si5b TimeDiff;
+
+	LatestTime = nanosec() / 1000000ULL;
+	if (LatestTime != LastTime) {
+
+		NewMacDateInSeconds = LatestTime / 1000;
+			/* no date and time api in SDL */
+
+		LastTime = LatestTime;
+		TimeDiff = (LatestTime - NextIntTime);
+			/* this should work even when time wraps */
+		if (TimeDiff >= 0) {
+			if (TimeDiff > 256) {
+				/* emulation interrupted, forget it */
+				++TrueEmulatedTime;
+				InitNextTime();
+
+#if dbglog_TimeStuff
+				dbglog_writelnNum("emulation interrupted",
+					TrueEmulatedTime);
+#endif
+			} else {
+				do {
+					++TrueEmulatedTime;
+					IncrNextTime();
+					TimeDiff = (LatestTime - NextIntTime);
+				} while (TimeDiff >= 0);
+			}
+			return trueblnr;
+		} else {
+			if (TimeDiff < -256) {
+#if dbglog_TimeStuff
+				dbglog_writeln("clock set back");
+#endif
+				/* clock goofed if ever get here, reset */
+				InitNextTime();
+			}
+		}
+	}
+	return falseblnr;
+}
+
+
+LOCALFUNC blnr CheckDateTime(void)
+{
+	if (CurMacDateInSeconds != NewMacDateInSeconds) {
+		CurMacDateInSeconds = NewMacDateInSeconds;
+		return trueblnr;
+	} else {
+		return falseblnr;
+	}
+}
+
+LOCALPROC StartUpTimeAdjust(void)
+{
+	LastTime = nanosec() / 1000000ULL;
+	InitNextTime();
+}
+
+LOCALFUNC blnr InitLocationDat(void)
+{
+	LastTime = nanosec() / 1000000ULL;
+	InitNextTime();
+	NewMacDateInSeconds = LastTime / 1000;
+	CurMacDateInSeconds = NewMacDateInSeconds;
+
+	return trueblnr;
+}
+
+/* --- sound --- */
+
+static int audiofd;
+static u8int *audiobuf;
+static int audiooff;
+
+GLOBALOSGLUFUNC tpSoundSamp MySound_BeginWrite(ui4r n, ui4r *actL)
+{
+	*actL = n;
+	audiooff += n;
+	return audiobuf + audiooff - n;
+}
+
+LOCALVAR blnr HaveSoundOut = falseblnr;
+
+static char audiofmt[32];
+
+static void
+runpcmconv(void *x)
+{
+	int *p;
+
+	p = x;
+	dup(p[0], 0); close(p[0]); close(p[1]);
+	dup(open("/dev/audio", OWRITE), 1);
+	procexecl(nil, "/bin/audio/pcmconv", "pcmconv", "-i", audiofmt, nil);
+	threadexits("exec: %r");
+}
+
+#define SOUND_SAMPLERATE 22255
+
+LOCALFUNC blnr MySound_Init(void)
+{
+	int p[2];
+
+	sprint(
+		audiofmt, "%c%dc1r%d",
+		3 == kLn2SoundSampSz ? 'u' : 's',
+		3 == kLn2SoundSampSz ? 8 : 16,
+		SOUND_SAMPLERATE
+	);
+
+	pipe(p);
+	procrfork(runpcmconv, p, 4096, RFFDG);
+	close(p[0]);
+	audiofd = p[1];
+	HaveSoundOut = trueblnr;
+	audiobuf = malloc(65536);
+
+	return trueblnr;
+}
+
+GLOBALOSGLUPROC MySound_EndWrite(ui4r actL)
+{
+	write(audiofd, audiobuf, audiooff);
+	audiooff = 0;
+}
+
+/* --- basic dialogs --- */
+
+LOCALPROC CheckSavedMacMsg(void)
+{
+	/* called only on quit, if error saved but not yet reported */
+
+	if (nullpr != SavedBriefMsg) {
+		char briefMsg0[ClStrMaxLength + 1];
+		char longMsg0[ClStrMaxLength + 1];
+
+		NativeStrFromCStr(briefMsg0, SavedBriefMsg);
+		NativeStrFromCStr(longMsg0, SavedLongMsg);
+
+		fprint(2, "%s\n", briefMsg0);
+		fprint(2, "%s\n", longMsg0);
+
+		SavedBriefMsg = nullpr;
+	}
+}
+
+/* --- main window creation and disposal --- */
+
+LOCALVAR int my_argc;
+LOCALVAR char **my_argv;
+
+enum {
+	Cmouse,
+	Cresize,
+	Numchan,
+};
+
+static Mousectl *mctl;
+static Keyboardctl kctl;
+static Rune rune;
+static Mouse mouse;
+static int altdown, ctldown, shiftdown;
+static Alt a[Numchan+1] = {
+	[Cmouse] = { nil, &mouse, CHANRCV },
+	[Cresize] = { nil, nil, CHANRCV },
+	{ nil, nil, CHANNOBLK },
+};
+
+static void
+kbdproc(void *)
+{
+	char buf[128], buf2[128], *s;
+	int kfd, n, kbin;
+	Rune r;
+
+	threadsetname("kbdproc");
+	if ((kfd = open("/dev/kbd", OREAD)) < 0)
+		sysfatal("/dev/kbd: %r");
+	kbin = open("/dev/kbin", OWRITE);
+
+	buf2[0] = 0;
+	buf2[1] = 0;
+	buf[0] = 0;
+	for (;;) {
+		if (buf[0] != 0) {
+			n = strlen(buf)+1;
+			memmove(buf, buf+n, sizeof(buf)-n);
+		}
+		if (buf[0] == 0) {
+			n = read(kfd, buf, sizeof(buf)-1);
+			if (n <= 0)
+				break;
+			buf[n-1] = 0;
+			buf[n] = 0;
+		}
+
+		switch (buf[0]) {
+		default:
+			continue;
+
+		case 'k':
+			s = buf+1;
+			while (*s) {
+				s += chartorune(&r, s);
+				if (utfrune(buf2+1, r) == nil) {
+					DoKeyCode(r, 1);
+					if (r == Kalt) {
+						/* magic trick: write Alt scancode to disable the "compose" mode */
+						if (kbin >= 0)
+							write(kbin, "\x46", 1);
+					}
+				}
+			}
+			break;
+
+		case 'K':
+			s = buf2+1;
+			while (*s) {
+				s += chartorune(&r, s);
+				if (utfrune(buf+1, r) == nil)
+					DoKeyCode(r, 0);
+			}
+			break;
+		}
+		strcpy(buf2, buf);
+	}
+
+	threadexits(nil);
+}
+
+static Cursor emptycursor = { {0, 0}, { 0 }, { 0 } };
+
+LOCALFUNC blnr Screen_Init(void)
+{
+	InitKeyCodes();
+
+	threadsetname(kStrAppName);
+
+	if(initdraw(nil, nil, kStrAppName) < 0)
+		sysfatal("initdraw: %r");
+	if ((mctl = initmouse(nil, screen)) == nil)
+		sysfatal("initmouse: %r");
+	setcursor(mctl, &emptycursor);
+	display->locking = 1;
+	unlockdisplay(display);
+
+	a[Cmouse].c = mctl->c;
+	a[Cresize].c = mctl->resizec;
+
+	proccreate(kbdproc, nil, mainstacksize);
+
+	return trueblnr;
+}
+
+#if MayFullScreen
+LOCALVAR blnr GrabMachine = falseblnr;
+#endif
+
+#if MayFullScreen
+LOCALPROC GrabTheMachine(void)
+{
+#if GrabKeysFullScreen
+#endif
+
+#if EnableFSMouseMotion
+	/*
+		if magnification changes, need to reset,
+		even if HaveMouseMotion already true
+	*/
+	if (MyMoveMouse(ViewHStart + (ViewHSize / 2),
+		ViewVStart + (ViewVSize / 2)))
+	{
+		SavedMouseH = ViewHStart + (ViewHSize / 2);
+		SavedMouseV = ViewVStart + (ViewVSize / 2);
+		HaveMouseMotion = trueblnr;
+	}
+#endif
+}
+#endif
+
+#if MayFullScreen
+LOCALPROC UngrabMachine(void)
+{
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		(void) MyMoveMouse(CurMouseH, CurMouseV);
+		HaveMouseMotion = falseblnr;
+	}
+#endif
+
+#if GrabKeysFullScreen
+#endif
+}
+#endif
+
+#if EnableFSMouseMotion
+LOCALPROC MyMouseConstrain(void)
+{
+	si4b shiftdh;
+	si4b shiftdv;
+
+	if (SavedMouseH < ViewHStart + (ViewHSize / 4)) {
+		shiftdh = ViewHSize / 2;
+	} else if (SavedMouseH > ViewHStart + ViewHSize - (ViewHSize / 4)) {
+		shiftdh = - ViewHSize / 2;
+	} else {
+		shiftdh = 0;
+	}
+	if (SavedMouseV < ViewVStart + (ViewVSize / 4)) {
+		shiftdv = ViewVSize / 2;
+	} else if (SavedMouseV > ViewVStart + ViewVSize - (ViewVSize / 4)) {
+		shiftdv = - ViewVSize / 2;
+	} else {
+		shiftdv = 0;
+	}
+	if ((shiftdh != 0) || (shiftdv != 0)) {
+		SavedMouseH += shiftdh;
+		SavedMouseV += shiftdv;
+		if (! MyMoveMouse(SavedMouseH, SavedMouseV)) {
+			HaveMouseMotion = falseblnr;
+		}
+	}
+}
+#endif
+
+LOCALFUNC blnr CreateMainWindow(void)
+{
+	int NewWindowHeight = vMacScreenHeight;
+	int NewWindowWidth = vMacScreenWidth;
+	blnr v = falseblnr;
+
+#if EnableMagnify && 1
+	if (UseMagnify) {
+		NewWindowHeight *= MyWindowScale;
+		NewWindowWidth *= MyWindowScale;
+	}
+#endif
+
+#if VarFullScreen
+	if (UseFullScreen)
+#endif
+#if MayFullScreen
+	{
+	}
+#endif
+
+	ViewHStart = 0;
+	ViewVStart = 0;
+	ViewHSize = vMacScreenWidth;
+	ViewVSize = vMacScreenHeight;
+
+	freeimage(my_surface);
+	my_surface = allocimage(
+		display,
+		Rect(0, 0, NewWindowWidth, NewWindowHeight),
+		CHAN4(CBlue, 8, CGreen, 8, CRed, 8, CIgnore, 8),
+		0,
+		DWhite);
+	if (NULL == my_surface) {
+		fprint(2, "allocimage: %r\n");
+	} else {
+#if 0 != vMacScreenDepth
+		ColorModeWorks = trueblnr;
+#endif
+		v = trueblnr;
+		pixels = realloc(pixels, 4*NewWindowWidth*NewWindowHeight);
+	}
+
+	return v;
+}
+
+#if EnableRecreateW
+LOCALFUNC blnr ReCreateMainWindow(void)
+{
+	ForceShowCursor(); /* hide/show cursor api is per window */
+
+#if MayFullScreen
+	if (GrabMachine) {
+		GrabMachine = falseblnr;
+		UngrabMachine();
+	}
+#endif
+
+#if EnableMagnify
+	UseMagnify = WantMagnify;
+#endif
+#if VarFullScreen
+	UseFullScreen = WantFullScreen;
+#endif
+
+	(void) CreateMainWindow();
+
+	if (HaveCursorHidden) {
+		(void) MyMoveMouse(CurMouseH, CurMouseV);
+	}
+
+	return trueblnr;
+}
+#endif
+
+LOCALPROC ZapWinStateVars(void)
+{
+}
+
+#if VarFullScreen
+LOCALPROC ToggleWantFullScreen(void)
+{
+	WantFullScreen = ! WantFullScreen;
+}
+#endif
+
+/* --- SavedTasks --- */
+
+LOCALPROC LeaveBackground(void)
+{
+	ReconnectKeyCodes3();
+	DisableKeyRepeat();
+}
+
+LOCALPROC EnterBackground(void)
+{
+	RestoreKeyRepeat();
+	DisconnectKeyCodes3();
+
+	ForceShowCursor();
+}
+
+LOCALPROC LeaveSpeedStopped(void)
+{
+	StartUpTimeAdjust();
+}
+
+LOCALPROC EnterSpeedStopped(void)
+{
+}
+
+LOCALPROC CheckForSavedTasks(void)
+{
+	if (MyEvtQNeedRecover) {
+		MyEvtQNeedRecover = falseblnr;
+
+		/* attempt cleanup, MyEvtQNeedRecover may get set again */
+		MyEvtQTryRecoverFromFull();
+	}
+
+#if EnableFSMouseMotion
+	if (HaveMouseMotion) {
+		MyMouseConstrain();
+	}
+#endif
+
+	if (RequestMacOff) {
+		RequestMacOff = falseblnr;
+		if (AnyDiskInserted()) {
+			MacMsgOverride(kStrQuitWarningTitle,
+				kStrQuitWarningMessage);
+		} else {
+			ForceMacOff = trueblnr;
+		}
+	}
+
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (gTrueBackgroundFlag != gBackgroundFlag) {
+		gBackgroundFlag = gTrueBackgroundFlag;
+		if (gTrueBackgroundFlag) {
+			EnterBackground();
+		} else {
+			LeaveBackground();
+		}
+	}
+
+	if (CurSpeedStopped != (SpeedStopped ||
+		(gBackgroundFlag && ! RunInBackground
+#if EnableAutoSlow && 0
+			&& (QuietSubTicks >= 4092)
+#endif
+		)))
+	{
+		CurSpeedStopped = ! CurSpeedStopped;
+		if (CurSpeedStopped) {
+			EnterSpeedStopped();
+		} else {
+			LeaveSpeedStopped();
+		}
+	}
+
+	if ((nullpr != SavedBriefMsg) & ! MacMsgDisplayed) {
+		MacMsgDisplayOn();
+	}
+
+#if EnableRecreateW
+	if (0
+#if EnableMagnify
+		|| (UseMagnify != WantMagnify)
+#endif
+#if VarFullScreen
+		|| (UseFullScreen != WantFullScreen)
+#endif
+		)
+	{
+		(void) ReCreateMainWindow();
+	}
+#endif
+
+#if MayFullScreen
+	if (GrabMachine != (
+#if VarFullScreen
+		UseFullScreen &&
+#endif
+		! (gTrueBackgroundFlag || CurSpeedStopped)))
+	{
+		GrabMachine = ! GrabMachine;
+		if (GrabMachine) {
+			GrabTheMachine();
+		} else {
+			UngrabMachine();
+		}
+	}
+#endif
+
+	if (NeedWholeScreenDraw) {
+		NeedWholeScreenDraw = falseblnr;
+		ScreenChangedAll();
+	}
+
+#if NeedRequestIthDisk
+	if (0 != RequestIthDisk) {
+		Sony_InsertIth(RequestIthDisk);
+		RequestIthDisk = 0;
+	}
+#endif
+
+	if (HaveCursorHidden != (WantCursorHidden
+		&& ! (gTrueBackgroundFlag || CurSpeedStopped)))
+	{
+		HaveCursorHidden = ! HaveCursorHidden;
+		//FIXME setcursor(mctl, HaveCursorHidden ? &emptycursor : nil);
+	}
+}
+
+/* --- command line parsing --- */
+
+LOCALFUNC blnr ScanCommandLine(void)
+{
+	char *pa;
+	int i = 1;
+
+label_retry:
+	if (i < my_argc) {
+		pa = my_argv[i++];
+		if ('-' == pa[0]) {
+			if ((0 == strcmp(pa, "--rom"))
+				|| (0 == strcmp(pa, "-r")))
+			{
+				if (i < my_argc) {
+					rom_path = my_argv[i++];
+					goto label_retry;
+				}
+			} else
+			{
+				MacMsg(kStrBadArgTitle, kStrBadArgMessage, falseblnr);
+			}
+		} else {
+			(void) Sony_Insert1(pa, falseblnr);
+			goto label_retry;
+		}
+	}
+
+	return trueblnr;
+}
+
+/* --- main program flow --- */
+
+GLOBALOSGLUFUNC blnr ExtraTimeNotOver(void)
+{
+	UpdateTrueEmulatedTime();
+	return TrueEmulatedTime == OnTrueTime;
+}
+
+LOCALPROC WaitForTheNextEvent(void)
+{
+	switch (alt(a)) {
+	case -1:
+		//threadexitsall(nil);
+
+	case Cmouse:
+		MousePositionNotify(mouse.xy.x-screen->r.min.x-(Dx(screen->r)-Dx(my_surface->r))/2, mouse.xy.y-screen->r.min.y-(Dx(screen->r)-Dx(my_surface->r))/2);
+		MyMouseButtonSet(mouse.buttons & 1);
+		break;
+
+	case Cresize:
+		if(getwindow(display, Refnone) < 0)
+			sysfatal("getwindow: %r");
+		break;
+	}
+}
+
+GLOBALOSGLUPROC WaitForNextTick(void)
+{
+label_retry:
+	CheckForSavedTasks();
+
+	if (ForceMacOff) {
+		return;
+	}
+
+	if (1) {//CurSpeedStopped) {
+		DoneWithDrawingForTick();
+		WaitForTheNextEvent();
+		if (CurSpeedStopped)
+			goto label_retry;
+	}
+
+	if (ExtraTimeNotOver()) {
+		sleep(NextIntTime - LastTime); /* FIXME do a better job like in orca */
+		goto label_retry;
+	}
+
+	if (CheckDateTime()) {
+#if EnableDemoMsg
+		DemoModeSecondNotify();
+#endif
+	}
+
+	OnTrueTime = TrueEmulatedTime;
+
+#if dbglog_TimeStuff
+	dbglog_writelnNum("WaitForNextTick, OnTrueTime", OnTrueTime);
+#endif
+}
+
+/* --- platform independent code can be thought of as going here --- */
+
+#include "PROGMAIN.h"
+
+LOCALPROC ZapOSGLUVars(void)
+{
+	InitDrives();
+	ZapWinStateVars();
+}
+
+LOCALPROC ReserveAllocAll(void)
+{
+#if dbglog_HAVE
+	dbglog_ReserveAlloc();
+#endif
+	ReserveAllocOneBlock(&ROM, kROM_Size, 5, falseblnr);
+
+	ReserveAllocOneBlock(&screencomparebuff,
+		vMacScreenNumBytes, 5, trueblnr);
+#if UseControlKeys
+	ReserveAllocOneBlock(&CntrlDisplayBuff,
+		vMacScreenNumBytes, 5, falseblnr);
+#endif
+
+	ReserveAllocOneBlock(&CLUT_final, CLUT_finalsz, 5, falseblnr);
+
+	EmulationReserveAlloc();
+}
+
+LOCALFUNC blnr AllocMyMemory(void)
+{
+	uimr n;
+	blnr IsOk = falseblnr;
+
+	ReserveAllocOffset = 0;
+	ReserveAllocBigBlock = nullpr;
+	ReserveAllocAll();
+	n = ReserveAllocOffset;
+	ReserveAllocBigBlock = (ui3p)calloc(1, n);
+	if (NULL == ReserveAllocBigBlock) {
+		MacMsg(kStrOutOfMemTitle, kStrOutOfMemMessage, trueblnr);
+	} else {
+		ReserveAllocOffset = 0;
+		ReserveAllocAll();
+		if (n != ReserveAllocOffset) {
+			/* oops, program error */
+		} else {
+			IsOk = trueblnr;
+		}
+	}
+
+	return IsOk;
+}
+
+LOCALPROC UnallocMyMemory(void)
+{
+	if (nullpr != ReserveAllocBigBlock) {
+		free((char *)ReserveAllocBigBlock);
+	}
+}
+
+LOCALFUNC blnr InitOSGLU(void)
+{
+	if (AllocMyMemory())
+#if dbglog_HAVE
+	if (dbglog_open())
+#endif
+	if (ScanCommandLine())
+	if (LoadMacRom())
+	if (LoadInitialImages())
+	if (InitLocationDat())
+	if (MySound_Init())
+	if (Screen_Init())
+	if (CreateMainWindow())
+	if (WaitForRom())
+	{
+		return trueblnr;
+	}
+	return falseblnr;
+}
+
+LOCALPROC UnInitOSGLU(void)
+{
+	if (MacMsgDisplayed) {
+		MacMsgDisplayOff();
+	}
+
+	RestoreKeyRepeat();
+#if MayFullScreen
+	UngrabMachine();
+#endif
+#if IncludePbufs
+	UnInitPbufs();
+#endif
+	UnInitDrives();
+
+	ForceShowCursor();
+
+#if dbglog_HAVE
+	dbglog_close();
+#endif
+
+	UnallocMyMemory();
+
+	CheckSavedMacMsg();
+}
+
+#if IncludeHostTextClipExchange
+GLOBALOSGLUFUNC tMacErr HTCEexport(tPbuf i)
+{
+	return mnvm_miscErr;
+}
+#endif
+
+#if IncludeHostTextClipExchange
+GLOBALOSGLUFUNC tMacErr HTCEimport(tPbuf *r)
+{
+	return mnvm_miscErr;
+}
+#endif
+
+void
+threadmain(int argc, char **argv)
+{
+	my_argc = argc;
+	my_argv = argv;
+
+	ZapOSGLUVars();
+	if (InitOSGLU()) {
+		ProgramMain();
+	}
+	UnInitOSGLU();
+
+	threadexitsall(nil);
+}
--- /dev/null
+++ b/src/PBUFSTDC.h
@@ -1,0 +1,121 @@
+/*
+	PBUFSTDC.h
+
+	Copyright (C) 2018 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Parameter BUFfers implemented with STanDard C library
+*/
+
+
+#if IncludePbufs
+LOCALVAR void *PbufDat[NumPbufs];
+#endif
+
+#if IncludePbufs
+LOCALFUNC tMacErr PbufNewFromPtr(void *p, ui5b count, tPbuf *r)
+{
+	tPbuf i;
+	tMacErr err;
+
+	if (! FirstFreePbuf(&i)) {
+		free(p);
+		err = mnvm_miscErr;
+	} else {
+		*r = i;
+		PbufDat[i] = p;
+		PbufNewNotify(i, count);
+		err = mnvm_noErr;
+	}
+
+	return err;
+}
+#endif
+
+#if IncludePbufs
+LOCALPROC PbufKillToPtr(void **p, ui5r *count, tPbuf r)
+{
+	*p = PbufDat[r];
+	*count = PbufSize[r];
+
+	PbufDisposeNotify(r);
+}
+#endif
+
+#if IncludePbufs
+GLOBALOSGLUFUNC tMacErr PbufNew(ui5b count, tPbuf *r)
+{
+	tMacErr err = mnvm_miscErr;
+
+	void *p = calloc(1, count);
+	if (NULL != p) {
+		err = PbufNewFromPtr(p, count, r);
+	}
+
+	return err;
+}
+#endif
+
+#if IncludePbufs
+GLOBALOSGLUPROC PbufDispose(tPbuf i)
+{
+	void *p;
+	ui5r count;
+
+	PbufKillToPtr(&p, &count, i);
+
+	free(p);
+}
+#endif
+
+#if IncludePbufs
+LOCALPROC UnInitPbufs(void)
+{
+	tPbuf i;
+
+	for (i = 0; i < NumPbufs; ++i) {
+		if (PbufIsAllocated(i)) {
+			PbufDispose(i);
+		}
+	}
+}
+#endif
+
+#if IncludePbufs
+#define PbufHaveLock 1
+#endif
+
+#if IncludePbufs
+LOCALFUNC ui3p PbufLock(tPbuf i)
+{
+	return (ui3p)PbufDat[i];
+}
+#endif
+
+#if IncludePbufs
+#define PbufUnlock(i)
+#endif
+
+#if IncludePbufs
+GLOBALOSGLUPROC PbufTransfer(ui3p Buffer,
+	tPbuf i, ui5r offset, ui5r count, blnr IsWrite)
+{
+	void *p = ((ui3p)PbufDat[i]) + offset;
+	if (IsWrite) {
+		(void) memcpy(p, Buffer, count);
+	} else {
+		(void) memcpy(Buffer, p, count);
+	}
+}
+#endif
--- /dev/null
+++ b/src/PMUEMDEV.c
@@ -1,0 +1,442 @@
+/*
+	PMUEMDEV.c
+
+	Copyright (C) 2008 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Power Management Unit EMulated DEVice
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+#include "MYOSGLUE.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+#include "VIAEMDEV.h"
+#endif
+
+#include "PMUEMDEV.h"
+
+/*
+	ReportAbnormalID unused 0x0E0E - 0x0EFF
+*/
+
+enum {
+	kPMUStateReadyForCommand,
+	kPMUStateRecievingLength,
+	kPMUStateRecievingBuffer,
+	kPMUStateRecievedCommand,
+	kPMUStateSendLength,
+	kPMUStateSendBuffer,
+
+	kPMUStates
+};
+
+#define PMU_BuffSz 8
+LOCALVAR ui3b PMU_BuffA[PMU_BuffSz];
+LOCALVAR ui3p PMU_p;
+LOCALVAR ui3r PMU_rem;
+LOCALVAR ui3r PMU_i;
+
+LOCALVAR int PMUState = kPMUStateReadyForCommand;
+
+LOCALVAR ui3r PMU_CurCommand;
+LOCALVAR ui3r PMU_SendNext;
+LOCALVAR ui3r PMU_BuffL;
+
+LOCALPROC PmuStartSendResult(ui3r ResultCode, ui3r L)
+{
+	PMU_SendNext = ResultCode;
+	PMU_BuffL = L;
+	PMUState = kPMUStateSendLength;
+}
+
+LOCALVAR ui3b PARAMRAM[128];
+
+LOCALPROC PmuCheckCommandOp(void)
+{
+	switch (PMU_CurCommand) {
+		case 0x10: /* kPMUpowerCntl - power plane/clock control */
+			break;
+		case 0x32: /* kPMUxPramWrite - write extended PRAM byte(s) */
+			if (kPMUStateRecievingBuffer == PMUState) {
+				if (0 == PMU_i) {
+					if (PMU_BuffL >= 2) {
+						PMU_p = PMU_BuffA;
+						PMU_rem = 2;
+					} else {
+						ReportAbnormalID(0x0E01,
+							"PMU_BuffL too small for kPMUxPramWrite");
+					}
+				} else if (2 == PMU_i) {
+					if ((PMU_BuffA[1] + 2 == PMU_BuffL)
+						&& (PMU_BuffA[0] + PMU_BuffA[1] <= 0x80))
+					{
+						PMU_p = &PARAMRAM[PMU_BuffA[0]];
+						PMU_rem = PMU_BuffA[1];
+					} else {
+						ReportAbnormalID(0x0E02,
+							"bad range for kPMUxPramWrite");
+					}
+				} else {
+					ReportAbnormalID(0x0E03,
+						"Wrong PMU_i for kPMUpramWrite");
+				}
+			} else if (kPMUStateRecievedCommand == PMUState) {
+				/* already done */
+			}
+			break;
+#if 0
+		case 0xE2: /* kPMUdownloadStatus - PRAM status */
+			break;
+#endif
+		case 0xE0: /* kPMUwritePmgrRAM - write to internal PMGR RAM */
+			break;
+		case 0x21: /* kPMUpMgrADBoff - turn ADB auto-poll off */
+			if (kPMUStateRecievedCommand == PMUState) {
+				if (0 != PMU_BuffL) {
+					ReportAbnormalID(0x0E04,
+						"kPMUpMgrADBoff nonzero length");
+				}
+			}
+			break;
+		case 0xEC: /* kPMUPmgrSelfTest - run the PMGR selftest */
+			if (kPMUStateRecievedCommand == PMUState) {
+				PmuStartSendResult(0, 0);
+			}
+			break;
+		case 0x78:
+			/* kPMUreadINT - get PMGR interrupt data */
+		case 0x68:
+			/*
+				kPMUbatteryRead - read battery/charger level and status
+			*/
+		case 0x7F:
+			/*
+				kPMUsleepReq - put the system to sleep (sleepSig='MATT')
+			*/
+			if (kPMUStateRecievedCommand == PMUState) {
+				PMU_BuffA[0] = 0;
+				PmuStartSendResult(0, 1);
+			}
+			break;
+		case 0xE8: /* kPMUreadPmgrRAM - read from internal PMGR RAM */
+			if (kPMUStateRecievedCommand == PMUState) {
+				if ((3 == PMU_BuffL)
+					&& (0 == PMU_BuffA[0])
+					&& (0xEE == PMU_BuffA[1])
+					&& (1 == PMU_BuffA[2]))
+				{
+					PMU_BuffA[0] = 1 << 5;
+					PmuStartSendResult(0, 1);
+				} else {
+					PMU_BuffA[0] = 0;
+					PmuStartSendResult(0, 1);
+					/* ReportAbnormal("Unknown kPMUreadPmgrRAM op"); */
+				}
+			}
+			break;
+		case 0x3A: /* kPMUxPramRead - read extended PRAM byte(s) */
+			if (kPMUStateRecievedCommand == PMUState) {
+				if ((2 == PMU_BuffL)
+					&& (PMU_BuffA[0] + PMU_BuffA[1] <= 0x80))
+				{
+					PMU_p = &PARAMRAM[PMU_BuffA[0]];
+					PMU_rem = PMU_BuffA[1];
+					PmuStartSendResult(0, PMU_rem);
+				} else {
+					ReportAbnormalID(0x0E05,
+						"Unknown kPMUxPramRead op");
+				}
+			}
+			break;
+		case 0x38:
+			/* kPMUtimeRead - read the time from the clock chip */
+			if (kPMUStateRecievedCommand == PMUState) {
+				if (0 == PMU_BuffL) {
+					PMU_BuffA[0] = 0;
+					PMU_BuffA[1] = 0;
+					PMU_BuffA[2] = 0;
+					PMU_BuffA[3] = 0;
+					PmuStartSendResult(0, 4);
+				} else {
+					ReportAbnormalID(0x0E06, "Unknown kPMUtimeRead op");
+				}
+			}
+			break;
+		case 0x31:
+			/*
+				kPMUpramWrite - write the original 20 bytes of PRAM
+				(Portable only)
+			*/
+			if (kPMUStateRecievedCommand == PMUState) {
+				if (20 == PMU_BuffL) {
+					/* done */
+				} else {
+					ReportAbnormalID(0x0E07,
+						"Unknown kPMUpramWrite op");
+				}
+			} else if (kPMUStateRecievingBuffer == PMUState) {
+				if (20 == PMU_BuffL) {
+					if (0 == PMU_i) {
+						PMU_p = &PARAMRAM[16];
+						PMU_rem = 16;
+					} else if (16 == PMU_i) {
+						PMU_p = &PARAMRAM[8];
+						PMU_rem = 4;
+					} else {
+						ReportAbnormalID(0x0E08,
+							"Wrong PMU_i for kPMUpramWrite");
+					}
+				}
+			}
+			break;
+		case 0x39:
+			/*
+				kPMUpramRead - read the original 20 bytes of PRAM
+				(Portable only)
+			*/
+			if (kPMUStateRecievedCommand == PMUState) {
+				if (0 == PMU_BuffL) {
+					PmuStartSendResult(0, 20);
+				} else {
+					ReportAbnormalID(0x0E09, "Unknown kPMUpramRead op");
+				}
+			} else if (kPMUStateSendBuffer == PMUState) {
+#if 0
+				{
+					int i;
+
+					for (i = 0; i < PMU_BuffSz; ++i) {
+						PMU_BuffA[i] = 0;
+					}
+				}
+#endif
+				if (0 == PMU_i) {
+					PMU_p = &PARAMRAM[16];
+					PMU_rem = 16;
+				} else if (16 == PMU_i) {
+					PMU_p = &PARAMRAM[8];
+					PMU_rem = 4;
+				} else {
+					ReportAbnormalID(0x0E0A,
+						"Wrong PMU_i for kPMUpramRead");
+				}
+			}
+			break;
+		default:
+			if (kPMUStateRecievedCommand == PMUState) {
+				ReportAbnormalID(0x0E0B, "Unknown PMU op");
+#if dbglog_HAVE
+				dbglog_writeCStr("Unknown PMU op ");
+				dbglog_writeHex(PMU_CurCommand);
+				dbglog_writeReturn();
+				dbglog_writeCStr("PMU_BuffL = ");
+				dbglog_writeHex(PMU_BuffL);
+				dbglog_writeReturn();
+				if (PMU_BuffL <= PMU_BuffSz) {
+					int i;
+
+					for (i = 0; i < PMU_BuffL; ++i) {
+						dbglog_writeCStr("PMU_BuffA[");
+						dbglog_writeNum(i);
+						dbglog_writeCStr("] = ");
+						dbglog_writeHex(PMU_BuffA[i]);
+						dbglog_writeReturn();
+					}
+				}
+#endif
+			}
+			break;
+	}
+}
+
+LOCALPROC LocBuffSetUpNextChunk(void)
+{
+	PMU_p = PMU_BuffA;
+	PMU_rem = PMU_BuffL - PMU_i;
+	if (PMU_rem >= PMU_BuffSz) {
+		PMU_rem = PMU_BuffSz;
+	}
+}
+
+LOCALFUNC ui3r GetPMUbus(void)
+{
+	ui3r v;
+
+	v = VIA1_iA7;
+	v <<= 1;
+	v |= VIA1_iA6;
+	v <<= 1;
+	v |= VIA1_iA5;
+	v <<= 1;
+	v |= VIA1_iA4;
+	v <<= 1;
+	v |= VIA1_iA3;
+	v <<= 1;
+	v |= VIA1_iA2;
+	v <<= 1;
+	v |= VIA1_iA1;
+	v <<= 1;
+	v |= VIA1_iA0;
+
+	return v;
+}
+
+LOCALPROC SetPMUbus(ui3r v)
+{
+	VIA1_iA0 = v & 0x01;
+	v >>= 1;
+	VIA1_iA1 = v & 0x01;
+	v >>= 1;
+	VIA1_iA2 = v & 0x01;
+	v >>= 1;
+	VIA1_iA3 = v & 0x01;
+	v >>= 1;
+	VIA1_iA4 = v & 0x01;
+	v >>= 1;
+	VIA1_iA5 = v & 0x01;
+	v >>= 1;
+	VIA1_iA6 = v & 0x01;
+	v >>= 1;
+	VIA1_iA7 = v & 0x01;
+}
+
+LOCALVAR blnr PMU_Sending = falseblnr;
+
+LOCALPROC PmuCheckCommandCompletion(void)
+{
+	if (PMU_i == PMU_BuffL) {
+		PMUState = kPMUStateRecievedCommand;
+		PmuCheckCommandOp();
+		if ((PMU_CurCommand & 0x08) == 0) {
+			PMUState = kPMUStateReadyForCommand;
+			SetPMUbus(0xFF);
+		} else {
+			if (PMUState != kPMUStateSendLength) {
+				PmuStartSendResult(0xFF, 0);
+				PMUState = kPMUStateSendLength;
+			}
+			PMU_i = 0;
+			PMU_Sending = trueblnr;
+			ICT_add(kICT_PMU_Task,
+				20400UL * kCycleScale / 64 * kMyClockMult);
+		}
+	}
+}
+
+GLOBALPROC PmuToReady_ChangeNtfy(void)
+{
+	if (PMU_Sending) {
+		PMU_Sending = falseblnr;
+		ReportAbnormalID(0x0E0C,
+			"PmuToReady_ChangeNtfy while PMU_Sending");
+		PmuFromReady = 0;
+	}
+	switch (PMUState) {
+		case kPMUStateReadyForCommand:
+			if (! PmuToReady) {
+				PmuFromReady = 0;
+			} else {
+				PMU_CurCommand = GetPMUbus();
+				PMUState = kPMUStateRecievingLength;
+				PmuFromReady = 1;
+			}
+			break;
+		case kPMUStateRecievingLength:
+			if (! PmuToReady) {
+				PmuFromReady = 0;
+			} else {
+				PMU_BuffL = GetPMUbus();
+				PMU_i = 0;
+				PMU_rem = 0;
+				PMUState = kPMUStateRecievingBuffer;
+				PmuCheckCommandCompletion();
+				PmuFromReady = 1;
+			}
+			break;
+		case kPMUStateRecievingBuffer:
+			if (! PmuToReady) {
+				PmuFromReady = 0;
+			} else {
+				ui3r v = GetPMUbus();
+				if (0 == PMU_rem) {
+					PMU_p = nullpr;
+					PmuCheckCommandOp();
+					if (nullpr == PMU_p) {
+						/* default handler */
+						LocBuffSetUpNextChunk();
+					}
+				}
+				if (nullpr == PMU_p) {
+					/* mini vmac bug if ever happens */
+					ReportAbnormalID(0x0E0D,
+						"PMU_p null while kPMUStateRecievingBuffer");
+				}
+				*PMU_p++ = v;
+				--PMU_rem;
+				++PMU_i;
+				PmuCheckCommandCompletion();
+				PmuFromReady = 1;
+			}
+			break;
+		case kPMUStateSendLength:
+			if (! PmuToReady) {
+				/* receiving */
+				PmuFromReady = 1;
+			} else {
+				PMU_SendNext = PMU_BuffL;
+				PMUState = kPMUStateSendBuffer;
+				PMU_Sending = trueblnr;
+				ICT_add(kICT_PMU_Task,
+					20400UL * kCycleScale / 64 * kMyClockMult);
+			}
+			break;
+		case kPMUStateSendBuffer:
+			if (! PmuToReady) {
+				/* receiving */
+				PmuFromReady = 1;
+			} else {
+				if (PMU_i == PMU_BuffL) {
+					PMUState = kPMUStateReadyForCommand;
+					SetPMUbus(0xFF);
+				} else {
+					if (0 == PMU_rem) {
+						PMU_p = nullpr;
+						PmuCheckCommandOp();
+						if (nullpr == PMU_p) {
+							/* default handler */
+							LocBuffSetUpNextChunk();
+						}
+					}
+					PMU_SendNext = *PMU_p++;
+					--PMU_rem;
+					++PMU_i;
+					PMU_Sending = trueblnr;
+					ICT_add(kICT_PMU_Task,
+						20400UL * kCycleScale / 64 * kMyClockMult);
+				}
+			}
+			break;
+	}
+}
+
+GLOBALPROC PMU_DoTask(void)
+{
+	if (PMU_Sending) {
+		PMU_Sending = falseblnr;
+		SetPMUbus(PMU_SendNext);
+		PmuFromReady = 0;
+	}
+}
--- /dev/null
+++ b/src/PMUEMDEV.h
@@ -1,0 +1,24 @@
+/*
+	PMUEMDEV.h
+
+	Copyright (C) 2008 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef PMUEMDEV_H
+#error "header already included"
+#else
+#define PMUEMDEV_H
+#endif
+
+EXPORTPROC PmuToReady_ChangeNtfy(void);
+EXPORTPROC PMU_DoTask(void);
--- /dev/null
+++ b/src/PROGMAIN.c
@@ -1,0 +1,562 @@
+/*
+	PROGMAIN.c
+
+	Copyright (C) 2009 Bernd Schmidt, Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	PROGram MAIN.
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+
+#include "MYOSGLUE.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+#include "M68KITAB.h"
+#include "MINEM68K.h"
+#include "VIAEMDEV.h"
+#if EmVIA2
+#include "VIA2EMDV.h"
+#endif
+#include "IWMEMDEV.h"
+#include "SCCEMDEV.h"
+#if EmRTC
+#include "RTCEMDEV.h"
+#endif
+#include "ROMEMDEV.h"
+#include "SCSIEMDV.h"
+#include "SONYEMDV.h"
+#include "SCRNEMDV.h"
+#if EmVidCard
+#include "VIDEMDEV.h"
+#endif
+#if EmClassicKbrd
+#include "KBRDEMDV.h"
+#elif EmPMU
+#include "PMUEMDEV.h"
+#else
+#include "ADBEMDEV.h"
+#endif
+#if EmASC
+#include "ASCEMDEV.h"
+#else
+#if MySoundEnabled && (CurEmMd != kEmMd_PB100)
+#include "SNDEMDEV.h"
+#endif
+#endif
+#include "MOUSEMDV.h"
+#endif
+
+
+#include "PROGMAIN.h"
+
+/*
+	ReportAbnormalID unused 0x1002 - 0x10FF
+*/
+
+LOCALPROC EmulatedHardwareZap(void)
+{
+	Memory_Reset();
+	ICT_Zap();
+	IWM_Reset();
+	SCC_Reset();
+	SCSI_Reset();
+	VIA1_Zap();
+#if EmVIA2
+	VIA2_Zap();
+#endif
+	Sony_Reset();
+	Extn_Reset();
+	m68k_reset();
+}
+
+LOCALPROC DoMacReset(void)
+{
+	Sony_EjectAllDisks();
+	EmulatedHardwareZap();
+}
+
+LOCALPROC InterruptReset_Update(void)
+{
+	SetInterruptButton(falseblnr);
+		/*
+			in case has been set. so only stays set
+			for 60th of a second.
+		*/
+
+	if (WantMacInterrupt) {
+		SetInterruptButton(trueblnr);
+		WantMacInterrupt = falseblnr;
+	}
+	if (WantMacReset) {
+		DoMacReset();
+		WantMacReset = falseblnr;
+	}
+}
+
+LOCALPROC SubTickNotify(int SubTick)
+{
+#if 0
+	dbglog_writeCStr("ending sub tick ");
+	dbglog_writeNum(SubTick);
+	dbglog_writeReturn();
+#endif
+#if EmASC
+	ASC_SubTick(SubTick);
+#else
+#if MySoundEnabled && (CurEmMd != kEmMd_PB100)
+	MacSound_SubTick(SubTick);
+#else
+	UnusedParam(SubTick);
+#endif
+#endif
+}
+
+#define CyclesScaledPerTick (130240UL * kMyClockMult * kCycleScale)
+#define CyclesScaledPerSubTick (CyclesScaledPerTick / kNumSubTicks)
+
+LOCALVAR ui4r SubTickCounter;
+
+LOCALPROC SubTickTaskDo(void)
+{
+	SubTickNotify(SubTickCounter);
+	++SubTickCounter;
+	if (SubTickCounter < (kNumSubTicks - 1)) {
+		/*
+			final SubTick handled by SubTickTaskEnd,
+			since CyclesScaledPerSubTick * kNumSubTicks
+			might not equal CyclesScaledPerTick.
+		*/
+
+		ICT_add(kICT_SubTick, CyclesScaledPerSubTick);
+	}
+}
+
+LOCALPROC SubTickTaskStart(void)
+{
+	SubTickCounter = 0;
+	ICT_add(kICT_SubTick, CyclesScaledPerSubTick);
+}
+
+LOCALPROC SubTickTaskEnd(void)
+{
+	SubTickNotify(kNumSubTicks - 1);
+}
+
+LOCALPROC SixtiethSecondNotify(void)
+{
+#if dbglog_HAVE && 0
+	dbglog_WriteNote("begin new Sixtieth");
+#endif
+	Mouse_Update();
+	InterruptReset_Update();
+#if EmClassicKbrd
+	KeyBoard_Update();
+#endif
+#if EmADB
+	ADB_Update();
+#endif
+
+	Sixtieth_PulseNtfy(); /* Vertical Blanking Interrupt */
+	Sony_Update();
+
+#if EmLocalTalk
+	LocalTalkTick();
+#endif
+#if EmRTC
+	RTC_Interrupt();
+#endif
+#if EmVidCard
+	Vid_Update();
+#endif
+
+	SubTickTaskStart();
+}
+
+LOCALPROC SixtiethEndNotify(void)
+{
+	SubTickTaskEnd();
+	Mouse_EndTickNotify();
+	Screen_EndTickNotify();
+#if dbglog_HAVE && 0
+	dbglog_WriteNote("end Sixtieth");
+#endif
+}
+
+LOCALPROC ExtraTimeBeginNotify(void)
+{
+#if 0
+	dbglog_writeCStr("begin extra time");
+	dbglog_writeReturn();
+#endif
+	VIA1_ExtraTimeBegin();
+#if EmVIA2
+	VIA2_ExtraTimeBegin();
+#endif
+}
+
+LOCALPROC ExtraTimeEndNotify(void)
+{
+	VIA1_ExtraTimeEnd();
+#if EmVIA2
+	VIA2_ExtraTimeEnd();
+#endif
+#if 0
+	dbglog_writeCStr("end extra time");
+	dbglog_writeReturn();
+#endif
+}
+
+GLOBALPROC EmulationReserveAlloc(void)
+{
+	ReserveAllocOneBlock(&RAM,
+		kRAM_Size + RAMSafetyMarginFudge, 5, falseblnr);
+#if EmVidCard
+	ReserveAllocOneBlock(&VidROM, kVidROM_Size, 5, falseblnr);
+#endif
+#if IncludeVidMem
+	ReserveAllocOneBlock(&VidMem,
+		kVidMemRAM_Size + RAMSafetyMarginFudge, 5, trueblnr);
+#endif
+#if SmallGlobals
+	MINEM68K_ReserveAlloc();
+#endif
+}
+
+LOCALFUNC blnr InitEmulation(void)
+{
+#if EmRTC
+	if (RTC_Init())
+#endif
+	if (ROM_Init())
+#if EmVidCard
+	if (Vid_Init())
+#endif
+	if (AddrSpac_Init())
+	{
+		EmulatedHardwareZap();
+		return trueblnr;
+	}
+	return falseblnr;
+}
+
+LOCALPROC ICT_DoTask(int taskid)
+{
+	switch (taskid) {
+		case kICT_SubTick:
+			SubTickTaskDo();
+			break;
+#if EmClassicKbrd
+		case kICT_Kybd_ReceiveEndCommand:
+			DoKybd_ReceiveEndCommand();
+			break;
+		case kICT_Kybd_ReceiveCommand:
+			DoKybd_ReceiveCommand();
+			break;
+#endif
+#if EmADB
+		case kICT_ADB_NewState:
+			ADB_DoNewState();
+			break;
+#endif
+#if EmPMU
+		case kICT_PMU_Task:
+			PMU_DoTask();
+			break;
+#endif
+		case kICT_VIA1_Timer1Check:
+			VIA1_DoTimer1Check();
+			break;
+		case kICT_VIA1_Timer2Check:
+			VIA1_DoTimer2Check();
+			break;
+#if EmVIA2
+		case kICT_VIA2_Timer1Check:
+			VIA2_DoTimer1Check();
+			break;
+		case kICT_VIA2_Timer2Check:
+			VIA2_DoTimer2Check();
+			break;
+#endif
+		default:
+			ReportAbnormalID(0x1001, "unknown taskid in ICT_DoTask");
+			break;
+	}
+}
+
+LOCALPROC ICT_DoCurrentTasks(void)
+{
+	int i = 0;
+	uimr m = ICTactive;
+
+	while (0 != m) {
+		if (0 != (m & 1)) {
+			if (i >= kNumICTs) {
+				/* shouldn't happen */
+				ICTactive &= ((1 << kNumICTs) - 1);
+				m = 0;
+			} else if (ICTwhen[i] == NextiCount) {
+				ICTactive &= ~ (1 << i);
+#ifdef _VIA_Debug
+				fprintf(stderr, "doing task %d, %d\n", NextiCount, i);
+#endif
+				ICT_DoTask(i);
+
+				/*
+					A Task may set the time of
+					any task, including itself.
+					But it cannot set any task
+					to execute immediately, so
+					one pass is sufficient.
+				*/
+			}
+		}
+		++i;
+		m >>= 1;
+	}
+}
+
+LOCALFUNC ui5b ICT_DoGetNext(ui5b maxn)
+{
+	int i = 0;
+	uimr m = ICTactive;
+	ui5b v = maxn;
+
+	while (0 != m) {
+		if (0 != (m & 1)) {
+			if (i >= kNumICTs) {
+				/* shouldn't happen */
+				m = 0;
+			} else {
+				ui5b d = ICTwhen[i] - NextiCount;
+				/* at this point d must be > 0 */
+				if (d < v) {
+#ifdef _VIA_Debug
+					fprintf(stderr, "coming task %d, %d, %d\n",
+						NextiCount, i, d);
+#endif
+					v = d;
+				}
+			}
+		}
+		++i;
+		m >>= 1;
+	}
+
+	return v;
+}
+
+LOCALPROC m68k_go_nCycles_1(ui5b n)
+{
+	ui5b n2;
+	ui5b StopiCount = NextiCount + n;
+	do {
+		ICT_DoCurrentTasks();
+		n2 = ICT_DoGetNext(n);
+#if dbglog_HAVE && 0
+		dbglog_StartLine();
+		dbglog_writeCStr("before m68k_go_nCycles, NextiCount:");
+		dbglog_writeHex(NextiCount);
+		dbglog_writeCStr(", n2:");
+		dbglog_writeHex(n2);
+		dbglog_writeCStr(", n:");
+		dbglog_writeHex(n);
+		dbglog_writeReturn();
+#endif
+		NextiCount += n2;
+		m68k_go_nCycles(n2);
+		n = StopiCount - NextiCount;
+	} while (n != 0);
+}
+
+LOCALVAR ui5b ExtraSubTicksToDo = 0;
+
+LOCALPROC DoEmulateOneTick(void)
+{
+#if EnableAutoSlow
+	{
+		ui5r NewQuietTime = QuietTime + 1;
+
+		if (NewQuietTime > QuietTime) {
+			/* if not overflow */
+			QuietTime = NewQuietTime;
+		}
+	}
+#endif
+#if EnableAutoSlow
+	{
+		ui5r NewQuietSubTicks = QuietSubTicks + kNumSubTicks;
+
+		if (NewQuietSubTicks > QuietSubTicks) {
+			/* if not overflow */
+			QuietSubTicks = NewQuietSubTicks;
+		}
+	}
+#endif
+
+	SixtiethSecondNotify();
+
+	m68k_go_nCycles_1(CyclesScaledPerTick);
+
+	SixtiethEndNotify();
+
+	if ((ui3b) -1 == SpeedValue) {
+		ExtraSubTicksToDo = (ui5b) -1;
+	} else {
+		ui5b ExtraAdd = (kNumSubTicks << SpeedValue) - kNumSubTicks;
+		ui5b ExtraLimit = ExtraAdd << 3;
+
+		ExtraSubTicksToDo += ExtraAdd;
+		if (ExtraSubTicksToDo > ExtraLimit) {
+			ExtraSubTicksToDo = ExtraLimit;
+		}
+	}
+}
+
+LOCALFUNC blnr MoreSubTicksToDo(void)
+{
+	blnr v = falseblnr;
+
+	if (ExtraTimeNotOver() && (ExtraSubTicksToDo > 0)) {
+#if EnableAutoSlow
+		if ((QuietSubTicks >= 16384)
+			&& (QuietTime >= 34)
+			&& ! WantNotAutoSlow)
+		{
+			ExtraSubTicksToDo = 0;
+		} else
+#endif
+		{
+			v = trueblnr;
+		}
+	}
+
+	return v;
+}
+
+LOCALPROC DoEmulateExtraTime(void)
+{
+	/*
+		DoEmulateExtraTime is used for
+		anything over emulation speed
+		of 1x. It periodically calls
+		ExtraTimeNotOver and stops
+		when this returns false (or it
+		is finished with emulating the
+		extra time).
+	*/
+
+	if (MoreSubTicksToDo()) {
+		ExtraTimeBeginNotify();
+		do {
+#if EnableAutoSlow
+			{
+				ui5r NewQuietSubTicks = QuietSubTicks + 1;
+
+				if (NewQuietSubTicks > QuietSubTicks) {
+					/* if not overflow */
+					QuietSubTicks = NewQuietSubTicks;
+				}
+			}
+#endif
+			m68k_go_nCycles_1(CyclesScaledPerSubTick);
+			--ExtraSubTicksToDo;
+		} while (MoreSubTicksToDo());
+		ExtraTimeEndNotify();
+	}
+}
+
+LOCALVAR ui5b CurEmulatedTime = 0;
+	/*
+		The number of ticks that have been
+		emulated so far.
+
+		That is, the number of times
+		"DoEmulateOneTick" has been called.
+	*/
+
+LOCALPROC RunEmulatedTicksToTrueTime(void)
+{
+	/*
+		The general idea is to call DoEmulateOneTick
+		once per tick.
+
+		But if emulation is lagging, we'll try to
+		catch up by calling DoEmulateOneTick multiple
+		times, unless we're too far behind, in
+		which case we forget it.
+
+		If emulating one tick takes longer than
+		a tick we don't want to sit here
+		forever. So the maximum number of calls
+		to DoEmulateOneTick is determined at
+		the beginning, rather than just
+		calling DoEmulateOneTick until
+		CurEmulatedTime >= TrueEmulatedTime.
+	*/
+
+	si3b n = OnTrueTime - CurEmulatedTime;
+
+	if (n > 0) {
+		DoEmulateOneTick();
+		++CurEmulatedTime;
+
+		DoneWithDrawingForTick();
+
+		if (n > 8) {
+			/* emulation not fast enough */
+			n = 8;
+			CurEmulatedTime = OnTrueTime - n;
+		}
+
+		if (ExtraTimeNotOver() && (--n > 0)) {
+			/* lagging, catch up */
+
+			EmVideoDisable = trueblnr;
+
+			do {
+				DoEmulateOneTick();
+				++CurEmulatedTime;
+			} while (ExtraTimeNotOver()
+				&& (--n > 0));
+
+			EmVideoDisable = falseblnr;
+		}
+
+		EmLagTime = n;
+	}
+}
+
+LOCALPROC MainEventLoop(void)
+{
+	for (; ; ) {
+		WaitForNextTick();
+		if (ForceMacOff) {
+			return;
+		}
+
+		RunEmulatedTicksToTrueTime();
+
+		DoEmulateExtraTime();
+	}
+}
+
+GLOBALPROC ProgramMain(void)
+{
+	if (InitEmulation())
+	{
+		MainEventLoop();
+	}
+}
--- /dev/null
+++ b/src/PROGMAIN.h
@@ -1,0 +1,25 @@
+/*
+	PROGMAIN.h
+
+	Copyright (C) 2009 Philip Cummins, Richard F. Bannister,
+		Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef PROGMAIN_H
+#error "header already included"
+#else
+#define PROGMAIN_H
+#endif
+
+EXPORTPROC EmulationReserveAlloc(void);
+EXPORTPROC ProgramMain(void);
--- /dev/null
+++ b/src/ROMEMDEV.c
@@ -1,0 +1,332 @@
+/*
+	ROMEMDEV.c
+
+	Copyright (C) 2007 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Read Only Memory EMulated DEVice
+
+	Checks the header of the loaded ROM image, and then patches
+	the ROM image.
+
+	This code descended from "ROM.c" in vMac by Philip Cummins.
+
+	Support for "Twiggy" Mac by Mathew Hybler.
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+#include "MYOSGLUE.h"
+#include "ENDIANAC.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+#endif
+
+#include "ROMEMDEV.h"
+
+#define UseSonyPatch \
+	((CurEmMd <= kEmMd_Classic) || (CurEmMd == kEmMd_II) \
+		|| (CurEmMd == kEmMd_IIx))
+
+#ifndef UseLargeScreenHack
+#define UseLargeScreenHack 0
+#endif
+
+#if UseSonyPatch
+LOCALVAR const ui3b sony_driver[] = {
+/*
+	Replacement for .Sony driver
+	68k machine code, compiled from mydriver.a
+*/
+0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xEE, 0x00, 0x18, 0x00, 0x24, 0x00, 0x4A,
+0x00, 0x8A, 0x05, 0x2E, 0x53, 0x6F, 0x6E, 0x79,
+0x48, 0xE7, 0x00, 0xC0, 0x55, 0x4F, 0x3F, 0x3C,
+0x00, 0x01, 0x60, 0x30, 0x48, 0xE7, 0x00, 0xC0,
+0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x02, 0x41, 0xFA,
+0x01, 0x84, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F,
+0x5C, 0x4F, 0x30, 0x1F, 0x4C, 0xDF, 0x03, 0x00,
+0x0C, 0x68, 0x00, 0x01, 0x00, 0x1A, 0x66, 0x1E,
+0x4E, 0x75, 0x48, 0xE7, 0x00, 0xC0, 0x55, 0x4F,
+0x3F, 0x3C, 0x00, 0x03, 0x41, 0xFA, 0x01, 0x5E,
+0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F,
+0x30, 0x1F, 0x4C, 0xDF, 0x03, 0x00, 0x32, 0x28,
+0x00, 0x06, 0x08, 0x01, 0x00, 0x09, 0x67, 0x0C,
+0x4A, 0x40, 0x6F, 0x02, 0x42, 0x40, 0x31, 0x40,
+0x00, 0x10, 0x4E, 0x75, 0x4A, 0x40, 0x6F, 0x04,
+0x42, 0x40, 0x4E, 0x75, 0x2F, 0x38, 0x08, 0xFC,
+0x4E, 0x75, 0x48, 0xE7, 0x00, 0xC0, 0x55, 0x4F,
+0x3F, 0x3C, 0x00, 0x04, 0x41, 0xFA, 0x01, 0x1E,
+0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F,
+0x30, 0x1F, 0x4C, 0xDF, 0x03, 0x00, 0x4E, 0x75,
+0x48, 0xE7, 0xE0, 0xC0, 0x20, 0x2F, 0x00, 0x14,
+0x59, 0x4F, 0x2F, 0x00, 0x55, 0x4F, 0x3F, 0x3C,
+0x00, 0x08, 0x41, 0xFA, 0x00, 0xF8, 0x2F, 0x18,
+0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F, 0x32, 0x1F,
+0x58, 0x4F, 0x20, 0x1F, 0x4A, 0x41, 0x66, 0x06,
+0x30, 0x7C, 0x00, 0x07, 0xA0, 0x2F, 0x4C, 0xDF,
+0x03, 0x07, 0x58, 0x4F, 0x4E, 0x73, 0x21, 0x40,
+0x00, 0x06, 0x43, 0xF8, 0x03, 0x08, 0x4E, 0xF9,
+0x00, 0x40, 0x0B, 0x20, 0x4E, 0x75, 0x48, 0xE7,
+0x1F, 0x10, 0x48, 0xE7, 0x00, 0xC0, 0x5D, 0x4F,
+0x3F, 0x3C, 0x00, 0x05, 0x41, 0xFA, 0x00, 0xB6,
+0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F,
+0x30, 0x1F, 0x2E, 0x1F, 0x0C, 0x40, 0xFF, 0xCF,
+0x66, 0x06, 0x42, 0x40, 0x60, 0x00, 0x00, 0x8E,
+0x4A, 0x40, 0x66, 0x00, 0x00, 0x88, 0x20, 0x07,
+0xA7, 0x1E, 0x26, 0x48, 0x20, 0x0B, 0x67, 0x00,
+0x00, 0x86, 0x9E, 0xFC, 0x00, 0x10, 0x2F, 0x0B,
+0x2F, 0x07, 0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x06,
+0x41, 0xFA, 0x00, 0x7A, 0x2F, 0x18, 0x20, 0x50,
+0x20, 0x8F, 0x5C, 0x4F, 0x30, 0x1F, 0x50, 0x4F,
+0x2E, 0x1F, 0x76, 0x00, 0x36, 0x1F, 0x38, 0x1F,
+0x3C, 0x1F, 0x3A, 0x1F, 0x26, 0x5F, 0x4A, 0x40,
+0x66, 0x4A, 0x20, 0x0B, 0x67, 0x0E, 0x41, 0xFA,
+0xFF, 0x8C, 0x27, 0x48, 0x00, 0x06, 0x20, 0x4B,
+0xA0, 0x58, 0x60, 0x1A, 0x41, 0xFA, 0xFF, 0x70,
+0x30, 0x3C, 0xA0, 0x4E, 0xA0, 0x47, 0x60, 0x0E,
+0x20, 0x47, 0x30, 0x06, 0x48, 0x40, 0x30, 0x05,
+0xA0, 0x4E, 0xDE, 0x83, 0x52, 0x46, 0x51, 0xCC,
+0xFF, 0xF0, 0x48, 0x7A, 0xFF, 0x1C, 0x55, 0x4F,
+0x3F, 0x3C, 0x00, 0x07, 0x41, 0xFA, 0x00, 0x1E,
+0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F,
+0x30, 0x1F, 0x58, 0x4F, 0x4C, 0xDF, 0x03, 0x00,
+0x4C, 0xDF, 0x08, 0xF8, 0x4E, 0x75, 0x30, 0x3C,
+0xFF, 0xFF, 0x60, 0xF0
+};
+#endif
+
+#if UseSonyPatch
+LOCALVAR const ui3b my_disk_icon[] = {
+	0x7F, 0xFF, 0xFF, 0xF0,
+	0x81, 0x00, 0x01, 0x08,
+	0x81, 0x00, 0x71, 0x04,
+	0x81, 0x00, 0x89, 0x02,
+	0x81, 0x00, 0x89, 0x01,
+	0x81, 0x00, 0x89, 0x01,
+	0x81, 0x00, 0x89, 0x01,
+	0x81, 0x00, 0x89, 0x01,
+	0x81, 0x00, 0x89, 0x01,
+	0x81, 0x00, 0x71, 0x01,
+	0x81, 0x00, 0x01, 0x01,
+	0x80, 0xFF, 0xFE, 0x01,
+	0x80, 0x00, 0x00, 0x01,
+	0x80, 0x00, 0x00, 0x01,
+	0x80, 0x00, 0x00, 0x01,
+	0x80, 0x00, 0x00, 0x01,
+	0x83, 0xFF, 0xFF, 0xC1,
+	0x84, 0x00, 0x00, 0x21,
+	0x84, 0x00, 0x00, 0x21,
+	0x84, 0x00, 0x00, 0x21,
+	0x84, 0x00, 0x00, 0x21,
+	0x84, 0x00, 0x00, 0x21,
+	0x84, 0x06, 0x30, 0x21,
+	0x84, 0x06, 0x60, 0x21,
+	0x84, 0x06, 0xC0, 0x21,
+	0x84, 0x07, 0x80, 0x21,
+	0x84, 0x07, 0x00, 0x21,
+	0x84, 0x06, 0x00, 0x21,
+	0x84, 0x00, 0x00, 0x21,
+	0x84, 0x00, 0x00, 0x21,
+	0x84, 0x00, 0x00, 0x21,
+	0x7F, 0xFF, 0xFF, 0xFE,
+
+	/* mask */
+
+	0x3F, 0xFF, 0xFF, 0xF0,
+	0x7F, 0xFF, 0xFF, 0xF0,
+	0xFF, 0xFF, 0xFF, 0xFC,
+	0xFF, 0xFF, 0xFF, 0xFC,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF,
+	0x7F, 0xFF, 0xFF, 0xFC,
+	0x3F, 0xFF, 0xFF, 0xFC,
+
+	/* empty pascal string */
+	0x00, 0x00,
+};
+#endif
+
+#if CurEmMd <= kEmMd_Twig43
+#define Sony_DriverBase 0x1836
+#elif CurEmMd <= kEmMd_Twiggy
+#define Sony_DriverBase 0x16E4
+#elif CurEmMd <= kEmMd_128K
+#define Sony_DriverBase 0x1690
+#elif CurEmMd <= kEmMd_Plus
+#define Sony_DriverBase 0x17D30
+#elif CurEmMd <= kEmMd_Classic
+#define Sony_DriverBase 0x34680
+#elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+#define Sony_DriverBase 0x2D72C
+#endif
+
+#define kVidMem_Base 0x00540000
+
+#if UseSonyPatch
+LOCALPROC Sony_Install(void)
+{
+	ui3p pto = Sony_DriverBase + ROM;
+
+	MyMoveBytes((anyp)sony_driver, (anyp)pto, sizeof(sony_driver));
+#if CurEmMd <= kEmMd_Twiggy
+	do_put_mem_long(pto + 0x14, 0x4469736B);
+		/* 'Disk' instead of 'Sony' */
+#if CurEmMd <= kEmMd_Twig43
+	do_put_mem_word(pto + 0xEA, 0x0C8A);
+#else
+	do_put_mem_word(pto + 0xEA, 0x0B74);
+#endif
+#endif
+
+	pto += sizeof(sony_driver);
+
+	do_put_mem_word(pto, kcom_callcheck);
+	pto += 2;
+	do_put_mem_word(pto, kExtnSony);
+	pto += 2;
+	do_put_mem_long(pto, kExtn_Block_Base); /* pokeaddr */
+	pto += 4;
+
+	my_disk_icon_addr = (pto - ROM) + kROM_Base;
+	MyMoveBytes((anyp)my_disk_icon, (anyp)pto, sizeof(my_disk_icon));
+	pto += sizeof(my_disk_icon);
+
+#if UseLargeScreenHack
+	{
+		ui3p patchp = pto;
+
+#include "SCRNHACK.h"
+	}
+#endif
+
+	(void) pto; /* avoid warning about unused */
+}
+#endif
+
+#ifndef DisableRomCheck
+#define DisableRomCheck 1
+#endif
+
+#ifndef DisableRamTest
+#define DisableRamTest 1
+#endif
+
+#ifdef CurAltHappyMac
+#include "HPMCHACK.h"
+#endif
+
+#ifdef ln2mtb
+LOCALPROC ROMscrambleForMTB(void)
+{
+	si5r j;
+	ui3p p = ROM;
+	ui3p p2 = ROM + (1 << ln2mtb);
+
+	for (j = kROM_Size / (1 << ln2mtb) / 2; --j >= 0; ) {
+		si5r i;
+
+		for (i = (1 << ln2mtb); --i >= 0; ) {
+			ui3b t0 = *p;
+			ui3b t1 = *p2;
+			*p++ = t1;
+			*p2++ = t0;
+		}
+
+		p += (1 << ln2mtb);
+		p2 += (1 << ln2mtb);
+	}
+}
+#endif
+
+GLOBALFUNC blnr ROM_Init(void)
+{
+#if DisableRomCheck
+
+/* skip the rom checksum */
+#if CurEmMd <= kEmMd_Twig43
+	/* no checksum code */
+#elif CurEmMd <= kEmMd_Twiggy
+	do_put_mem_word(0x136 + ROM, 0x6004);
+#elif CurEmMd <= kEmMd_128K
+	do_put_mem_word(0xE2 + ROM, 0x6004);
+#elif CurEmMd <= kEmMd_Plus
+	do_put_mem_word(0xD7A + ROM, 0x6022);
+#elif CurEmMd <= kEmMd_Classic
+	do_put_mem_word(0x1C68 + ROM, 0x6008);
+#elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+	do_put_mem_word(0x2AB0 + ROM, 0x6008);
+#endif
+
+#endif /* DisableRomCheck */
+
+
+#if DisableRamTest
+
+#if CurEmMd <= kEmMd_128K
+#elif CurEmMd <= kEmMd_Plus
+	do_put_mem_word(3752 + ROM, 0x4E71);
+		/* shorten the ram check read */
+	do_put_mem_word(3728 + ROM, 0x4E71);
+		/* shorten the ram check write */
+#elif CurEmMd <= kEmMd_Classic
+	do_put_mem_word(134 + ROM, 0x6002);
+	do_put_mem_word(286 + ROM, 0x6002);
+#elif (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+	do_put_mem_word(0xEE + ROM, 0x6002);
+	do_put_mem_word(0x1AA + ROM, 0x6002);
+#endif
+
+#endif /* DisableRamTest */
+
+#ifdef CurAltHappyMac
+	PatchHappyMac();
+#endif
+
+	/* do_put_mem_word(862 + ROM, 0x4E71); */ /* shorten set memory */
+
+#if UseSonyPatch
+	Sony_Install();
+#endif
+
+#ifdef ln2mtb
+	ROMscrambleForMTB();
+#endif
+
+	return trueblnr;
+}
--- /dev/null
+++ b/src/ROMEMDEV.h
@@ -1,0 +1,23 @@
+/*
+	ROMEMDEV.h
+
+	Copyright (C) 2003 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef ROMEMDEV_H
+#error "header already included"
+#else
+#define ROMEMDEV_H
+#endif
+
+EXPORTFUNC blnr ROM_Init(void);
--- /dev/null
+++ b/src/RTCEMDEV.c
@@ -1,0 +1,509 @@
+/*
+	RTCEMDEV.c
+
+	Copyright (C) 2003 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Real Time Clock EMulated DEVice
+
+	Emulates the RTC found in the Mac Plus.
+
+	This code adapted from "RTC.c" in vMac by Philip Cummins.
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+#include "MYOSGLUE.h"
+#include "ENDIANAC.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+#endif
+
+/* define _RTC_Debug */
+#ifdef _RTC_Debug
+#include <stdio.h>
+#endif
+
+#include "RTCEMDEV.h"
+
+#define HaveXPRAM (CurEmMd >= kEmMd_Plus)
+
+/*
+	ReportAbnormalID unused 0x0805 - 0x08FF
+*/
+
+#if HaveXPRAM
+#define PARAMRAMSize 256
+#else
+#define PARAMRAMSize 20
+#endif
+
+#if HaveXPRAM
+#define Group1Base 0x10
+#define Group2Base 0x08
+#else
+#define Group1Base 0x00
+#define Group2Base 0x10
+#endif
+
+typedef struct
+{
+	/* RTC VIA Flags */
+	ui3b WrProtect;
+	ui3b DataOut;
+	ui3b DataNextOut;
+
+	/* RTC Data */
+	ui3b ShiftData;
+	ui3b Counter;
+	ui3b Mode;
+	ui3b SavedCmd;
+#if HaveXPRAM
+	ui3b Sector;
+#endif
+
+	/* RTC Registers */
+	ui3b Seconds_1[4];
+	ui3b PARAMRAM[PARAMRAMSize];
+} RTC_Ty;
+
+LOCALVAR RTC_Ty RTC;
+
+/* RTC Functions */
+
+LOCALVAR ui5b LastRealDate;
+
+#ifndef RTCinitPRAM
+#define RTCinitPRAM 1
+#endif
+
+#ifndef TrackSpeed /* in 0..4 */
+#define TrackSpeed 0
+#endif
+
+#ifndef AlarmOn /* in 0..1 */
+#define AlarmOn 0
+#endif
+
+#ifndef DiskCacheSz /* in 1,2,3,4,6,8,12 */
+/* actual cache size is DiskCacheSz * 32k */
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+#define DiskCacheSz 1
+#else
+#define DiskCacheSz 4
+#endif
+#endif
+
+#ifndef StartUpDisk /* in 0..1 */
+#define StartUpDisk 0
+#endif
+
+#ifndef DiskCacheOn /* in 0..1 */
+#define DiskCacheOn 0
+#endif
+
+#ifndef MouseScalingOn /* in 0..1 */
+#define MouseScalingOn 0
+#endif
+
+#define prb_fontHi 0
+#define prb_fontLo 2
+#define prb_kbdPrintHi (AutoKeyRate + (AutoKeyThresh << 4))
+#define prb_kbdPrintLo 0
+#define prb_volClickHi (SpeakerVol + (TrackSpeed << 3) + (AlarmOn << 7))
+#define prb_volClickLo (CaretBlinkTime + (DoubleClickTime << 4))
+#define prb_miscHi DiskCacheSz
+#define prb_miscLo \
+	((MenuBlink << 2) + (StartUpDisk << 4) \
+		+ (DiskCacheOn << 5) + (MouseScalingOn << 6))
+
+#if dbglog_HAVE && 0
+EXPORTPROC DumpRTC(void);
+
+GLOBALPROC DumpRTC(void)
+{
+	int Counter;
+
+	dbglog_writeln("RTC Parameter RAM");
+	for (Counter = 0; Counter < PARAMRAMSize; Counter++) {
+		dbglog_writeNum(Counter);
+		dbglog_writeCStr(", ");
+		dbglog_writeHex(RTC.PARAMRAM[Counter]);
+		dbglog_writeReturn();
+	}
+}
+#endif
+
+GLOBALFUNC blnr RTC_Init(void)
+{
+	int Counter;
+	ui5b secs;
+
+	RTC.Mode = RTC.ShiftData = RTC.Counter = 0;
+	RTC.DataOut = RTC.DataNextOut = 0;
+	RTC.WrProtect = falseblnr;
+
+	secs = CurMacDateInSeconds;
+	LastRealDate = secs;
+
+	RTC.Seconds_1[0] = secs & 0xFF;
+	RTC.Seconds_1[1] = (secs & 0xFF00) >> 8;
+	RTC.Seconds_1[2] = (secs & 0xFF0000) >> 16;
+	RTC.Seconds_1[3] = (secs & 0xFF000000) >> 24;
+
+	for (Counter = 0; Counter < PARAMRAMSize; Counter++) {
+		RTC.PARAMRAM[Counter] = 0;
+	}
+
+#if RTCinitPRAM
+	RTC.PARAMRAM[0 + Group1Base] = 168; /* valid */
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+	RTC.PARAMRAM[2 + Group1Base] = 1;
+		/* node id hint for printer port (AppleTalk) */
+#endif
+	RTC.PARAMRAM[3 + Group1Base] = 34;
+		/*
+			serial ports config bits: 4-7 A, 0-3 B
+				useFree   0 Use undefined
+				useATalk  1 AppleTalk
+				useAsync  2 Async
+				useExtClk 3 externally clocked
+		*/
+
+	RTC.PARAMRAM[4 + Group1Base] = 204; /* portA, high */
+	RTC.PARAMRAM[5 + Group1Base] = 10; /* portA, low */
+	RTC.PARAMRAM[6 + Group1Base] = 204; /* portB, high */
+	RTC.PARAMRAM[7 + Group1Base] = 10; /* portB, low */
+	RTC.PARAMRAM[13 + Group1Base] = prb_fontLo;
+	RTC.PARAMRAM[14 + Group1Base] = prb_kbdPrintHi;
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+	RTC.PARAMRAM[15 + Group1Base] = 1;
+		/*
+			printer, if any, connected to modem port
+			because printer port used for appletalk.
+		*/
+#endif
+
+#if prb_volClickHi != 0
+	RTC.PARAMRAM[0 + Group2Base] = prb_volClickHi;
+#endif
+	RTC.PARAMRAM[1 + Group2Base] = prb_volClickLo;
+	RTC.PARAMRAM[2 + Group2Base] = prb_miscHi;
+	RTC.PARAMRAM[3 + Group2Base] = prb_miscLo
+#if 0 != vMacScreenDepth
+		| 0x80
+#endif
+		;
+
+#if HaveXPRAM /* extended parameter ram initialized */
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+	RTC.PARAMRAM[12] = 0x4e;
+	RTC.PARAMRAM[13] = 0x75;
+	RTC.PARAMRAM[14] = 0x4d;
+	RTC.PARAMRAM[15] = 0x63;
+#else
+	RTC.PARAMRAM[12] = 0x42;
+	RTC.PARAMRAM[13] = 0x75;
+	RTC.PARAMRAM[14] = 0x67;
+	RTC.PARAMRAM[15] = 0x73;
+#endif
+#endif
+
+#if ((CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_Classic)) \
+	|| (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+
+	RTC.PARAMRAM[0x01] = 0x80;
+	RTC.PARAMRAM[0x02] = 0x4F;
+#endif
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+	RTC.PARAMRAM[0x03] = 0x48;
+
+	/* video board id */
+	RTC.PARAMRAM[0x46] = /* 0x42 */ 0x76; /* 'v' */
+	RTC.PARAMRAM[0x47] = /* 0x32 */ 0x4D; /* 'M' */
+	/* mode */
+#if (0 == vMacScreenDepth) || (vMacScreenDepth >= 4)
+	RTC.PARAMRAM[0x48] = 0x80;
+#else
+	RTC.PARAMRAM[0x48] = 0x81;
+		/* 0x81 doesn't quite work right at boot */
+			/* no, it seems to work now (?) */
+			/* but only if depth <= 3 */
+#endif
+#endif
+
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+	RTC.PARAMRAM[0x77] = 0x01;
+#endif
+
+#if ((CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_Classic)) \
+	|| (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+
+	/* start up disk (encoded how?) */
+	RTC.PARAMRAM[0x78] = 0x00;
+	RTC.PARAMRAM[0x79] = 0x01;
+	RTC.PARAMRAM[0x7A] = 0xFF;
+	RTC.PARAMRAM[0x7B] = 0xFE;
+#endif
+
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+	RTC.PARAMRAM[0x80] = 0x09;
+	RTC.PARAMRAM[0x81] = 0x80;
+#endif
+
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+
+#define pr_HilColRedHi (pr_HilColRed >> 8)
+#if 0 != pr_HilColRedHi
+	RTC.PARAMRAM[0x82] = pr_HilColRedHi;
+#endif
+#define pr_HilColRedLo (pr_HilColRed & 0xFF)
+#if 0 != pr_HilColRedLo
+	RTC.PARAMRAM[0x83] = pr_HilColRedLo;
+#endif
+
+#define pr_HilColGreenHi (pr_HilColGreen >> 8)
+#if 0 != pr_HilColGreenHi
+	RTC.PARAMRAM[0x84] = pr_HilColGreenHi;
+#endif
+#define pr_HilColGreenLo (pr_HilColGreen & 0xFF)
+#if 0 != pr_HilColGreenLo
+	RTC.PARAMRAM[0x85] = pr_HilColGreenLo;
+#endif
+
+#define pr_HilColBlueHi (pr_HilColBlue >> 8)
+#if 0 != pr_HilColBlueHi
+	RTC.PARAMRAM[0x86] = pr_HilColBlueHi;
+#endif
+#define pr_HilColBlueLo (pr_HilColBlue & 0xFF)
+#if 0 != pr_HilColBlueLo
+	RTC.PARAMRAM[0x87] = pr_HilColBlueLo;
+#endif
+
+#endif /* (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx) */
+
+#if HaveXPRAM /* extended parameter ram initialized */
+	do_put_mem_long(&RTC.PARAMRAM[0xE4], CurMacLatitude);
+	do_put_mem_long(&RTC.PARAMRAM[0xE8], CurMacLongitude);
+	do_put_mem_long(&RTC.PARAMRAM[0xEC], CurMacDelta);
+#endif
+
+#endif /* RTCinitPRAM */
+
+	return trueblnr;
+}
+
+#ifdef RTC_OneSecond_PulseNtfy
+IMPORTPROC RTC_OneSecond_PulseNtfy(void);
+#endif
+
+GLOBALPROC RTC_Interrupt(void)
+{
+	ui5b Seconds = 0;
+	ui5b NewRealDate = CurMacDateInSeconds;
+	ui5b DateDelta = NewRealDate - LastRealDate;
+
+	if (DateDelta != 0) {
+		Seconds = (RTC.Seconds_1[3] << 24) + (RTC.Seconds_1[2] << 16)
+			+ (RTC.Seconds_1[1] << 8) + RTC.Seconds_1[0];
+		Seconds += DateDelta;
+		RTC.Seconds_1[0] = Seconds & 0xFF;
+		RTC.Seconds_1[1] = (Seconds & 0xFF00) >> 8;
+		RTC.Seconds_1[2] = (Seconds & 0xFF0000) >> 16;
+		RTC.Seconds_1[3] = (Seconds & 0xFF000000) >> 24;
+
+		LastRealDate = NewRealDate;
+
+#ifdef RTC_OneSecond_PulseNtfy
+		RTC_OneSecond_PulseNtfy();
+#endif
+	}
+}
+
+LOCALFUNC ui3b RTC_Access_PRAM_Reg(ui3b Data, blnr WriteReg, ui3b t)
+{
+	if (WriteReg) {
+		if (! RTC.WrProtect) {
+			RTC.PARAMRAM[t] = Data;
+#ifdef _RTC_Debug
+			printf("Writing Address %2x, Data %2x\n", t, Data);
+#endif
+		}
+	} else {
+		Data = RTC.PARAMRAM[t];
+	}
+	return Data;
+}
+
+LOCALFUNC ui3b RTC_Access_Reg(ui3b Data, blnr WriteReg, ui3b TheCmd)
+{
+	ui3b t = (TheCmd & 0x7C) >> 2;
+	if (t < 8) {
+		if (WriteReg) {
+			if (! RTC.WrProtect) {
+				RTC.Seconds_1[t & 0x03] = Data;
+			}
+		} else {
+			Data = RTC.Seconds_1[t & 0x03];
+		}
+	} else if (t < 12) {
+		Data = RTC_Access_PRAM_Reg(Data, WriteReg,
+			(t & 0x03) + Group2Base);
+	} else if (t < 16) {
+		if (WriteReg) {
+			switch (t) {
+				case 12 :
+					break; /* Test Write, do nothing */
+				case 13 :
+					RTC.WrProtect = (Data & 0x80) != 0;
+					break; /* Write_Protect Register */
+				default :
+					ReportAbnormalID(0x0801, "Write RTC Reg unknown");
+					break;
+			}
+		} else {
+			ReportAbnormalID(0x0802, "Read RTC Reg unknown");
+		}
+	} else {
+		Data = RTC_Access_PRAM_Reg(Data, WriteReg,
+			(t & 0x0F) + Group1Base);
+	}
+	return Data;
+}
+
+LOCALPROC RTC_DoCmd(void)
+{
+	switch (RTC.Mode) {
+		case 0: /* This Byte is a RTC Command */
+#if HaveXPRAM
+			if ((RTC.ShiftData & 0x78) == 0x38) { /* Extended Command */
+				RTC.SavedCmd = RTC.ShiftData;
+				RTC.Mode = 2;
+#ifdef _RTC_Debug
+				printf("Extended command %2x\n", RTC.ShiftData);
+#endif
+			} else
+#endif
+			{
+				if ((RTC.ShiftData & 0x80) != 0x00) { /* Read Command */
+					RTC.ShiftData =
+						RTC_Access_Reg(0, falseblnr, RTC.ShiftData);
+					RTC.DataNextOut = 1;
+				} else { /* Write Command */
+					RTC.SavedCmd = RTC.ShiftData;
+					RTC.Mode = 1;
+				}
+			}
+			break;
+		case 1: /* This Byte is data for RTC Write */
+			(void) RTC_Access_Reg(RTC.ShiftData,
+				trueblnr, RTC.SavedCmd);
+			RTC.Mode = 0;
+			break;
+#if HaveXPRAM
+		case 2: /* This Byte is rest of Extended RTC command address */
+#ifdef _RTC_Debug
+			printf("Mode 2 %2x\n", RTC.ShiftData);
+#endif
+			RTC.Sector = ((RTC.SavedCmd & 0x07) << 5)
+				| ((RTC.ShiftData & 0x7C) >> 2);
+			if ((RTC.SavedCmd & 0x80) != 0x00) { /* Read Command */
+				RTC.ShiftData = RTC.PARAMRAM[RTC.Sector];
+				RTC.DataNextOut = 1;
+				RTC.Mode = 0;
+#ifdef _RTC_Debug
+				printf("Reading X Address %2x, Data  %2x\n",
+					RTC.Sector, RTC.ShiftData);
+#endif
+			} else {
+				RTC.Mode = 3;
+#ifdef _RTC_Debug
+				printf("Writing X Address %2x\n", RTC.Sector);
+#endif
+			}
+			break;
+		case 3: /* This Byte is data for an Extended RTC Write */
+			(void) RTC_Access_PRAM_Reg(RTC.ShiftData,
+				trueblnr, RTC.Sector);
+			RTC.Mode = 0;
+			break;
+#endif
+	}
+}
+
+GLOBALPROC RTCunEnabled_ChangeNtfy(void)
+{
+	if (RTCunEnabled) {
+		/* abort anything going on */
+		if (RTC.Counter != 0) {
+#ifdef _RTC_Debug
+			printf("aborting, %2x\n", RTC.Counter);
+#endif
+			ReportAbnormalID(0x0803, "RTC aborting");
+		}
+		RTC.Mode = 0;
+		RTC.DataOut = 0;
+		RTC.DataNextOut = 0;
+		RTC.ShiftData = 0;
+		RTC.Counter = 0;
+	}
+}
+
+GLOBALPROC RTCclock_ChangeNtfy(void)
+{
+	if (! RTCunEnabled) {
+		if (RTCclock) {
+			RTC.DataOut = RTC.DataNextOut;
+			RTC.Counter = (RTC.Counter - 1) & 0x07;
+			if (RTC.DataOut) {
+				RTCdataLine = ((RTC.ShiftData >> RTC.Counter) & 0x01);
+				/*
+					should notify VIA if changed, so can check
+					data direction
+				*/
+				if (RTC.Counter == 0) {
+					RTC.DataNextOut = 0;
+				}
+			} else {
+				RTC.ShiftData = (RTC.ShiftData << 1) | RTCdataLine;
+				if (RTC.Counter == 0) {
+					RTC_DoCmd();
+				}
+			}
+		}
+	}
+}
+
+GLOBALPROC RTCdataLine_ChangeNtfy(void)
+{
+#if dbglog_HAVE
+	if (RTC.DataOut) {
+		if (! RTC.DataNextOut) {
+			/*
+				ignore. The ROM doesn't read from the RTC the
+				way described in the Hardware Reference.
+				It reads the data after setting the clock to
+				one instead of before, and then immediately
+				changes the VIA direction. So the RTC
+				has no way of knowing to stop driving the
+				data line, which certainly can't really be
+				correct.
+			*/
+		} else {
+			ReportAbnormalID(0x0804,
+				"write RTC Data unexpected direction");
+		}
+	}
+#endif
+}
--- /dev/null
+++ b/src/RTCEMDEV.h
@@ -1,0 +1,28 @@
+/*
+	RTCEMDEV.h
+
+	Copyright (C) 2003 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef RTCEMDEV_H
+#error "header already included"
+#else
+#define RTCEMDEV_H
+#endif
+
+EXPORTFUNC blnr RTC_Init(void);
+EXPORTPROC RTC_Interrupt(void);
+
+EXPORTPROC RTCunEnabled_ChangeNtfy(void);
+EXPORTPROC RTCclock_ChangeNtfy(void);
+EXPORTPROC RTCdataLine_ChangeNtfy(void);
--- /dev/null
+++ b/src/SCCEMDEV.c
@@ -1,0 +1,2801 @@
+/*
+	SCCEMDEV.c
+
+	Copyright (C) 2012 Philip Cummins, Weston Pawlowski,
+		Michael Fort, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Serial Communications Controller EMulated DEVice
+
+	additions for LocalTalk networking support
+		Copyright 2011-2012, Michael Fort
+		enabled with "EmLocalTalk"
+
+	-- original description: --
+
+	Emulates the Z8530 SCC found in the Mac Plus.
+		But only the minimum amount needed to emulate
+		normal operation in a Mac Plus with nothing
+		connected to the serial ports.
+		(and not even that much is complete yet)
+
+	This code adapted from "SCC.c" in vMac by Philip Cummins.
+	With additional code by Weston Pawlowski from the Windows
+	port of vMac.
+
+	Further information was found in the
+	"Zilog SCC/ESCC User's Manual".
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+
+#include "MYOSGLUE.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+#endif
+
+#include "SCCEMDEV.h"
+
+/*
+	ReportAbnormalID unused 0x0721, 0x0722, 0x074D - 0x07FF
+*/
+
+#define SCC_dolog (dbglog_HAVE && 0)
+#define SCC_TrackMore 0
+
+/* Just to make things a little easier */
+#define Bit0 1
+#define Bit1 2
+#define Bit2 4
+#define Bit3 8
+#define Bit4 16
+#define Bit5 32
+#define Bit6 64
+#define Bit7 128
+
+/* SCC Interrupts */
+#define SCC_A_Rx       8 /* Rx Char Available */
+#define SCC_A_Rx_Spec  7 /* Rx Special Condition */
+#define SCC_A_Tx_Empty 6 /* Tx Buffer Empty */
+#define SCC_A_Ext      5 /* External/Status Change */
+#define SCC_B_Rx       4 /* Rx Char Available */
+#define SCC_B_Rx_Spec  3 /* Rx Special Condition */
+#define SCC_B_Tx_Empty 2 /* Tx Buffer Empty */
+#define SCC_B_Ext      1 /* External/Status Change */
+
+typedef struct {
+	blnr TxEnable;
+	blnr RxEnable;
+	blnr TxIE; /* Transmit Interrupt Enable */
+	blnr TxUnderrun;
+	blnr SyncHunt;
+	blnr TxIP; /* Transmit Interrupt Pending */
+#if EmLocalTalk
+	ui3r RxBuff;
+#endif
+#if EmLocalTalk
+	/* otherwise TxBufferEmpty always true */
+	/*
+		though should behave as went false
+		for an instant when write to transmit buffer
+	*/
+	blnr TxBufferEmpty;
+#endif
+#if EmLocalTalk || SCC_TrackMore
+	blnr ExtIE;
+#endif
+#if SCC_TrackMore
+	blnr WaitRqstEnbl;
+#endif
+#if SCC_TrackMore
+	blnr WaitRqstSlct;
+#endif
+#if SCC_TrackMore
+	blnr WaitRqstRT;
+#endif
+#if SCC_TrackMore
+	blnr PrtySpclCond;
+#endif
+#if SCC_TrackMore
+	blnr PrtyEnable;
+#endif
+#if SCC_TrackMore
+	blnr PrtyEven;
+#endif
+#if SCC_TrackMore
+	blnr RxCRCEnbl;
+#endif
+#if SCC_TrackMore
+	blnr TxCRCEnbl;
+#endif
+#if SCC_TrackMore
+	blnr RTSctrl;
+#endif
+#if SCC_TrackMore
+	blnr SndBrkCtrl;
+#endif
+#if SCC_TrackMore
+	blnr DTRctrl;
+#endif
+#if EmLocalTalk || SCC_TrackMore
+	blnr AddrSrchMd;
+#endif
+#if SCC_TrackMore
+	blnr SyncChrLdInhb;
+#endif
+#if SCC_TrackMore
+	ui3r ClockRate;
+#endif
+#if SCC_TrackMore
+	ui3r DataEncoding;
+#endif
+#if SCC_TrackMore
+	ui3r TRxCsrc;
+#endif
+#if SCC_TrackMore
+	ui3r TClkSlct;
+#endif
+#if SCC_TrackMore
+	ui3r RClkSlct;
+#endif
+#if SCC_TrackMore
+	ui3r RBitsPerChar;
+#endif
+#if SCC_TrackMore
+	ui3r TBitsPerChar;
+#endif
+#if EmLocalTalk || SCC_TrackMore
+	ui3r RxIntMode;
+#endif
+#if EmLocalTalk || SCC_TrackMore
+	blnr FirstChar;
+#endif
+#if EmLocalTalk || SCC_TrackMore
+	ui3r SyncMode;
+#endif
+#if SCC_TrackMore
+	ui3r StopBits;
+#endif
+#if 0 /* AllSent always true */
+	blnr AllSent;
+#endif
+#if 0 /* CTS always false */
+	blnr CTS; /* input pin, unattached, so false? */
+#endif
+#if 0 /* DCD always false */
+	blnr DCD; /* Data Carrier Detect */
+		/*
+			input pin for mouse interrupts. but since
+			not emulating mouse this way, leave false.
+		*/
+#endif
+#if EmLocalTalk
+	/* otherwise RxChrAvail always false */
+	blnr RxChrAvail;
+#endif
+#if 0 /* RxOverrun always false */
+	blnr RxOverrun;
+#endif
+#if 0 /* CRCFramingErr always false */
+	blnr CRCFramingErr;
+#endif
+#if EmLocalTalk
+	/* otherwise EndOfFrame always false */
+	blnr EndOfFrame;
+#endif
+#if 0 /* ParityErr always false */
+	blnr ParityErr;
+#endif
+#if 0 /* ZeroCount always false */
+	blnr ZeroCount;
+#endif
+#if 0 /* BreakAbort always false */
+	blnr BreakAbort;
+#endif
+#if 0 /* SyncHuntIE usually false */
+	blnr SyncHuntIE;
+#endif
+#if SCC_TrackMore /* don't care about CTS_IE */
+	blnr CTS_IE;
+#endif
+#if SCC_TrackMore
+	blnr CRCPreset;
+#endif
+#if SCC_TrackMore
+	blnr BRGEnbl;
+#endif
+#if 0 /* don't care about DCD_IE, always true */
+	blnr DCD_IE;
+#endif
+#if SCC_TrackMore /* don't care about BreakAbortIE */
+	blnr BreakAbortIE;
+#endif
+#if SCC_TrackMore /* don't care about Baud */
+	ui3r BaudLo;
+	ui3r BaudHi;
+#endif
+} Channel_Ty;
+
+typedef struct {
+	Channel_Ty a[2]; /* 0 = channel A, 1 = channel B */
+	int SCC_Interrupt_Type;
+	int PointerBits;
+	ui3b InterruptVector;
+	blnr MIE; /* master interrupt enable */
+#if SCC_TrackMore
+	blnr NoVectorSlct;
+#endif
+#if 0 /* StatusHiLo always false */
+	blnr StatusHiLo;
+#endif
+} SCC_Ty;
+
+LOCALVAR SCC_Ty SCC;
+
+#if 0
+LOCALVAR int ReadPrint;
+LOCALVAR int ReadModem;
+#endif
+
+#if EmLocalTalk
+static int rx_data_offset = 0;
+	/* when data pending, this is used */
+#endif
+
+EXPORTFUNC blnr SCC_InterruptsEnabled(void)
+{
+	return SCC.MIE;
+}
+
+/* ---- */
+
+/* Function used to update the interrupt state of the SCC */
+LOCALPROC CheckSCCInterruptFlag(void)
+{
+#if 0 /* ReceiveAInterrupt always false */
+	blnr ReceiveAInterrupt = falseblnr
+		/*
+			also dependeds on WR1, bits 3 and 4, but
+			this doesn't change that it's all false
+		*/
+#if EmLocalTalk
+		/* otherwise RxChrAvail always false */
+		| SCC.a[0].RxChrAvail
+#endif
+#if 0 /* RxOverrun always false */
+		| SCC.a[0].RxOverrun
+#endif
+#if 0 /* CRCFramingErr always false */
+		| SCC.a[0].CRCFramingErr
+#endif
+#if EmLocalTalk
+		/* otherwise EndOfFrame always false */
+		| SCC.a[0].EndOfFrame
+#endif
+#if 0 /* ParityErr always false */
+		| SCC.a[0].ParityErr
+#endif
+		;
+#endif
+#if 0
+	blnr TransmitAInterrupt = SCC.a[0].TxBufferEmpty;
+	/*
+		but probably looking for transitions not
+		current value
+	*/
+#endif
+#if 0
+	blnr ExtStatusAInterrupt = 0
+#if 0 /* ZeroCount always false */
+		| SCC.a[0].ZeroCount
+#endif
+		/* probably want transition for these, not value */
+#if 0 /* DCD always false */
+		| SCC.a[0].DCD /* DCD IE always true */
+#endif
+#if 0 /* CTS always false */
+		| SCC.a[0].CTS /* would depend on CTS_IE */
+#endif
+		| SCC.a[0].SyncHunt /* SyncHuntIE usually false */
+		| SCC.a[0].TxUnderrun /* Tx underrun/EOM IE always false */
+#if 0 /* BreakAbort always false */
+		| SCC.a[0].BreakAbort
+#endif
+		;
+#endif
+	ui3b NewSCCInterruptRequest;
+
+#if EmLocalTalk
+	blnr ReceiveBInterrupt = falseblnr;
+	blnr RxSpclBInterrupt = falseblnr
+		/* otherwise EndOfFrame always false */
+		| SCC.a[1].EndOfFrame
+		;
+#endif
+
+#if EmLocalTalk
+	switch (SCC.a[1].RxIntMode) {
+		case 0:
+			/* disabled */
+			RxSpclBInterrupt = falseblnr;
+			break;
+		case 1:
+			/* Rx INT on 1st char or special condition */
+			if (SCC.a[1].RxChrAvail && SCC.a[1].FirstChar) {
+				ReceiveBInterrupt = trueblnr;
+			}
+			break;
+		case 2:
+			/* INT on all Rx char or special condition */
+			if (SCC.a[1].RxChrAvail) {
+				ReceiveBInterrupt = trueblnr;
+			}
+			break;
+		case 3:
+			/* Rx INT on special condition only */
+			break;
+	}
+#endif
+
+	/* Master Interrupt Enable */
+	if (! SCC.MIE) {
+		SCC.SCC_Interrupt_Type = 0;
+	} else
+#if 0
+	/* External Interrupt Enable */
+	if (SCC.a[1].ExtIE) {
+		/* DCD Interrupt Enable */
+		if (SCC.a[1].DCD_IE && 0) { /* dcd unchanged */
+			SCC.SCC_Interrupt_Type = ??;
+		}
+	}
+#endif
+	if (SCC.a[0].TxIP && SCC.a[0].TxIE) {
+		SCC.SCC_Interrupt_Type = SCC_A_Tx_Empty;
+	} else
+#if EmLocalTalk
+	if (ReceiveBInterrupt) {
+		SCC.SCC_Interrupt_Type = SCC_B_Rx;
+	} else
+	if (RxSpclBInterrupt) {
+		SCC.SCC_Interrupt_Type = SCC_B_Rx_Spec;
+	} else
+#endif
+	if (SCC.a[1].TxIP && SCC.a[1].TxIE) {
+		SCC.SCC_Interrupt_Type = SCC_B_Tx_Empty;
+	} else
+	{
+		SCC.SCC_Interrupt_Type = 0;
+	}
+
+	NewSCCInterruptRequest = (SCC.SCC_Interrupt_Type != 0) ? 1 : 0;
+	if (NewSCCInterruptRequest != SCCInterruptRequest) {
+#if SCC_dolog
+		dbglog_WriteSetBool("SCCInterruptRequest change",
+			NewSCCInterruptRequest);
+
+		dbglog_StartLine();
+		dbglog_writeCStr("SCC.SCC_Interrupt_Type <- ");
+		dbglog_writeHex(SCC.SCC_Interrupt_Type);
+		dbglog_writeReturn();
+#endif
+		SCCInterruptRequest = NewSCCInterruptRequest;
+#ifdef SCCinterruptChngNtfy
+		SCCinterruptChngNtfy();
+#endif
+	}
+}
+
+LOCALPROC SCC_InitChannel(int chan)
+{
+	/* anything not done by ResetChannel */
+
+	SCC.a[chan].SyncHunt = trueblnr;
+#if 0 /* DCD always false */
+	SCC.a[chan].DCD = falseblnr; /* input pin, reset doesn't change */
+#endif
+#if 0 /* CTS always false */
+	SCC.a[chan].CTS = falseblnr; /* input pin, reset doesn't change */
+#endif
+#if 0 /* AllSent always true */
+	SCC.a[chan].AllSent = trueblnr;
+#endif
+#if SCC_TrackMore /* don't care about Baud */
+	SCC.a[chan].BaudLo = 0;
+	SCC.a[chan].BaudHi = 0;
+#endif
+#if 0 /* BreakAbort always false */
+	SCC.a[chan].BreakAbort = falseblnr;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].BRGEnbl = falseblnr;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].TRxCsrc = 0;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].TClkSlct = 1;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].RClkSlct = 0;
+#endif
+}
+
+LOCALPROC SCC_ResetChannel(int chan)
+{
+/* RR 0 */
+#if EmLocalTalk
+	SCC.a[chan].RxBuff = 0;
+#endif
+#if EmLocalTalk
+	/* otherwise RxChrAvail always false */
+	SCC.a[chan].RxChrAvail = falseblnr;
+#endif
+#if 0 /* ZeroCount always false */
+	SCC.a[chan].ZeroCount = falseblnr;
+#endif
+#if EmLocalTalk
+	/* otherwise TxBufferEmpty always true */
+	SCC.a[chan].TxBufferEmpty = trueblnr;
+#endif
+	SCC.a[chan].TxUnderrun = trueblnr;
+/* RR 1 */
+#if 0 /* ParityErr always false */
+	SCC.a[chan].ParityErr = falseblnr;
+#endif
+#if 0 /* RxOverrun always false */
+	SCC.a[chan].RxOverrun = falseblnr;
+#endif
+#if 0 /* CRCFramingErr always false */
+	SCC.a[chan].CRCFramingErr = falseblnr;
+#endif
+#if EmLocalTalk
+	/* otherwise EndOfFrame always false */
+	SCC.a[chan].EndOfFrame = falseblnr;
+#endif
+/* RR 3 */
+#if EmLocalTalk || SCC_TrackMore
+	SCC.a[chan].ExtIE = falseblnr;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].RxCRCEnbl = falseblnr;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].TxCRCEnbl = falseblnr;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].RTSctrl = falseblnr;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].SndBrkCtrl = falseblnr;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].DTRctrl = falseblnr;
+#endif
+#if EmLocalTalk || SCC_TrackMore
+	SCC.a[chan].AddrSrchMd = falseblnr;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].SyncChrLdInhb = falseblnr;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].WaitRqstEnbl = falseblnr;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].WaitRqstSlct = falseblnr;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].WaitRqstRT = falseblnr;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].PrtySpclCond = falseblnr;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].PrtyEnable = falseblnr;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].PrtyEven = falseblnr;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].ClockRate = 0;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].DataEncoding = 0;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].RBitsPerChar = 0;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].TBitsPerChar = 0;
+#endif
+#if EmLocalTalk || SCC_TrackMore
+	SCC.a[chan].RxIntMode = 0;
+#endif
+#if EmLocalTalk || SCC_TrackMore
+	SCC.a[chan].FirstChar = falseblnr;
+#endif
+#if EmLocalTalk || SCC_TrackMore
+	SCC.a[chan].SyncMode = 0;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].StopBits = 0;
+#endif
+#if SCC_TrackMore
+	SCC.NoVectorSlct = falseblnr;
+#endif
+	SCC.a[chan].TxIP = falseblnr;
+
+	SCC.a[chan].TxEnable = falseblnr;
+	SCC.a[chan].RxEnable = falseblnr;
+	SCC.a[chan].TxIE = falseblnr;
+
+#if 0 /* don't care about DCD_IE, always true */
+	SCC.a[chan].DCD_IE = trueblnr;
+#endif
+#if SCC_TrackMore /* don't care about CTS_IE */
+	SCC.a[chan].CTS_IE = trueblnr;
+#endif
+#if SCC_TrackMore
+	SCC.a[chan].CRCPreset = falseblnr;
+#endif
+#if 0 /* SyncHuntIE usually false */
+	SCC.a[chan].SyncHuntIE = trueblnr;
+#endif
+#if SCC_TrackMore /* don't care about BreakAbortIE */
+	SCC.a[chan].BreakAbortIE = trueblnr;
+#endif
+
+	SCC.PointerBits = 0;
+
+#if 0
+	if (chan != 0) {
+		ReadPrint = 0;
+	} else {
+		ReadModem = 0;
+	}
+#endif
+}
+
+GLOBALPROC SCC_Reset(void)
+{
+	SCCwaitrq = 1;
+
+	SCC.SCC_Interrupt_Type = 0;
+
+	SCCInterruptRequest = 0;
+	SCC.PointerBits = 0;
+	SCC.MIE = falseblnr;
+	SCC.InterruptVector = 0;
+#if 0 /* StatusHiLo always false */
+	SCC.StatusHiLo = falseblnr;
+#endif
+
+	SCC_InitChannel(1);
+	SCC_InitChannel(0);
+
+	SCC_ResetChannel(1);
+	SCC_ResetChannel(0);
+}
+
+
+#if EmLocalTalk
+
+LOCALVAR blnr CTSpacketPending = falseblnr;
+LOCALVAR ui3r CTSpacketRxDA;
+LOCALVAR ui3r CTSpacketRxSA;
+
+/*
+	Function used when all the tx data is sent to the SCC as indicated
+	by resetting the TX underrun/EOM latch.  If the transmit packet is
+	a unicast RTS LAPD packet, we fake the corresponding CTS LAPD
+	packet.  This is okay because it is only a collision avoidance
+	mechanism and the Ethernet device itself and BPF automatically
+	handle collision detection and retransmission.  Besides this is
+	what a standard AppleTalk (LocalTalk to EtherTalk) bridge does.
+*/
+LOCALPROC process_transmit(void)
+{
+	/* Check for LLAP packets, which we won't send */
+	if (LT_TxBuffSz == 3) {
+		/*
+			We will automatically and immediately acknowledge
+			any non-broadcast RTS packets
+		*/
+		if ((LT_TxBuffer[0] != 0xFF) && (LT_TxBuffer[2] == 0x84)) {
+#if SCC_dolog
+			dbglog_WriteNote("SCC LLAP packet in process_transmit");
+#endif
+			if (CTSpacketPending) {
+				ReportAbnormalID(0x0701,
+					"Already CTSpacketPending in process_transmit");
+			} else {
+				CTSpacketRxDA = LT_TxBuffer[1]; /* rx da = tx sa */
+				CTSpacketRxSA = LT_TxBuffer[0]; /* rx sa = tx da */
+				CTSpacketPending = trueblnr;
+			}
+		}
+	} else {
+		LT_TransmitPacket();
+	}
+}
+
+LOCALPROC SCC_TxBuffPut(ui3r Data)
+{
+	/* Buffer the data in the transmit buffer */
+	if (LT_TxBuffSz < LT_TxBfMxSz) {
+		LT_TxBuffer[LT_TxBuffSz] = Data;
+		++LT_TxBuffSz;
+	}
+}
+
+LOCALVAR ui3b MyCTSBuffer[4];
+
+LOCALPROC GetCTSpacket(void)
+{
+	/* Get a single buffer worth of packets at a time */
+	ui3p device_buffer = MyCTSBuffer;
+
+#if SCC_dolog
+	dbglog_WriteNote("SCC receiving CTS packet");
+#endif
+	/* Create the fake response from the other node */
+	device_buffer[0] = CTSpacketRxDA;
+	device_buffer[1] = CTSpacketRxSA;
+	device_buffer[2] = 0x85;          /* llap cts */
+
+	/* Start the receiver */
+	LT_RxBuffer = device_buffer;
+	LT_RxBuffSz = 3;
+
+	CTSpacketPending = falseblnr;
+}
+
+/*
+	This function is called once all the normal packet bytes have been
+	received.
+*/
+LOCALPROC rx_complete(void)
+{
+	if (SCC.a[1].EndOfFrame) {
+		ReportAbnormalID(0x0702, "EndOfFrame true in rx_complete");
+	}
+	if (! SCC.a[1].RxChrAvail) {
+		ReportAbnormalID(0x0703, "RxChrAvail false in rx_complete");
+	}
+	if (SCC.a[1].SyncHunt) {
+		ReportAbnormalID(0x0704, "SyncHunt true in rx_complete");
+	}
+
+	/*
+		Need to wait for rx_eof_pending (end of frame) to clear before
+		preparing the next packet for receive.
+	*/
+	LT_RxBuffer = nullpr;
+
+	SCC.a[1].EndOfFrame = trueblnr;
+}
+
+LOCALPROC SCC_RxBuffAdvance(void)
+{
+	ui3r value;
+
+	/*
+		From the manual:
+		"If status is checked, it must be done before the data is read,
+		because the act of reading the data pops both the data and
+		error FIFOs."
+	*/
+
+	if (nullpr == LT_RxBuffer) {
+		value = 0x7E;
+		SCC.a[1].RxChrAvail = falseblnr;
+	} else {
+		if (rx_data_offset < LT_RxBuffSz) {
+			value = LT_RxBuffer[rx_data_offset];
+		} else {
+			ui5r i = rx_data_offset - LT_RxBuffSz;
+
+			/* if i==0 in first byte of CRC, have not got EOF yet */
+			if (i == 1) {
+				rx_complete();
+			}
+
+			value = 0;
+		}
+		++rx_data_offset;
+	}
+
+	SCC.a[1].RxBuff = value;
+}
+
+/* LLAP/SDLC address */
+LOCALVAR ui3b my_node_address = 0;
+
+LOCALPROC GetNextPacketForMe(void)
+{
+	unsigned char dst;
+	unsigned char src;
+
+label_retry:
+	LT_ReceivePacket();
+
+	if (nullpr != LT_RxBuffer) {
+#if SCC_dolog
+		dbglog_WriteNote("SCC receiving packet from BPF");
+#endif
+
+		/* Is this packet destined for me? */
+		dst = LT_RxBuffer[0];
+		src = LT_RxBuffer[1];
+		if (src == my_node_address) {
+#if SCC_dolog
+			dbglog_WriteNote("SCC ignore packet from myself");
+#endif
+			LT_RxBuffer = nullpr;
+			goto label_retry;
+		} else if ((dst == my_node_address)
+			|| (dst == 0xFF)
+			|| ! SCC.a[1].AddrSrchMd)
+		{
+			/* ok */
+		} else {
+#if SCC_dolog
+			dbglog_WriteNote("SCC ignore packet not for me");
+#endif
+			LT_RxBuffer = nullpr;
+			goto label_retry;
+		}
+	}
+}
+
+/*
+	External function, called periodically, to poll for any new LTOE
+	packets. Any new packets are queued into the packet receipt queue.
+*/
+GLOBALPROC LocalTalkTick(void)
+{
+	if (SCC.a[1].RxEnable
+		&& (! SCC.a[1].RxChrAvail))
+	{
+		if (nullpr != LT_RxBuffer) {
+#if SCC_dolog
+			dbglog_WriteNote("SCC recover abandoned packet");
+#endif
+		} else {
+			if (CTSpacketPending)  {
+				GetCTSpacket();
+			} else {
+				GetNextPacketForMe();
+			}
+		}
+
+		if (nullpr != LT_RxBuffer) {
+			rx_data_offset  = 0;
+			SCC.a[1].EndOfFrame = falseblnr;
+			SCC.a[1].RxChrAvail = trueblnr;
+			SCC.a[1].SyncHunt = falseblnr;
+
+			SCC_RxBuffAdvance();
+			/* We can update the rx interrupt if enabled */
+			CheckSCCInterruptFlag();
+		}
+	}
+}
+
+#endif
+
+
+#if 0
+LOCALPROC SCC_Interrupt(int Type)
+{
+	if (SCC.MIE) { /* Master Interrupt Enable */
+
+		if (Type > SCC.SCC_Interrupt_Type) {
+			SCC.SCC_Interrupt_Type = Type;
+		}
+
+		CheckSCCInterruptFlag();
+	}
+}
+#endif
+
+#if 0
+LOCALPROC SCC_Int(void)
+{
+	/* This should be called at regular intervals */
+
+	/* Turn off Sync/Hunt Mode */
+	if (SCC.a[0].SyncHunt) {
+		SCC.a[0].SyncHunt = falseblnr;
+
+#ifdef _SCC_Debug2
+		vMac_Message("SCC_Int: Disable Sync/Hunt on A");
+#endif
+
+#if 0 /* SyncHuntIE usually false */
+		if (SCC.a[0].SyncHuntIE) {
+			SCC_Interrupt(SCC_A_Ext);
+		}
+#endif
+	}
+	if (SCC.a[1].SyncHunt) {
+		SCC.a[1].SyncHunt = falseblnr;
+
+#ifdef _SCC_Debug2
+		vMac_Message("SCC_Int: Disable Sync/Hunt on B");
+#endif
+
+#if 0 /* SyncHuntIE usually false */
+		if (SCC.a[1].SyncHuntIE) {
+			SCC_Interrupt(SCC_B_Ext);
+		}
+#endif
+	}
+
+#if 0
+	/* Check for incoming data */
+	if (ModemPort)
+	{
+		if (! SCC.a[0].RxEnable) { /* Rx Disabled */
+			ReadModem = 0;
+		}
+
+		if ((ModemBytes > 0) && (ModemCount > ModemBytes - 1))
+		{
+			SCC.a[0].RxChrAvail = falseblnr;
+			ReadModem = ModemBytes = ModemCount = 0;
+		}
+
+		if (ReadModem) {
+			ReadModem = 2;
+
+			SCC.a[0].RxChrAvail = trueblnr;
+
+			if (SCC.a[0].WR[0] & Bit5
+				&& ! (SCC.a[0].WR[0] & (Bit4 | Bit3)))
+			{
+				/* Int on next Rx char */
+				SCC_Interrupt(SCC_A_Rx);
+			} else if (SCC.a[0].WR[1] & Bit3
+				&& ! (SCC.a[0].WR[1] & Bit4))
+			{
+				/* Int on first Rx char */
+				SCC_Interrupt(SCC_A_Rx);
+			} else if (SCC.a[0].WR[1] & Bit4
+				&& ! (SCC.a[0].WR[1] & Bit3))
+			{
+				/* Int on all Rx chars */
+				SCC_Interrupt(SCC_A_Rx);
+			}
+		}
+	}
+	if (PrintPort) {
+		if (! SCC.a[1].RxEnable) {
+			/* Rx Disabled */
+			ReadPrint = 0;
+		}
+
+		if ((PrintBytes > 0) && (PrintCount > PrintBytes - 1)) {
+			SCC.a[1].RxChrAvail = falseblnr;
+			ReadPrint = PrintBytes = PrintCount = 0;
+		}
+
+		if (ReadPrint) {
+			ReadPrint = 2;
+
+			SCC.a[1].RxChrAvail = trueblnr;
+
+			if (SCC.a[1].WR[0] & Bit5
+				&& ! (SCC.a[1].WR[0] & (Bit4 | Bit3)))
+			{
+				/* Int on next Rx char */
+				SCC_Interrupt(SCC_B_Rx);
+			} else if (SCC.a[1].WR[1] & Bit3
+				&& ! (SCC.a[1].WR[1] & Bit4))
+			{
+				/* Int on first Rx char */
+				SCC_Interrupt(SCC_B_Rx);
+			} else if (SCC.a[1].WR[1] & Bit4
+				&& ! (SCC.a[1].WR[1] & Bit3))
+			{
+				/* Int on all Rx chars */
+				SCC_Interrupt(SCC_B_Rx);
+			}
+		}
+	}
+#endif
+}
+#endif
+
+#if SCC_dolog
+LOCALPROC SCC_DbgLogChanStartLine(int chan)
+{
+	dbglog_StartLine();
+	dbglog_writeCStr("SCC chan(");
+	if (chan) {
+		dbglog_writeCStr("B");
+	} else {
+		dbglog_writeCStr("A");
+	}
+	/* dbglog_writeHex(chan); */
+	dbglog_writeCStr(")");
+}
+#endif
+
+LOCALFUNC ui3r SCC_GetRR0(int chan)
+{
+	/* happens on boot always */
+
+	return 0
+#if 0 /* BreakAbort always false */
+		| (SCC.a[chan].BreakAbort ? (1 << 7) : 0)
+#endif
+		| (SCC.a[chan].TxUnderrun ? (1 << 6) : 0)
+#if 0 /* CTS always false */
+		| (SCC.a[chan].CTS ? (1 << 5) : 0)
+#endif
+		| (SCC.a[chan].SyncHunt ? (1 << 4) : 0)
+#if 0 /* DCD always false */
+		| (SCC.a[chan].DCD ? (1 << 3) : 0)
+#endif
+#if EmLocalTalk
+		| (SCC.a[chan].TxBufferEmpty ? (1 << 2) : 0)
+#else
+		/* otherwise TxBufferEmpty always true */
+		| (1 << 2)
+#endif
+#if 0 /* ZeroCount always false */
+		| (SCC.a[chan].ZeroCount ? (1 << 1) : 0)
+#endif
+#if EmLocalTalk
+		/* otherwise RxChrAvail always false */
+		| (SCC.a[chan].RxChrAvail ? (1 << 0) : 0)
+#endif
+		;
+}
+
+LOCALFUNC ui3r SCC_GetRR1(int chan)
+{
+	/* happens in MacCheck */
+
+	ui3r value;
+#if ! EmLocalTalk
+	UnusedParam(chan);
+#endif
+
+	value = Bit2 | Bit1
+#if 0 /* AllSent always true */
+		| (SCC.a[chan].AllSent ? (1 << 0) : 0)
+#else
+		| Bit0
+#endif
+#if 0 /* ParityErr always false */
+		| (SCC.a[chan].ParityErr ? (1 << 4) : 0)
+#endif
+#if 0 /* RxOverrun always false */
+		| (SCC.a[chan].RxOverrun ? (1 << 5) : 0)
+#endif
+#if 0 /* CRCFramingErr always false */
+		| (SCC.a[chan].CRCFramingErr ? (1 << 6) : 0)
+#endif
+#if EmLocalTalk
+		/* otherwise EndOfFrame always false */
+		| (SCC.a[chan].EndOfFrame ? (1 << 7) : 0)
+#endif
+		;
+
+	return value;
+}
+
+LOCALFUNC ui3r SCC_GetRR2(int chan)
+{
+	/* happens in MacCheck */
+	/* happens in Print to ImageWriter */
+
+	ui3r value = SCC.InterruptVector;
+
+	if (chan != 0) { /* B Channel */
+#if 0 /* StatusHiLo always false */
+		if (SCC.StatusHiLo) {
+			/* Status High */
+			value = value
+				& (Bit0 | Bit1 | Bit2 | Bit3 | Bit7);
+
+			ReportAbnormalID(0x0705, "Status high/low");
+			switch (SCC.SCC_Interrupt_Type) {
+				case SCC_A_Rx:
+					value |= Bit4 | Bit5;
+					break;
+
+				case SCC_A_Rx_Spec:
+					value |= Bit4 | Bit5 | Bit6;
+					break;
+
+				case SCC_A_Tx_Empty:
+					value |= Bit4;
+					break;
+
+				case SCC_A_Ext:
+					value |= Bit4 | Bit6;
+					break;
+
+				case SCC_B_Rx:
+					value |= Bit5;
+					break;
+
+				case SCC_B_Rx_Spec:
+					value |= Bit5 | Bit6;
+					break;
+
+				case SCC_B_Tx_Empty:
+					value |= 0;
+					break;
+
+				case SCC_B_Ext:
+					value |= Bit6;
+					break;
+
+				default:
+					value |= Bit5 | Bit6;
+					break;
+			}
+		} else
+#endif
+		{
+			/* Status Low */
+			value = value
+				& (Bit0 | Bit4 | Bit5 | Bit6 | Bit7);
+
+			switch (SCC.SCC_Interrupt_Type) {
+				case SCC_A_Rx:
+					value |= Bit3 | Bit2;
+					break;
+
+				case SCC_A_Rx_Spec:
+					value |= Bit3 | Bit2 | Bit1;
+					break;
+
+				case SCC_A_Tx_Empty:
+					value |= Bit3;
+					break;
+
+				case SCC_A_Ext:
+					value |= Bit3 | Bit1;
+					break;
+
+				case SCC_B_Rx:
+					value |= Bit2;
+					break;
+
+				case SCC_B_Rx_Spec:
+					value |= Bit2 | Bit1;
+					break;
+
+				case SCC_B_Tx_Empty:
+					value |= 0;
+					break;
+
+				case SCC_B_Ext:
+					value |= Bit1;
+					break;
+
+				default:
+					value |= Bit2 | Bit1;
+					break;
+			}
+		}
+
+		/* SCC.SCC_Interrupt_Type = 0; */
+	}
+
+	return value;
+}
+
+LOCALFUNC ui3r SCC_GetRR3(int chan)
+{
+	ui3r value = 0;
+
+	UnusedParam(chan);
+	ReportAbnormalID(0x0706, "RR 3");
+
+#if 0
+	if (chan == 0) {
+		value = 0
+			| (SCC.a[1].TxIP ? (1 << 1) : 0)
+			| (SCC.a[0].TxIP ? (1 << 4) : 0)
+			;
+	} else {
+		value = 0;
+	}
+#endif
+
+	return value;
+}
+
+LOCALFUNC ui3r SCC_GetRR8(int chan)
+{
+	ui3r value = 0;
+
+	/* Receive Buffer */
+	/* happens on boot with appletalk on */
+	if (SCC.a[chan].RxEnable) {
+#if EmLocalTalk
+		if (0 != chan) {
+			/*
+				Check the receive state, handling a complete rx
+				if necessary
+			*/
+			value = SCC.a[1].RxBuff;
+			SCC.a[1].FirstChar = falseblnr;
+			SCC_RxBuffAdvance();
+		} else {
+			value = 0x7E;
+		}
+#else
+		/* Rx Enable */
+#if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx)
+		/* don't report */
+#else
+		ReportAbnormalID(0x0707, "read rr8 when RxEnable");
+#endif
+
+		/* Input 1 byte from Modem Port/Printer into Data */
+#endif
+	} else {
+		/* happens on boot with appletalk on */
+	}
+
+	return value;
+}
+
+LOCALFUNC ui3r SCC_GetRR10(int chan)
+{
+	/* happens on boot with appletalk on */
+
+	ui3r value = 0;
+	UnusedParam(chan);
+
+#if 0 && EmLocalTalk
+	value = 2;
+#endif
+
+	return value;
+}
+
+LOCALFUNC ui3r SCC_GetRR12(int chan)
+{
+	ui3r value = 0;
+
+#if ! SCC_TrackMore
+	UnusedParam(chan);
+#endif
+	ReportAbnormalID(0x0708, "RR 12");
+
+#if SCC_TrackMore /* don't care about Baud */
+	value = SCC.a[chan].BaudLo;
+#endif
+
+	return value;
+}
+
+LOCALFUNC ui3r SCC_GetRR13(int chan)
+{
+	ui3r value = 0;
+
+#if ! SCC_TrackMore
+	UnusedParam(chan);
+#endif
+	ReportAbnormalID(0x0709, "RR 13");
+
+#if SCC_TrackMore /* don't care about Baud */
+	value = SCC.a[chan].BaudHi;
+#endif
+
+	return value;
+}
+
+LOCALFUNC ui3r SCC_GetRR15(int chan)
+{
+	ui3r value = 0;
+
+	UnusedParam(chan);
+	ReportAbnormalID(0x070A, "RR 15");
+
+#if 0
+	value = 0
+#if 0 /* don't care about DCD_IE, always true */
+		| (SCC.a[chan].DCD_IE ? Bit3 : 0)
+#else
+		| Bit3
+#endif
+#if 0 /* SyncHuntIE usually false */
+		| (SCC.a[chan].SyncHuntIE ? Bit4 : 0)
+#endif
+#if SCC_TrackMore /* don't care about CTS_IE */
+		| (SCC.a[chan].CTS_IE ? Bit5 : 0)
+#endif
+#if SCC_TrackMore /* don't care about BreakAbortIE */
+		| (SCC.a[chan].BreakAbortIE ? Bit7 : 0)
+#endif
+		;
+#endif
+
+	return value;
+}
+
+#if SCC_dolog
+LOCALPROC SCC_DbgLogChanCmnd(int chan, char *s)
+{
+	SCC_DbgLogChanStartLine(chan);
+	dbglog_writeCStr(" ");
+	dbglog_writeCStr(s);
+	dbglog_writeReturn();
+}
+#endif
+
+#if SCC_dolog
+LOCALPROC SCC_DbgLogChanChngBit(int chan, char *s, blnr v)
+{
+	SCC_DbgLogChanStartLine(chan);
+	dbglog_writeCStr(" ");
+	dbglog_writeCStr(s);
+	dbglog_writeCStr(" <- ");
+	if (v) {
+		dbglog_writeCStr("1");
+	} else {
+		dbglog_writeCStr("0");
+	}
+	dbglog_writeReturn();
+}
+#endif
+
+LOCALPROC SCC_PutWR0(ui3r Data, int chan)
+/*
+	"CRC initialize, initialization commands for the various modes,
+	Register Pointers"
+*/
+{
+	switch ((Data >> 6) & 3) {
+		case 1:
+			ReportAbnormalID(0x070B, "Reset Rx CRC Checker");
+			break;
+		case 2:
+#if SCC_dolog
+			SCC_DbgLogChanCmnd(chan, "Reset Tx CRC Generator");
+#endif
+			/* happens on boot with appletalk on */
+			break;
+		case 3:
+#if SCC_dolog
+			SCC_DbgLogChanCmnd(chan,
+				"Reset Tx Underrun/EOM Latch");
+#endif
+			/* happens on boot with appletalk on */
+#if EmLocalTalk
+			/*
+				This is the indication we are done transmitting
+				data for the current packet.
+			*/
+			process_transmit();
+#endif
+#if 0 /* It seems to work better without this */
+			if (SCC.a[chan].TxEnable) {
+				/* Tx Enabled */
+				SCC.a[chan].TxUnderrun = falseblnr;
+
+				if (SCC.a[chan].WR[10] & Bit2) {
+					/* Abort/Flag on Underrun */
+					/* Send Abort */
+					SCC.a[chan].TxUnderrun = trueblnr;
+#if 0 /* TxBufferEmpty always true */
+					SCC.a[chan].TxBufferEmpty = trueblnr;
+#endif
+
+					/* Send Flag */
+				}
+			}
+#endif
+			break;
+		case 0:
+		default:
+			/* Null Code */
+			break;
+	}
+	SCC.PointerBits = Data & 0x07;
+	switch ((Data >> 3) & 7) {
+		case 1: /* Point High */
+			SCC.PointerBits |= 8;
+			break;
+		case 2:
+#if SCC_dolog
+			SCC_DbgLogChanCmnd(chan, "Reset Ext/Status Ints");
+#endif
+			/* happens on boot always */
+			SCC.a[chan].SyncHunt = falseblnr;
+#if 0 /* only in sync mode */
+			SCC.a[chan].TxUnderrun = falseblnr;
+#endif
+#if 0 /* ZeroCount always false */
+			SCC.a[chan].ZeroCount = falseblnr;
+#endif
+#if 0 /* BreakAbort always false */
+			SCC.a[chan].BreakAbort = falseblnr;
+#endif
+			break;
+		case 3:
+			ReportAbnormalID(0x070C, "Send Abort (SDLC)");
+#if EmLocalTalk
+			SCC.a[chan].TxBufferEmpty = trueblnr;
+#endif
+#if 0
+			SCC.a[chan].TxUnderrun = trueblnr;
+#if 0 /* TxBufferEmpty always true */
+			SCC.a[chan].TxBufferEmpty = trueblnr;
+#endif
+#endif
+			break;
+		case 4:
+#if SCC_dolog
+			SCC_DbgLogChanCmnd(chan,
+				"Enable Int on next Rx char");
+#endif
+#if EmLocalTalk || SCC_TrackMore
+			SCC.a[chan].FirstChar = trueblnr;
+#endif
+			/* happens in MacCheck */
+			break;
+		case 5:
+#if SCC_dolog
+			SCC_DbgLogChanCmnd(chan, "Reset Tx Int Pending");
+#endif
+			/* happens in MacCheck */
+			/* happens in Print to ImageWriter */
+			SCC.a[chan].TxIP = falseblnr;
+			CheckSCCInterruptFlag();
+			break;
+		case 6:
+#if SCC_dolog
+			SCC_DbgLogChanCmnd(chan, "Error Reset");
+#endif
+			/* happens on boot with appletalk on */
+#if EmLocalTalk
+			SCC.a[chan].EndOfFrame = falseblnr;
+#endif
+#if 0 /* ParityErr always false */
+			SCC.a[chan].ParityErr = falseblnr;
+#endif
+#if 0 /* RxOverrun always false */
+			SCC.a[chan].RxOverrun = falseblnr;
+#endif
+#if 0 /* CRCFramingErr always false */
+			SCC.a[chan].CRCFramingErr = falseblnr;
+#endif
+			break;
+		case 7:
+			/* happens in "Network Watch" program (Cayman Systems) */
+#if SCC_dolog
+			SCC_DbgLogChanCmnd(chan, "Reset Highest IUS");
+#endif
+			break;
+		case 0:
+		default:
+			/* Null Code */
+			break;
+	}
+}
+
+LOCALPROC SCC_PutWR1(ui3r Data, int chan)
+/*
+	"Transmit/Receive interrupt and data transfer mode definition"
+*/
+{
+#if EmLocalTalk || SCC_TrackMore
+	{
+		blnr NewExtIE = (Data & Bit0) != 0;
+		if (SCC.a[chan].ExtIE != NewExtIE) {
+			SCC.a[chan].ExtIE = NewExtIE;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan, "EXT INT Enable",
+				NewExtIE);
+#endif
+			/*
+				set to 1 on start up, set to 0 in MacCheck
+				and in Print to ImageWriter
+			*/
+		}
+	}
+#endif
+
+	{
+		blnr NewTxIE = (Data & Bit1) != 0;
+		if (SCC.a[chan].TxIE != NewTxIE) {
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan, "Tx Int Enable",
+				NewTxIE);
+#endif
+			/* happens in MacCheck */
+			/* happens in Print to ImageWriter */
+			SCC.a[chan].TxIE = NewTxIE;
+			CheckSCCInterruptFlag();
+		}
+	}
+
+#if SCC_TrackMore
+	{
+		blnr NewPrtySpclCond = (Data & Bit2) != 0;
+		if (SCC.a[chan].PrtySpclCond != NewPrtySpclCond) {
+			SCC.a[chan].PrtySpclCond = NewPrtySpclCond;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"Parity is special condition", NewPrtySpclCond);
+#endif
+			/*
+				set to 1 in MacCheck
+				and in Print to ImageWriter
+			*/
+		}
+	}
+#endif
+
+#if EmLocalTalk || SCC_TrackMore
+	{
+		ui3r NewRxIntMode = (Data >> 3) & 3;
+		if (SCC.a[chan].RxIntMode != NewRxIntMode) {
+			SCC.a[chan].RxIntMode = NewRxIntMode;
+
+			switch (NewRxIntMode) {
+				case 0:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan, "Rx INT Disable");
+#endif
+					/* happens on boot always */
+					break;
+				case 1:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"Rx INT on 1st char"
+						" or special condition");
+#endif
+					SCC.a[chan].FirstChar = trueblnr;
+					/* happens on boot with appletalk on */
+					break;
+				case 2:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"INT on all Rx char"
+						" or special condition");
+#endif
+					/* happens in MacCheck */
+					/* happens in Print to ImageWriter */
+					break;
+				case 3:
+					ReportAbnormalID(0x070D,
+						"Rx INT on special condition only");
+					break;
+			}
+		}
+	}
+#endif
+
+#if SCC_TrackMore
+	{
+		blnr NewWaitRqstRT = (Data & Bit5) != 0;
+		if (SCC.a[chan].WaitRqstRT != NewWaitRqstRT) {
+			SCC.a[chan].WaitRqstRT = NewWaitRqstRT;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"Wait/DMA request on receive/transmit",
+				NewWaitRqstRT);
+#endif
+			/* happens in MacCheck */
+		}
+	}
+#endif
+
+#if SCC_TrackMore
+	{
+		blnr NewWaitRqstSlct = (Data & Bit6) != 0;
+		if (SCC.a[chan].WaitRqstSlct != NewWaitRqstSlct) {
+			SCC.a[chan].WaitRqstSlct = NewWaitRqstSlct;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"Wait/DMA request function", NewWaitRqstSlct);
+#endif
+			/* happens in MacCheck */
+		}
+	}
+#endif
+
+#if SCC_TrackMore
+	{
+		blnr NewWaitRqstEnbl = (Data & Bit7) != 0;
+		if (SCC.a[chan].WaitRqstEnbl != NewWaitRqstEnbl) {
+			SCC.a[chan].WaitRqstEnbl = NewWaitRqstEnbl;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"Wait/DMA request enable", NewWaitRqstEnbl);
+#endif
+			/* happens in MacCheck */
+		}
+	}
+#endif
+}
+
+LOCALPROC SCC_PutWR2(ui3r Data, int chan)
+/* "Interrupt Vector (accessed through either channel)" */
+{
+	/*
+		Only 1 interrupt vector for the SCC, which
+		is stored in channels A and B. B is modified
+		when read.
+	*/
+
+	/* happens on boot always */
+
+#if ! SCC_dolog
+	UnusedParam(chan);
+#endif
+
+	if (SCC.InterruptVector != Data) {
+#if SCC_dolog
+		SCC_DbgLogChanStartLine(chan);
+		dbglog_writeCStr(" InterruptVector <- ");
+		dbglog_writeHex(Data);
+		dbglog_writeReturn();
+#endif
+		SCC.InterruptVector = Data;
+	}
+	if ((Data & Bit0) != 0) { /* interrupt vector 0 */
+		ReportAbnormalID(0x070E, "interrupt vector 0");
+	}
+	if ((Data & Bit1) != 0) { /* interrupt vector 1 */
+		ReportAbnormalID(0x070F, "interrupt vector 1");
+	}
+	if ((Data & Bit2) != 0) { /* interrupt vector 2 */
+		ReportAbnormalID(0x0710, "interrupt vector 2");
+	}
+	if ((Data & Bit3) != 0) { /* interrupt vector 3 */
+		ReportAbnormalID(0x0711, "interrupt vector 3");
+	}
+	if ((Data & Bit4) != 0) { /* interrupt vector 4 */
+		/* happens on boot with appletalk on */
+	}
+	if ((Data & Bit5) != 0) { /* interrupt vector 5 */
+		/* happens on boot with appletalk on */
+	}
+	if ((Data & Bit6) != 0) { /* interrupt vector 6 */
+		ReportAbnormalID(0x0712, "interrupt vector 6");
+	}
+	if ((Data & Bit7) != 0) { /* interrupt vector 7 */
+		ReportAbnormalID(0x0713, "interrupt vector 7");
+	}
+}
+
+LOCALPROC SCC_PutWR3(ui3r Data, int chan)
+/* "Receive parameters and control" */
+{
+#if SCC_TrackMore
+	{
+		ui3r NewRBitsPerChar = (Data >> 6) & 3;
+		if (SCC.a[chan].RBitsPerChar != NewRBitsPerChar) {
+			SCC.a[chan].RBitsPerChar = NewRBitsPerChar;
+
+			switch (NewRBitsPerChar) {
+				case 0:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"Rx Bits/Character <- 5");
+#endif
+					break;
+				case 1:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"Rx Bits/Character <- 7");
+#endif
+					break;
+				case 2:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"Rx Bits/Character <- 6");
+#endif
+					break;
+				case 3:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"Rx Bits/Character <- 8");
+#endif
+					break;
+			}
+		}
+	}
+#endif
+
+	if ((Data & Bit5) != 0) { /* Auto Enables */
+		/*
+			use DCD input as receiver enable,
+			and set RTS output when transmit buffer empty
+		*/
+		ReportAbnormalID(0x0714, "Auto Enables");
+	}
+
+	if ((Data & Bit4) != 0) { /* Enter Hunt Mode */
+#if SCC_dolog
+		SCC_DbgLogChanCmnd(chan, "Enter Hunt Mode");
+#endif
+		/* happens on boot with appletalk on */
+		if (! (SCC.a[chan].SyncHunt)) {
+			SCC.a[chan].SyncHunt = trueblnr;
+
+#if 0 /* SyncHuntIE usually false */
+			if (SCC.a[chan].SyncHuntIE) {
+				SCC_Interrupt((chan == 0)
+					? SCC_A_Ext
+					: SCC_B_Ext);
+			}
+#endif
+		}
+	}
+
+#if SCC_TrackMore
+	{
+		blnr NewRxCRCEnbl = (Data & Bit3) != 0;
+		if (SCC.a[chan].RxCRCEnbl != NewRxCRCEnbl) {
+			SCC.a[chan].RxCRCEnbl = NewRxCRCEnbl;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"Rx CRC Enable", NewRxCRCEnbl);
+#endif
+			/* happens on boot with appletalk on */
+		}
+	}
+#endif
+
+#if EmLocalTalk || SCC_TrackMore
+	{
+		blnr NewAddrSrchMd = (Data & Bit2) != 0;
+		if (SCC.a[chan].AddrSrchMd != NewAddrSrchMd) {
+			SCC.a[chan].AddrSrchMd = NewAddrSrchMd;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"Addr Search Mode (SDLC)", NewAddrSrchMd);
+#endif
+			/* happens on boot with appletalk on */
+		}
+	}
+#endif
+
+#if SCC_TrackMore
+	{
+		blnr NewSyncChrLdInhb = (Data & Bit1) != 0;
+		if (SCC.a[chan].SyncChrLdInhb != NewSyncChrLdInhb) {
+			SCC.a[chan].SyncChrLdInhb = NewSyncChrLdInhb;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"Sync Char Load Inhibit", NewSyncChrLdInhb);
+#endif
+			/* happens on boot with appletalk on */
+		}
+	}
+#endif
+
+	{
+		blnr NewRxEnable = (Data & Bit0) != 0;
+		if (SCC.a[chan].RxEnable != NewRxEnable) {
+			SCC.a[chan].RxEnable = NewRxEnable;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"Rx Enable", NewRxEnable);
+#endif
+			/* true on boot with appletalk on */
+			/* true on Print to ImageWriter */
+
+#if EmLocalTalk
+			if (! NewRxEnable) {
+#if SCC_dolog
+				if ((0 != chan) && (nullpr != LT_RxBuffer)) {
+					dbglog_WriteNote("SCC abandon packet");
+				}
+#endif
+
+				/*
+					Go back into the idle state if we were
+					waiting for EOF
+				*/
+				SCC.a[chan].EndOfFrame = falseblnr;
+				SCC.a[chan].RxChrAvail = falseblnr;
+				SCC.a[chan].SyncHunt = trueblnr;
+			} else {
+				/* look for a packet */
+				LocalTalkTick();
+			}
+#endif
+		}
+	}
+}
+
+LOCALPROC SCC_PutWR4(ui3r Data, int chan)
+/* "Transmit/Receive miscellaneous parameters and modes" */
+{
+#if ! (EmLocalTalk || SCC_TrackMore)
+	UnusedParam(Data);
+	UnusedParam(chan);
+#endif
+
+#if SCC_TrackMore
+	{
+		blnr NewPrtyEnable = (Data & Bit0) != 0;
+		if (SCC.a[chan].PrtyEnable != NewPrtyEnable) {
+			SCC.a[chan].PrtyEnable = NewPrtyEnable;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"Parity Enable", NewPrtyEnable);
+#endif
+		}
+	}
+#endif
+
+#if SCC_TrackMore
+	{
+		blnr NewPrtyEven = (Data & Bit1) != 0;
+		if (SCC.a[chan].PrtyEven != NewPrtyEven) {
+			SCC.a[chan].PrtyEven = NewPrtyEven;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"Parity Enable", NewPrtyEven);
+#endif
+		}
+	}
+#endif
+
+#if SCC_TrackMore
+	{
+		ui3r NewStopBits = (Data >> 2) & 3;
+		if (SCC.a[chan].StopBits != NewStopBits) {
+			SCC.a[chan].StopBits = NewStopBits;
+
+			/* SCC_SetStopBits(chan, NewStopBits); */
+			switch (NewStopBits) {
+				case 0:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"Sync Modes Enable");
+#endif
+					break;
+				case 1:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan, "1 Stop Bit");
+#endif
+					break;
+				case 2:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan, "1 1/2 Stop Bits");
+#endif
+					break;
+				case 3:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan, "2 Stop Bits");
+#endif
+					break;
+			}
+		}
+	}
+#endif
+
+#if EmLocalTalk || SCC_TrackMore
+	{
+		ui3r NewSyncMode = (Data >> 4) & 3;
+		if (SCC.a[chan].SyncMode != NewSyncMode) {
+			SCC.a[chan].SyncMode = NewSyncMode;
+
+			switch (NewSyncMode) {
+				case 0:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan, "8 bit sync char");
+#endif
+					/* happens on boot always */
+					break;
+				case 1:
+					ReportAbnormalID(0x0715, "16 bit sync char");
+					break;
+				case 2:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan, "SDLC MODE");
+#endif
+					/* happens on boot with appletalk on */
+#if EmLocalTalk
+					SCC.a[chan].TxBufferEmpty = trueblnr;
+#endif
+					break;
+				case 3:
+					ReportAbnormalID(0x0716, "External sync mode");
+					break;
+			}
+		}
+	}
+#endif
+
+#if SCC_TrackMore
+	{
+		ui3r NewClockRate = (Data >> 6) & 3;
+		if (SCC.a[chan].ClockRate != NewClockRate) {
+			SCC.a[chan].ClockRate = NewClockRate;
+
+			switch (NewClockRate) {
+				case 0:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"Clock Rate <- X1");
+#endif
+					/* happens on boot with appletalk on */
+					break;
+				case 1:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"Clock Rate <- X16");
+#endif
+					/* happens on boot always */
+					break;
+				case 2:
+					ReportAbnormalID(0x0717, "Clock Rate <- X32");
+					break;
+				case 3:
+					ReportAbnormalID(0x0718, "Clock Rate <- X64");
+					break;
+			}
+		}
+	}
+#endif
+}
+
+LOCALPROC SCC_PutWR5(ui3r Data, int chan)
+/* "Transmit parameters and controls" */
+{
+	/* happens on boot with appletalk on */
+	/* happens in Print to ImageWriter */
+
+#if SCC_TrackMore
+	{
+		blnr NewTxCRCEnbl = (Data & Bit0) != 0;
+		if (SCC.a[chan].TxCRCEnbl != NewTxCRCEnbl) {
+			SCC.a[chan].TxCRCEnbl = NewTxCRCEnbl;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"Tx CRC Enable", NewTxCRCEnbl);
+#endif
+			/* both values on boot with appletalk on */
+		}
+	}
+#endif
+
+#if SCC_TrackMore
+	{
+		blnr NewRTSctrl = (Data & Bit1) != 0;
+		if (SCC.a[chan].RTSctrl != NewRTSctrl) {
+			SCC.a[chan].RTSctrl = NewRTSctrl;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"RTS Control", NewRTSctrl);
+#endif
+			/* both values on boot with appletalk on */
+			/*
+				value of Request To Send output pin, when
+				Auto Enable is off
+			*/
+		}
+	}
+#endif
+
+	if ((Data & Bit2) != 0) { /* SDLC/CRC-16 */
+		ReportAbnormalID(0x0719, "SDLC/CRC-16");
+	}
+
+	{
+		blnr NewTxEnable = (Data & Bit3) != 0;
+		if (SCC.a[chan].TxEnable != NewTxEnable) {
+			SCC.a[chan].TxEnable = NewTxEnable;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"Tx Enable", NewTxEnable);
+#endif
+
+			if (NewTxEnable) {
+				/* happens on boot with appletalk on */
+				/* happens in Print to ImageWriter */
+#if EmLocalTalk
+				LT_TxBuffSz = 0;
+#endif
+			} else {
+#if EmLocalTalk
+				SCC.a[chan].TxBufferEmpty = trueblnr;
+#endif
+			}
+		}
+	}
+
+#if SCC_TrackMore
+	{
+		blnr NewSndBrkCtrl = (Data & Bit4) != 0;
+		if (SCC.a[chan].SndBrkCtrl != NewSndBrkCtrl) {
+			SCC.a[chan].SndBrkCtrl = NewSndBrkCtrl;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"Send Break Control", NewSndBrkCtrl);
+#endif
+			/* true in Print to LaserWriter 300 */
+		}
+	}
+#endif
+
+#if SCC_TrackMore
+	{
+		ui3r NewTBitsPerChar = (Data >> 5) & 3;
+		if (SCC.a[chan].TBitsPerChar != NewTBitsPerChar) {
+			SCC.a[chan].TBitsPerChar = NewTBitsPerChar;
+
+			switch (NewTBitsPerChar) {
+				case 0:
+					ReportAbnormalID(0x071A, "Tx Bits/Character <- 5");
+					break;
+				case 1:
+					ReportAbnormalID(0x071B, "Tx Bits/Character <- 7");
+					break;
+				case 2:
+					ReportAbnormalID(0x071C, "Tx Bits/Character <- 6");
+					break;
+				case 3:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"Tx Bits/Character <- 8");
+#endif
+					/* happens on boot with appletalk on */
+					/* happens in Print to ImageWriter */
+					break;
+			}
+		}
+	}
+#endif
+
+#if SCC_TrackMore
+	{
+		blnr NewDTRctrl = (Data & Bit7) != 0;
+		if (SCC.a[chan].DTRctrl != NewDTRctrl) {
+			SCC.a[chan].DTRctrl = NewDTRctrl;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"Data Terminal Ready Control", NewDTRctrl);
+#endif
+			/* zero happens in MacCheck */
+			/*
+				value of Data Terminal Ready output pin,
+				when WR14 D2 = 0 (DTR/request function)
+			*/
+		}
+	}
+#endif
+}
+
+LOCALPROC SCC_PutWR6(ui3r Data, int chan)
+/* "Sync characters or SDLC address field" */
+{
+	/* happens on boot with appletalk on */
+
+#if ! (EmLocalTalk || SCC_dolog)
+	UnusedParam(Data);
+#endif
+#if ! SCC_dolog
+	UnusedParam(chan);
+#endif
+
+#if SCC_dolog
+	SCC_DbgLogChanStartLine(chan);
+	dbglog_writeCStr(" Sync Char <- ");
+	dbglog_writeHex(Data);
+	dbglog_writeReturn();
+#endif
+
+#if EmLocalTalk
+	if (0 != Data) {
+		my_node_address = Data;
+	}
+#endif
+}
+
+LOCALPROC SCC_PutWR7(ui3r Data, int chan)
+/* "Sync character or SDLC flag" */
+{
+	/* happens on boot with appletalk on */
+
+#if ! SCC_TrackMore
+	UnusedParam(Data);
+	UnusedParam(chan);
+#endif
+
+#if SCC_TrackMore
+	if (2 == SCC.a[chan].SyncMode) {
+		if (0x7E != Data) {
+			ReportAbnormalID(0x071D,
+				"unexpect flag character for SDLC");
+		}
+	} else {
+		ReportAbnormalID(0x071E, "WR7 and not SDLC");
+	}
+#endif
+}
+
+LOCALPROC SCC_PutWR8(ui3r Data, int chan)
+/* "Transmit Buffer" */
+{
+	/* happens on boot with appletalk on */
+	/* happens in Print to ImageWriter */
+
+#if ! (EmLocalTalk || SCC_dolog)
+	UnusedParam(Data);
+#endif
+
+#if SCC_dolog
+	SCC_DbgLogChanStartLine(chan);
+	dbglog_writeCStr(" Transmit Buffer");
+	dbglog_writeCStr(" <- ");
+	dbglog_writeHex(Data);
+	dbglog_writeCStr(" '");
+	dbglog_writeMacChar(Data);
+	dbglog_writeCStr("'");
+	dbglog_writeReturn();
+#endif
+
+	if (SCC.a[chan].TxEnable) { /* Tx Enable */
+		/* Output (Data) to Modem(B) or Printer(A) Port */
+
+		/* happens on boot with appletalk on */
+#if EmLocalTalk
+		if (chan != 0) {
+			SCC_TxBuffPut(Data);
+		}
+#else
+#if 0 /* TxBufferEmpty always true */
+		SCC.a[chan].TxBufferEmpty = trueblnr;
+#endif
+		SCC.a[chan].TxUnderrun = trueblnr; /* underrun ? */
+#endif
+
+		SCC.a[chan].TxIP = trueblnr;
+		CheckSCCInterruptFlag();
+	} else {
+		ReportAbnormalID(0x071F,
+			"write when Transmit Buffer not Enabled");
+#if 0 /* TxBufferEmpty always true */
+		SCC.a[chan].TxBufferEmpty = falseblnr;
+#endif
+	}
+}
+
+LOCALPROC SCC_PutWR9(ui3r Data, int chan)
+/*
+	"Master interrupt control and reset
+	(accessed through either channel)"
+*/
+{
+	/* Only 1 WR9 in the SCC */
+
+	UnusedParam(chan);
+
+	if ((Data & Bit0) != 0) { /* VIS */
+		ReportAbnormalID(0x0720, "VIS");
+	}
+
+#if SCC_TrackMore
+	{
+		blnr NewNoVectorSlct = (Data & Bit1) != 0;
+		if (SCC.NoVectorSlct != NewNoVectorSlct) {
+			SCC.NoVectorSlct = NewNoVectorSlct;
+#if SCC_dolog
+			dbglog_WriteSetBool("SCC No Vector select",
+				NewNoVectorSlct);
+#endif
+			/* has both values on boot always */
+		}
+	}
+#endif
+
+	if ((Data & Bit2) != 0) { /* DLC */
+		ReportAbnormalID(0x0723, "DLC");
+	}
+
+	{
+		blnr NewMIE = (Data & Bit3) != 0;
+			/* has both values on boot always */
+		if (SCC.MIE != NewMIE) {
+			SCC.MIE = NewMIE;
+#if SCC_dolog
+			dbglog_WriteSetBool("SCC Master Interrupt Enable",
+				NewMIE);
+#endif
+			CheckSCCInterruptFlag();
+		}
+	}
+
+#if 0 /* StatusHiLo always false */
+	SCC.StatusHiLo = (Data & Bit4) != 0;
+#else
+	if ((Data & Bit4) != 0) { /* Status high/low */
+		ReportAbnormalID(0x0724, "Status high/low");
+	}
+#endif
+	if ((Data & Bit5) != 0) { /* WR9 b5 should be 0 */
+		ReportAbnormalID(0x0725, "WR9 b5 should be 0");
+	}
+
+	switch ((Data >> 6) & 3) {
+		case 1:
+#if SCC_dolog
+			SCC_DbgLogChanCmnd(1, "Channel Reset");
+#endif
+			/* happens on boot always */
+			SCC_ResetChannel(1);
+			CheckSCCInterruptFlag();
+			break;
+		case 2:
+#if SCC_dolog
+			SCC_DbgLogChanCmnd(0, "Channel Reset");
+#endif
+			/* happens on boot always */
+			SCC_ResetChannel(0);
+			CheckSCCInterruptFlag();
+			break;
+		case 3:
+#if SCC_dolog
+			dbglog_WriteNote("SCC Force Hardware Reset");
+#endif
+#if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx)
+			/* don't report */
+#else
+			ReportAbnormalID(0x0726, "SCC_Reset");
+#endif
+			SCC_Reset();
+			CheckSCCInterruptFlag();
+			break;
+		case 0: /* No Reset */
+		default:
+			break;
+	}
+}
+
+LOCALPROC SCC_PutWR10(ui3r Data, int chan)
+/* "Miscellaneous transmitter/receiver control bits" */
+{
+	/* happens on boot with appletalk on */
+	/* happens in Print to ImageWriter */
+
+#if ! SCC_TrackMore
+	UnusedParam(chan);
+#endif
+
+	if ((Data & Bit0) != 0) { /* 6 bit/8 bit sync */
+		ReportAbnormalID(0x0727, "6 bit/8 bit sync");
+	}
+	if ((Data & Bit1) != 0) { /* loop mode */
+		ReportAbnormalID(0x0728, "loop mode");
+	}
+	if ((Data & Bit2) != 0) { /* abort/flag on underrun */
+		ReportAbnormalID(0x0729, "abort/flag on underrun");
+	}
+	if ((Data & Bit3) != 0) { /* mark/flag idle */
+		ReportAbnormalID(0x072A, "mark/flag idle");
+	}
+	if ((Data & Bit4) != 0) { /* go active on poll */
+		ReportAbnormalID(0x072B, "go active on poll");
+	}
+
+#if SCC_TrackMore
+	{
+		ui3r NewDataEncoding = (Data >> 5) & 3;
+		if (SCC.a[chan].DataEncoding != NewDataEncoding) {
+			SCC.a[chan].DataEncoding = NewDataEncoding;
+
+			switch (NewDataEncoding) {
+				case 0:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"Data Encoding <- NRZ");
+#endif
+					/* happens in MacCheck */
+					/* happens in Print to ImageWriter */
+					break;
+				case 1:
+					ReportAbnormalID(0x072C, "Data Encoding <- NRZI");
+					break;
+				case 2:
+					ReportAbnormalID(0x072D, "Data Encoding <- FM1");
+					break;
+				case 3:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"Data Encoding <- FM0");
+#endif
+					/* happens on boot with appletalk on */
+					break;
+			}
+		}
+	}
+#endif
+
+#if SCC_TrackMore
+	{
+		blnr NewCRCPreset = (Data & Bit7) != 0;
+		if (SCC.a[chan].CRCPreset != NewCRCPreset) {
+			SCC.a[chan].CRCPreset = NewCRCPreset;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"CRC preset I/O", NewCRCPreset);
+#endif
+			/* false happens in MacCheck */
+			/* true happens in Print to ImageWriter */
+		}
+	}
+#endif
+}
+
+LOCALPROC SCC_PutWR11(ui3r Data, int chan)
+/* "Clock mode control" */
+{
+	/* happens on boot with appletalk on */
+	/* happens in Print to ImageWriter */
+	/* happens in MacCheck */
+
+#if ! SCC_TrackMore
+	UnusedParam(chan);
+#endif
+
+#if SCC_TrackMore
+	/* Transmit External Control Selection */
+	{
+		ui3r NewTRxCsrc = Data & 3;
+		if (SCC.a[chan].TRxCsrc != NewTRxCsrc) {
+			SCC.a[chan].TRxCsrc = NewTRxCsrc;
+
+			switch (NewTRxCsrc) {
+				case 0:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"TRxC OUT = XTAL output");
+#endif
+					/* happens on boot with appletalk on */
+					/* happens in Print to ImageWriter */
+					/* happens in MacCheck */
+					break;
+				case 1:
+					ReportAbnormalID(0x072E,
+						"TRxC OUT = transmit clock");
+					break;
+				case 2:
+					ReportAbnormalID(0x072F,
+						"TRxC OUT = BR generator output");
+					break;
+				case 3:
+					ReportAbnormalID(0x0730, "TRxC OUT = dpll output");
+					break;
+			}
+		}
+	}
+#endif
+
+	if ((Data & Bit2) != 0) {
+		ReportAbnormalID(0x0731, "TRxC O/I");
+	}
+
+#if SCC_TrackMore
+	{
+		ui3r NewTClkSlct = (Data >> 3) & 3;
+		if (SCC.a[chan].TClkSlct != NewTClkSlct) {
+			SCC.a[chan].TClkSlct = NewTClkSlct;
+
+			switch (NewTClkSlct) {
+				case 0:
+					ReportAbnormalID(0x0732,
+						"transmit clock = RTxC pin");
+					break;
+				case 1:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"transmit clock = TRxC pin");
+#endif
+					/* happens in Print to LaserWriter 300 */
+					break;
+				case 2:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"transmit clock = BR generator output");
+#endif
+					/* happens on boot with appletalk on */
+					/* happens in Print to ImageWriter */
+					/* happens in MacCheck */
+					break;
+				case 3:
+					ReportAbnormalID(0x0733,
+						"transmit clock = dpll output");
+					break;
+			}
+		}
+	}
+#endif
+
+#if SCC_TrackMore
+	{
+		ui3r NewRClkSlct = (Data >> 5) & 3;
+		if (SCC.a[chan].RClkSlct != NewRClkSlct) {
+			SCC.a[chan].RClkSlct = NewRClkSlct;
+
+			switch (NewRClkSlct) {
+				case 0:
+					ReportAbnormalID(0x0734,
+						"receive clock = RTxC pin");
+					break;
+				case 1:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"receive clock = TRxC pin");
+#endif
+					/* happens in Print to LaserWriter 300 */
+					break;
+				case 2:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"receive clock = BR generator output");
+#endif
+					/* happens in MacCheck */
+					/* happens in Print to ImageWriter */
+					break;
+				case 3:
+#if SCC_dolog
+					SCC_DbgLogChanCmnd(chan,
+						"receive clock = dpll output");
+#endif
+					/* happens on boot with appletalk on */
+					break;
+			}
+		}
+	}
+#endif
+
+	if ((Data & Bit7) != 0) {
+		ReportAbnormalID(0x0735, "RTxC XTAL/NO XTAL");
+	}
+}
+
+LOCALPROC SCC_PutWR12(ui3r Data, int chan)
+/* "Lower byte of baud rate generator time constant" */
+{
+	/* happens on boot with appletalk on */
+	/* happens in Print to ImageWriter */
+
+#if ! SCC_TrackMore
+	UnusedParam(Data);
+	UnusedParam(chan);
+#endif
+
+#if SCC_TrackMore /* don't care about Baud */
+	if (SCC.a[chan].BaudLo != Data) {
+		SCC.a[chan].BaudLo = Data;
+
+#if SCC_dolog
+		SCC_DbgLogChanStartLine(chan);
+		dbglog_writeCStr(" BaudLo <- ");
+		dbglog_writeHex(Data);
+		dbglog_writeReturn();
+#endif
+	}
+#endif
+
+#if 0
+	SCC_SetBaud(chan,
+		SCC.a[chan].BaudLo + (SCC.a[chan].BaudHi << 8));
+		/* 380: BaudRate = 300   */
+		/*  94: BaudRate = 1200  */
+		/*  46: BaudRate = 2400  */
+		/*  22: BaudRate = 4800  */
+		/*  10: BaudRate = 9600  */
+		/*   4: BaudRate = 19200 */
+		/*   1: BaudRate = 38400 */
+		/*   0: BaudRate = 57600 */
+#endif
+}
+
+LOCALPROC SCC_PutWR13(ui3r Data, int chan)
+/* "Upper byte of baud rate generator time constant" */
+{
+	/* happens on boot with appletalk on */
+	/* happens in Print to ImageWriter */
+
+#if ! SCC_TrackMore
+	UnusedParam(Data);
+	UnusedParam(chan);
+#endif
+
+#if SCC_TrackMore /* don't care about Baud */
+	if (SCC.a[chan].BaudHi != Data) {
+		SCC.a[chan].BaudHi = Data;
+
+#if SCC_dolog
+		SCC_DbgLogChanStartLine(chan);
+		dbglog_writeCStr(" BaudHi <- ");
+		dbglog_writeHex(Data);
+		dbglog_writeReturn();
+#endif
+	}
+#endif
+
+#if 0
+	SCC_SetBaud(chan,
+		SCC.a[chan].BaudLo + (SCC.a[chan].BaudHi << 8));
+#endif
+}
+
+LOCALPROC SCC_PutWR14(ui3r Data, int chan)
+/* "Miscellaneous control bits" */
+{
+	/* happens on boot with appletalk on */
+
+#if ! (SCC_TrackMore || SCC_dolog)
+	UnusedParam(chan);
+#endif
+
+#if SCC_TrackMore
+	{
+		blnr NewBRGEnbl = (Data & Bit0) != 0;
+		if (SCC.a[chan].BRGEnbl != NewBRGEnbl) {
+			SCC.a[chan].BRGEnbl = NewBRGEnbl;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"BR generator enable", NewBRGEnbl);
+#endif
+			/* both values on boot with appletalk on */
+			/* true happens in Print to ImageWriter */
+		}
+	}
+#endif
+
+	if ((Data & Bit1) != 0) { /* BR generator source */
+		ReportAbnormalID(0x0736, "BR generator source");
+	}
+	if ((Data & Bit2) != 0) { /* DTR/request function */
+		ReportAbnormalID(0x0737, "DTR/request function");
+	}
+	if ((Data & Bit3) != 0) { /* auto echo */
+		ReportAbnormalID(0x0738, "auto echo");
+	}
+	if ((Data & Bit4) != 0) { /* local loopback */
+		ReportAbnormalID(0x0739, "local loopback");
+	}
+
+	switch ((Data >> 5) & 7) {
+		case 1:
+#if SCC_dolog
+			SCC_DbgLogChanCmnd(chan, "enter search mode");
+#endif
+			/* happens on boot with appletalk on */
+			break;
+		case 2:
+#if SCC_dolog
+			SCC_DbgLogChanCmnd(chan, "reset missing clock");
+#endif
+			/* happens on boot with appletalk on */
+			/*
+				should clear Bit 6 and Bit 7 of RR[10], but
+				since these are never set, don't need
+				to do anything
+			*/
+			break;
+		case 3:
+			ReportAbnormalID(0x073A, "disable dpll");
+			/*
+				should clear Bit 6 and Bit 7 of RR[10], but
+				since these are never set, don't need
+				to do anything
+			*/
+			break;
+		case 4:
+			ReportAbnormalID(0x073B, "set source = br generator");
+			break;
+		case 5:
+			ReportAbnormalID(0x073C, "set source = RTxC");
+			break;
+		case 6:
+#if SCC_dolog
+			SCC_DbgLogChanCmnd(chan, "set FM mode");
+#endif
+			/* happens on boot with appletalk on */
+			break;
+		case 7:
+			ReportAbnormalID(0x073D, "set NRZI mode");
+			break;
+		case 0: /* No Reset */
+		default:
+			break;
+	}
+}
+
+LOCALPROC SCC_PutWR15(ui3r Data, int chan)
+/* "External/Status interrupt control" */
+{
+	/* happens on boot always */
+
+#if ! SCC_TrackMore
+	UnusedParam(chan);
+#endif
+
+	if ((Data & Bit0) != 0) { /* WR15 b0 should be 0 */
+		ReportAbnormalID(0x073E, "WR15 b0 should be 0");
+	}
+	if ((Data & Bit1) != 0) { /* zero count IE */
+		ReportAbnormalID(0x073F, "zero count IE");
+	}
+	if ((Data & Bit2) != 0) { /* WR15 b2 should be 0 */
+		ReportAbnormalID(0x0740, "WR15 b2 should be 0");
+	}
+
+#if 0 /* don't care about DCD_IE, always true */
+	SCC.a[chan].DCD_IE = (Data & Bit3) != 0;
+#else
+	if ((Data & Bit3) == 0) { /* DCD_IE */
+#if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx)
+		/* don't report */
+#else
+		ReportAbnormalID(0x0741, "not DCD IE");
+#endif
+	}
+#endif
+
+#if 0 /* SyncHuntIE usually false */
+	SCC.a[chan].SyncHuntIE = (Data & Bit4) != 0;
+#else
+	if ((Data & Bit4) != 0) {
+		/* SYNC/HUNT IE */
+		ReportAbnormalID(0x0742, "SYNC/HUNT IE");
+	}
+#endif
+
+#if SCC_TrackMore /* don't care about CTS_IE */
+	{
+		blnr NewCTS_IE = (Data & Bit5) != 0;
+		if (SCC.a[chan].CTS_IE != NewCTS_IE) {
+			SCC.a[chan].CTS_IE = NewCTS_IE;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"CTS IE", NewCTS_IE);
+#endif
+			/* happens in MacCheck */
+			/* happens in Print to ImageWriter */
+		}
+	}
+#endif
+
+	if ((Data & Bit6) != 0) { /* Tx underrun/EOM IE */
+		ReportAbnormalID(0x0743, "Tx underrun/EOM IE");
+	}
+
+#if SCC_TrackMore
+	{
+		blnr NewBreakAbortIE = (Data & Bit7) != 0;
+		if (SCC.a[chan].BreakAbortIE != NewBreakAbortIE) {
+			SCC.a[chan].BreakAbortIE = NewBreakAbortIE;
+#if SCC_dolog
+			SCC_DbgLogChanChngBit(chan,
+				"BreakAbort IE", NewBreakAbortIE);
+#endif
+			/* happens in MacCheck */
+			/* happens in Print to ImageWriter */
+		}
+	}
+#endif
+}
+
+LOCALFUNC ui3r SCC_GetReg(int chan, ui3r SCC_Reg)
+{
+	ui3r value;
+
+	switch (SCC_Reg) {
+		case 0:
+			value = SCC_GetRR0(chan);
+			break;
+		case 1:
+			value = SCC_GetRR1(chan);
+			break;
+		case 2:
+			value = SCC_GetRR2(chan);
+			break;
+		case 3:
+			value = SCC_GetRR3(chan);
+			break;
+		case 4:
+			ReportAbnormalID(0x0744, "RR 4"); /* same as RR0 */
+			value = SCC_GetRR0(chan);
+			break;
+		case 5:
+			ReportAbnormalID(0x0745, "RR 5"); /* same as RR1 */
+			value = SCC_GetRR1(chan);
+			break;
+		case 6:
+			ReportAbnormalID(0x0746, "RR 6"); /* same as RR2 */
+			value = SCC_GetRR2(chan);
+			break;
+		case 7:
+			ReportAbnormalID(0x0747, "RR 7"); /* same as RR3 */
+			value = SCC_GetRR3(chan);
+			break;
+		case 8:
+			value = SCC_GetRR8(chan);
+			break;
+		case 9:
+			ReportAbnormalID(0x0748, "RR 9"); /* same as RR13 */
+			value = SCC_GetRR13(chan);
+			break;
+		case 10:
+			value = SCC_GetRR10(chan);
+			break;
+		case 11:
+			ReportAbnormalID(0x0749, "RR 11"); /* same as RR15 */
+			value = SCC_GetRR15(chan);
+			break;
+		case 12:
+			value = SCC_GetRR12(chan);
+			break;
+		case 13:
+			value = SCC_GetRR13(chan);
+			break;
+		case 14:
+			ReportAbnormalID(0x074A, "RR 14");
+			value = 0;
+			break;
+		case 15:
+			value = SCC_GetRR15(chan);
+			break;
+		default:
+			ReportAbnormalID(0x074B,
+				"unexpected SCC_Reg in SCC_GetReg");
+			value = 0;
+			break;
+	}
+
+#if EmLocalTalk
+	/*
+		Always check to see if interrupt state changed after
+		ANY register access
+	*/
+	CheckSCCInterruptFlag();
+#endif
+
+#if SCC_dolog
+	SCC_DbgLogChanStartLine(chan);
+	dbglog_writeCStr(" RR[");
+	dbglog_writeHex(SCC_Reg);
+	dbglog_writeCStr("] -> ");
+	dbglog_writeHex(value);
+	dbglog_writeReturn();
+#endif
+
+	return value;
+}
+
+LOCALPROC SCC_PutReg(ui3r Data, int chan, ui3r SCC_Reg)
+{
+#if SCC_dolog && 0
+	SCC_DbgLogChanStartLine(chan);
+	dbglog_writeCStr(" WR[");
+	dbglog_writeHex(SCC_Reg);
+	dbglog_writeCStr("] <- ");
+	dbglog_writeHex(Data);
+	dbglog_writeReturn();
+#endif
+
+	switch (SCC_Reg) {
+		case 0:
+			SCC_PutWR0(Data, chan);
+			break;
+		case 1:
+			SCC_PutWR1(Data, chan);
+			break;
+		case 2:
+			SCC_PutWR2(Data, chan);
+			break;
+		case 3:
+			SCC_PutWR3(Data, chan);
+			break;
+		case 4:
+			SCC_PutWR4(Data, chan);
+			break;
+		case 5:
+			SCC_PutWR5(Data, chan);
+			break;
+		case 6:
+			SCC_PutWR6(Data, chan);
+			break;
+		case 7:
+			SCC_PutWR7(Data, chan);
+			break;
+		case 8:
+			SCC_PutWR8(Data, chan);
+			break;
+		case 9:
+			SCC_PutWR9(Data, chan);
+			break;
+		case 10:
+			SCC_PutWR10(Data, chan);
+			break;
+		case 11:
+			SCC_PutWR11(Data, chan);
+			break;
+		case 12:
+			SCC_PutWR12(Data, chan);
+			break;
+		case 13:
+			SCC_PutWR13(Data, chan);
+			break;
+		case 14:
+			SCC_PutWR14(Data, chan);
+			break;
+		case 15:
+			SCC_PutWR15(Data, chan);
+			break;
+		default:
+			ReportAbnormalID(0x074C,
+				"unexpected SCC_Reg in SCC_PutReg");
+			break;
+	}
+
+#if EmLocalTalk
+	/*
+		Always check to see if interrupt state changed after ANY
+		register access
+	*/
+	CheckSCCInterruptFlag();
+#endif
+}
+
+GLOBALFUNC ui5b SCC_Access(ui5b Data, blnr WriteMem, CPTR addr)
+{
+#if EmLocalTalk
+	/*
+		Determine channel, data, and access type from address.  The bus
+		for the 8350 is non-standard, so the Macintosh connects address
+		bus lines to various signals on the 8350 as shown below. The
+		68K will use the upper byte of the data bus for odd addresses,
+		and the 8350 is only wired to the upper byte, therefore use
+		only odd addresses or you risk resetting the 8350.
+
+		68k   8350
+		----- ------
+		a1    a/b
+		a2    d/c
+		a21   wr/rd
+	*/
+#endif
+	ui3b SCC_Reg;
+	int chan = (~ addr) & 1; /* 0=modem, 1=printer */
+	if (((addr >> 1) & 1) == 0) {
+		/* Channel Control */
+		SCC_Reg = SCC.PointerBits;
+		SCC.PointerBits = 0;
+	} else {
+		/* Channel Data */
+		SCC_Reg = 8;
+	}
+	if (WriteMem) {
+		SCC_PutReg(Data, chan, SCC_Reg);
+	} else {
+		Data = SCC_GetReg(chan, SCC_Reg);
+	}
+
+	return Data;
+}
--- /dev/null
+++ b/src/SCCEMDEV.h
@@ -1,0 +1,32 @@
+/*
+	SCCEMDEV.h
+
+	Copyright (C) 2004 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef SCCEMDEV_H
+#error "header already included"
+#else
+#define SCCEMDEV_H
+#endif
+
+EXPORTPROC SCC_Reset(void);
+
+EXPORTFUNC ui5b SCC_Access(ui5b Data, blnr WriteMem, CPTR addr);
+
+EXPORTFUNC blnr SCC_InterruptsEnabled(void);
+
+#if EmLocalTalk
+EXPORTPROC LocalTalkTick(void);
+EXPORTFUNC int InitLocalTalk(void);
+#endif
--- /dev/null
+++ b/src/SCRNEMDV.c
@@ -1,0 +1,59 @@
+/*
+	SCRNEMDV.c
+
+	Copyright (C) 2006 Philip Cummins, Richard F. Bannister,
+		Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	SCReeN EMulated DeVice
+
+	Emulation of the screen in the Mac Plus.
+
+	This code descended from "Screen-MacOS.c" in Richard F. Bannister's
+	Macintosh port of vMac, by Philip Cummins.
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+#include "MYOSGLUE.h"
+#include "ENDIANAC.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+#endif
+
+#include "SCRNEMDV.h"
+
+#if ! IncludeVidMem
+#define kMain_Offset      0x5900
+#define kAlternate_Offset 0xD900
+#define kMain_Buffer      (kRAM_Size - kMain_Offset)
+#define kAlternate_Buffer (kRAM_Size - kAlternate_Offset)
+#endif
+
+GLOBALPROC Screen_EndTickNotify(void)
+{
+	ui3p screencurrentbuff;
+
+#if IncludeVidMem
+	screencurrentbuff = VidMem;
+#else
+	if (SCRNvPage2 == 1) {
+		screencurrentbuff = get_ram_address(kMain_Buffer);
+	} else {
+		screencurrentbuff = get_ram_address(kAlternate_Buffer);
+	}
+#endif
+
+	Screen_OutputFrame(screencurrentbuff);
+}
--- /dev/null
+++ b/src/SCRNEMDV.h
@@ -1,0 +1,24 @@
+/*
+	SCRNEMDV.h
+
+	Copyright (C) 2006 Philip Cummins, Richard F. Bannister,
+		Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef SCRNEMDV_H
+#error "header already included"
+#else
+#define SCRNEMDV_H
+#endif
+
+EXPORTPROC Screen_EndTickNotify(void);
--- /dev/null
+++ b/src/SCRNHACK.h
@@ -1,0 +1,397 @@
+/*
+	SCRNHACK.h
+
+	Copyright (C) 2007 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	SCReeN Hack
+
+	Patch ROM to support other screen sizes.
+*/
+
+
+#if CurEmMd <= kEmMd_128K
+	do_put_mem_long(112 + ROM, kVidMem_Base);
+	do_put_mem_long(260 + ROM, kVidMem_Base);
+	do_put_mem_long(292 + ROM, kVidMem_Base
+		+ (((vMacScreenHeight / 4) * 2 + 9) * vMacScreenWidth
+			+ (vMacScreenWidth / 2 - 24))
+			/ 8);
+
+	/* sad mac, error code */
+	do_put_mem_word(330 + ROM, vMacScreenWidth / 8);
+	do_put_mem_word(342 + ROM, vMacScreenWidth / 8);
+	do_put_mem_word(350 + ROM, vMacScreenWidth / 4 * 3 - 1);
+	/* sad mac, blink pixels */
+	do_put_mem_word(358 + ROM, vMacScreenWidth - 4);
+
+	do_put_mem_word(456 + ROM,
+		(vMacScreenHeight * vMacScreenWidth / 32) - 1 + 32);
+
+	/* screen setup, main */
+	{
+		pto = 862 + ROM;
+		do_put_mem_word(pto, 0x4EB9); /* JSR */
+		pto += 2;
+		do_put_mem_long(pto, kROM_Base + (patchp - ROM));
+		pto += 4;
+
+		do_put_mem_word(patchp, 0x21FC); /* MOVE.L */
+		patchp += 2;
+		do_put_mem_long(patchp, kVidMem_Base); /* kVidMem_Base */
+		patchp += 4;
+		do_put_mem_word(patchp, 0x0824); /* (ScrnBase) */
+		patchp += 2;
+		do_put_mem_word(patchp, 0x4E75); /* RTS */
+		patchp += 2;
+	}
+	do_put_mem_word(892 + ROM, vMacScreenHeight - 1);
+	do_put_mem_word(894 + ROM, vMacScreenWidth - 1);
+
+	/* blink floppy, disk icon */
+	do_put_mem_long(1388 + ROM, kVidMem_Base
+		+ (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth
+			+ (vMacScreenWidth / 2 - 16))
+			/ 8);
+	/* blink floppy, question mark */
+	do_put_mem_long(1406 + ROM, kVidMem_Base
+		+ (((vMacScreenHeight / 4) * 2 - 10) * vMacScreenWidth
+			+ (vMacScreenWidth / 2 - 8))
+			/ 8);
+
+	/* blink floppy and sadmac, position */
+	do_put_mem_word(1966 + ROM, vMacScreenWidth / 8 - 4);
+	do_put_mem_word(1982 + ROM, vMacScreenWidth / 8);
+	/* sad mac, mac icon */
+	do_put_mem_long(2008 + ROM, kVidMem_Base
+		+ (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth
+			+ (vMacScreenWidth / 2 - 16))
+			/ 8);
+	/* sad mac, frown */
+	do_put_mem_long(2020 + ROM, kVidMem_Base
+		+ (((vMacScreenHeight / 4) * 2 - 19) * vMacScreenWidth
+			+ (vMacScreenWidth / 2 - 8))
+			/ 8);
+	do_put_mem_word(2052 + ROM, vMacScreenWidth / 8 - 2);
+
+	/* cursor handling */
+#if vMacScreenWidth >= 1024
+	pto = 3448 + ROM;
+	do_put_mem_word(pto, 0x4EB9); /* JSR */
+	pto += 2;
+	do_put_mem_long(pto, kROM_Base + (patchp - ROM));
+	pto += 4;
+
+	do_put_mem_word(patchp, 0x41F8); /* Lea.L     (CrsrSave),A0 */
+	patchp += 2;
+	do_put_mem_word(patchp, 0x088C);
+	patchp += 2;
+	do_put_mem_word(patchp, 0x203C); /* MOVE.L #$x,D0 */
+	patchp += 2;
+	do_put_mem_long(patchp, (vMacScreenWidth / 8));
+	patchp += 4;
+	do_put_mem_word(patchp, 0x4E75); /* RTS */
+	patchp += 2;
+#else
+	do_put_mem_word(3452 + ROM, 0x7000 + (vMacScreenWidth / 8));
+#endif
+	do_put_mem_word(3572 + ROM, vMacScreenWidth - 32);
+	do_put_mem_word(3578 + ROM, vMacScreenWidth - 32);
+	do_put_mem_word(3610 + ROM, vMacScreenHeight - 16);
+	do_put_mem_word(3616 + ROM, vMacScreenHeight);
+#if vMacScreenWidth >= 1024
+	pto = 3646 + ROM;
+	do_put_mem_word(pto, 0x4EB9); /* JSR */
+	pto += 2;
+	do_put_mem_long(pto, kROM_Base + (patchp - ROM));
+	pto += 4;
+
+	do_put_mem_word(patchp, 0x2A3C); /* MOVE.L #$x,D5 */
+	patchp += 2;
+	do_put_mem_long(patchp, (vMacScreenWidth / 8));
+	patchp += 4;
+	do_put_mem_word(patchp, 0xC2C5); /* MulU      D5,D1 */
+	patchp += 2;
+	do_put_mem_word(patchp, 0xD3C1); /* AddA.L    D1,A1 */
+	patchp += 2;
+	do_put_mem_word(patchp, 0x4E75); /* RTS */
+	patchp += 2;
+#else
+	do_put_mem_word(3646 + ROM, 0x7A00 + (vMacScreenWidth / 8));
+#endif
+
+	/* set up screen bitmap */
+	do_put_mem_word(3832 + ROM, vMacScreenHeight);
+	do_put_mem_word(3838 + ROM, vMacScreenWidth);
+	/* do_put_mem_word(7810 + ROM, vMacScreenHeight); */
+
+#elif CurEmMd <= kEmMd_Plus
+
+	do_put_mem_long(138 + ROM, kVidMem_Base);
+	do_put_mem_long(326 + ROM, kVidMem_Base);
+	do_put_mem_long(356 + ROM, kVidMem_Base
+		+ (((vMacScreenHeight / 4) * 2 + 9) * vMacScreenWidth
+			+ (vMacScreenWidth / 2 - 24))
+			/ 8);
+
+	/* sad mac, error code */
+	do_put_mem_word(392 + ROM, vMacScreenWidth / 8);
+	do_put_mem_word(404 + ROM, vMacScreenWidth / 8);
+	do_put_mem_word(412 + ROM, vMacScreenWidth / 4 * 3 - 1);
+	/* sad mac, blink pixels */
+	do_put_mem_long(420 + ROM, kVidMem_Base
+		+ (((vMacScreenHeight / 4) * 2 + 17) * vMacScreenWidth
+			+ (vMacScreenWidth / 2 - 8))
+			/ 8);
+
+	do_put_mem_word(494 + ROM,
+		(vMacScreenHeight * vMacScreenWidth / 32) - 1);
+
+	/* screen setup, main */
+	{
+		pto = 1132 + ROM;
+		do_put_mem_word(pto, 0x4EB9); /* JSR */
+		pto += 2;
+		do_put_mem_long(pto, kROM_Base + (patchp - ROM));
+		pto += 4;
+
+		do_put_mem_word(patchp, 0x21FC); /* MOVE.L */
+		patchp += 2;
+		do_put_mem_long(patchp, kVidMem_Base); /* kVidMem_Base */
+		patchp += 4;
+		do_put_mem_word(patchp, 0x0824); /* (ScrnBase) */
+		patchp += 2;
+		do_put_mem_word(patchp, 0x4E75); /* RTS */
+		patchp += 2;
+	}
+	do_put_mem_word(1140 + ROM, vMacScreenWidth / 8);
+	do_put_mem_word(1172 + ROM, vMacScreenHeight);
+	do_put_mem_word(1176 + ROM, vMacScreenWidth);
+
+	/* blink floppy, disk icon */
+	do_put_mem_long(2016 + ROM, kVidMem_Base
+		+ (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth
+			+ (vMacScreenWidth / 2 - 16))
+			/ 8);
+	/* blink floppy, question mark */
+	do_put_mem_long(2034 + ROM, kVidMem_Base
+		+ (((vMacScreenHeight / 4) * 2 - 10) * vMacScreenWidth
+			+ (vMacScreenWidth / 2 - 8))
+			/ 8);
+
+	do_put_mem_word(2574 + ROM, vMacScreenHeight);
+	do_put_mem_word(2576 + ROM, vMacScreenWidth);
+
+	/* blink floppy and sadmac, position */
+	do_put_mem_word(3810 + ROM, vMacScreenWidth / 8 - 4);
+	do_put_mem_word(3826 + ROM, vMacScreenWidth / 8);
+	/* sad mac, mac icon */
+	do_put_mem_long(3852 + ROM, kVidMem_Base
+		+ (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth
+			+ (vMacScreenWidth / 2 - 16))
+			/ 8);
+	/* sad mac, frown */
+	do_put_mem_long(3864 + ROM, kVidMem_Base
+		+ (((vMacScreenHeight / 4) * 2 - 19) * vMacScreenWidth
+			+ (vMacScreenWidth / 2 - 8))
+			/ 8);
+	do_put_mem_word(3894 + ROM, vMacScreenWidth / 8 - 2);
+
+	/* cursor handling */
+#if vMacScreenWidth >= 1024
+	pto = 7372 + ROM;
+	do_put_mem_word(pto, 0x4EB9); /* JSR */
+	pto += 2;
+	do_put_mem_long(pto, kROM_Base + (patchp - ROM));
+	pto += 4;
+
+	do_put_mem_word(patchp, 0x41F8); /* Lea.L     (CrsrSave), A0 */
+	patchp += 2;
+	do_put_mem_word(patchp, 0x088C);
+	patchp += 2;
+	do_put_mem_word(patchp, 0x203C); /* MOVE.L #$x, D0 */
+	patchp += 2;
+	do_put_mem_long(patchp, (vMacScreenWidth / 8));
+	patchp += 4;
+	do_put_mem_word(patchp, 0x4E75); /* RTS */
+	patchp += 2;
+#else
+	do_put_mem_word(7376 + ROM, 0x7000 + (vMacScreenWidth / 8));
+#endif
+	do_put_mem_word(7496 + ROM, vMacScreenWidth - 32);
+	do_put_mem_word(7502 + ROM, vMacScreenWidth - 32);
+	do_put_mem_word(7534 + ROM, vMacScreenHeight - 16);
+	do_put_mem_word(7540 + ROM, vMacScreenHeight);
+#if vMacScreenWidth >= 1024
+	pto = 7570 + ROM;
+	do_put_mem_word(pto, 0x4EB9); /* JSR */
+	pto += 2;
+	do_put_mem_long(pto, kROM_Base + (patchp - ROM));
+	pto += 4;
+
+	do_put_mem_word(patchp, 0x2A3C); /* MOVE.L #$x,D5 */
+	patchp += 2;
+	do_put_mem_long(patchp, (vMacScreenWidth / 8));
+	patchp += 4;
+	do_put_mem_word(patchp, 0xC2C5); /* MulU      D5,D1 */
+	patchp += 2;
+	do_put_mem_word(patchp, 0xD3C1); /* AddA.L    D1,A1 */
+	patchp += 2;
+	do_put_mem_word(patchp, 0x4E75); /* RTS */
+	patchp += 2;
+#else
+	do_put_mem_word(7570 + ROM, 0x7A00 + (vMacScreenWidth / 8));
+#endif
+
+	/* set up screen bitmap */
+	do_put_mem_word(7784 + ROM, vMacScreenHeight);
+	do_put_mem_word(7790 + ROM, vMacScreenWidth);
+	do_put_mem_word(7810 + ROM, vMacScreenHeight);
+
+#if 0
+	/*
+		Haven't got these working. Alert outlines ok, but
+		not contents. Perhaps global position of contents
+		stored in system resource file.
+	*/
+
+	/* perhaps switch disk alert */
+	do_put_mem_word(10936 + ROM, vMacScreenHeight / 2 - 91);
+	do_put_mem_word(10938 + ROM, vMacScreenWidth / 2 - 136);
+	do_put_mem_word(10944 + ROM, vMacScreenHeight / 2 - 19);
+	do_put_mem_word(10946 + ROM, vMacScreenWidth / 2 + 149);
+
+	do_put_mem_word(11008 + ROM, ?);
+	do_put_mem_word(11010 + ROM, ?);
+
+	/* DSAlertRect */
+	do_put_mem_word(4952 + ROM, vMacScreenHeight / 2 - 107);
+	do_put_mem_word(4954 + ROM, vMacScreenWidth / 2 - 236);
+	do_put_mem_word(4958 + ROM, vMacScreenHeight / 2 + 19);
+	do_put_mem_word(4960 + ROM, vMacScreenWidth / 2 + 236);
+
+	do_put_mem_word(5212 + ROM, vMacScreenHeight / 2 - 101);
+	do_put_mem_word(5214 + ROM, vMacScreenWidth / 2 - 218);
+#endif
+
+#elif CurEmMd <= kEmMd_Classic
+
+	/* screen setup, main */
+	{
+		pto = 1482 + ROM;
+		do_put_mem_word(pto, 0x4EB9); /* JSR */
+		pto += 2;
+		do_put_mem_long(pto, kROM_Base + (patchp - ROM));
+		pto += 4;
+
+		do_put_mem_word(patchp, 0x21FC); /* MOVE.L */
+		patchp += 2;
+		do_put_mem_long(patchp, kVidMem_Base); /* kVidMem_Base */
+		patchp += 4;
+		do_put_mem_word(patchp, 0x0824); /* (ScrnBase) */
+		patchp += 2;
+		do_put_mem_word(patchp, 0x4E75); /* RTS */
+		patchp += 2;
+	}
+	do_put_mem_word(1490 + ROM, vMacScreenWidth / 8);
+	do_put_mem_word(1546 + ROM, vMacScreenHeight);
+	do_put_mem_word(1550 + ROM, vMacScreenWidth);
+
+	do_put_mem_word(2252 + ROM, vMacScreenHeight);
+	do_put_mem_word(2254 + ROM, vMacScreenWidth);
+
+	/* blink floppy, disk icon */
+	do_put_mem_long(3916 + ROM, kVidMem_Base
+		+ (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth
+			+ (vMacScreenWidth / 2 - 16))
+			/ 8);
+	/* blink floppy, question mark */
+	do_put_mem_long(3934 + ROM, kVidMem_Base
+		+ (((vMacScreenHeight / 4) * 2 - 10) * vMacScreenWidth
+			+ (vMacScreenWidth / 2 - 8))
+			/ 8);
+
+	do_put_mem_long(4258 + ROM, kVidMem_Base);
+	do_put_mem_word(4264 + ROM, vMacScreenHeight);
+	do_put_mem_word(4268 + ROM, vMacScreenWidth);
+	do_put_mem_word(4272 + ROM, vMacScreenWidth / 8);
+	do_put_mem_long(4276 + ROM, vMacScreenNumBytes);
+
+	/* sad mac, mac icon */
+	do_put_mem_long(4490 + ROM, kVidMem_Base
+		+ (((vMacScreenHeight / 4) * 2 - 25) * vMacScreenWidth
+			+ (vMacScreenWidth / 2 - 16))
+			/ 8);
+	/* sad mac, frown */
+	do_put_mem_long(4504 + ROM, kVidMem_Base
+		+ (((vMacScreenHeight / 4) * 2 - 19) * vMacScreenWidth
+			+ (vMacScreenWidth / 2 - 8))
+			/ 8);
+	do_put_mem_word(4528 + ROM, vMacScreenWidth / 8);
+	/* blink floppy and sadmac, position */
+	do_put_mem_word(4568 + ROM, vMacScreenWidth / 8);
+	do_put_mem_word(4586 + ROM, vMacScreenWidth / 8);
+
+	/* cursor handling */
+#if vMacScreenWidth >= 1024
+	pto = 101886 + ROM;
+	do_put_mem_word(pto, 0x4EB9); /* JSR */
+	pto += 2;
+	do_put_mem_long(pto, kROM_Base + (patchp - ROM));
+	pto += 4;
+
+	do_put_mem_word(patchp, 0x41F8); /* Lea.L     (CrsrSave),A0 */
+	patchp += 2;
+	do_put_mem_word(patchp, 0x088C);
+	patchp += 2;
+	do_put_mem_word(patchp, 0x203C); /* MOVE.L #$x,D0 */
+	patchp += 2;
+	do_put_mem_long(patchp, (vMacScreenWidth / 8));
+	patchp += 4;
+	do_put_mem_word(patchp, 0x4E75); /* RTS */
+	patchp += 2;
+#else
+	do_put_mem_word(101890 + ROM, 0x7000 + (vMacScreenWidth / 8));
+#endif
+	do_put_mem_word(102010 + ROM, vMacScreenWidth - 32);
+	do_put_mem_word(102016 + ROM, vMacScreenWidth - 32);
+	do_put_mem_word(102048 + ROM, vMacScreenHeight - 16);
+	do_put_mem_word(102054 + ROM, vMacScreenHeight);
+#if vMacScreenWidth >= 1024
+	pto = 102084 + ROM;
+	do_put_mem_word(pto, 0x4EB9); /* JSR */
+	pto += 2;
+	do_put_mem_long(pto, kROM_Base + (patchp - ROM));
+	pto += 4;
+
+	do_put_mem_word(patchp, 0x2A3C); /* MOVE.L #$x, D5 */
+	patchp += 2;
+	do_put_mem_long(patchp, (vMacScreenWidth / 8));
+	patchp += 4;
+	do_put_mem_word(patchp, 0xC2C5); /* MulU      D5, D1 */
+	patchp += 2;
+	do_put_mem_word(patchp, 0xD3C1); /* AddA.L    D1, A1 */
+	patchp += 2;
+	do_put_mem_word(patchp, 0x4E75); /* RTS */
+	patchp += 2;
+#else
+	do_put_mem_word(102084 + ROM, 0x7A00 + (vMacScreenWidth / 8));
+#endif
+
+	/* set up screen bitmap */
+	do_put_mem_word(102298 + ROM, vMacScreenHeight);
+	do_put_mem_word(102304 + ROM, vMacScreenWidth);
+	do_put_mem_word(102324 + ROM, vMacScreenHeight);
+
+#endif
--- /dev/null
+++ b/src/SCRNMAPR.h
@@ -1,0 +1,168 @@
+/*
+	SCRNMAPR.h
+
+	Copyright (C) 2012 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	SCReeN MAPpeR
+*/
+
+/* required arguments for this template */
+
+#ifndef ScrnMapr_DoMap /* procedure to be created by this template */
+#error "ScrnMapr_DoMap not defined"
+#endif
+#ifndef ScrnMapr_Src
+#error "ScrnMapr_Src not defined"
+#endif
+#ifndef ScrnMapr_Dst
+#error "ScrnMapr_Dst not defined"
+#endif
+#ifndef ScrnMapr_SrcDepth
+#error "ScrnMapr_SrcDepth not defined"
+#endif
+#ifndef ScrnMapr_DstDepth
+#error "ScrnMapr_DstDepth not defined"
+#endif
+#ifndef ScrnMapr_Map
+#error "ScrnMapr_Map not defined"
+#endif
+
+/* optional argument for this template */
+
+#ifndef ScrnMapr_Scale
+#define ScrnMapr_Scale 1
+#endif
+
+/* check of parameters */
+
+#if (ScrnMapr_SrcDepth < 0) || (ScrnMapr_SrcDepth > 3)
+#error "bad ScrnMapr_SrcDepth"
+#endif
+
+#if (ScrnMapr_DstDepth < ScrnMapr_SrcDepth)
+#error "bad ScrnMapr_Dst"
+#endif
+
+/* calculate a few things local to this template */
+
+#define ScrnMapr_MapElSz \
+	(ScrnMapr_Scale << (ScrnMapr_DstDepth - ScrnMapr_SrcDepth))
+
+#if 0 == (ScrnMapr_MapElSz & 3)
+#define ScrnMapr_TranT ui5b
+#define ScrnMapr_TranLn2Sz 2
+#elif 0 == (ScrnMapr_MapElSz & 1)
+#define ScrnMapr_TranT ui4b
+#define ScrnMapr_TranLn2Sz 1
+#else
+#define ScrnMapr_TranT ui3b
+#define ScrnMapr_TranLn2Sz 0
+#endif
+
+#define ScrnMapr_TranN (ScrnMapr_MapElSz >> ScrnMapr_TranLn2Sz)
+
+#define ScrnMapr_ScrnWB (vMacScreenWidth >> (3 - ScrnMapr_SrcDepth))
+
+/* now define the procedure */
+
+LOCALPROC ScrnMapr_DoMap(si4b top, si4b left,
+	si4b bottom, si4b right)
+{
+	int i;
+	int j;
+#if (ScrnMapr_TranN > 4) || (ScrnMapr_Scale > 2)
+	int k;
+#endif
+	ui5r t0;
+	ScrnMapr_TranT *pMap;
+#if ScrnMapr_Scale > 1
+	ScrnMapr_TranT *p3;
+#endif
+
+	ui4r leftB = left >> (3 - ScrnMapr_SrcDepth);
+	ui4r rightB = (right + (1 << (3 - ScrnMapr_SrcDepth)) - 1)
+		>> (3 - ScrnMapr_SrcDepth);
+	ui4r jn = rightB - leftB;
+	ui4r SrcSkip = ScrnMapr_ScrnWB - jn;
+	ui3b *pSrc = ((ui3b *)ScrnMapr_Src)
+		+ leftB + ScrnMapr_ScrnWB * (ui5r)top;
+	ScrnMapr_TranT *pDst = ((ScrnMapr_TranT *)ScrnMapr_Dst)
+		+ ((leftB + ScrnMapr_ScrnWB * ScrnMapr_Scale * (ui5r)top)
+			* ScrnMapr_TranN);
+	ui5r DstSkip = SrcSkip * ScrnMapr_TranN;
+
+	for (i = bottom - top; --i >= 0; ) {
+#if ScrnMapr_Scale > 1
+		p3 = pDst;
+#endif
+
+		for (j = jn; --j >= 0; ) {
+			t0 = *pSrc++;
+			pMap =
+				&((ScrnMapr_TranT *)ScrnMapr_Map)[t0 * ScrnMapr_TranN];
+
+#if ScrnMapr_TranN > 4
+			for (k = ScrnMapr_TranN; --k >= 0; ) {
+				*pDst++ = *pMap++;
+			}
+#else
+
+#if ScrnMapr_TranN >= 2
+			*pDst++ = *pMap++;
+#endif
+#if ScrnMapr_TranN >= 3
+			*pDst++ = *pMap++;
+#endif
+#if ScrnMapr_TranN >= 4
+			*pDst++ = *pMap++;
+#endif
+			*pDst++ = *pMap;
+
+#endif /* ! ScrnMapr_TranN > 4 */
+
+		}
+		pSrc += SrcSkip;
+		pDst += DstSkip;
+
+#if ScrnMapr_Scale > 1
+#if ScrnMapr_Scale > 2
+		for (k = ScrnMapr_Scale - 1; --k >= 0; )
+#endif
+		{
+			pMap = p3;
+			for (j = ScrnMapr_TranN * jn; --j >= 0; ) {
+				*pDst++ = *pMap++;
+			}
+			pDst += DstSkip;
+		}
+#endif /* ScrnMapr_Scale > 1 */
+	}
+}
+
+/* undefine template locals and parameters */
+
+#undef ScrnMapr_ScrnWB
+#undef ScrnMapr_TranN
+#undef ScrnMapr_TranLn2Sz
+#undef ScrnMapr_TranT
+#undef ScrnMapr_MapElSz
+
+#undef ScrnMapr_DoMap
+#undef ScrnMapr_Src
+#undef ScrnMapr_Dst
+#undef ScrnMapr_SrcDepth
+#undef ScrnMapr_DstDepth
+#undef ScrnMapr_Map
+#undef ScrnMapr_Scale
--- /dev/null
+++ b/src/SCRNTRNS.h
@@ -1,0 +1,161 @@
+/*
+	SCRNTRNS.h
+
+	Copyright (C) 2012 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	SCReeN TRaNSlater
+*/
+
+/* required arguments for this template */
+
+#ifndef ScrnTrns_DoTrans /* procedure to be created by this template */
+#error "ScrnTrns_DoTrans not defined"
+#endif
+#ifndef ScrnTrns_Src
+#error "ScrnTrns_Src not defined"
+#endif
+#ifndef ScrnTrns_Dst
+#error "ScrnTrns_Dst not defined"
+#endif
+#ifndef ScrnTrns_SrcDepth
+#error "ScrnTrns_SrcDepth not defined"
+#endif
+#ifndef ScrnTrns_DstDepth
+#error "ScrnTrns_DstDepth not defined"
+#endif
+
+/* optional argument for this template */
+
+#ifndef ScrnTrns_Scale
+#define ScrnTrns_Scale 1
+#endif
+
+#ifndef ScrnTrns_DstZLo
+#define ScrnTrns_DstZLo 0
+#endif
+
+/* check of parameters */
+
+#if (ScrnTrns_SrcDepth < 4)
+#error "bad ScrnTrns_SrcDepth"
+#endif
+
+#if (ScrnTrns_DstDepth < 4)
+#error "bad ScrnTrns_Dst"
+#endif
+
+/* now define the procedure */
+
+LOCALPROC ScrnTrns_DoTrans(si4b top, si4b left,
+	si4b bottom, si4b right)
+{
+	int i;
+	int j;
+	ui5b t0;
+	ui5b t1;
+	ui4r jn = right - left;
+	ui4r SrcSkip = vMacScreenByteWidth
+		- (jn << (ScrnTrns_SrcDepth - 3));
+	ui3b *pSrc = ((ui3b *)ScrnTrns_Src)
+		+ (left << (ScrnTrns_SrcDepth - 3))
+		+ vMacScreenByteWidth * (ui5r)top;
+	ui5b *pDst = ((ui5b *)ScrnTrns_Dst)
+		+ left * ScrnTrns_Scale
+		+ (ui5r)vMacScreenWidth * ScrnTrns_Scale * ScrnTrns_Scale * top;
+	ui4r DstSkip = (vMacScreenWidth - jn) * ScrnTrns_Scale;
+#if ScrnTrns_Scale > 1
+	int k;
+	ui5b *p3;
+	ui5b *p4;
+#endif
+
+	for (i = bottom - top; --i >= 0; ) {
+#if ScrnTrns_Scale > 1
+		p3 = pDst;
+#endif
+
+		for (j = jn; --j >= 0; ) {
+#if 4 == ScrnTrns_SrcDepth
+			t0 = do_get_mem_word(pSrc);
+			pSrc += 2;
+			t1 =
+#if ScrnTrns_DstZLo
+				((t0 & 0x7C00) << 17) |
+				((t0 & 0x7000) << 12) |
+				((t0 & 0x03E0) << 14) |
+				((t0 & 0x0380) << 9) |
+				((t0 & 0x001F) << 11) |
+				((t0 & 0x001C) << 6);
+#else
+				((t0 & 0x7C00) << 9) |
+				((t0 & 0x7000) << 4) |
+				((t0 & 0x03E0) << 6) |
+				((t0 & 0x0380) << 1) |
+				((t0 & 0x001F) << 3) |
+				((t0 & 0x001C) >> 2);
+#endif
+#if 0
+				((t0 & 0x7C00) << 1) |
+				((t0 & 0x7000) >> 4) |
+				((t0 & 0x03E0) << 14) |
+				((t0 & 0x0380) << 9) |
+				((t0 & 0x001F) << 27) |
+				((t0 & 0x001C) << 22);
+#endif
+
+#elif 5 == ScrnTrns_SrcDepth
+			t0 = do_get_mem_long(pSrc);
+			pSrc += 4;
+#if ScrnTrns_DstZLo
+			t1 = t0 << 8;
+#else
+			t1 = t0;
+#endif
+#endif
+
+#if ScrnTrns_Scale > 1
+			for (k = ScrnTrns_Scale; --k >= 0; )
+#endif
+			{
+				*pDst++ = t1;
+			}
+		}
+		pSrc += SrcSkip;
+		pDst += DstSkip;
+
+#if ScrnTrns_Scale > 1
+#if ScrnTrns_Scale > 2
+		for (k = ScrnTrns_Scale - 1; --k >= 0; )
+#endif
+		{
+			p4 = p3;
+			for (j = ScrnTrns_Scale * jn; --j >= 0; ) {
+				*pDst++ = *p4++;
+			}
+			pDst += DstSkip;
+		}
+#endif /* ScrnTrns_Scale > 1 */
+	}
+}
+
+/* undefine template locals and parameters */
+
+#undef ScrnTrns_DoTrans
+#undef ScrnTrns_Src
+#undef ScrnTrns_Dst
+#undef ScrnTrns_SrcDepth
+#undef ScrnTrns_DstDepth
+#undef ScrnTrns_Scale
+#undef ScrnTrns_DstZLo
--- /dev/null
+++ b/src/SCSIEMDV.c
@@ -1,0 +1,156 @@
+/*
+	SCSIEMDV.c
+
+	Copyright (C) 2004 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Small Computer System Interface EMulated DeVice
+
+	Emulates the SCSI found in the Mac Plus.
+
+	This code adapted from "SCSI.c" in vMac by Philip Cummins.
+*/
+
+/* NCR5380 chip emulation by Yoav Shadmi, 1998 */
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+
+#include "ENDIANAC.h"
+#include "MYOSGLUE.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+#include "MINEM68K.h"
+#endif
+
+#include "SCSIEMDV.h"
+
+#define scsiRd   0x00
+#define scsiWr   0x01
+
+#define sCDR     0x00 /* current scsi data register  (r/o) */
+#define sODR     0x00 /* output data register        (w/o) */
+#define sICR     0x02 /* initiator command register  (r/w) */
+#define sMR      0x04 /* mode register               (r/w) */
+#define sTCR     0x06 /* target command register     (r/w) */
+#define sCSR     0x08 /* current SCSI bus status     (r/o) */
+#define sSER     0x08 /* select enable register      (w/o) */
+#define sBSR     0x0A /* bus and status register     (r/o) */
+#define sDMAtx   0x0A /* start DMA send              (w/o) */
+#define sIDR     0x0C /* input data register         (r/o) */
+#define sTDMArx  0x0C /* start DMA target receive    (w/o) */
+#define sRESET   0x0E /* reset parity/interrupt      (r/o) */
+#define sIDMArx  0x0E /* start DMA initiator receive (w/o) */
+
+#define kSCSI_Size 0x00010
+
+LOCALVAR ui3b SCSI[kSCSI_Size];
+
+GLOBALPROC SCSI_Reset(void)
+{
+	int i;
+
+	for (i = 0; i < kSCSI_Size; i++) {
+		SCSI[i] = 0;
+	}
+}
+
+LOCALPROC SCSI_BusReset(void)
+{
+	SCSI[scsiRd + sCDR] = 0;
+	SCSI[scsiWr + sODR] = 0;
+	SCSI[scsiRd + sICR] = 0x80;
+	SCSI[scsiWr + sICR] &= 0x80;
+	SCSI[scsiRd + sMR] &= 0x40;
+	SCSI[scsiWr + sMR] &= 0x40;
+	SCSI[scsiRd + sTCR] = 0;
+	SCSI[scsiWr + sTCR] = 0;
+	SCSI[scsiRd + sCSR] = 0x80;
+	SCSI[scsiWr + sSER] = 0;
+	SCSI[scsiRd + sBSR] = 0x10;
+	SCSI[scsiWr + sDMAtx] = 0;
+	SCSI[scsiRd + sIDR] = 0;
+	SCSI[scsiWr + sTDMArx] = 0;
+	SCSI[scsiRd + sRESET] = 0;
+	SCSI[scsiWr + sIDMArx] = 0;
+#if 0
+	SCSI[scsiRd + sODR + dackWr] = 0;
+	SCSI[scsiWr + sIDR + dackRd] = 0;
+#endif
+
+	/* The missing piece of the puzzle.. :) */
+	put_ram_word(0xb22, get_ram_word(0xb22) | 0x8000);
+}
+
+LOCALPROC SCSI_Check(void)
+{
+	/*
+		The arbitration select/reselect scenario
+		[stub.. doesn't really work...]
+	*/
+	if ((SCSI[scsiWr + sODR] >> 7) == 1) {
+		/* Check if the Mac tries to be an initiator */
+		if ((SCSI[scsiWr + sMR] & 1) == 1) {
+			/* the Mac set arbitration in progress */
+			/*
+				stub! tell the mac that there
+				is arbitration in progress...
+			*/
+			SCSI[scsiRd + sICR] |= 0x40;
+			/* ... that we didn't lose arbitration ... */
+			SCSI[scsiRd + sICR] &= ~ 0x20;
+			/*
+				... and that there isn't a higher priority ID present...
+			*/
+			SCSI[scsiRd + sCDR] = 0x00;
+
+			/*
+				... the arbitration and selection/reselection is
+				complete. the initiator tries to connect to the SCSI
+				device, fails and returns after timeout.
+			*/
+		}
+	}
+
+	/* check the chip registers, AS SET BY THE CPU */
+	if ((SCSI[scsiWr + sICR] >> 7) == 1) {
+		/* Check Assert RST */
+		SCSI_BusReset();
+	} else {
+		SCSI[scsiRd + sICR] &= ~ 0x80;
+		SCSI[scsiRd + sCSR] &= ~ 0x80;
+	}
+
+	if ((SCSI[scsiWr + sICR] >> 2) == 1) {
+		/* Check Assert SEL */
+		SCSI[scsiRd + sCSR] |= 0x02;
+		SCSI[scsiRd + sBSR] = 0x10;
+	} else {
+		SCSI[scsiRd + sCSR] &= ~ 0x02;
+	}
+}
+
+GLOBALFUNC ui5b SCSI_Access(ui5b Data, blnr WriteMem, CPTR addr)
+{
+	if (addr < (kSCSI_Size / 2)) {
+		addr *= 2;
+		if (WriteMem) {
+			SCSI[addr + 1] = Data;
+			SCSI_Check();
+		} else {
+			Data = SCSI[addr];
+		}
+	}
+	return Data;
+}
--- /dev/null
+++ b/src/SCSIEMDV.h
@@ -1,0 +1,25 @@
+/*
+	SCSIEMDV.h
+
+	Copyright (C) 2004 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef SCSIEMDV_H
+#error "header already included"
+#else
+#define SCSIEMDV_H
+#endif
+
+EXPORTPROC SCSI_Reset(void);
+
+EXPORTFUNC ui5b SCSI_Access(ui5b Data, blnr WriteMem, CPTR addr);
--- /dev/null
+++ b/src/SGLUALSA.h
@@ -1,0 +1,1618 @@
+/*
+	SGLUALSA.h
+
+	Copyright (C) 2012 Stephan Kochen, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Sound GLUe for ALSA
+
+	ALSA sound support by Stephan Kochen.
+*/
+
+#ifndef RaspbianWorkAround
+#define RaspbianWorkAround 0
+#endif
+
+#if 0
+
+#include "alsa/asoundlib.h"
+	/* and link with "-lasound" */
+
+#define My_snd_pcm_t snd_pcm_t
+#define My_snd_pcm_hw_params_t snd_pcm_hw_params_t
+#define My_snd_pcm_sw_params_t snd_pcm_sw_params_t
+#define My_snd_pcm_state_t snd_pcm_state_t
+#if RaspbianWorkAround
+#define My_snd_pcm_status_t snd_pcm_status_t
+#endif
+
+#define My_SND_PCM_STATE_OPEN SND_PCM_STATE_OPEN
+#define My_SND_PCM_STATE_SETUP SND_PCM_STATE_SETUP
+#define My_SND_PCM_STATE_PREPARED SND_PCM_STATE_PREPARED
+#define My_SND_PCM_STATE_RUNNING SND_PCM_STATE_RUNNING
+#define My_SND_PCM_STATE_XRUN SND_PCM_STATE_XRUN
+#define My_SND_PCM_STATE_DRAINING SND_PCM_STATE_DRAINING
+#define My_SND_PCM_STATE_PAUSED SND_PCM_STATE_PAUSED
+#define My_SND_PCM_STATE_SUSPENDED SND_PCM_STATE_SUSPENDED
+#define My_SND_PCM_STATE_DISCONNECTED SND_PCM_STATE_DISCONNECTED
+#define My_SND_PCM_STATE_LAST SND_PCM_STATE_LAST
+
+#define My_snd_pcm_stream_t snd_pcm_stream_t
+
+#define My_SND_PCM_STREAM_PLAYBACK SND_PCM_STREAM_PLAYBACK
+#define My_SND_PCM_STREAM_CAPTURE SND_PCM_STREAM_CAPTURE
+#define My_SND_PCM_STREAM_LAST SND_PCM_STREAM_LAST
+
+#define My_snd_pcm_access_t snd_pcm_access_t
+
+#define My_SND_PCM_ACCESS_MMAP_INTERLEAVED \
+	SND_PCM_ACCESS_MMAP_INTERLEAVED
+#define My_SND_PCM_ACCESS_MMAP_NONINTERLEAVED \
+	SND_PCM_ACCESS_MMAP_NONINTERLEAVED
+#define My_SND_PCM_ACCESS_MMAP_COMPLEX \
+	SND_PCM_ACCESS_MMAP_COMPLEX
+#define My_SND_PCM_ACCESS_RW_INTERLEAVED \
+	SND_PCM_ACCESS_RW_INTERLEAVED
+#define My_SND_PCM_ACCESS_RW_NONINTERLEAVED \
+	SND_PCM_ACCESS_RW_NONINTERLEAVED
+#define My_SND_PCM_ACCESS_LAST \
+	SND_PCM_ACCESS_LAST
+
+#define My_snd_pcm_format_t snd_pcm_format_t
+
+#define My_SND_PCM_FORMAT_UNKNOWN SND_PCM_FORMAT_UNKNOWN
+#define My_SND_PCM_FORMAT_S8 SND_PCM_FORMAT_S8
+#define My_SND_PCM_FORMAT_U8 SND_PCM_FORMAT_U8
+#define My_SND_PCM_FORMAT_S16_LE SND_PCM_FORMAT_S16_LE
+#define My_SND_PCM_FORMAT_S16_BE SND_PCM_FORMAT_S16_BE
+#define My_SND_PCM_FORMAT_U16_LE SND_PCM_FORMAT_U16_LE
+#define My_SND_PCM_FORMAT_U16_BE SND_PCM_FORMAT_U16_BE
+#define My_SND_PCM_FORMAT_S24_LE SND_PCM_FORMAT_S24_LE
+#define My_SND_PCM_FORMAT_S24_BE SND_PCM_FORMAT_S24_BE
+#define My_SND_PCM_FORMAT_U24_LE SND_PCM_FORMAT_U24_LE
+#define My_SND_PCM_FORMAT_U24_BE SND_PCM_FORMAT_U24_BE
+#define My_SND_PCM_FORMAT_S32_LE SND_PCM_FORMAT_S32_LE
+#define My_SND_PCM_FORMAT_S32_BE SND_PCM_FORMAT_S32_BE
+#define My_SND_PCM_FORMAT_U32_LE SND_PCM_FORMAT_U32_LE
+#define My_SND_PCM_FORMAT_U32_BE SND_PCM_FORMAT_U32_BE
+#define My_SND_PCM_FORMAT_FLOAT_LE SND_PCM_FORMAT_FLOAT_LE
+#define My_SND_PCM_FORMAT_FLOAT_BE SND_PCM_FORMAT_FLOAT_BE
+#define My_SND_PCM_FORMAT_FLOAT64_LE SND_PCM_FORMAT_FLOAT64_LE
+#define My_SND_PCM_FORMAT_FLOAT64_BE SND_PCM_FORMAT_FLOAT64_BE
+#define My_SND_PCM_FORMAT_IEC958_SUBFRAME_LE \
+	SND_PCM_FORMAT_IEC958_SUBFRAME_LE
+#define My_SND_PCM_FORMAT_IEC958_SUBFRAME_BE \
+	SND_PCM_FORMAT_IEC958_SUBFRAME_BE
+#define My_SND_PCM_FORMAT_MU_LAW SND_PCM_FORMAT_MU_LAW
+#define My_SND_PCM_FORMAT_A_LAW SND_PCM_FORMAT_A_LAW
+#define My_SND_PCM_FORMAT_IMA_ADPCM SND_PCM_FORMAT_IMA_ADPCM
+#define My_SND_PCM_FORMAT_MPEG SND_PCM_FORMAT_MPEG
+#define My_SND_PCM_FORMAT_GSM SND_PCM_FORMAT_GSM
+#define My_SND_PCM_FORMAT_SPECIAL SND_PCM_FORMAT_SPECIAL
+#define My_SND_PCM_FORMAT_S24_3LE SND_PCM_FORMAT_S24_3LE
+#define My_SND_PCM_FORMAT_S24_3BE SND_PCM_FORMAT_S24_3BE
+#define My_SND_PCM_FORMAT_U24_3LE SND_PCM_FORMAT_U24_3LE
+#define My_SND_PCM_FORMAT_U24_3BE SND_PCM_FORMAT_U24_3BE
+#define My_SND_PCM_FORMAT_S20_3LE SND_PCM_FORMAT_S20_3LE
+#define My_SND_PCM_FORMAT_S20_3BE SND_PCM_FORMAT_S20_3BE
+#define My_SND_PCM_FORMAT_U20_3LE SND_PCM_FORMAT_U20_3LE
+#define My_SND_PCM_FORMAT_U20_3BE SND_PCM_FORMAT_U20_3BE
+#define My_SND_PCM_FORMAT_S18_3LE SND_PCM_FORMAT_S18_3LE
+#define My_SND_PCM_FORMAT_S18_3BE SND_PCM_FORMAT_S18_3BE
+#define My_SND_PCM_FORMAT_U18_3LE SND_PCM_FORMAT_U18_3LE
+#define My_SND_PCM_FORMAT_U18_3BE SND_PCM_FORMAT_U18_3BE
+#define My_SND_PCM_FORMAT_LAST SND_PCM_FORMAT_LAST
+
+#define My_SND_PCM_FORMAT_S16 SND_PCM_FORMAT_S16
+#define My_SND_PCM_FORMAT_U16 SND_PCM_FORMAT_U16
+#define My_SND_PCM_FORMAT_S24 SND_PCM_FORMAT_S24
+#define My_SND_PCM_FORMAT_U24 SND_PCM_FORMAT_U24
+#define My_SND_PCM_FORMAT_S32 SND_PCM_FORMAT_S32
+#define My_SND_PCM_FORMAT_U32 SND_PCM_FORMAT_U32
+#define My_SND_PCM_FORMAT_FLOAT SND_PCM_FORMAT_FLOAT
+#define My_SND_PCM_FORMAT_FLOAT64 SND_PCM_FORMAT_FLOAT64
+#define My_SND_PCM_FORMAT_IEC958_SUBFRAME SND_PCM_FORMAT_FLOAT64
+
+#define My_snd_pcm_uframes_t snd_pcm_uframes_t
+#define My_snd_pcm_sframes_t snd_pcm_sframes_t
+
+#define My_SND_PCM_NONBLOCK SND_PCM_NONBLOCK
+
+#define My_snd_pcm_open snd_pcm_open
+#define HaveMy_snd_pcm_open() (1)
+
+#define My_snd_pcm_close snd_pcm_close
+#define HaveMy_snd_pcm_close() (1)
+
+#define My_snd_pcm_hw_params_malloc snd_pcm_hw_params_malloc
+#define HaveMy_snd_pcm_hw_params_malloc() (1)
+
+#define My_snd_pcm_hw_params_free snd_pcm_hw_params_free
+#define HaveMy_snd_pcm_hw_params_free() (1)
+
+#define My_snd_pcm_hw_params_any snd_pcm_hw_params_any
+#define HaveMy_snd_pcm_hw_params_any() (1)
+
+#define My_snd_pcm_hw_params_set_access snd_pcm_hw_params_set_access
+#define HaveMy_snd_pcm_hw_params_set_access() (1)
+
+#define My_snd_pcm_hw_params_set_format snd_pcm_hw_params_set_format
+#define HaveMy_snd_pcm_hw_params_set_format() (1)
+
+#define My_snd_pcm_hw_params_set_rate_near \
+	snd_pcm_hw_params_set_rate_near
+#define HaveMy_snd_pcm_hw_params_set_rate_near() (1)
+
+#define My_snd_pcm_hw_params_set_channels \
+	snd_pcm_hw_params_set_channels
+#define HaveMy_snd_pcm_hw_params_set_channels() (1)
+
+#define My_snd_pcm_hw_params_set_buffer_size_near \
+	snd_pcm_hw_params_set_buffer_size_near
+#define HaveMy_snd_pcm_hw_params_set_buffer_size_near() (1)
+
+#define My_snd_pcm_hw_params_set_period_size_near \
+	snd_pcm_hw_params_set_period_size_near
+#define HaveMy_snd_pcm_hw_params_set_period_size_near() (1)
+
+#define My_snd_pcm_hw_params snd_pcm_hw_params
+#define HaveMy_snd_pcm_hw_params() (1)
+
+#define My_snd_pcm_sw_params_malloc snd_pcm_sw_params_malloc
+#define HaveMy_snd_pcm_sw_params_malloc() (1)
+
+#define My_snd_pcm_sw_params_free snd_pcm_sw_params_free
+#define HaveMy_snd_pcm_sw_params_free() (1)
+
+#define My_snd_pcm_sw_params_current snd_pcm_sw_params_current
+#define HaveMy_snd_pcm_sw_params_current() (1)
+
+#define My_snd_pcm_sw_params_set_start_threshold \
+	snd_pcm_sw_params_set_start_threshold
+#define HaveMy_snd_pcm_sw_params_set_start_threshold() (1)
+
+#define My_snd_pcm_sw_params_set_avail_min \
+	snd_pcm_sw_params_set_avail_min
+#define HaveMy_snd_pcm_sw_params_set_avail_min() (1)
+
+#define My_snd_pcm_sw_params_set_xfer_align \
+	snd_pcm_sw_params_set_xfer_align
+#define HaveMy_snd_pcm_sw_params_set_xfer_align() (1)
+
+#define My_snd_pcm_sw_params snd_pcm_sw_params
+#define HaveMy_snd_pcm_sw_params() (1)
+
+#define My_snd_pcm_nonblock snd_pcm_nonblock
+#define HaveMy_snd_pcm_nonblock() (1)
+
+#define My_snd_pcm_state snd_pcm_state
+#define HaveMy_snd_pcm_state() (1)
+
+#define My_snd_pcm_prepare snd_pcm_prepare
+#define HaveMy_snd_pcm_prepare() (1)
+
+#define My_snd_pcm_start snd_pcm_start
+#define HaveMy_snd_pcm_start() (1)
+
+#define My_snd_pcm_resume snd_pcm_resume
+#define HaveMy_snd_pcm_resume() (1)
+
+#define My_snd_pcm_avail_update snd_pcm_avail_update
+#define HaveMy_snd_pcm_avail_update() (1)
+
+#define My_snd_pcm_writei snd_pcm_writei
+#define HaveMy_snd_pcm_writei() (1)
+
+#define My_snd_pcm_drop snd_pcm_drop
+#define HaveMy_snd_pcm_drop() (1)
+
+#if RaspbianWorkAround
+#define My_snd_pcm_status_malloc snd_pcm_status_malloc
+#define HaveMy_snd_pcm_status_malloc() (1)
+
+#define My_snd_pcm_status snd_pcm_status
+#define HaveMy_snd_pcm_status() (1)
+
+#define My_snd_pcm_status_get_avail snd_pcm_status_get_avail
+#define HaveMy_snd_pcm_status_get_avail() (1)
+#endif
+
+#define My_snd_strerror snd_strerror
+#define HaveMy_snd_strerror() (1)
+
+#define MyCloseAlsaLib()
+
+#else
+
+static void *alsa_handle = NULL;
+
+LOCALVAR blnr DidAlsaLib = falseblnr;
+
+LOCALFUNC blnr HaveAlsaLib(void)
+{
+	if (! DidAlsaLib) {
+		alsa_handle = dlopen("libasound.so.2", RTLD_NOW);
+		if (NULL == alsa_handle) {
+			fprintf(stderr, "dlopen libasound failed\n");
+		}
+		DidAlsaLib = trueblnr;
+	}
+	return (alsa_handle != NULL);
+}
+
+LOCALPROC MyCloseAlsaLib(void)
+{
+	if (NULL != alsa_handle) {
+		if (0 != dlclose(alsa_handle)) {
+			fprintf(stderr, "dlclose libasound failed\n");
+		}
+		alsa_handle = NULL;
+	}
+}
+
+/* PCM handle */
+typedef struct My__snd_pcm My_snd_pcm_t;
+/* PCM hardware configuration space container */
+typedef struct My__snd_pcm_hw_params My_snd_pcm_hw_params_t;
+/* PCM software configuration container */
+typedef struct My__snd_pcm_sw_params My_snd_pcm_sw_params_t;
+
+#if RaspbianWorkAround
+/* PCM status container */
+typedef struct My__snd_pcm_status My_snd_pcm_status_t;
+#endif
+
+/* PCM state */
+typedef enum My__snd_pcm_state {
+	/* Open */
+	My_SND_PCM_STATE_OPEN = 0,
+	/* Setup installed */
+	My_SND_PCM_STATE_SETUP,
+	/* Ready to start */
+	My_SND_PCM_STATE_PREPARED,
+	/* Running */
+	My_SND_PCM_STATE_RUNNING,
+	/* Stopped: underrun (playback) or overrun (capture) detected */
+	My_SND_PCM_STATE_XRUN,
+	/* Draining: running (playback) or stopped (capture) */
+	My_SND_PCM_STATE_DRAINING,
+	/* Paused */
+	My_SND_PCM_STATE_PAUSED,
+	/* Hardware is suspended */
+	My_SND_PCM_STATE_SUSPENDED,
+	/* Hardware is disconnected */
+	My_SND_PCM_STATE_DISCONNECTED,
+	My_SND_PCM_STATE_LAST = My_SND_PCM_STATE_DISCONNECTED
+} My_snd_pcm_state_t;
+
+/* PCM stream (direction) */
+typedef enum My__snd_pcm_stream {
+	/* Playback stream */
+	My_SND_PCM_STREAM_PLAYBACK = 0,
+	/* Capture stream */
+	My_SND_PCM_STREAM_CAPTURE,
+	My_SND_PCM_STREAM_LAST = My_SND_PCM_STREAM_CAPTURE
+} My_snd_pcm_stream_t;
+
+/* PCM access type */
+typedef enum My__snd_pcm_access {
+	/* mmap access with simple interleaved channels */
+	My_SND_PCM_ACCESS_MMAP_INTERLEAVED = 0,
+	/* mmap access with simple non interleaved channels */
+	My_SND_PCM_ACCESS_MMAP_NONINTERLEAVED,
+	/* mmap access with complex placement */
+	My_SND_PCM_ACCESS_MMAP_COMPLEX,
+	/* snd_pcm_readi/snd_pcm_writei access */
+	My_SND_PCM_ACCESS_RW_INTERLEAVED,
+	/* snd_pcm_readn/snd_pcm_writen access */
+	My_SND_PCM_ACCESS_RW_NONINTERLEAVED,
+	My_SND_PCM_ACCESS_LAST = My_SND_PCM_ACCESS_RW_NONINTERLEAVED
+} My_snd_pcm_access_t;
+
+/* PCM sample format */
+typedef enum My__snd_pcm_format {
+	/* Unknown */
+	My_SND_PCM_FORMAT_UNKNOWN = -1,
+	/* Signed 8 bit */
+	My_SND_PCM_FORMAT_S8 = 0,
+	/* Unsigned 8 bit */
+	My_SND_PCM_FORMAT_U8,
+	/* Signed 16 bit Little Endian */
+	My_SND_PCM_FORMAT_S16_LE,
+	/* Signed 16 bit Big Endian */
+	My_SND_PCM_FORMAT_S16_BE,
+	/* Unsigned 16 bit Little Endian */
+	My_SND_PCM_FORMAT_U16_LE,
+	/* Unsigned 16 bit Big Endian */
+	My_SND_PCM_FORMAT_U16_BE,
+	/*
+		Signed 24 bit Little Endian using low three bytes in 32-bit word
+	*/
+	My_SND_PCM_FORMAT_S24_LE,
+	/* Signed 24 bit Big Endian using low three bytes in 32-bit word */
+	My_SND_PCM_FORMAT_S24_BE,
+	/*
+		Unsigned 24 bit Little Endian using low three bytes in
+		32-bit word
+	*/
+	My_SND_PCM_FORMAT_U24_LE,
+	/*
+		Unsigned 24 bit Big Endian using low three bytes in 32-bit word
+	*/
+	My_SND_PCM_FORMAT_U24_BE,
+	/* Signed 32 bit Little Endian */
+	My_SND_PCM_FORMAT_S32_LE,
+	/* Signed 32 bit Big Endian */
+	My_SND_PCM_FORMAT_S32_BE,
+	/* Unsigned 32 bit Little Endian */
+	My_SND_PCM_FORMAT_U32_LE,
+	/* Unsigned 32 bit Big Endian */
+	My_SND_PCM_FORMAT_U32_BE,
+	/* Float 32 bit Little Endian, Range -1.0 to 1.0 */
+	My_SND_PCM_FORMAT_FLOAT_LE,
+	/* Float 32 bit Big Endian, Range -1.0 to 1.0 */
+	My_SND_PCM_FORMAT_FLOAT_BE,
+	/* Float 64 bit Little Endian, Range -1.0 to 1.0 */
+	My_SND_PCM_FORMAT_FLOAT64_LE,
+	/* Float 64 bit Big Endian, Range -1.0 to 1.0 */
+	My_SND_PCM_FORMAT_FLOAT64_BE,
+	/* IEC-958 Little Endian */
+	My_SND_PCM_FORMAT_IEC958_SUBFRAME_LE,
+	/* IEC-958 Big Endian */
+	My_SND_PCM_FORMAT_IEC958_SUBFRAME_BE,
+	/* Mu-Law */
+	My_SND_PCM_FORMAT_MU_LAW,
+	/* A-Law */
+	My_SND_PCM_FORMAT_A_LAW,
+	/* Ima-ADPCM */
+	My_SND_PCM_FORMAT_IMA_ADPCM,
+	/* MPEG */
+	My_SND_PCM_FORMAT_MPEG,
+	/* GSM */
+	My_SND_PCM_FORMAT_GSM,
+	/* Special */
+	My_SND_PCM_FORMAT_SPECIAL = 31,
+	/* Signed 24bit Little Endian in 3bytes format */
+	My_SND_PCM_FORMAT_S24_3LE = 32,
+	/* Signed 24bit Big Endian in 3bytes format */
+	My_SND_PCM_FORMAT_S24_3BE,
+	/* Unsigned 24bit Little Endian in 3bytes format */
+	My_SND_PCM_FORMAT_U24_3LE,
+	/* Unsigned 24bit Big Endian in 3bytes format */
+	My_SND_PCM_FORMAT_U24_3BE,
+	/* Signed 20bit Little Endian in 3bytes format */
+	My_SND_PCM_FORMAT_S20_3LE,
+	/* Signed 20bit Big Endian in 3bytes format */
+	My_SND_PCM_FORMAT_S20_3BE,
+	/* Unsigned 20bit Little Endian in 3bytes format */
+	My_SND_PCM_FORMAT_U20_3LE,
+	/* Unsigned 20bit Big Endian in 3bytes format */
+	My_SND_PCM_FORMAT_U20_3BE,
+	/* Signed 18bit Little Endian in 3bytes format */
+	My_SND_PCM_FORMAT_S18_3LE,
+	/* Signed 18bit Big Endian in 3bytes format */
+	My_SND_PCM_FORMAT_S18_3BE,
+	/* Unsigned 18bit Little Endian in 3bytes format */
+	My_SND_PCM_FORMAT_U18_3LE,
+	/* Unsigned 18bit Big Endian in 3bytes format */
+	My_SND_PCM_FORMAT_U18_3BE,
+	My_SND_PCM_FORMAT_LAST = My_SND_PCM_FORMAT_U18_3BE,
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+	/* Signed 16 bit CPU endian */
+	My_SND_PCM_FORMAT_S16 = My_SND_PCM_FORMAT_S16_LE,
+	/* Unsigned 16 bit CPU endian */
+	My_SND_PCM_FORMAT_U16 = My_SND_PCM_FORMAT_U16_LE,
+	/* Signed 24 bit CPU endian */
+	My_SND_PCM_FORMAT_S24 = My_SND_PCM_FORMAT_S24_LE,
+	/* Unsigned 24 bit CPU endian */
+	My_SND_PCM_FORMAT_U24 = My_SND_PCM_FORMAT_U24_LE,
+	/* Signed 32 bit CPU endian */
+	My_SND_PCM_FORMAT_S32 = My_SND_PCM_FORMAT_S32_LE,
+	/* Unsigned 32 bit CPU endian */
+	My_SND_PCM_FORMAT_U32 = My_SND_PCM_FORMAT_U32_LE,
+	/* Float 32 bit CPU endian */
+	My_SND_PCM_FORMAT_FLOAT = My_SND_PCM_FORMAT_FLOAT_LE,
+	/* Float 64 bit CPU endian */
+	My_SND_PCM_FORMAT_FLOAT64 = My_SND_PCM_FORMAT_FLOAT64_LE,
+	/* IEC-958 CPU Endian */
+	My_SND_PCM_FORMAT_IEC958_SUBFRAME =
+		My_SND_PCM_FORMAT_IEC958_SUBFRAME_LE
+#elif __BYTE_ORDER == __BIG_ENDIAN
+	/* Signed 16 bit CPU endian */
+	My_SND_PCM_FORMAT_S16 = My_SND_PCM_FORMAT_S16_BE,
+	/* Unsigned 16 bit CPU endian */
+	My_SND_PCM_FORMAT_U16 = My_SND_PCM_FORMAT_U16_BE,
+	/* Signed 24 bit CPU endian */
+	My_SND_PCM_FORMAT_S24 = My_SND_PCM_FORMAT_S24_BE,
+	/* Unsigned 24 bit CPU endian */
+	My_SND_PCM_FORMAT_U24 = My_SND_PCM_FORMAT_U24_BE,
+	/* Signed 32 bit CPU endian */
+	My_SND_PCM_FORMAT_S32 = My_SND_PCM_FORMAT_S32_BE,
+	/* Unsigned 32 bit CPU endian */
+	My_SND_PCM_FORMAT_U32 = My_SND_PCM_FORMAT_U32_BE,
+	/* Float 32 bit CPU endian */
+	My_SND_PCM_FORMAT_FLOAT = My_SND_PCM_FORMAT_FLOAT_BE,
+	/* Float 64 bit CPU endian */
+	My_SND_PCM_FORMAT_FLOAT64 = My_SND_PCM_FORMAT_FLOAT64_BE,
+	/* IEC-958 CPU Endian */
+	My_SND_PCM_FORMAT_IEC958_SUBFRAME =
+		My_SND_PCM_FORMAT_IEC958_SUBFRAME_BE
+#else
+#error "Unknown endian"
+#endif
+} My_snd_pcm_format_t;
+
+/* Unsigned frames quantity */
+typedef unsigned long My_snd_pcm_uframes_t;
+/* Signed frames quantity */
+typedef long My_snd_pcm_sframes_t;
+
+/* Non blocking mode (flag for open mode) \hideinitializer */
+#define My_SND_PCM_NONBLOCK 0x00000001
+
+typedef int (*snd_pcm_open_ProcPtr)
+	(My_snd_pcm_t **pcm, const char *name, My_snd_pcm_stream_t stream,
+		int mode);
+LOCALVAR snd_pcm_open_ProcPtr My_snd_pcm_open = NULL;
+LOCALVAR blnr Did_snd_pcm_open = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_open(void)
+{
+	if (! Did_snd_pcm_open) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_open = (snd_pcm_open_ProcPtr)dlsym(alsa_handle,
+				"snd_pcm_open");
+			if (NULL == My_snd_pcm_open) {
+				fprintf(stderr, "dlsym snd_pcm_open failed\n");
+			}
+		}
+		Did_snd_pcm_open = trueblnr;
+	}
+	return (My_snd_pcm_open != NULL);
+}
+
+typedef int (*snd_pcm_close_ProcPtr)(My_snd_pcm_t *pcm);
+LOCALVAR snd_pcm_close_ProcPtr My_snd_pcm_close = NULL;
+LOCALVAR blnr Did_snd_pcm_close = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_close(void)
+{
+	if (! Did_snd_pcm_close) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_close = (snd_pcm_close_ProcPtr)dlsym(alsa_handle,
+				"snd_pcm_close");
+			if (NULL == My_snd_pcm_close) {
+				fprintf(stderr, "dlsym snd_pcm_close failed\n");
+			}
+		}
+		Did_snd_pcm_close = trueblnr;
+	}
+	return (My_snd_pcm_close != NULL);
+}
+
+typedef int (*snd_pcm_hw_params_malloc_ProcPtr)
+	(My_snd_pcm_hw_params_t **ptr);
+LOCALVAR snd_pcm_hw_params_malloc_ProcPtr My_snd_pcm_hw_params_malloc
+	= NULL;
+LOCALVAR blnr Did_snd_pcm_hw_params_malloc = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_hw_params_malloc(void)
+{
+	if (! Did_snd_pcm_hw_params_malloc) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_hw_params_malloc =
+				(snd_pcm_hw_params_malloc_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_hw_params_malloc");
+			if (NULL == My_snd_pcm_hw_params_malloc) {
+				fprintf(stderr,
+					"dlsym snd_pcm_hw_params_malloc failed\n");
+			}
+		}
+		Did_snd_pcm_hw_params_malloc = trueblnr;
+	}
+	return (My_snd_pcm_hw_params_malloc != NULL);
+}
+
+typedef void (*snd_pcm_hw_params_free_ProcPtr)
+	(My_snd_pcm_hw_params_t *obj);
+LOCALVAR snd_pcm_hw_params_free_ProcPtr
+	My_snd_pcm_hw_params_free = NULL;
+LOCALVAR blnr Did_snd_pcm_hw_params_free = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_hw_params_free(void)
+{
+	if (! Did_snd_pcm_hw_params_free) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_hw_params_free = (snd_pcm_hw_params_free_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_hw_params_free");
+			if (NULL == My_snd_pcm_hw_params_free) {
+				fprintf(stderr,
+					"dlsym snd_pcm_hw_params_free failed\n");
+			}
+		}
+		Did_snd_pcm_hw_params_free = trueblnr;
+	}
+	return (My_snd_pcm_hw_params_free != NULL);
+}
+
+typedef int (*snd_pcm_hw_params_any_ProcPtr)
+	(My_snd_pcm_t *pcm, My_snd_pcm_hw_params_t *params);
+LOCALVAR snd_pcm_hw_params_any_ProcPtr My_snd_pcm_hw_params_any = NULL;
+LOCALVAR blnr Did_snd_pcm_hw_params_any = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_hw_params_any(void)
+{
+	if (! Did_snd_pcm_hw_params_any) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_hw_params_any = (snd_pcm_hw_params_any_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_hw_params_any");
+			if (NULL == My_snd_pcm_hw_params_any) {
+				fprintf(stderr, "dlsym snd_pcm_hw_params_any failed\n");
+			}
+		}
+		Did_snd_pcm_hw_params_any = trueblnr;
+	}
+	return (My_snd_pcm_hw_params_any != NULL);
+}
+
+typedef int (*snd_pcm_hw_params_set_access_ProcPtr)
+	(My_snd_pcm_t *pcm, My_snd_pcm_hw_params_t *params,
+		My_snd_pcm_access_t _access);
+LOCALVAR snd_pcm_hw_params_set_access_ProcPtr
+	My_snd_pcm_hw_params_set_access = NULL;
+LOCALVAR blnr Did_snd_pcm_hw_params_set_access = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_hw_params_set_access(void)
+{
+	if (! Did_snd_pcm_hw_params_set_access) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_hw_params_set_access =
+				(snd_pcm_hw_params_set_access_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_hw_params_set_access");
+			if (NULL == My_snd_pcm_hw_params_set_access) {
+				fprintf(stderr,
+					"dlsym snd_pcm_hw_params_set_access failed\n");
+			}
+		}
+		Did_snd_pcm_hw_params_set_access = trueblnr;
+	}
+	return (My_snd_pcm_hw_params_set_access != NULL);
+}
+
+typedef int (*snd_pcm_hw_params_set_format_ProcPtr)
+	(My_snd_pcm_t *pcm, My_snd_pcm_hw_params_t *params,
+		My_snd_pcm_format_t val);
+LOCALVAR snd_pcm_hw_params_set_format_ProcPtr
+	My_snd_pcm_hw_params_set_format = NULL;
+LOCALVAR blnr Did_snd_pcm_hw_params_set_format = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_hw_params_set_format(void)
+{
+	if (! Did_snd_pcm_hw_params_set_format) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_hw_params_set_format =
+				(snd_pcm_hw_params_set_format_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_hw_params_set_format");
+			if (NULL == My_snd_pcm_hw_params_set_format) {
+				fprintf(stderr,
+					"dlsym snd_pcm_hw_params_set_format failed\n");
+			}
+		}
+		Did_snd_pcm_hw_params_set_format = trueblnr;
+	}
+	return (My_snd_pcm_hw_params_set_format != NULL);
+}
+
+typedef int (*snd_pcm_hw_params_set_rate_near_ProcPtr)
+	(My_snd_pcm_t *pcm, My_snd_pcm_hw_params_t *params,
+		unsigned int *val, int *dir);
+LOCALVAR snd_pcm_hw_params_set_rate_near_ProcPtr
+	My_snd_pcm_hw_params_set_rate_near = NULL;
+LOCALVAR blnr Did_snd_pcm_hw_params_set_rate_near = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_hw_params_set_rate_near(void)
+{
+	if (! Did_snd_pcm_hw_params_set_rate_near) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_hw_params_set_rate_near =
+				(snd_pcm_hw_params_set_rate_near_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_hw_params_set_rate_near");
+			if (NULL == My_snd_pcm_hw_params_set_rate_near) {
+				fprintf(stderr,
+					"dlsym snd_pcm_hw_params_set_rate_near failed\n");
+			}
+		}
+		Did_snd_pcm_hw_params_set_rate_near = trueblnr;
+	}
+	return (My_snd_pcm_hw_params_set_rate_near != NULL);
+}
+
+typedef int (*snd_pcm_hw_params_set_channels_ProcPtr)
+	(My_snd_pcm_t *pcm, My_snd_pcm_hw_params_t *params,
+	unsigned int val);
+LOCALVAR snd_pcm_hw_params_set_channels_ProcPtr
+	My_snd_pcm_hw_params_set_channels = NULL;
+LOCALVAR blnr Did_snd_pcm_hw_params_set_channels = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_hw_params_set_channels(void)
+{
+	if (! Did_snd_pcm_hw_params_set_channels) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_hw_params_set_channels =
+				(snd_pcm_hw_params_set_channels_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_hw_params_set_channels");
+			if (NULL == My_snd_pcm_hw_params_set_channels) {
+				fprintf(stderr,
+					"dlsym snd_pcm_hw_params_set_channels failed\n");
+			}
+		}
+		Did_snd_pcm_hw_params_set_channels = trueblnr;
+	}
+	return (My_snd_pcm_hw_params_set_channels != NULL);
+}
+
+typedef int (*snd_pcm_hw_params_set_buffer_size_near_ProcPtr)
+	(My_snd_pcm_t *pcm, My_snd_pcm_hw_params_t *params,
+		My_snd_pcm_uframes_t *val);
+LOCALVAR snd_pcm_hw_params_set_buffer_size_near_ProcPtr
+	My_snd_pcm_hw_params_set_buffer_size_near = NULL;
+LOCALVAR blnr Did_snd_pcm_hw_params_set_buffer_size_near = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_hw_params_set_buffer_size_near(void)
+{
+	if (! Did_snd_pcm_hw_params_set_buffer_size_near) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_hw_params_set_buffer_size_near =
+				(snd_pcm_hw_params_set_buffer_size_near_ProcPtr)
+				dlsym(alsa_handle,
+					"snd_pcm_hw_params_set_buffer_size_near");
+			if (NULL == My_snd_pcm_hw_params_set_buffer_size_near) {
+				fprintf(stderr,
+					"dlsym snd_pcm_hw_params_set_buffer_size_near"
+					" failed\n");
+			}
+		}
+		Did_snd_pcm_hw_params_set_buffer_size_near = trueblnr;
+	}
+	return (My_snd_pcm_hw_params_set_buffer_size_near != NULL);
+}
+
+typedef int (*snd_pcm_hw_params_set_period_size_near_ProcPtr)
+	(My_snd_pcm_t *pcm, My_snd_pcm_hw_params_t *params,
+		My_snd_pcm_uframes_t *val, int *dir);
+LOCALVAR snd_pcm_hw_params_set_period_size_near_ProcPtr
+	My_snd_pcm_hw_params_set_period_size_near = NULL;
+LOCALVAR blnr Did_snd_pcm_hw_params_set_period_size_near = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_hw_params_set_period_size_near(void)
+{
+	if (! Did_snd_pcm_hw_params_set_period_size_near) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_hw_params_set_period_size_near =
+				(snd_pcm_hw_params_set_period_size_near_ProcPtr)
+				dlsym(alsa_handle,
+					"snd_pcm_hw_params_set_period_size_near");
+			if (NULL == My_snd_pcm_hw_params_set_period_size_near) {
+				fprintf(stderr,
+					"dlsym snd_pcm_hw_params_set_period_size_near"
+					" failed\n");
+			}
+		}
+		Did_snd_pcm_hw_params_set_period_size_near = trueblnr;
+	}
+	return (My_snd_pcm_hw_params_set_period_size_near != NULL);
+}
+
+typedef int (*snd_pcm_hw_params_ProcPtr)
+	(My_snd_pcm_t *pcm, My_snd_pcm_hw_params_t *params);
+LOCALVAR snd_pcm_hw_params_ProcPtr My_snd_pcm_hw_params = NULL;
+LOCALVAR blnr Did_snd_pcm_hw_params = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_hw_params(void)
+{
+	if (! Did_snd_pcm_hw_params) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_hw_params = (snd_pcm_hw_params_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_hw_params");
+			if (NULL == My_snd_pcm_hw_params) {
+				fprintf(stderr, "dlsym snd_pcm_hw_params failed\n");
+			}
+		}
+		Did_snd_pcm_hw_params = trueblnr;
+	}
+	return (My_snd_pcm_hw_params != NULL);
+}
+
+typedef int (*snd_pcm_sw_params_malloc_ProcPtr)
+	(My_snd_pcm_sw_params_t **ptr);
+LOCALVAR snd_pcm_sw_params_malloc_ProcPtr
+	My_snd_pcm_sw_params_malloc = NULL;
+LOCALVAR blnr Did_snd_pcm_sw_params_malloc = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_sw_params_malloc(void)
+{
+	if (! Did_snd_pcm_sw_params_malloc) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_sw_params_malloc =
+				(snd_pcm_sw_params_malloc_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_sw_params_malloc");
+			if (NULL == My_snd_pcm_sw_params_malloc) {
+				fprintf(stderr,
+					"dlsym snd_pcm_sw_params_malloc failed\n");
+			}
+		}
+		Did_snd_pcm_sw_params_malloc = trueblnr;
+	}
+	return (My_snd_pcm_sw_params_malloc != NULL);
+}
+
+typedef void (*snd_pcm_sw_params_free_ProcPtr)
+	(My_snd_pcm_sw_params_t *obj);
+LOCALVAR snd_pcm_sw_params_free_ProcPtr
+	My_snd_pcm_sw_params_free = NULL;
+LOCALVAR blnr Did_snd_pcm_sw_params_free = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_sw_params_free(void)
+{
+	if (! Did_snd_pcm_sw_params_free) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_sw_params_free = (snd_pcm_sw_params_free_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_sw_params_free");
+			if (NULL == My_snd_pcm_sw_params_free) {
+				fprintf(stderr,
+					"dlsym snd_pcm_sw_params_free failed\n");
+			}
+		}
+		Did_snd_pcm_sw_params_free = trueblnr;
+	}
+	return (My_snd_pcm_sw_params_free != NULL);
+}
+
+typedef int (*snd_pcm_sw_params_current_ProcPtr)
+	(My_snd_pcm_t *pcm, My_snd_pcm_sw_params_t *params);
+LOCALVAR snd_pcm_sw_params_current_ProcPtr
+	My_snd_pcm_sw_params_current = NULL;
+LOCALVAR blnr Did_snd_pcm_sw_params_current = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_sw_params_current(void)
+{
+	if (! Did_snd_pcm_sw_params_current) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_sw_params_current =
+				(snd_pcm_sw_params_current_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_sw_params_current");
+			if (NULL == My_snd_pcm_sw_params_current) {
+				fprintf(stderr,
+					"dlsym snd_pcm_sw_params_current failed\n");
+			}
+		}
+		Did_snd_pcm_sw_params_current = trueblnr;
+	}
+	return (My_snd_pcm_sw_params_current != NULL);
+}
+
+typedef int (*snd_pcm_sw_params_set_start_threshold_ProcPtr)
+	(My_snd_pcm_t *pcm, My_snd_pcm_sw_params_t *params,
+		My_snd_pcm_uframes_t val);
+LOCALVAR snd_pcm_sw_params_set_start_threshold_ProcPtr
+	My_snd_pcm_sw_params_set_start_threshold = NULL;
+LOCALVAR blnr Did_snd_pcm_sw_params_set_start_threshold = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_sw_params_set_start_threshold(void)
+{
+	if (! Did_snd_pcm_sw_params_set_start_threshold) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_sw_params_set_start_threshold =
+				(snd_pcm_sw_params_set_start_threshold_ProcPtr)
+				dlsym(alsa_handle,
+					"snd_pcm_sw_params_set_start_threshold");
+			if (NULL == My_snd_pcm_sw_params_set_start_threshold) {
+				fprintf(stderr,
+					"dlsym snd_pcm_sw_params_set_start_threshold"
+					" failed\n");
+			}
+		}
+		Did_snd_pcm_sw_params_set_start_threshold = trueblnr;
+	}
+	return (My_snd_pcm_sw_params_set_start_threshold != NULL);
+}
+
+typedef int (*snd_pcm_sw_params_set_avail_min_ProcPtr)
+	(My_snd_pcm_t *pcm, My_snd_pcm_sw_params_t *params,
+		My_snd_pcm_uframes_t val);
+LOCALVAR snd_pcm_sw_params_set_avail_min_ProcPtr
+	My_snd_pcm_sw_params_set_avail_min = NULL;
+LOCALVAR blnr Did_snd_pcm_sw_params_set_avail_min = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_sw_params_set_avail_min(void)
+{
+	if (! Did_snd_pcm_sw_params_set_avail_min) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_sw_params_set_avail_min =
+				(snd_pcm_sw_params_set_avail_min_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_sw_params_set_avail_min");
+			if (NULL == My_snd_pcm_sw_params_set_avail_min) {
+				fprintf(stderr,
+					"dlsym snd_pcm_sw_params_set_avail_min failed\n");
+			}
+		}
+		Did_snd_pcm_sw_params_set_avail_min = trueblnr;
+	}
+	return (My_snd_pcm_sw_params_set_avail_min != NULL);
+}
+
+typedef int (*snd_pcm_sw_params_set_xfer_align_ProcPtr)
+	(My_snd_pcm_t *pcm, My_snd_pcm_sw_params_t *params,
+		My_snd_pcm_uframes_t val);
+LOCALVAR snd_pcm_sw_params_set_xfer_align_ProcPtr
+	My_snd_pcm_sw_params_set_xfer_align = NULL;
+LOCALVAR blnr Did_snd_pcm_sw_params_set_xfer_align = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_sw_params_set_xfer_align(void)
+{
+	if (! Did_snd_pcm_sw_params_set_xfer_align) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_sw_params_set_xfer_align =
+				(snd_pcm_sw_params_set_xfer_align_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_sw_params_set_xfer_align");
+			if (NULL == My_snd_pcm_sw_params_set_xfer_align) {
+				fprintf(stderr,
+					"dlsym snd_pcm_sw_params_set_xfer_align failed\n");
+			}
+		}
+		Did_snd_pcm_sw_params_set_xfer_align = trueblnr;
+	}
+	return (My_snd_pcm_sw_params_set_xfer_align != NULL);
+}
+
+typedef int (*snd_pcm_sw_params_ProcPtr)
+	(My_snd_pcm_t *pcm, My_snd_pcm_sw_params_t *params);
+LOCALVAR snd_pcm_sw_params_ProcPtr My_snd_pcm_sw_params = NULL;
+LOCALVAR blnr Did_snd_pcm_sw_params = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_sw_params(void)
+{
+	if (! Did_snd_pcm_sw_params) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_sw_params = (snd_pcm_sw_params_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_sw_params");
+			if (NULL == My_snd_pcm_sw_params) {
+				fprintf(stderr, "dlsym snd_pcm_sw_params failed\n");
+			}
+		}
+		Did_snd_pcm_sw_params = trueblnr;
+	}
+	return (My_snd_pcm_sw_params != NULL);
+}
+
+typedef int (*snd_pcm_nonblock_ProcPtr)
+	(My_snd_pcm_t *pcm, int nonblock);
+LOCALVAR snd_pcm_nonblock_ProcPtr My_snd_pcm_nonblock = NULL;
+LOCALVAR blnr Did_snd_pcm_nonblock = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_nonblock(void)
+{
+	if (! Did_snd_pcm_nonblock) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_nonblock = (snd_pcm_nonblock_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_nonblock");
+			if (NULL == My_snd_pcm_nonblock) {
+				fprintf(stderr, "dlsym snd_pcm_nonblock failed\n");
+			}
+		}
+		Did_snd_pcm_nonblock = trueblnr;
+	}
+	return (My_snd_pcm_nonblock != NULL);
+}
+
+typedef My_snd_pcm_state_t (*snd_pcm_state_ProcPtr)(My_snd_pcm_t *pcm);
+LOCALVAR snd_pcm_state_ProcPtr My_snd_pcm_state = NULL;
+LOCALVAR blnr Did_snd_pcm_state = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_state(void)
+{
+	if (! Did_snd_pcm_state) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_state = (snd_pcm_state_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_state");
+			if (NULL == My_snd_pcm_state) {
+				fprintf(stderr, "dlsym snd_pcm_state failed\n");
+			}
+		}
+		Did_snd_pcm_state = trueblnr;
+	}
+	return (My_snd_pcm_state != NULL);
+}
+
+typedef int (*snd_pcm_prepare_ProcPtr)(My_snd_pcm_t *pcm);
+LOCALVAR snd_pcm_prepare_ProcPtr My_snd_pcm_prepare = NULL;
+LOCALVAR blnr Did_snd_pcm_prepare = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_prepare(void)
+{
+	if (! Did_snd_pcm_prepare) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_prepare = (snd_pcm_prepare_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_prepare");
+			if (NULL == My_snd_pcm_prepare) {
+				fprintf(stderr, "dlsym snd_pcm_prepare failed\n");
+			}
+		}
+		Did_snd_pcm_prepare = trueblnr;
+	}
+	return (My_snd_pcm_prepare != NULL);
+}
+
+typedef int (*snd_pcm_start_ProcPtr)(My_snd_pcm_t *pcm);
+LOCALVAR snd_pcm_start_ProcPtr My_snd_pcm_start = NULL;
+LOCALVAR blnr Did_snd_pcm_start = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_start(void)
+{
+	if (! Did_snd_pcm_start) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_start = (snd_pcm_start_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_start");
+			if (NULL == My_snd_pcm_start) {
+				fprintf(stderr, "dlsym snd_pcm_start failed\n");
+			}
+		}
+		Did_snd_pcm_start = trueblnr;
+	}
+	return (My_snd_pcm_start != NULL);
+}
+
+typedef int (*snd_pcm_resume_ProcPtr)(My_snd_pcm_t *pcm);
+LOCALVAR snd_pcm_resume_ProcPtr My_snd_pcm_resume = NULL;
+LOCALVAR blnr Did_snd_pcm_resume = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_resume(void)
+{
+	if (! Did_snd_pcm_resume) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_resume = (snd_pcm_resume_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_resume");
+			if (NULL == My_snd_pcm_resume) {
+				fprintf(stderr, "dlsym snd_pcm_resume failed\n");
+			}
+		}
+		Did_snd_pcm_resume = trueblnr;
+	}
+	return (My_snd_pcm_resume != NULL);
+}
+
+typedef My_snd_pcm_sframes_t (*snd_pcm_avail_update_ProcPtr)
+	(My_snd_pcm_t *pcm);
+LOCALVAR snd_pcm_avail_update_ProcPtr My_snd_pcm_avail_update = NULL;
+LOCALVAR blnr Did_snd_pcm_avail_update = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_avail_update(void)
+{
+	if (! Did_snd_pcm_avail_update) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_avail_update = (snd_pcm_avail_update_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_avail_update");
+			if (NULL == My_snd_pcm_avail_update) {
+				fprintf(stderr, "dlsym snd_pcm_avail_update failed\n");
+			}
+		}
+		Did_snd_pcm_avail_update = trueblnr;
+	}
+	return (My_snd_pcm_avail_update != NULL);
+}
+
+typedef My_snd_pcm_sframes_t (*snd_pcm_writei_ProcPtr)
+	(My_snd_pcm_t *pcm, const void *buffer, My_snd_pcm_uframes_t size);
+LOCALVAR snd_pcm_writei_ProcPtr My_snd_pcm_writei = NULL;
+LOCALVAR blnr Did_snd_pcm_writei = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_writei(void)
+{
+	if (! Did_snd_pcm_writei) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_writei = (snd_pcm_writei_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_writei");
+			if (NULL == My_snd_pcm_writei) {
+				fprintf(stderr, "dlsym snd_pcm_writei failed\n");
+			}
+		}
+		Did_snd_pcm_writei = trueblnr;
+	}
+	return (My_snd_pcm_writei != NULL);
+}
+
+typedef int (*snd_pcm_drop_ProcPtr)(My_snd_pcm_t *pcm);
+LOCALVAR snd_pcm_drop_ProcPtr My_snd_pcm_drop = NULL;
+LOCALVAR blnr Did_snd_pcm_drop = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_drop(void)
+{
+	if (! Did_snd_pcm_drop) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_drop = (snd_pcm_drop_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_drop");
+			if (NULL == My_snd_pcm_drop) {
+				fprintf(stderr, "dlsym snd_pcm_drop failed\n");
+			}
+		}
+		Did_snd_pcm_drop = trueblnr;
+	}
+	return (My_snd_pcm_drop != NULL);
+}
+
+#if RaspbianWorkAround
+typedef int (*snd_pcm_status_malloc_ProcPtr)
+	(My_snd_pcm_status_t **ptr);
+LOCALVAR snd_pcm_status_malloc_ProcPtr My_snd_pcm_status_malloc = NULL;
+LOCALVAR blnr Did_snd_pcm_status_malloc = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_status_malloc(void)
+{
+	if (! Did_snd_pcm_status_malloc) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_status_malloc = (snd_pcm_status_malloc_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_status_malloc");
+			if (NULL == My_snd_pcm_status_malloc) {
+				fprintf(stderr, "dlsym snd_pcm_status_malloc failed\n");
+			}
+		}
+		Did_snd_pcm_status_malloc = trueblnr;
+	}
+	return (My_snd_pcm_status_malloc != NULL);
+}
+#endif
+
+#if RaspbianWorkAround
+typedef int (*snd_pcm_status_ProcPtr)(My_snd_pcm_t *pcm,
+	My_snd_pcm_status_t *status);
+LOCALVAR snd_pcm_status_ProcPtr My_snd_pcm_status = NULL;
+LOCALVAR blnr Did_snd_pcm_status = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_status(void)
+{
+	if (! Did_snd_pcm_status) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_status = (snd_pcm_status_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_status");
+			if (NULL == My_snd_pcm_status) {
+				fprintf(stderr, "dlsym snd_pcm_status failed\n");
+			}
+		}
+		Did_snd_pcm_status = trueblnr;
+	}
+	return (My_snd_pcm_status != NULL);
+}
+#endif
+
+#if RaspbianWorkAround
+typedef My_snd_pcm_uframes_t (*snd_pcm_status_get_avail_ProcPtr)
+	(const My_snd_pcm_status_t *obj);
+LOCALVAR snd_pcm_status_get_avail_ProcPtr
+	My_snd_pcm_status_get_avail = NULL;
+LOCALVAR blnr Did_snd_pcm_status_get_avail = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_pcm_status_get_avail(void)
+{
+	if (! Did_snd_pcm_status_get_avail) {
+		if (HaveAlsaLib()) {
+			My_snd_pcm_status_get_avail =
+				(snd_pcm_status_get_avail_ProcPtr)
+				dlsym(alsa_handle, "snd_pcm_status_get_avail");
+			if (NULL == My_snd_pcm_status_get_avail) {
+				fprintf(stderr,
+					"dlsym snd_pcm_status_get_avail failed\n");
+			}
+		}
+		Did_snd_pcm_status_get_avail = trueblnr;
+	}
+	return (My_snd_pcm_status_get_avail != NULL);
+}
+#endif
+
+typedef const char * (*snd_strerror_ProcPtr)(int errnum);
+LOCALVAR snd_strerror_ProcPtr My_snd_strerror = NULL;
+LOCALVAR blnr Did_snd_strerror = falseblnr;
+
+LOCALFUNC blnr HaveMy_snd_strerror(void)
+{
+	if (! Did_snd_strerror) {
+		if (HaveAlsaLib()) {
+			My_snd_strerror = (snd_strerror_ProcPtr)
+				dlsym(alsa_handle, "snd_strerror");
+			if (NULL == My_snd_strerror) {
+				fprintf(stderr, "dlsym snd_strerror failed\n");
+			}
+		}
+		Did_snd_strerror = trueblnr;
+	}
+	return (My_snd_strerror != NULL);
+}
+
+#endif
+
+
+/*
+	The elaborate private buffer is mostly
+	redundant since alsa has its own ring
+	buffer. But using it keeps the code
+	closer to the other ports. And anyway
+	there is no guarantee just what size
+	buffer you'll get from alsa.
+*/
+
+
+#if 4 == kLn2SoundSampSz
+LOCALPROC ConvertSoundBlockToNative(tpSoundSamp p)
+{
+	int i;
+
+	for (i = kOneBuffLen; --i >= 0; ) {
+		*p++ -= 0x8000;
+	}
+}
+#else
+#define ConvertSoundBlockToNative(p)
+#endif
+
+#define desired_alsa_buffer_size kAllBuffLen
+#define desired_alsa_period_size kOneBuffLen
+
+LOCALVAR char *alsadev_name = NULL;
+
+LOCALVAR My_snd_pcm_t *pcm_handle = NULL;
+LOCALVAR My_snd_pcm_uframes_t buffer_size;
+LOCALVAR My_snd_pcm_uframes_t period_size;
+
+
+LOCALVAR blnr MySound_StartPend = falseblnr;
+
+#if RaspbianWorkAround
+LOCALVAR My_snd_pcm_status_t *my_status = NULL;
+
+LOCALFUNC blnr HaveMyStatusAlloc(void)
+{
+	if (NULL == my_status) {
+		if (HaveMy_snd_pcm_status_malloc())
+		if (HaveMy_snd_pcm_status())
+		if (HaveMy_snd_pcm_status_get_avail())
+		{
+			if (My_snd_pcm_status_malloc(&my_status) < 0) {
+				my_status = NULL; /* just to make sure */
+			} else {
+				/* snd_pcm_status_free(my_status); */
+			}
+		}
+	}
+
+	return NULL != my_status;
+}
+#endif
+
+LOCALPROC MySound_WriteOut(void)
+{
+	int retry_count = 32;
+
+label_retry:
+	if (--retry_count > 0) {
+		My_snd_pcm_sframes_t avail;
+		int err;
+		My_snd_pcm_state_t cur_state = My_snd_pcm_state(pcm_handle);
+
+		if (My_SND_PCM_STATE_PREPARED == cur_state) {
+			if (! MySound_StartPend) {
+				if (TheFillOffset - ThePlayOffset >= kAllBuffLen) {
+					MySound_StartPend = trueblnr;
+				}
+			}
+			if (MySound_StartPend) {
+				cur_state = My_SND_PCM_STATE_RUNNING;
+			}
+		}
+
+		if (My_SND_PCM_STATE_RUNNING != cur_state) {
+			switch (cur_state) {
+				case My_SND_PCM_STATE_SETUP:
+				case My_SND_PCM_STATE_XRUN:
+					err = My_snd_pcm_prepare(pcm_handle);
+					if (err < 0) {
+						fprintf(stderr, "pcm prepare error: %s\n",
+							My_snd_strerror(err));
+					} else {
+						/* fprintf(stderr, "prepare succeeded\n"); */
+						goto label_retry;
+					}
+					break;
+				case My_SND_PCM_STATE_SUSPENDED:
+					err = My_snd_pcm_resume(pcm_handle);
+					if (err < 0) {
+						fprintf(stderr, "pcm resume error: %s\n",
+							My_snd_strerror(err));
+					} else {
+						/* fprintf(stderr, "resume succeeded\n"); */
+						goto label_retry;
+					}
+					break;
+				case My_SND_PCM_STATE_DISCONNECTED:
+					/* just abort ? */
+					break;
+				case My_SND_PCM_STATE_PREPARED:
+					/* leave */
+					break;
+				default:
+					fprintf(stderr, "unknown alsa pcm state\n");
+					break;
+			}
+		} else if ((avail = My_snd_pcm_avail_update(pcm_handle)) < 0) {
+			fprintf(stderr, "pcm update error: %s\n",
+				My_snd_strerror(avail));
+		} else {
+			tpSoundSamp NextPlayPtr;
+			ui4b PlayNowSize = 0;
+			ui4b MaskedFillOffset = ThePlayOffset & kOneBuffMask;
+
+#if RaspbianWorkAround
+			if ((avail > buffer_size) || (avail < 0)) {
+				/*
+					fprintf(stderr, "need avail workaround: %d\n",
+						(int)avail);
+				*/
+				/* work around bug observed in Raspbian */
+				if (HaveMyStatusAlloc()) {
+					if (My_snd_pcm_status(pcm_handle, my_status) >= 0) {
+						avail = My_snd_pcm_status_get_avail(my_status);
+					}
+				}
+			}
+#endif
+
+			if (! MySound_StartPend) {
+				My_snd_pcm_uframes_t used = buffer_size - avail;
+				ui4b TotPendBuffs = used >> kLnOneBuffLen;
+
+				if (TotPendBuffs < MinFilledSoundBuffs) {
+					MinFilledSoundBuffs = TotPendBuffs;
+				}
+				/* fprintf(stderr, "buffer used %d\n", (int)used); */
+			}
+
+			if (MaskedFillOffset != 0) {
+				/* take care of left overs */
+				PlayNowSize = kOneBuffLen - MaskedFillOffset;
+				NextPlayPtr =
+					TheSoundBuffer + (ThePlayOffset & kAllBuffMask);
+			} else if (0 !=
+				((TheFillOffset - ThePlayOffset) >> kLnOneBuffLen))
+			{
+				PlayNowSize = kOneBuffLen;
+				NextPlayPtr =
+					TheSoundBuffer + (ThePlayOffset & kAllBuffMask);
+			} else {
+				/* nothing to play now */
+			}
+
+			if (PlayNowSize > avail) {
+				/*
+					This isn't supposed to be needed with nonblock
+					mode. But in Ubuntu 7.04 running in Parallels,
+					snd_pcm_writei seemed to block anyway.
+				*/
+				PlayNowSize = avail;
+			}
+
+			if (0 != PlayNowSize) {
+				err = My_snd_pcm_writei(
+					pcm_handle, NextPlayPtr, PlayNowSize);
+				if (err < 0) {
+					if ((- EAGAIN == err) || (- ESTRPIPE == err)) {
+						/* buffer full, try again later */
+						/* fprintf(stderr, "pcm write: EAGAIN\n"); */
+					} else if (- EPIPE == err) {
+						/* buffer seems to have emptied */
+						/* fprintf(stderr, "pcm write emptied\n"); */
+						goto label_retry;
+					} else {
+						fprintf(stderr, "pcm write error: %s\n",
+							My_snd_strerror(err));
+					}
+				} else {
+					ThePlayOffset += err;
+					goto label_retry;
+				}
+			} else if (MySound_StartPend) {
+				MySound_StartPend = falseblnr;
+				if ((err = My_snd_pcm_start(pcm_handle)) < 0) {
+					fprintf(stderr, "pcm start error: %s\n",
+						My_snd_strerror(err));
+				}
+			}
+		}
+	}
+}
+
+LOCALPROC MySound_Start(void)
+{
+	if (pcm_handle != NULL) {
+		MySound_Start0();
+	}
+}
+
+LOCALPROC MySound_Stop(void)
+{
+	if (pcm_handle != NULL) {
+		My_snd_pcm_drop(pcm_handle);
+	}
+}
+
+LOCALFUNC blnr HaveAlsaRoutines(void)
+{
+	blnr IsOk = falseblnr;
+
+	if (HaveMy_snd_pcm_open())
+	if (HaveMy_snd_pcm_close())
+	if (HaveMy_snd_pcm_hw_params_malloc())
+	if (HaveMy_snd_pcm_hw_params_free())
+	if (HaveMy_snd_pcm_hw_params_any())
+	if (HaveMy_snd_pcm_hw_params_set_access())
+	if (HaveMy_snd_pcm_hw_params_set_format())
+	if (HaveMy_snd_pcm_hw_params_set_rate_near())
+	if (HaveMy_snd_pcm_hw_params_set_channels())
+	if (HaveMy_snd_pcm_hw_params_set_buffer_size_near())
+	if (HaveMy_snd_pcm_hw_params_set_period_size_near())
+	if (HaveMy_snd_pcm_hw_params())
+	if (HaveMy_snd_pcm_sw_params_malloc())
+	if (HaveMy_snd_pcm_sw_params_free())
+	if (HaveMy_snd_pcm_sw_params_current())
+	if (HaveMy_snd_pcm_sw_params_set_start_threshold())
+	if (HaveMy_snd_pcm_sw_params_set_avail_min())
+	if (HaveMy_snd_pcm_sw_params())
+	if (HaveMy_snd_pcm_nonblock())
+	if (HaveMy_snd_pcm_state())
+	if (HaveMy_snd_pcm_prepare())
+	if (HaveMy_snd_pcm_start())
+	if (HaveMy_snd_pcm_resume())
+	if (HaveMy_snd_pcm_avail_update())
+	if (HaveMy_snd_pcm_writei())
+	if (HaveMy_snd_pcm_drop())
+	if (HaveMy_snd_strerror())
+	{
+		IsOk = trueblnr;
+	}
+
+	return IsOk;
+}
+
+#if 4 == kLn2SoundSampSz
+#define MyDesiredFormat My_SND_PCM_FORMAT_S16
+#else
+#define MyDesiredFormat My_SND_PCM_FORMAT_U8
+#endif
+
+LOCALPROC MySound_Init0(void)
+{
+	My_snd_pcm_hw_params_t *hw_params = NULL;
+	My_snd_pcm_sw_params_t *sw_params = NULL;
+	unsigned int rrate = SOUND_SAMPLERATE;
+	int err;
+
+	buffer_size = desired_alsa_buffer_size;
+	period_size = desired_alsa_period_size;
+
+	/* Open the sound device */
+	if (NULL == alsadev_name) {
+		alsadev_name = getenv("AUDIODEV");
+		if (NULL == alsadev_name) {
+			alsadev_name = strdup("default");
+		}
+	}
+
+	if ((err = My_snd_pcm_open(&pcm_handle, alsadev_name,
+		My_SND_PCM_STREAM_PLAYBACK, My_SND_PCM_NONBLOCK)) < 0)
+	{
+		fprintf(stderr, "cannot open audio device %s (%s)\n",
+			alsadev_name, My_snd_strerror(err));
+		pcm_handle = NULL;
+	} else
+	/* Set some hardware parameters */
+	if ((err = My_snd_pcm_hw_params_malloc(&hw_params)) < 0) {
+		fprintf(stderr,
+			"cannot allocate hardware parameter structure (%s)\n",
+			My_snd_strerror(err));
+		hw_params = NULL;
+	} else
+	if ((err = My_snd_pcm_hw_params_any(pcm_handle, hw_params)) < 0) {
+		fprintf(stderr,
+			"cannot initialize hardware parameter structure (%s)\n",
+			My_snd_strerror(err));
+	} else
+	if ((err = My_snd_pcm_hw_params_set_access(pcm_handle,
+		hw_params, My_SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
+	{
+		fprintf(stderr, "cannot set access type (%s)\n",
+			My_snd_strerror(err));
+	} else
+	if ((err = My_snd_pcm_hw_params_set_format(pcm_handle,
+		hw_params, MyDesiredFormat)) < 0)
+	{
+		fprintf(stderr, "cannot set sample format (%s)\n",
+			My_snd_strerror(err));
+	} else
+	if ((err = My_snd_pcm_hw_params_set_rate_near(pcm_handle,
+		hw_params, &rrate, NULL)) < 0)
+	{
+		fprintf(stderr, "cannot set sample rate (%s)\n",
+			My_snd_strerror(err));
+	} else
+	if ((err = My_snd_pcm_hw_params_set_channels(pcm_handle,
+		hw_params, 1)) < 0)
+	{
+		fprintf(stderr, "cannot set channel count (%s)\n",
+			My_snd_strerror(err));
+	} else
+	if ((err = My_snd_pcm_hw_params_set_buffer_size_near(pcm_handle,
+		hw_params, &buffer_size)) < 0)
+	{
+		fprintf(stderr, "cannot set buffer size count (%s)\n",
+			My_snd_strerror(err));
+	} else
+	if ((err = My_snd_pcm_hw_params_set_period_size_near(pcm_handle,
+		hw_params, &period_size, NULL)) < 0)
+	{
+		fprintf(stderr, "cannot set period size count (%s)\n",
+			My_snd_strerror(err));
+	} else
+	if ((err = My_snd_pcm_hw_params(pcm_handle, hw_params)) < 0) {
+		fprintf(stderr, "cannot set parameters (%s)\n",
+			My_snd_strerror(err));
+	} else
+	{
+		if (rrate != SOUND_SAMPLERATE) {
+			fprintf(stderr, "Warning: sample rate is off by %i Hz\n",
+				SOUND_SAMPLERATE - rrate);
+		}
+
+#if 0
+		if (buffer_size != desired_alsa_buffer_size) {
+			fprintf(stderr,
+				"Warning: buffer size is off,"
+				" desired %li, actual %li\n",
+				desired_alsa_buffer_size, buffer_size);
+		}
+
+		if (period_size != desired_alsa_period_size) {
+			fprintf(stderr,
+				"Warning: period size is off,"
+				" desired %li, actual %li\n",
+				desired_alsa_period_size, period_size);
+		}
+#endif
+
+		My_snd_pcm_hw_params_free(hw_params);
+		hw_params = NULL;
+
+		/* Set some software parameters */
+		if ((err = My_snd_pcm_sw_params_malloc(&sw_params)) < 0) {
+			fprintf(stderr,
+				"cannot allocate software parameter structure (%s)\n",
+				My_snd_strerror(err));
+			sw_params = NULL;
+		} else
+		if ((err = My_snd_pcm_sw_params_current(pcm_handle,
+			sw_params)) < 0)
+		{
+			fprintf(stderr,
+				"Unable to determine current"
+				" sw_params for playback: %s\n",
+				My_snd_strerror(err));
+		} else
+		if ((err = My_snd_pcm_sw_params_set_start_threshold(pcm_handle,
+			sw_params, 0x7FFFFFFF /* buffer_size - period_size */)) < 0)
+		{
+			fprintf(stderr,
+				"Unable to set start threshold mode for playback: %s\n",
+				My_snd_strerror(err));
+		} else
+#if 0
+		if ((err = My_snd_pcm_sw_params_set_avail_min(pcm_handle,
+			sw_params, period_size)) < 0)
+		{
+			fprintf(stderr,
+				"Unable to set avail min for playback: %s\n",
+				My_snd_strerror(err));
+		} else
+#endif
+		/*
+			snd_pcm_sw_params_set_xfer_align deprecated, but
+			call if available. According to one report, bad results
+			in old version of alsa lib if not called.
+		*/
+		if (HaveMy_snd_pcm_sw_params_set_xfer_align()
+			&& ((err = My_snd_pcm_sw_params_set_xfer_align(pcm_handle,
+			sw_params, 1)) < 0))
+		{
+			fprintf(stderr,
+				"Unable to set transfer align for playback: %s\n",
+				My_snd_strerror(err));
+		} else
+		if ((err = My_snd_pcm_sw_params(pcm_handle, sw_params)) < 0) {
+			fprintf(stderr,
+				"Unable to set sw params for playback: %s\n",
+				My_snd_strerror(err));
+		} else
+		{
+			My_snd_pcm_sw_params_free(sw_params);
+			sw_params = NULL;
+
+			My_snd_pcm_nonblock(pcm_handle, 0);
+
+			goto label_done; /* success */
+		}
+	}
+
+	/* clean up after failure */
+
+	if (sw_params != NULL) {
+		My_snd_pcm_sw_params_free(sw_params);
+	}
+	if (hw_params != NULL) {
+		My_snd_pcm_hw_params_free(hw_params);
+	}
+	if (pcm_handle != NULL) {
+		My_snd_pcm_close(pcm_handle);
+		pcm_handle = NULL;
+	}
+
+label_done:
+	;
+}
+
+LOCALFUNC blnr MySound_Init(void)
+{
+	if (HaveAlsaRoutines()) {
+		MySound_Init0();
+	}
+
+	return trueblnr; /* keep going, even if no sound */
+}
+
+LOCALPROC MySound_UnInit(void)
+{
+	if (NULL != pcm_handle) {
+		if (HaveMy_snd_pcm_close()) {
+			My_snd_pcm_close(pcm_handle);
+		}
+		pcm_handle = NULL;
+	}
+	MyCloseAlsaLib();
+}
+
+GLOBALOSGLUPROC MySound_EndWrite(ui4r actL)
+{
+	if (MySound_EndWrite0(actL)) {
+		ConvertSoundBlockToNative(TheSoundBuffer
+			+ ((TheFillOffset - kOneBuffLen) & kAllBuffMask));
+		if (NULL != pcm_handle) {
+			MySound_WriteOut();
+		}
+	}
+}
+
+LOCALPROC MySound_SecondNotify(void)
+{
+	if (NULL != pcm_handle) {
+		MySound_SecondNotify0();
+	}
+}
+
+#define UsingAlsa 1
--- /dev/null
+++ b/src/SGLUDDSP.h
@@ -1,0 +1,228 @@
+/*
+	SGLUDDSP.h
+
+	Copyright (C) 2012 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Sound GLUe for "/Dev/DSP"
+		OSS and related, accessed through "/dev/dsp"
+*/
+
+LOCALVAR int audio_fd = -1;
+LOCALVAR blnr audio_started;
+
+#if 4 == kLn2SoundSampSz
+LOCALPROC ConvertSoundBlockToNative(tpSoundSamp p)
+{
+	int i;
+
+	for (i = kOneBuffLen; --i >= 0; ) {
+		*p++ -= 0x8000;
+	}
+}
+#else
+#define ConvertSoundBlockToNative(p)
+#endif
+
+LOCALPROC MySound_WriteOut(void)
+{
+	int retry_count = 32;
+
+label_retry:
+	if (--retry_count > 0) {
+		int err;
+		struct audio_buf_info info;
+
+		if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) != 0) {
+			fprintf(stderr, "SNDCTL_DSP_GETOSPACE fails\n");
+		} else {
+			tpSoundSamp NextPlayPtr;
+			ui4b PlayNowSize = 0;
+			ui4b MaskedFillOffset = ThePlayOffset & kOneBuffMask;
+			ui4b PrivateBuffUsed = TheFillOffset - ThePlayOffset;
+			int used = (info.fragstotal * info.fragsize) - info.bytes;
+
+			if (audio_started) {
+				ui4b TotPendBuffs = used >> kLnOneBuffSz;
+
+				if (TotPendBuffs < MinFilledSoundBuffs) {
+					MinFilledSoundBuffs = TotPendBuffs;
+				}
+				/* fprintf(stderr, "buffer used %d\n", (int)used); */
+			} else {
+				if (PrivateBuffUsed >= kAllBuffLen - kOneBuffLen) {
+					audio_started = trueblnr;
+				} else {
+					info.bytes = 0;
+				}
+			}
+
+			if (MaskedFillOffset != 0) {
+				/* take care of left overs */
+				PlayNowSize = kOneBuffLen - MaskedFillOffset;
+				NextPlayPtr =
+					TheSoundBuffer + (ThePlayOffset & kAllBuffMask);
+			} else if (0 !=
+				((TheFillOffset - ThePlayOffset) >> kLnOneBuffLen))
+			{
+				PlayNowSize = kOneBuffLen;
+				NextPlayPtr =
+					TheSoundBuffer + (ThePlayOffset & kAllBuffMask);
+			} else {
+				/* nothing to play now */
+			}
+
+#if 4 == kLn2SoundSampSz
+			PlayNowSize <<= 1;
+#endif
+
+			if (PlayNowSize > info.bytes) {
+				PlayNowSize = info.bytes;
+			}
+
+			if (0 != PlayNowSize) {
+				err = write(
+					audio_fd, NextPlayPtr, PlayNowSize);
+				if (err < 0) {
+					if (- EAGAIN == err) {
+						/* buffer full, try again later */
+						fprintf(stderr, "pcm write: EAGAIN\n");
+					} else if (- EPIPE == err) {
+						/* buffer seems to have emptied */
+						fprintf(stderr, "pcm write emptied\n");
+						goto label_retry;
+					} else {
+						fprintf(stderr, "audio_fd write error: %d\n",
+							err);
+					}
+				} else {
+					ThePlayOffset += err
+#if 4 == kLn2SoundSampSz
+						>> 1
+#endif
+						;
+					goto label_retry;
+				}
+			}
+		}
+	}
+}
+
+LOCALPROC MySound_Start(void)
+{
+	if (audio_fd >= 0) {
+		MySound_Start0();
+		audio_started = falseblnr;
+	}
+}
+
+LOCALPROC MySound_Stop(void)
+{
+	if (audio_fd >= 0) {
+		if (0 !=
+			ioctl(audio_fd, SNDCTL_DSP_RESET /* SNDCTL_DSP_HALT */,
+				NULL))
+		{
+			fprintf(stderr, "SNDCTL_DSP_RESET fails\n");
+		}
+	}
+}
+
+#if 4 == kLn2SoundSampSz
+#define MyDesiredFormat AFMT_S16_NE
+#else
+#define MyDesiredFormat AFMT_U8
+#endif
+
+LOCALFUNC blnr MySound_Init(void)
+{
+	blnr IsOk = falseblnr;
+
+	audio_fd = open(AudioDevPath, O_WRONLY, 0);
+	if (audio_fd < 0) {
+		fprintf(stderr, "open /dev/dsp fails: %d\n", audio_fd);
+	} else {
+		int fragment_value =  (16 /* 16 fragments */ << 16)
+#if 4 == kLn2SoundSampSz
+			| 10 /* of 1024 bytes */
+#else
+			| 9 /* of 512 bytes */
+#endif
+			;
+		int channels_value = 1;
+		int fmt_value = MyDesiredFormat;
+		int speed_value = SOUND_SAMPLERATE;
+
+		/* fprintf(stderr, "open /dev/dsp works\n"); */
+
+		if (0 !=
+			ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_value))
+		{
+			fprintf(stderr, "SNDCTL_DSP_SETFRAGMENT fails\n");
+		} else if ((0 !=
+				ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &channels_value))
+			|| (channels_value != 1))
+		{
+			fprintf(stderr, "SNDCTL_DSP_CHANNELS fails\n");
+		} else if ((0 !=
+				ioctl(audio_fd, SNDCTL_DSP_SETFMT, &fmt_value))
+			|| (fmt_value != MyDesiredFormat))
+		{
+			fprintf(stderr, "SNDCTL_DSP_SETFMT fails\n");
+		} else if ((0 !=
+				ioctl(audio_fd, SNDCTL_DSP_SPEED, &speed_value))
+			|| (speed_value != SOUND_SAMPLERATE))
+		{
+			fprintf(stderr, "SNDCTL_DSP_SPEED fails\n");
+		} else
+		{
+			IsOk = trueblnr;
+		}
+
+		if (! IsOk) {
+			(void) close(audio_fd);
+			audio_fd = -1;
+		}
+	}
+
+	return trueblnr; /* keep going, even if no sound */
+}
+
+LOCALPROC MySound_UnInit(void)
+{
+	if (audio_fd >= 0) {
+		if (close(audio_fd) != 0) {
+			fprintf(stderr, "close /dev/dsp fails\n");
+		}
+		audio_fd = -1;
+	}
+}
+
+GLOBALOSGLUPROC MySound_EndWrite(ui4r actL)
+{
+	if (MySound_EndWrite0(actL)) {
+		ConvertSoundBlockToNative(TheSoundBuffer
+			+ ((TheFillOffset - kOneBuffLen) & kAllBuffMask));
+		if (audio_fd >= 0) {
+			MySound_WriteOut();
+		}
+	}
+}
+
+LOCALPROC MySound_SecondNotify(void)
+{
+	if (audio_fd >= 0) {
+		MySound_SecondNotify0();
+	}
+}
--- /dev/null
+++ b/src/SNDEMDEV.c
@@ -1,0 +1,223 @@
+/*
+	SNDEMDEV.c
+
+	Copyright (C) 2003 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	SouND EMulated DEVice
+
+	Emulation of Sound in the Mac Plus could go here.
+
+	This code adapted from "Sound.c" in vMac by Philip Cummins.
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+
+#include "MYOSGLUE.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+#include "MINEM68K.h"
+#endif
+
+#include "SNDEMDEV.h"
+
+
+#if MySoundEnabled
+
+#define kSnd_Main_Offset   0x0300
+#define kSnd_Alt_Offset    0x5F00
+
+#define kSnd_Main_Buffer (kRAM_Size - kSnd_Main_Offset)
+#define kSnd_Alt_Buffer (kRAM_Size - kSnd_Alt_Offset)
+
+/*
+	approximate volume levels of vMac, so:
+
+	x * vol_mult[SoundVolume] >> 16
+		+ vol_offset[SoundVolume]
+	= {approx} (x - kCenterSound) / (8 - SoundVolume) + kCenterSound;
+*/
+
+LOCALVAR const ui4b vol_mult[] = {
+	8192, 9362, 10922, 13107, 16384, 21845, 32768
+};
+
+LOCALVAR const trSoundSamp vol_offset[] = {
+#if 3 == kLn2SoundSampSz
+	112, 110, 107, 103, 96, 86, 64, 0
+#elif 4 == kLn2SoundSampSz
+	28672, 28087, 27307, 26215, 24576, 21846, 16384, 0
+#else
+#error "unsupported kLn2SoundSampSz"
+#endif
+};
+
+LOCALVAR const ui4b SubTick_offset[kNumSubTicks] = {
+	0,    25,  50,  90, 102, 115, 138, 161,
+	185, 208, 231, 254, 277, 300, 323, 346
+};
+
+LOCALVAR const ui3r SubTick_n[kNumSubTicks] = {
+	25,   25,  40,  12,  13,  23,  23,  24,
+	23,   23,  23,  23,  23,  23,  23,  24
+};
+
+/*
+	One version of free form sound driver
+	spends around 18000 cycles writing
+	offsets 50 to 370, then around another 3000
+	cycles writing 0 to 50. So be done
+	with 0 to 50 at end of second sixtieth.
+*/
+
+/*
+	Different in system 6.0.4:
+	spends around 23500 cycles writing
+	offsets 90 to 370, then around another 7500
+	cycles writing 0 to 90. This is nastier,
+	because gets to be a very small gap
+	between where is being read and
+	where written. So read a bit in
+	advance for third subtick.
+*/
+
+/*
+	startup sound spends around 19500 cycles
+	writing offsets 0 to 370. presumably
+	writing offset 0 before it is read.
+*/
+
+LOCALVAR ui5b SoundInvertPhase = 0;
+LOCALVAR ui4b SoundInvertState = 0;
+
+IMPORTFUNC ui4b GetSoundInvertTime(void);
+
+GLOBALPROC MacSound_SubTick(int SubTick)
+{
+	ui4r actL;
+	tpSoundSamp p;
+	ui4r i;
+	ui5b StartOffset = SubTick_offset[SubTick];
+	ui4r n = SubTick_n[SubTick];
+	unsigned long addy =
+#ifdef SoundBuffer
+		(SoundBuffer == 0) ? kSnd_Alt_Buffer :
+#endif
+		kSnd_Main_Buffer;
+#ifndef ln2mtb
+	ui3p addr = addy + (2 * StartOffset) + RAM;
+#else
+	CPTR addr = addy + (2 * StartOffset);
+#endif
+	ui4b SoundInvertTime = GetSoundInvertTime();
+	ui3b SoundVolume = SoundVolb0
+		| (SoundVolb1 << 1)
+		| (SoundVolb2 << 2);
+
+#if dbglog_HAVE && 0
+	dbglog_StartLine();
+	dbglog_writeCStr("reading sound buffer ");
+	dbglog_writeHex(StartOffset);
+	dbglog_writeCStr(" to ");
+	dbglog_writeHex(StartOffset + n);
+	dbglog_writeReturn();
+#endif
+
+label_retry:
+	p = MySound_BeginWrite(n, &actL);
+	if (actL > 0) {
+		if (SoundDisable && (SoundInvertTime == 0)) {
+			for (i = 0; i < actL; i++) {
+#if 0
+				*p++ = 0x00; /* this is believed more accurate */
+#else
+				/* But this avoids more clicks. */
+				*p++ = kCenterSound;
+#endif
+			}
+		} else {
+			for (i = 0; i < actL; i++) {
+				/* Copy sound data, high byte of each word */
+				*p++ =
+#ifndef ln2mtb
+					*addr
+#else
+					get_vm_byte(addr)
+#endif
+#if 4 == kLn2SoundSampSz
+					<< 8
+#endif
+					;
+
+				/* Move the address on */
+				addr += 2;
+			}
+
+			if (SoundInvertTime != 0) {
+				ui5b PhaseIncr = (ui5b)SoundInvertTime * (ui5b)20;
+				p -= actL;
+
+				for (i = 0; i < actL; i++) {
+					if (SoundInvertPhase < 704) {
+						ui5b OnPortion = 0;
+						ui5b LastPhase = 0;
+						do {
+							if (! SoundInvertState) {
+								OnPortion +=
+									(SoundInvertPhase - LastPhase);
+							}
+							SoundInvertState = ! SoundInvertState;
+							LastPhase = SoundInvertPhase;
+							SoundInvertPhase += PhaseIncr;
+						} while (SoundInvertPhase < 704);
+						if (! SoundInvertState) {
+							OnPortion += 704 - LastPhase;
+						}
+						*p = (*p * OnPortion) / 704;
+					} else {
+						if (SoundInvertState) {
+							*p = 0;
+						}
+					}
+					SoundInvertPhase -= 704;
+					p++;
+				}
+			}
+		}
+
+		if (SoundVolume < 7) {
+			/*
+				Usually have volume at 7, so this
+				is just for completeness.
+			*/
+			ui5b mult = (ui5b)vol_mult[SoundVolume];
+			trSoundSamp offset = vol_offset[SoundVolume];
+
+			p -= actL;
+			for (i = 0; i < actL; i++) {
+				*p = (trSoundSamp)((ui5b)(*p) * mult >> 16) + offset;
+				++p;
+			}
+		}
+
+		MySound_EndWrite(actL);
+		n -= actL;
+		if (n > 0) {
+			goto label_retry;
+		}
+	}
+}
+
+#endif
--- /dev/null
+++ b/src/SNDEMDEV.h
@@ -1,0 +1,25 @@
+/*
+	SNDEMDEV.h
+
+	Copyright (C) 2003 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef SNDEMDEV_H
+#error "header already included"
+#else
+#define SNDEMDEV_H
+#endif
+
+#if MySoundEnabled
+EXPORTPROC MacSound_SubTick(int SubTick);
+#endif
--- /dev/null
+++ b/src/SONYEMDV.c
@@ -1,0 +1,1644 @@
+/*
+	SONYEMDV.c
+
+	Copyright (C) 2009 Philip Cummins, Jesus A. Alvarez, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	SONY floppy disk EMulated DeVice
+
+	The Sony hardware is not actually emulated. Instead the
+	ROM is patched to replace the Sony disk driver with
+	code that calls Mini vMac extensions implemented in
+	the file.
+
+	Information neeeded to better support the Disk Copy 4.2
+	format was found in libdc42.c of the Lisa Emulator Project
+	by Ray A. Arachelian, and adapted to Mini vMac
+	by Jesus A. Alvarez.
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+#include "MYOSGLUE.h"
+#include "ENDIANAC.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+#include "MINEM68K.h"
+#endif
+
+#include "SONYEMDV.h"
+
+/*
+	ReportAbnormalID unused 0x090B - 0x09FF
+*/
+
+
+LOCALVAR ui5b vSonyMountedMask = 0;
+
+#define vSonyIsLocked(Drive_No) \
+	((vSonyWritableMask & ((ui5b)1 << (Drive_No))) == 0)
+#define vSonyIsMounted(Drive_No) \
+	((vSonyMountedMask & ((ui5b)1 << (Drive_No))) != 0)
+
+LOCALFUNC blnr vSonyNextPendingInsert0(tDrive *Drive_No)
+{
+	/* find next drive to Mount */
+	ui5b MountPending = vSonyInsertedMask & (~ vSonyMountedMask);
+	if (MountPending != 0) {
+		tDrive i;
+		for (i = 0; i < NumDrives; ++i) {
+			if ((MountPending & ((ui5b)1 << i)) != 0) {
+				*Drive_No = i;
+				return trueblnr; /* only one disk at a time */
+			}
+		}
+	}
+
+	return falseblnr;
+}
+
+LOCALFUNC tMacErr CheckReadableDrive(tDrive Drive_No)
+{
+	tMacErr result;
+
+	if (Drive_No >= NumDrives) {
+		result = mnvm_nsDrvErr;
+	} else if (! vSonyIsMounted(Drive_No)) {
+		result = mnvm_offLinErr;
+	} else {
+		result = mnvm_noErr;
+	}
+
+	return result;
+}
+
+LOCALFUNC tMacErr vSonyTransferVM(blnr IsWrite,
+	CPTR Buffera, tDrive Drive_No,
+	ui5r Sony_Start, ui5r Sony_Count, ui5r *Sony_ActCount)
+{
+	/*
+		Transfer data between emulated disk and emulated memory. Taking
+		into account that the emulated memory may not be contiguous in
+		real memory. (Though it generally is for macintosh emulation.)
+	*/
+	tMacErr result;
+	ui5b contig;
+	ui5r actual;
+	ui3p Buffer;
+	ui5r offset = Sony_Start;
+	ui5r n = Sony_Count;
+
+label_1:
+	if (0 == n) {
+		result = mnvm_noErr;
+	} else {
+		Buffer = get_real_address0(n, ! IsWrite, Buffera, &contig);
+		if (0 == contig) {
+			result = mnvm_miscErr;
+		} else {
+			result = vSonyTransfer(IsWrite, Buffer, Drive_No,
+				offset, contig, &actual);
+			offset += actual;
+			Buffera += actual;
+			n -= actual;
+			if (mnvm_noErr == result) {
+				goto label_1;
+			}
+		}
+	}
+
+	if (nullpr != Sony_ActCount) {
+		*Sony_ActCount = Sony_Count - n;
+	}
+	return result;
+}
+
+LOCALPROC MyMoveBytesVM(CPTR srcPtr, CPTR dstPtr, si5b byteCount)
+{
+	ui3p src;
+	ui3p dst;
+	ui5b contigSrc;
+	ui5b contigDst;
+	ui5r contig;
+
+label_1:
+	if (0 != byteCount) {
+		src = get_real_address0(byteCount, falseblnr, srcPtr,
+			&contigSrc);
+		dst = get_real_address0(byteCount, trueblnr,  dstPtr,
+			&contigDst);
+		if ((0 == contigSrc) || (0 == contigDst)) {
+			ReportAbnormalID(0x0901, "MyMoveBytesVM fails");
+		} else {
+			contig = (contigSrc < contigDst) ? contigSrc : contigDst;
+			MyMoveBytes(src, dst, contig);
+			srcPtr += contig;
+			dstPtr += contig;
+			byteCount -= contig;
+			goto label_1;
+		}
+	}
+}
+
+LOCALVAR ui5r ImageDataOffset[NumDrives];
+	/* size of any header in disk image file */
+LOCALVAR ui5r ImageDataSize[NumDrives];
+	/* size of disk image file contents */
+
+#if Sony_SupportTags
+LOCALVAR ui5r ImageTagOffset[NumDrives];
+	/* offset to disk image file tags */
+#endif
+
+#if Sony_SupportDC42
+#define kDC42offset_diskName      0
+#define kDC42offset_dataSize     64
+#define kDC42offset_tagSize      68
+#define kDC42offset_dataChecksum 72
+#define kDC42offset_tagChecksum  76
+#define kDC42offset_diskFormat   80
+#define kDC42offset_formatByte   81
+#define kDC42offset_private      82
+#define kDC42offset_userData     84
+#endif
+
+#define ChecksumBlockSize 1024
+
+#if Sony_SupportDC42 && Sony_WantChecksumsUpdated
+LOCALFUNC tMacErr DC42BlockChecksum(tDrive Drive_No,
+	ui5r Sony_Start, ui5r Sony_Count, ui5r *r)
+{
+	tMacErr result;
+	ui5r n;
+	ui3b Buffer[ChecksumBlockSize];
+	ui3b *p;
+	ui5b sum = 0;
+	ui5r offset = Sony_Start;
+	ui5r remaining = Sony_Count;
+
+	while (0 != remaining) {
+		/* read a block */
+		if (remaining > ChecksumBlockSize) {
+			n = ChecksumBlockSize;
+		} else {
+			n = remaining;
+		}
+
+		result = vSonyTransfer(falseblnr, Buffer, Drive_No, offset,
+			n, nullpr);
+		if (mnvm_noErr != result) {
+			return result;
+		}
+
+		offset += n;
+		remaining -= n;
+
+		/* add to Checksum */
+		p = Buffer;
+		n >>= 1; /* n = number of words */
+		while (0 != n) {
+			--n;
+			/* ROR.l sum+word */
+			sum += do_get_mem_word(p);
+			p += 2;
+			sum = (sum >> 1) | ((sum & 1) << 31);
+		}
+	}
+
+	*r = sum;
+	return mnvm_noErr;
+}
+#endif
+
+#if Sony_SupportDC42 && Sony_WantChecksumsUpdated
+#if Sony_SupportTags
+#define SizeCheckSumsToUpdate 8
+#else
+#define SizeCheckSumsToUpdate 4
+#endif
+#endif
+
+#if Sony_WantChecksumsUpdated
+LOCALPROC Drive_UpdateChecksums(tDrive Drive_No)
+{
+	if (! vSonyIsLocked(Drive_No)) {
+		ui5r DataOffset = ImageDataOffset[Drive_No];
+#if Sony_SupportDC42
+		if (kDC42offset_userData == DataOffset) {
+			/* a disk copy 4.2 image */
+			tMacErr result;
+			ui5r dataChecksum;
+			ui3b Buffer[SizeCheckSumsToUpdate];
+			ui5r Sony_Count = SizeCheckSumsToUpdate;
+			ui5r DataSize = ImageDataSize[Drive_No];
+
+			/* Checksum image data */
+			result = DC42BlockChecksum(Drive_No,
+				DataOffset, DataSize, &dataChecksum);
+			if (mnvm_noErr != result) {
+				ReportAbnormalID(0x0902, "Failed to find dataChecksum");
+				dataChecksum = 0;
+			}
+			do_put_mem_long(Buffer, dataChecksum);
+#if Sony_SupportTags
+			{
+				ui5r tagChecksum;
+				ui5r TagOffset = ImageTagOffset[Drive_No];
+				ui5r TagSize =
+					(0 == TagOffset) ? 0 : ((DataSize >> 9) * 12);
+				if (TagSize < 12) {
+					tagChecksum = 0;
+				} else {
+					/*
+						Checksum of tags doesn't include first block.
+						presumably because of bug in original disk
+						copy program.
+					*/
+					result = DC42BlockChecksum(Drive_No,
+						TagOffset + 12, TagSize - 12, &tagChecksum);
+					if (mnvm_noErr != result) {
+						ReportAbnormalID(0x0903,
+							"Failed to find tagChecksum");
+						tagChecksum = 0;
+					}
+				}
+				do_put_mem_long(Buffer + 4, tagChecksum);
+			}
+#endif
+
+			/* write Checksums */
+			vSonyTransfer(trueblnr, Buffer, Drive_No,
+				kDC42offset_dataChecksum, Sony_Count, nullpr);
+		}
+#endif
+	}
+}
+#endif
+
+#define checkheaderoffset 0
+#define checkheadersize 128
+
+#define Sony_SupportOtherFormats Sony_SupportDC42
+
+LOCALFUNC tMacErr vSonyNextPendingInsert(tDrive *Drive_No)
+{
+	tDrive i;
+	tMacErr result;
+	ui5r L;
+
+	if (! vSonyNextPendingInsert0(&i)) {
+		result = mnvm_nsDrvErr;
+	} else {
+		result = vSonyGetSize(i, &L);
+		if (mnvm_noErr == result) {
+			/* first, set up for default format */
+			ui5r DataOffset = 0;
+			ui5r DataSize = L;
+#if Sony_SupportTags
+			ui5r TagOffset = 0;
+#endif
+
+#if Sony_SupportOtherFormats
+#if IncludeSonyRawMode
+			if (! vSonyRawMode)
+#endif
+			{
+				ui5r DataOffset0;
+				ui5r DataSize0;
+				ui5r TagOffset0;
+				ui5r TagSize0;
+				ui3b Temp[checkheadersize];
+				ui5r Sony_Count = checkheadersize;
+				blnr gotFormat = falseblnr;
+
+				result = vSonyTransfer(falseblnr, Temp, i,
+					checkheaderoffset, Sony_Count, nullpr);
+				if (mnvm_noErr == result) {
+#if Sony_SupportDC42
+					/* Detect Disk Copy 4.2 image */
+					if (0x0100 == do_get_mem_word(
+						&Temp[kDC42offset_private]))
+					{
+						/* DC42 signature found, check sizes */
+						DataSize0 = do_get_mem_long(
+							&Temp[kDC42offset_dataSize]);
+						TagSize0 = do_get_mem_long(
+							&Temp[kDC42offset_tagSize]);
+						DataOffset0 = kDC42offset_userData;
+						TagOffset0 = DataOffset0 + DataSize0;
+						if (L >= (TagOffset0 + TagSize0))
+						if (0 == (DataSize0 & 0x01FF))
+						if ((DataSize0 >> 9) >= 4)
+						if (Temp[kDC42offset_diskName] < 64)
+							/* length of pascal string */
+						{
+							if (0 == TagSize0) {
+								/* no tags */
+								gotFormat = trueblnr;
+							} else if ((DataSize0 >> 9) * 12
+								== TagSize0)
+							{
+								/* 12 byte tags */
+								gotFormat = trueblnr;
+							}
+							if (gotFormat) {
+#if Sony_VerifyChecksums /* mostly useful to check the Checksum code */
+								ui5r dataChecksum;
+								ui5r tagChecksum;
+								ui5r dataChecksum0 = do_get_mem_long(
+									&Temp[kDC42offset_dataChecksum]);
+								ui5r tagChecksum0 = do_get_mem_long(
+									&Temp[kDC42offset_tagChecksum]);
+								result = DC42BlockChecksum(i,
+									DataOffset0, DataSize0,
+									&dataChecksum);
+								if (TagSize0 >= 12) {
+									result = DC42BlockChecksum(i,
+										TagOffset0 + 12, TagSize0 - 12,
+										&tagChecksum);
+								} else {
+									tagChecksum = 0;
+								}
+								if (dataChecksum != dataChecksum0) {
+									ReportAbnormalID(0x0904,
+										"bad dataChecksum");
+								}
+								if (tagChecksum != tagChecksum0) {
+									ReportAbnormalID(0x0905,
+										"bad tagChecksum");
+								}
+#endif
+								DataOffset = DataOffset0;
+								DataSize = DataSize0;
+#if Sony_SupportTags
+								TagOffset =
+									(0 == TagSize0) ? 0 : TagOffset0;
+#endif
+
+#if (! Sony_SupportTags) || (! Sony_WantChecksumsUpdated)
+								if (! vSonyIsLocked(i)) {
+#if ! Sony_WantChecksumsUpdated
+									/* unconditionally revoke */
+#else
+									if (0 != TagSize0)
+#endif
+									{
+										DiskRevokeWritable(i);
+									}
+								}
+#endif
+							}
+						}
+					}
+#endif /* Sony_SupportDC42 */
+				}
+			}
+			if (mnvm_noErr == result)
+#endif /* Sony_SupportOtherFormats */
+			{
+				vSonyMountedMask |= ((ui5b)1 << i);
+
+				ImageDataOffset[i] = DataOffset;
+				ImageDataSize[i] = DataSize;
+#if Sony_SupportTags
+				ImageTagOffset[i] = TagOffset;
+#endif
+
+				*Drive_No = i;
+			}
+		}
+
+		if (mnvm_noErr != result) {
+			(void) vSonyEject(i);
+		}
+	}
+
+	return result;
+}
+
+#define MinTicksBetweenInsert 240
+	/*
+		if call PostEvent too frequently, insert events seem to get lost
+	*/
+
+LOCALVAR ui4r DelayUntilNextInsert;
+
+LOCALVAR CPTR MountCallBack = 0;
+
+/* This checks to see if a disk (image) has been inserted */
+GLOBALPROC Sony_Update (void)
+{
+	if (DelayUntilNextInsert != 0) {
+		--DelayUntilNextInsert;
+	} else {
+		if (MountCallBack != 0) {
+			tDrive i;
+
+			if (mnvm_noErr == vSonyNextPendingInsert(&i)) {
+				ui5b data = i;
+
+				if (vSonyIsLocked(i)) {
+					data |= ((ui5b)0x00FF) << 16;
+				}
+
+				DiskInsertedPsuedoException(MountCallBack, data);
+
+#if IncludeSonyRawMode
+				if (! vSonyRawMode)
+#endif
+				{
+					DelayUntilNextInsert = MinTicksBetweenInsert;
+					/*
+						but usually will reach kDriveStatus first,
+						where shorten delay.
+					*/
+				}
+			}
+		}
+	}
+}
+
+LOCALFUNC tMacErr Drive_Transfer(blnr IsWrite, CPTR Buffera,
+	tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count,
+	ui5r *Sony_ActCount)
+{
+	tMacErr result;
+
+	QuietEnds();
+
+	if (nullpr != Sony_ActCount) {
+		*Sony_ActCount = 0;
+	}
+
+	result = CheckReadableDrive(Drive_No);
+	if (mnvm_noErr == result) {
+		if (IsWrite && vSonyIsLocked(Drive_No)) {
+			result = mnvm_vLckdErr;
+		} else {
+			ui5r DataSize = ImageDataSize[Drive_No];
+			if (Sony_Start > DataSize) {
+				result = mnvm_eofErr;
+			} else {
+				blnr hit_eof = falseblnr;
+				ui5r L = DataSize - Sony_Start;
+				if (L >= Sony_Count) {
+					L = Sony_Count;
+				} else {
+					hit_eof = trueblnr;
+				}
+				result = vSonyTransferVM(IsWrite, Buffera, Drive_No,
+					ImageDataOffset[Drive_No] + Sony_Start, L,
+					Sony_ActCount);
+				if ((mnvm_noErr == result) && hit_eof) {
+					result = mnvm_eofErr;
+				}
+			}
+		}
+	}
+
+	return result;
+}
+
+LOCALVAR blnr QuitOnEject = falseblnr;
+
+GLOBALPROC Sony_SetQuitOnEject(void)
+{
+	QuitOnEject = trueblnr;
+}
+
+LOCALFUNC tMacErr Drive_Eject(tDrive Drive_No)
+{
+	tMacErr result;
+
+	result = CheckReadableDrive(Drive_No);
+	if (mnvm_noErr == result) {
+		vSonyMountedMask &= ~ ((ui5b)1 << Drive_No);
+#if Sony_WantChecksumsUpdated
+		Drive_UpdateChecksums(Drive_No);
+#endif
+		result = vSonyEject(Drive_No);
+		if (QuitOnEject != 0) {
+			if (! AnyDiskInserted()) {
+				ForceMacOff = trueblnr;
+			}
+		}
+	}
+
+	return result;
+}
+
+#if IncludeSonyNew
+LOCALFUNC tMacErr Drive_EjectDelete(tDrive Drive_No)
+{
+	tMacErr result;
+
+	result = CheckReadableDrive(Drive_No);
+	if (mnvm_noErr == result) {
+		if (vSonyIsLocked(Drive_No)) {
+			result = mnvm_vLckdErr;
+		} else {
+			vSonyMountedMask &= ~ ((ui5b)1 << Drive_No);
+			result = vSonyEjectDelete(Drive_No);
+		}
+	}
+
+	return result;
+}
+#endif
+
+GLOBALPROC Sony_EjectAllDisks(void)
+{
+	tDrive i;
+
+	vSonyMountedMask = 0;
+	for (i = 0; i < NumDrives; ++i) {
+		if (vSonyIsInserted(i)) {
+#if Sony_WantChecksumsUpdated
+			Drive_UpdateChecksums(i);
+#endif
+			(void) vSonyEject(i);
+		}
+	}
+}
+
+GLOBALPROC Sony_Reset(void)
+{
+	DelayUntilNextInsert = 0;
+	QuitOnEject = falseblnr;
+	MountCallBack = 0;
+}
+
+/*
+	Mini vMac extension for low level access to disk operations.
+*/
+
+#define kCmndDiskNDrives 1
+#define kCmndDiskRead 2
+#define kCmndDiskWrite 3
+#define kCmndDiskEject 4
+#define kCmndDiskGetSize 5
+#define kCmndDiskGetCallBack 6
+#define kCmndDiskSetCallBack 7
+#define kCmndDiskQuitOnEject 8
+#define kCmndDiskFeatures 9
+#define kCmndDiskNextPendingInsert 10
+#if IncludeSonyRawMode
+#define kCmndDiskGetRawMode 11
+#define kCmndDiskSetRawMode 12
+#endif
+#if IncludeSonyNew
+#define kCmndDiskNew 13
+#define kCmndDiskGetNewWanted 14
+#define kCmndDiskEjectDelete 15
+#endif
+#if IncludeSonyGetName
+#define kCmndDiskGetName 16
+#endif
+
+#define kFeatureCmndDisk_RawMode 0
+#define kFeatureCmndDisk_New 1
+#define kFeatureCmndDisk_NewName 2
+#define kFeatureCmndDisk_GetName 3
+
+#define kParamDiskNumDrives 8
+#define kParamDiskStart 8
+#define kParamDiskCount 12
+#define kParamDiskBuffer 16
+#define kParamDiskDrive_No 20
+
+GLOBALPROC ExtnDisk_Access(CPTR p)
+{
+	tMacErr result = mnvm_controlErr;
+
+	switch (get_vm_word(p + ExtnDat_commnd)) {
+		case kCmndVersion:
+			put_vm_word(p + ExtnDat_version, 2);
+			result = mnvm_noErr;
+			break;
+		case kCmndDiskNDrives: /* count drives */
+			put_vm_word(p + kParamDiskNumDrives, NumDrives);
+			result = mnvm_noErr;
+			break;
+		case kCmndDiskRead:
+			{
+				ui5r Sony_ActCount;
+				CPTR Buffera = get_vm_long(p + kParamDiskBuffer);
+				tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No);
+				ui5r Sony_Start = get_vm_long(p + kParamDiskStart);
+				ui5r Sony_Count = get_vm_long(p + kParamDiskCount);
+
+				result = Drive_Transfer(falseblnr, Buffera, Drive_No,
+					Sony_Start, Sony_Count, &Sony_ActCount);
+
+				put_vm_long(p + kParamDiskCount, Sony_ActCount);
+			}
+			break;
+		case kCmndDiskWrite:
+			{
+				ui5r Sony_ActCount;
+				CPTR Buffera = get_vm_long(p + kParamDiskBuffer);
+				tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No);
+				ui5r Sony_Start = get_vm_long(p + kParamDiskStart);
+				ui5r Sony_Count = get_vm_long(p + kParamDiskCount);
+
+				result = Drive_Transfer(trueblnr, Buffera, Drive_No,
+					Sony_Start, Sony_Count, &Sony_ActCount);
+
+				put_vm_long(p + kParamDiskCount, Sony_ActCount);
+			}
+			break;
+		case kCmndDiskEject:
+			{
+				tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No);
+				result = Drive_Eject(Drive_No);
+			}
+			break;
+		case kCmndDiskGetSize:
+			{
+				tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No);
+
+				result = CheckReadableDrive(Drive_No);
+				if (mnvm_noErr == result) {
+					put_vm_long(p + kParamDiskCount,
+						ImageDataSize[Drive_No]);
+					result = mnvm_noErr;
+				}
+			}
+			break;
+		case kCmndDiskGetCallBack:
+			put_vm_long(p + kParamDiskBuffer, MountCallBack);
+			result = mnvm_noErr;
+			break;
+		case kCmndDiskSetCallBack:
+			MountCallBack = get_vm_long(p + kParamDiskBuffer);
+			result = mnvm_noErr;
+			break;
+		case kCmndDiskQuitOnEject:
+			QuitOnEject = trueblnr;
+			result = mnvm_noErr;
+			break;
+		case kCmndDiskFeatures:
+			{
+				ui5r v = (0
+#if IncludeSonyRawMode
+					| ((ui5b)1 << kFeatureCmndDisk_RawMode)
+#endif
+#if IncludeSonyNew
+					| ((ui5b)1 << kFeatureCmndDisk_New)
+#endif
+#if IncludeSonyNameNew
+					| ((ui5b)1 << kFeatureCmndDisk_NewName)
+#endif
+#if IncludeSonyGetName
+					| ((ui5b)1 << kFeatureCmndDisk_GetName)
+#endif
+					);
+
+				put_vm_long(p + ExtnDat_params + 0, v);
+				result = mnvm_noErr;
+			}
+			break;
+		case kCmndDiskNextPendingInsert:
+			{
+				tDrive i;
+
+				result = vSonyNextPendingInsert(&i);
+				if (mnvm_noErr == result) {
+					put_vm_word(p + kParamDiskDrive_No, i);
+				}
+			}
+			break;
+#if IncludeSonyRawMode
+		case kCmndDiskGetRawMode:
+			put_vm_word(p + kParamDiskBuffer, vSonyRawMode);
+			result = mnvm_noErr;
+			break;
+		case kCmndDiskSetRawMode:
+			vSonyRawMode = get_vm_word(p + kParamDiskBuffer);
+			result = mnvm_noErr;
+			break;
+#endif
+#if IncludeSonyNew
+		case kCmndDiskNew:
+			{
+				ui5b count = get_vm_long(p + ExtnDat_params + 0);
+				tPbuf Pbuf_No = get_vm_word(p + ExtnDat_params + 4);
+				/* reserved word at offset 6, should be zero */
+
+				result = mnvm_noErr;
+
+#if IncludePbufs
+				if (Pbuf_No != NotAPbuf) {
+					result = CheckPbuf(Pbuf_No);
+					if (mnvm_noErr == result) {
+						vSonyNewDiskWanted = trueblnr;
+						vSonyNewDiskSize = count;
+#if IncludeSonyNameNew
+						if (vSonyNewDiskName != NotAPbuf) {
+							PbufDispose(vSonyNewDiskName);
+						}
+						vSonyNewDiskName = Pbuf_No;
+#else
+						PbufDispose(Pbuf_No);
+#endif
+					}
+				} else
+#endif
+				{
+					vSonyNewDiskWanted = trueblnr;
+					vSonyNewDiskSize = count;
+				}
+			}
+			break;
+		case kCmndDiskGetNewWanted:
+			put_vm_word(p + kParamDiskBuffer, vSonyNewDiskWanted);
+			result = mnvm_noErr;
+			break;
+		case kCmndDiskEjectDelete:
+			{
+				tDrive Drive_No = get_vm_word(p + kParamDiskDrive_No);
+				result = Drive_EjectDelete(Drive_No);
+			}
+			break;
+#endif
+#if IncludeSonyGetName
+		case kCmndDiskGetName:
+			{
+				tDrive Drive_No = get_vm_word(p + ExtnDat_params + 0);
+				/* reserved word at offset 2, should be zero */
+				result = CheckReadableDrive(Drive_No);
+				if (mnvm_noErr == result) {
+					tPbuf Pbuf_No;
+					result = vSonyGetName(Drive_No, &Pbuf_No);
+					put_vm_word(p + ExtnDat_params + 4, Pbuf_No);
+				}
+			}
+			break;
+#endif
+	}
+
+	put_vm_word(p + ExtnDat_result, result);
+}
+
+
+/*
+	Mini vMac extension that implements most of the logic
+	of the replacement disk driver patched into the emulated ROM.
+	(sony_driver in ROMEMDEV.c)
+
+	This logic used to be completely contained in the 68k code
+	of the replacement driver, using only the low level
+	disk access extension.
+*/
+
+/* Sony Variable Drive Setting Offsets */
+
+#define kTrack       0 /* Current Track */
+#define kWriteProt   2 /* FF if Write Protected, 00 if readable */
+#define kDiskInPlace 3
+	/*
+		00 = No Disk, 01 = Disk In,
+		2 = MacOS Read, FC-FF = Just Ejected
+	*/
+#define kInstalled   4
+	/* 00 = Unknown, 01 = Installed, FF = Not Installed */
+#define kSides       5
+	/* 00 if Single Sided Drive, FF if Doubled Sided Drive */
+#define kQLink       6 /* Link to Next Drive */
+#define kQType      10 /* Drive Type (0 = Size Saved, 1 = Very Large) */
+#define kQDriveNo   12 /* Drive Number (1 = Internal, 2 = External) */
+#define kQRefNum    14
+	/* Driver Reference Number (-5 for .Sony, FFFB) */
+#define kQFSID      16 /* File System ID (0 = MacOS) */
+#define kQDrvSz     18 /* size, low-order word */
+#define kQDrvSz2    20 /* size, hi-order word */
+
+#define kTwoSideFmt 18
+	/* FF if double-sided format, 00 if single-sided format */
+#define kNewIntf    19
+	/* FF if new 800K interface or 00 if old 400K interface */
+#define kDriveErrs  20 /* Drive Soft Errors */
+
+/* Sony Driver Control Call csCodes */
+
+#define kKillIO             1
+#define kVerifyDisk         5
+#define kFormatDisk         6
+#define kEjectDisk          7
+#define kSetTagBuffer       8
+#define kTrackCacheControl  9
+#define kGetIconID         20
+#define kDriveIcon         21
+#define kMediaIcon         22
+#define kDriveInfo         23
+#define kFormatCopy     21315
+
+/* Sony Driver Status Call csCodes */
+
+#define kReturnFormatList  6
+#define kDriveStatus       8
+#define kMFMStatus        10
+#define kDuplicatorVersionSupport  17494
+
+/* Parameter Block Offsets */
+
+#define kqLink         0
+#define kqType         4
+#define kioTrap        6
+#define kioCmdAddr     8
+#define kioCompletion 12
+#define kioResult     16
+#define kioNamePtr    18
+#define kioVRefNum    22
+#define kioRefNum     24
+#define kcsCode       26
+#define kcsParam      28
+#define kioBuffer     32 /* Buffer to store data into */
+#define kioReqCount   36 /* Requested Number of Bytes */
+#define kioActCount   40 /* Actual Number of Bytes obtained */
+#define kioPosMode    44 /* Positioning Mode */
+#define kioPosOffset  46 /* Position Offset */
+
+/* Positioning Modes */
+
+#define kfsAtMark    0 /* At Mark (Ignore PosOffset) */
+#define kfsFromStart 1 /* At Start (PosOffset is absolute) */
+#define kfsFromLEOF  2 /* From Logical End of File - PosOffset */
+#define kfsFromMark  3 /* At Mark + PosOffset */
+
+/* Device Control Entry Offsets */
+
+#define kdCtlPosition 16
+
+#if 0
+struct MyDriverDat_R {
+	ui5b zeroes[4];  /*  0 */
+	ui5b checkval;   /* 16 */
+	ui5b pokeaddr;   /* 20 */
+	ui4b NumDrives;  /* 24 */
+	ui4b DiskExtn;   /* 26 */
+	TMTask NullTask; /* 28 */
+	/* total size must be <= FirstDriveVarsOffset */
+};
+
+typedef struct MyDriverDat_R MyDriverDat_R;
+#endif
+
+
+#if CurEmMd <= kEmMd_Twiggy
+
+#define SonyVarsPtr 0x0128 /* TwiggyVars, actually */
+
+#if CurEmMd <= kEmMd_Twig43
+#define MinSonVarsSize 0x000000FA
+#define FirstDriveVarsOffset 0x004A
+#define EachDriveVarsSize 0x0042
+#else
+#define MinSonVarsSize 0x000000E6
+#define FirstDriveVarsOffset 0x004C
+#define EachDriveVarsSize 0x002E
+#endif
+
+#else
+
+#define SonyVarsPtr 0x0134
+
+#define FirstDriveVarsOffset 0x004A
+#define EachDriveVarsSize 0x0042
+#if CurEmMd <= kEmMd_128K
+#define MinSonVarsSize 0x000000FA
+#else
+#define MinSonVarsSize 0x00000310
+#endif
+
+#endif
+
+#define kcom_checkval 0x841339E2
+
+#define Sony_dolog (dbglog_HAVE && 0)
+
+#if Sony_SupportTags
+LOCALVAR CPTR TheTagBuffer;
+#endif
+
+LOCALFUNC ui5b DriveVarsLocation(tDrive Drive_No)
+{
+	CPTR SonyVars = get_vm_long(SonyVarsPtr);
+
+	if (Drive_No < NumDrives) {
+		return SonyVars + FirstDriveVarsOffset
+			+ EachDriveVarsSize * Drive_No;
+	} else {
+		return 0;
+	}
+}
+
+LOCALFUNC tMacErr Sony_Mount(CPTR p)
+{
+	ui5b data = get_vm_long(p + ExtnDat_params + 0);
+	tMacErr result = mnvm_miscErr;
+	tDrive i = data & 0x0000FFFF;
+	CPTR dvl = DriveVarsLocation(i);
+
+	if (0 == dvl) {
+#if Sony_dolog
+		dbglog_WriteNote("Sony : Mount : no dvl");
+#endif
+
+		result = mnvm_nsDrvErr;
+	} else if (get_vm_byte(dvl + kDiskInPlace) == 0x00) {
+		ui5b L = ImageDataSize[i] >> 9; /* block count */
+
+#if Sony_dolog
+		dbglog_StartLine();
+		dbglog_writeCStr("Sony : Mount : Drive=");
+		dbglog_writeHex(i);
+		dbglog_writeCStr(", L=");
+		dbglog_writeHex(L);
+		dbglog_writeReturn();
+#endif
+
+#if CurEmMd <= kEmMd_Twiggy
+		if (L == 1702) {
+			put_vm_byte(dvl + kTwoSideFmt, 0xFF);
+				/* Drive i Single Format */
+			put_vm_byte(dvl + kNewIntf, 0x00);
+				/* Drive i doesn't use new interface */
+			put_vm_word(dvl + kQType, 0x00); /* Drive Type */
+			put_vm_word(dvl + kDriveErrs, 0x0000);
+				/* Drive i has no errors */
+		} else
+#else
+		if ((L == 800)
+#if CurEmMd > kEmMd_128K
+			|| (L == 1600)
+#endif
+		)
+		{
+#if CurEmMd <= kEmMd_128K
+			put_vm_byte(dvl + kTwoSideFmt, 0x00);
+				/* Drive i Single Format */
+			put_vm_byte(dvl + kNewIntf, 0x00);
+				/* Drive i doesn't use new interface */
+#else
+			if (L == 800) {
+				put_vm_byte(dvl + kTwoSideFmt, 0x00);
+					/* Drive i Single Format */
+			} else {
+				put_vm_byte(dvl + kTwoSideFmt, 0xFF);
+					/* Drive Double Format */
+			}
+			put_vm_byte(dvl + kNewIntf, 0xFF);
+				/* Drive i uses new interface */
+#endif
+			put_vm_word(dvl + kQType, 0x00); /* Drive Type */
+			put_vm_word(dvl + kDriveErrs, 0x0000);
+				/* Drive i has no errors */
+		} else
+#endif
+		{
+			put_vm_word(dvl + kQRefNum, 0xFFFE);  /* Driver */
+			put_vm_word(dvl + kQType, 0x01); /* Drive Type */
+			put_vm_word(dvl + kQDrvSz , L);
+			put_vm_word(dvl + kQDrvSz2, L >> 16);
+		}
+
+#if CurEmMd <= kEmMd_Twiggy
+		put_vm_word(dvl + kQFSID, 0x00); /* kQFSID must be 0 for 4.3T */
+#endif
+
+		put_vm_byte(dvl + kWriteProt, data >> 16);
+		put_vm_byte(dvl + kDiskInPlace, 0x01); /* Drive Disk Inserted */
+
+		put_vm_long(p + ExtnDat_params + 4, i + 1);
+			/* PostEvent Disk Inserted eventMsg */
+		result = mnvm_noErr;
+	} else {
+		/* disk already in place, a mistake has been made */
+#if Sony_dolog
+		dbglog_WriteNote("Sony : Mount : already in place");
+#endif
+	}
+
+	return result;
+}
+
+#if Sony_SupportTags
+LOCALFUNC tMacErr Sony_PrimeTags(tDrive Drive_No,
+	ui5r Sony_Start, ui5r Sony_Count, blnr IsWrite)
+{
+	tMacErr result = mnvm_noErr;
+	ui5r TagOffset = ImageTagOffset[Drive_No];
+
+	if ((0 != TagOffset) && (Sony_Count > 0)) {
+		ui5r block = Sony_Start >> 9;
+		ui5r n = Sony_Count >> 9; /* is >= 1 if get here */
+
+		TagOffset += block * 12;
+
+		if (0 != TheTagBuffer) {
+			ui5r count = 12 * n;
+			result = vSonyTransferVM(IsWrite, TheTagBuffer, Drive_No,
+				TagOffset, count, nullpr);
+			if (mnvm_noErr == result) {
+				MyMoveBytesVM(TheTagBuffer + count - 12, 0x02FC, 12);
+			}
+		} else {
+			if (! IsWrite) {
+				/* only need to read the last block tags */
+				ui5r count = 12;
+				TagOffset += 12 * (n - 1);
+				result = vSonyTransferVM(falseblnr, 0x02FC, Drive_No,
+					TagOffset, count, nullpr);
+			} else {
+				ui5r count = 12;
+				ui4r BufTgFBkNum = get_vm_word(0x0302);
+				do {
+					put_vm_word(0x0302, BufTgFBkNum);
+					result = vSonyTransferVM(trueblnr, 0x02FC, Drive_No,
+						TagOffset, count, nullpr);
+					if (mnvm_noErr != result) {
+						goto label_fail;
+					}
+					BufTgFBkNum += 1;
+					TagOffset += 12;
+				} while (--n != 0);
+			}
+		}
+	}
+
+label_fail:
+	return result;
+}
+#endif
+
+/* Handles I/O to disks */
+LOCALFUNC tMacErr Sony_Prime(CPTR p)
+{
+	tMacErr result;
+	ui5r Sony_Count;
+	ui5r Sony_Start;
+	ui5r Sony_ActCount = 0;
+	CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 0);
+	CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 4);
+	tDrive Drive_No = get_vm_word(ParamBlk + kioVRefNum) - 1;
+	ui4r IOTrap = get_vm_word(ParamBlk + kioTrap);
+	CPTR dvl = DriveVarsLocation(Drive_No);
+
+	if (0 == dvl) {
+#if Sony_dolog
+		dbglog_WriteNote("Sony : Prime : no dvl");
+#endif
+
+		result = mnvm_nsDrvErr;
+	} else
+#if CurEmMd >= kEmMd_Twiggy
+	if (0xA002 != (IOTrap & 0xF0FE)) {
+#if Sony_dolog
+		dbglog_WriteNote("Sony : Prime : "
+			"not read (0xA002) or write (0xA003)");
+#endif
+
+		result = mnvm_controlErr;
+	} else
+#endif
+	{
+		blnr IsWrite = (0 != (IOTrap & 0x0001));
+		ui3b DiskInPlaceV = get_vm_byte(dvl + kDiskInPlace);
+
+		if (DiskInPlaceV != 0x02) {
+			if (DiskInPlaceV == 0x01) {
+				put_vm_byte(dvl + kDiskInPlace, 0x02); /* Clamp Drive */
+			} else {
+				result = mnvm_offLinErr;
+				goto label_fail;
+				/*
+					if don't check for this, will go right
+					ahead and boot off a disk that hasn't
+					been mounted yet by Sony_Update.
+					(disks other than the boot disk aren't
+					seen unless mounted by Sony_Update)
+				*/
+			}
+		}
+
+#if 0
+		ui4r PosMode = get_vm_word(ParamBlk + kioPosMode);
+
+		if (0 != (PosMode & 64)) {
+#if ExtraAbnormalReports
+			/*
+				This is used when copy to floppy
+				disk with Finder. But not implemented
+				yet.
+			*/
+			ReportAbnormalID(0x0906, "read verify mode requested");
+#endif
+			PosMode &= ~ 64;
+		}
+
+		/*
+			Don't use the following code, because
+			according to Apple's Technical Note FL24
+			the Device Manager takes care of this,
+			and puts the result in dCtlPosition.
+			(The RAMDisk example in Apple's sample
+			code serves to confirm this. Further
+			evidence found in Basilisk II emulator,
+			and disassembly of Mac Plus disk driver.)
+		*/
+		ui5r PosOffset = get_vm_long(ParamBlk + kioPosOffset);
+		switch (PosMode) {
+			case kfsAtMark:
+				Sony_Start = get_vm_long(DeviceCtl + kdCtlPosition);
+				break;
+			case kfsFromStart:
+				Sony_Start = PosOffset;
+				break;
+#if 0
+			/*
+				not valid for device driver.
+				actually only kfsFromStart seems to be used.
+			*/
+			case kfsFromLEOF:
+				Sony_Start = ImageDataSize[Drive_No]
+					+ PosOffset;
+				break;
+#endif
+			case kfsFromMark:
+				Sony_Start = PosOffset
+					+ get_vm_long(DeviceCtl + kdCtlPosition);
+				break;
+			default:
+				ReportAbnormalID(0x0907, "unknown PosMode");
+				result = mnvm_paramErr;
+				goto label_fail;
+				break;
+		}
+#endif
+		Sony_Start = get_vm_long(DeviceCtl + kdCtlPosition);
+
+		Sony_Count = get_vm_long(ParamBlk + kioReqCount);
+
+#if Sony_dolog
+		dbglog_StartLine();
+		dbglog_writeCStr("Sony : Prime : Drive=");
+		dbglog_writeHex(Drive_No);
+		dbglog_writeCStr(", IsWrite=");
+		dbglog_writeHex(IsWrite);
+		dbglog_writeCStr(", Start=");
+		dbglog_writeHex(Sony_Start);
+		dbglog_writeCStr(", Count=");
+		dbglog_writeHex(Sony_Count);
+		dbglog_writeReturn();
+#endif
+
+		if ((0 != (Sony_Start & 0x1FF))
+			|| (0 != (Sony_Count & 0x1FF)))
+		{
+			/* only whole blocks allowed */
+#if ExtraAbnormalReports
+			ReportAbnormalID(0x0908, "not blockwise in Sony_Prime");
+#endif
+			result = mnvm_paramErr;
+		} else if (IsWrite && (get_vm_byte(dvl + kWriteProt) != 0)) {
+			result = mnvm_wPrErr;
+		} else {
+			CPTR Buffera = get_vm_long(ParamBlk + kioBuffer);
+			result = Drive_Transfer(IsWrite, Buffera, Drive_No,
+					Sony_Start, Sony_Count, &Sony_ActCount);
+#if Sony_SupportTags
+			if (mnvm_noErr == result) {
+				result = Sony_PrimeTags(Drive_No,
+					Sony_Start, Sony_Count, IsWrite);
+			}
+#endif
+			put_vm_long(DeviceCtl + kdCtlPosition,
+				Sony_Start + Sony_ActCount);
+		}
+	}
+
+label_fail:
+	put_vm_word(ParamBlk + kioResult, result);
+	put_vm_long(ParamBlk + kioActCount, Sony_ActCount);
+
+	if (mnvm_noErr != result) {
+		put_vm_word(0x0142 /* DskErr */, result);
+	}
+	return result;
+}
+
+/* Implements control csCodes for the Sony driver */
+LOCALFUNC tMacErr Sony_Control(CPTR p)
+{
+	tMacErr result;
+	CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 0);
+	/* CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 4); */
+	ui4r OpCode = get_vm_word(ParamBlk + kcsCode);
+
+	if (kKillIO == OpCode) {
+#if Sony_dolog
+		dbglog_WriteNote("Sony : Control : kKillIO");
+#endif
+
+		result = mnvm_miscErr;
+	} else if (kSetTagBuffer == OpCode) {
+#if Sony_dolog
+		dbglog_WriteNote("Sony : Control : kSetTagBuffer");
+#endif
+
+#if Sony_SupportTags
+		TheTagBuffer = get_vm_long(ParamBlk + kcsParam);
+		result = mnvm_noErr;
+#else
+		result = mnvm_controlErr;
+#endif
+	} else if (kTrackCacheControl == OpCode) {
+#if Sony_dolog
+		dbglog_WriteNote("Sony : Control : kTrackCacheControl");
+#endif
+
+#if CurEmMd <= kEmMd_128K
+		result = mnvm_controlErr;
+#else
+#if 0
+		ui3r Arg1 = get_vm_byte(ParamBlk + kcsParam);
+		ui3r Arg2 = get_vm_byte(ParamBlk + kcsParam + 1);
+		if (0 == Arg1) {
+			/* disable track cache */
+		} else {
+			/* enable track cache */
+		}
+		if (Arg2 < 0) {
+			/* remove track cache */
+		} else if (Arg2 > 0) {
+			/* install track cache */
+		}
+#endif
+		result = mnvm_noErr;
+			/* not implemented, but pretend we did it */
+#endif
+	} else {
+		tDrive Drive_No = get_vm_word(ParamBlk + kioVRefNum) - 1;
+		CPTR dvl = DriveVarsLocation(Drive_No);
+
+		if (0 == dvl) {
+#if Sony_dolog
+			dbglog_WriteNote("Sony : Control : no dvl");
+#endif
+
+			result = mnvm_nsDrvErr;
+		} else if (get_vm_byte(dvl + kDiskInPlace) == 0) {
+#if Sony_dolog
+			dbglog_WriteNote("Sony : Control : not DiskInPlace");
+#endif
+
+			result = mnvm_offLinErr;
+		} else {
+			switch (OpCode) {
+				case kVerifyDisk :
+#if Sony_dolog
+					dbglog_WriteNote("Sony : Control : kVerifyDisk");
+#endif
+
+					result = mnvm_noErr;
+					break;
+				case kEjectDisk :
+#if Sony_dolog
+					dbglog_StartLine();
+					dbglog_writeCStr("Sony : Control : kEjectDisk : ");
+					dbglog_writeHex(Drive_No);
+					dbglog_writeReturn();
+#endif
+
+					put_vm_byte(dvl + kWriteProt, 0x00);
+						/* Drive Writeable */
+					put_vm_byte(dvl + kDiskInPlace, 0x00);
+						/* Drive No Disk */
+#if 0
+					put_vm_byte(dvl + kTwoSideFmt, 0x00);
+						/* Drive Single Format (Initially) */
+#endif
+					put_vm_word(dvl + kQRefNum, 0xFFFB);
+						/* Drive i uses .Sony */
+
+					result = Drive_Eject(Drive_No);
+					break;
+				case kFormatDisk :
+#if Sony_dolog
+					dbglog_StartLine();
+					dbglog_writeCStr("Sony : Control : kFormatDisk : ");
+					dbglog_writeHex(Drive_No);
+					dbglog_writeReturn();
+#endif
+
+					result = mnvm_noErr;
+					break;
+				case kDriveIcon :
+#if Sony_dolog
+					dbglog_StartLine();
+					dbglog_writeCStr("Sony : Control : kDriveIcon : ");
+					dbglog_writeHex(Drive_No);
+					dbglog_writeReturn();
+#endif
+
+					if (get_vm_word(dvl + kQType) != 0) {
+						put_vm_long(ParamBlk + kcsParam,
+							my_disk_icon_addr);
+						result = mnvm_noErr;
+					} else {
+						result = mnvm_controlErr;
+							/*
+								Driver can't respond to
+								this Control call (-17)
+							*/
+					}
+					break;
+#if CurEmMd >= kEmMd_SE
+				case kDriveInfo :
+					{
+						ui5b v;
+
+#if Sony_dolog
+						dbglog_StartLine();
+						dbglog_writeCStr(
+							"Sony : Control : kDriveInfo : ");
+						dbglog_writeHex(kDriveIcon);
+						dbglog_writeReturn();
+#endif
+
+						if (get_vm_word(dvl + kQType) != 0) {
+							v = 0x00000001; /* unspecified drive */
+						} else {
+#if CurEmMd <= kEmMd_128K
+							v = 0x00000002; /* 400K Drive */
+#else
+							v = 0x00000003; /* 800K Drive */
+#endif
+						}
+						if (Drive_No != 0) {
+							v += 0x00000900;
+								/* Secondary External Drive */
+						}
+						put_vm_long(ParamBlk + kcsParam, v);
+						result = mnvm_noErr; /* No error (0) */
+					}
+					break;
+#endif
+				default :
+#if Sony_dolog
+					dbglog_StartLine();
+					dbglog_writeCStr("Sony : Control : OpCode : ");
+					dbglog_writeHex(OpCode);
+					dbglog_writeReturn();
+#endif
+#if ExtraAbnormalReports
+					if ((kGetIconID != OpCode)
+						&& (kMediaIcon != OpCode)
+						&& (kDriveInfo != OpCode))
+					{
+						ReportAbnormalID(0x0909,
+							"unexpected OpCode in Sony_Control");
+					}
+#endif
+					result = mnvm_controlErr;
+						/*
+							Driver can't respond to
+							this Control call (-17)
+						*/
+					break;
+			}
+		}
+	}
+
+	if (mnvm_noErr != result) {
+		put_vm_word(0x0142 /* DskErr */, result);
+	}
+	return result;
+}
+
+/* Handles the DriveStatus call */
+LOCALFUNC tMacErr Sony_Status(CPTR p)
+{
+	tMacErr result;
+	CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 0);
+	/* CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 4); */
+	ui4r OpCode = get_vm_word(ParamBlk + kcsCode);
+
+#if Sony_dolog
+	dbglog_StartLine();
+	dbglog_writeCStr("Sony : Sony_Status OpCode = ");
+	dbglog_writeHex(OpCode);
+	dbglog_writeReturn();
+#endif
+
+	if (kDriveStatus == OpCode) {
+		tDrive Drive_No = get_vm_word(ParamBlk + kioVRefNum) - 1;
+		CPTR Src = DriveVarsLocation(Drive_No);
+		if (Src == 0) {
+			result = mnvm_nsDrvErr;
+		} else {
+			if (DelayUntilNextInsert > 4) {
+				DelayUntilNextInsert = 4;
+			}
+			MyMoveBytesVM(Src, ParamBlk + kcsParam, 22);
+			result = mnvm_noErr;
+		}
+	} else {
+#if ExtraAbnormalReports
+		if ((kReturnFormatList != OpCode)
+			&& (kDuplicatorVersionSupport != OpCode))
+		{
+			ReportAbnormalID(0x090A,
+				"unexpected OpCode in Sony_Control");
+		}
+#endif
+		result = mnvm_statusErr;
+	}
+
+	if (mnvm_noErr != result) {
+		put_vm_word(0x0142 /* DskErr */, result);
+	}
+	return result;
+}
+
+LOCALFUNC tMacErr Sony_Close(CPTR p)
+{
+#if 0
+	CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 0);
+	CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 4);
+#endif
+	UnusedParam(p);
+	return mnvm_closErr; /* Can't Close Driver */
+}
+
+LOCALFUNC tMacErr Sony_OpenA(CPTR p)
+{
+#if Sony_dolog
+	dbglog_WriteNote("Sony : OpenA");
+#endif
+
+	if (MountCallBack != 0) {
+		return mnvm_opWrErr; /* driver already open */
+	} else {
+		ui5b L = FirstDriveVarsOffset + EachDriveVarsSize * NumDrives;
+
+		if (L < MinSonVarsSize) {
+			L = MinSonVarsSize;
+		}
+
+		put_vm_long(p + ExtnDat_params + 0, L);
+
+		return mnvm_noErr;
+	}
+}
+
+LOCALFUNC tMacErr Sony_OpenB(CPTR p)
+{
+	si4b i;
+	CPTR dvl;
+
+#if Sony_dolog
+	dbglog_WriteNote("Sony : OpenB");
+#endif
+
+	CPTR SonyVars = get_vm_long(p + ExtnDat_params + 4);
+	/* CPTR ParamBlk = get_vm_long(p + ExtnDat_params + 24); (unused) */
+#if CurEmMd > kEmMd_128K
+	CPTR DeviceCtl = get_vm_long(p + ExtnDat_params + 28);
+#endif
+
+	put_vm_long(SonyVars + 16 /* checkval */, kcom_checkval);
+	put_vm_long(SonyVars + 20 /* pokeaddr */, kExtn_Block_Base);
+	put_vm_word(SonyVars + 24 /* NumDrives */, NumDrives);
+	put_vm_word(SonyVars + 26 /* DiskExtn */, kExtnDisk);
+
+	put_vm_long(SonyVarsPtr, SonyVars);
+
+	for (i = 0; (dvl = DriveVarsLocation(i)) != 0; ++i) {
+		put_vm_byte(dvl + kDiskInPlace, 0x00); /* Drive i No Disk */
+		put_vm_byte(dvl + kInstalled, 0x01);   /* Drive i Installed */
+#if CurEmMd <= kEmMd_128K
+		put_vm_byte(dvl + kSides, 0x00);
+			/* Drive i Single Sided */
+#else
+		put_vm_byte(dvl + kSides, 0xFF);
+			/* Drive i Double Sided */
+#endif
+		put_vm_word(dvl + kQDriveNo, i + 1);   /* Drive i is Drive 1 */
+		put_vm_word(dvl + kQRefNum, 0xFFFB);   /* Drive i uses .Sony */
+	}
+
+	{
+		CPTR UTableBase = get_vm_long(0x011C);
+
+		put_vm_long(UTableBase + 4 * 1,
+			get_vm_long(UTableBase + 4 * 4));
+			/* use same drive for hard disk as used for sony floppies */
+	}
+
+#if CurEmMd > kEmMd_128K
+	/* driver version in driver i/o queue header */
+	put_vm_byte(DeviceCtl + 7, 1);
+#endif
+
+#if CurEmMd <= kEmMd_128K
+	/* init Drive Queue */
+	put_vm_word(0x308, 0);
+	put_vm_long(0x308 + 2, 0);
+	put_vm_long(0x308 + 6, 0);
+#endif
+
+	put_vm_long(p + ExtnDat_params + 8,
+		SonyVars + FirstDriveVarsOffset + kQLink);
+	put_vm_word(p + ExtnDat_params + 12, EachDriveVarsSize);
+	put_vm_word(p + ExtnDat_params + 14, NumDrives);
+	put_vm_word(p + ExtnDat_params + 16, 1);
+	put_vm_word(p + ExtnDat_params + 18, 0xFFFB);
+#if CurEmMd <= kEmMd_128K
+	put_vm_long(p + ExtnDat_params + 20, 0);
+#else
+	put_vm_long(p + ExtnDat_params + 20, SonyVars + 28 /* NullTask */);
+#endif
+
+#if Sony_SupportTags
+	TheTagBuffer = 0;
+#endif
+
+	return mnvm_noErr;
+}
+
+LOCALFUNC tMacErr Sony_OpenC(CPTR p)
+{
+#if Sony_dolog
+	dbglog_WriteNote("Sony : OpenC");
+#endif
+
+	MountCallBack = get_vm_long(p + ExtnDat_params + 0)
+#if (CurEmMd == kEmMd_II) || (CurEmMd == kEmMd_IIx)
+		| 0x40000000
+#endif
+		;
+	return mnvm_noErr;
+}
+
+#define kCmndSonyPrime 1
+#define kCmndSonyControl 2
+#define kCmndSonyStatus 3
+#define kCmndSonyClose 4
+#define kCmndSonyOpenA 5
+#define kCmndSonyOpenB 6
+#define kCmndSonyOpenC 7
+#define kCmndSonyMount 8
+
+GLOBALPROC ExtnSony_Access(CPTR p)
+{
+	tMacErr result;
+
+	switch (get_vm_word(p + ExtnDat_commnd)) {
+		case kCmndVersion:
+			put_vm_word(p + ExtnDat_version, 0);
+			result = mnvm_noErr;
+			break;
+		case kCmndSonyPrime:
+			result = Sony_Prime(p);
+			break;
+		case kCmndSonyControl:
+			result = Sony_Control(p);
+			break;
+		case kCmndSonyStatus:
+			result = Sony_Status(p);
+			break;
+		case kCmndSonyClose:
+			result = Sony_Close(p);
+			break;
+		case kCmndSonyOpenA:
+			result = Sony_OpenA(p);
+			break;
+		case kCmndSonyOpenB:
+			result = Sony_OpenB(p);
+			break;
+		case kCmndSonyOpenC:
+			result = Sony_OpenC(p);
+			break;
+		case kCmndSonyMount:
+			result = Sony_Mount(p);
+			break;
+		default:
+			result = mnvm_controlErr;
+			break;
+	}
+
+	put_vm_word(p + ExtnDat_result, result);
+}
--- /dev/null
+++ b/src/SONYEMDV.h
@@ -1,0 +1,31 @@
+/*
+	SONYEMDV.h
+
+	Copyright (C) 2004 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef SONYEMDV_H
+#error "header already included"
+#else
+#define SONYEMDV_H
+#endif
+
+EXPORTPROC ExtnDisk_Access(CPTR p);
+EXPORTPROC ExtnSony_Access(CPTR p);
+
+EXPORTPROC Sony_SetQuitOnEject(void);
+
+EXPORTPROC Sony_EjectAllDisks(void);
+EXPORTPROC Sony_Reset(void);
+
+EXPORTPROC Sony_Update(void);
--- /dev/null
+++ b/src/STRCNCAT.h
@@ -1,0 +1,167 @@
+/*
+	STRCNCAT.h
+
+	Copyright (C) 2017 ArduinoXino, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file;ls see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY;ls without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	STRing CoNstants for CATalan
+
+	These strings were translated by ArduinoXino.
+*/
+
+#define kStrAboutTitle "Sobre"
+#define kStrAboutMessage "Per mostrar informaci;eo sobre aquest programa, utilitzeu el comandament ;]A;} del ^p Mode Control. Per coneixer m;ees sobre el Mode Control, vegi ;[M;ees Comandaments;ll;{ en el menu ;[Especial;{ ."
+
+#define kStrMoreCommandsTitle "M;ees comandaments est;`an disponibles en el mode de control de ^p ."
+#define kStrMoreCommandsMessage "Per entrar en el mode de control, mantingueu premut la tecla ;]^c;} . Seguir;`a en el mode control fins que deixeu anar la tecla ;]^c;} . Polsi ;]H;} en el mode control per llistar els comandaments disponibles."
+
+#define kStrTooManyImagesTitle "Massa imatges de disc"
+#define kStrTooManyImagesMessage "No es poden muntar tantes imatges de disc. Proveu treure alguna."
+
+#define kStrImageInUseTitle "Imatge de disc en ;eus"
+#define kStrImageInUseMessage "No es pot muntar la imatge disc perqu;`e ja est;`a en ;eus per una altra aplicaci;eo, o ja est;`a oberta a ^p."
+
+#define kStrOutOfMemTitle "Mem;`oria insuficient"
+#define kStrOutOfMemMessage "No hi ha prou mem;`oria disponible per a llan;car ^p."
+
+#define kStrNoROMTitle "Impossible localitzar la imatge ROM"
+#define kStrNoROMMessage "No es troba la imatge del fitxer ROM ;[^r;{. Per a m;ees informaci;eo, veure: ;[^w;{."
+
+#define kStrCorruptedROMTitle "El control checksum de la ROM ha fracassat"
+#define kStrCorruptedROMMessage "El fitxer d;laimatge ROM ;[^r;{ pot estar corromput."
+
+#define kStrUnsupportedROMTitle "ROM no suportada"
+#define kStrUnsupportedROMMessage "Fitxer d;laimatge ROM ;[^r;{ carregat amb ;`exit, per;`o aquesta versi;eo no est;`a suportada."
+
+#define kStrQuitWarningTitle "Si us plau, apagueu l;laordinador emulat abans de sortir."
+#define kStrQuitWarningMessage "Per for;car ^p sortir, amb risc de corrupci;eo en les imatges de discos muntades, utilitzeu la ordre ;]Q;} del ^p Mode Control. Per coneixer m;ees sobre el Mode Control, vegi ;[M;ees Comandaments;ll;{ al menu ;[Especial;{ ."
+
+#define kStrReportAbnormalTitle "Situaci;eo anormal"
+#define kStrReportAbnormalMessage "L;laordinador emulat intenta fer una operaci;eo no esperada en un ;eus normal."
+
+#define kStrBadArgTitle "Argument desconegut"
+#define kStrBadArgMessage "No es va comprendre algun dels arguments de la l;einia d;laordres, i es va ignorar."
+
+#define kStrOpenFailTitle "Obertura fracassada"
+#define kStrOpenFailMessage "No s;laha pogut obrir la imatge disc."
+
+#define kStrNoReadROMTitle "No es pot obrir la imatge ROM"
+#define kStrNoReadROMMessage "Es va trobar el fitxer d;laimatge ROM ;[^r;{, per;`o no es va poder llegir."
+
+#define kStrShortROMTitle "Imatge ROM massa curta"
+#define kStrShortROMMessage "El fitxer d;laimatge ROM ;[^r;{ ;ees m;ees curt del que hauria de ser."
+
+/* state of a boolean option */
+#define kStrOn "activat"
+#define kStrOff "desactivat"
+
+/* state of a key */
+#define kStrPressed "polsada"
+#define kStrReleased "deixada anar"
+
+/* state of Stopped */
+#define kStrStoppedOn kStrOn
+#define kStrStoppedOff kStrOff
+
+/* About Screen */
+#define kStrProgramInfo "^v"
+#define kStrSponsorIs "^v. Aquesta variaci;eo est;`a patrocinada per:"
+#define kStrWorkOfMany "Copyright ^y. ^p cont;ee el treball de moltes persones. Aquesta versi;eo ;ees mantinguda per:"
+#define kStrForMoreInfo "Per m;ees informaci;eo, vegeu:"
+#define kStrLicense "^p es distribueix sota els termes de la llic;`encia p;eublica GNU, versi;eo 2."
+#define kStrDisclaimer " ^p es distribueix amb l;laesperan;ca de ser ;eutil, per;`o SENSE CAP GARANTIA;ls fins i tot sense la garantia impl;eicita de MERCANTIBILITAT O ADECUACI;eO PER A UN ;eUS PARTICULAR."
+
+/* Help Screen */
+#define kStrHowToLeaveControl "Per sortir del Mode Control, deixeu anar la tecla ;]^c;} ."
+#define kStrHowToPickACommand "Sin;eo, polsi una lletra. Els comandaments disponibles s;eon:"
+#define kStrCmdAbout "Sobre (informaci;eo sobre versi;eo)"
+#define kStrCmdOpenDiskImage "Obrir imatge de disc..."
+#define kStrCmdQuit "Sortir"
+#define kStrCmdSpeedControl "Control de velocitat;ll (^s)"
+#define kStrCmdMagnifyToggle "Magnificaci;eo (^g)"
+#define kStrCmdFullScrnToggle "Pantalla completa (^f)"
+#define kStrCmdCtrlKeyToggle "Toggle emulaci;eo tecla ;]^m;} (^k)"
+#define kStrCmdReset "Restablir"
+#define kStrCmdInterrupt "Interrompre"
+#define kStrCmdHelp "Ajuda (mostra aquesta p;`agina)"
+
+/* Speed Control Screen */
+#define kStrCurrentSpeed "Velocitat actual: ^s"
+#define kStrSpeedAllOut "M;`axima velocitat"
+#define kStrSpeedStopped "Aturar (^h)"
+#define kStrSpeedBackToggle "Executar en segon pla (^b)"
+#define kStrSpeedAutoSlowToggle "AutoSlow (^l)"
+#define kStrSpeedExit "Sortir del control de velocitat"
+
+#define kStrNewSpeed "Velocitat: ^s"
+#define kStrSpeedValueAllOut kStrSpeedAllOut
+
+#define kStrNewStopped "Aturar est;ea ^h."
+#define kStrNewRunInBack "Executar en segon pla est;`a ^b."
+#define kStrNewAutoSlow "AutoSlow est;`a ^l."
+
+#define kStrNewMagnify "Magnificaci;eo est;`a ^g."
+
+#define kStrNewFullScreen "Pantalla completa est;`a ^f."
+
+#define kStrNewCntrlKey "Emulat tecla ;]^m;} ^k."
+
+#define kStrCmdCancel "cancel;l.lar"
+
+#define kStrConfirmReset "Est;`a segur de voler reiniciar l;laordinador emulat? Els canvis no salvats es perdran, i hi ha risc de corrupci;eo en les imatges de discos muntades. Premeu una tecla:"
+#define kStrResetDo "restablir"
+#define kStrResetNo kStrCmdCancel
+
+#define kStrHaveReset "S;laha reiniciat l;laordinador emulat"
+
+#define kStrCancelledReset "Reset cancel;l.lat"
+
+#define kStrConfirmInterrupt "Est;`a segur de voler interrompre l;laordinador emulat? Aix;`o invocar;`a qualsevol debugger instal;l.lat. Premeu una tecla:"
+#define kStrInterruptDo "interrompre"
+#define kStrInterruptNo kStrCmdCancel
+
+#define kStrHaveInterrupted "S;laha interromput l;laordinador emulat"
+
+#define kStrCancelledInterrupt "Interrupci;eo cancel;l.lada"
+
+#define kStrConfirmQuit "Est;`a segur de desitjar sortir de ^p? Hauria apagar l;laordinador emulat abans de sortir, per evitar corrupcions en les imatges de discos muntades. Premeu una tecla:"
+#define kStrQuitDo "sortir"
+#define kStrQuitNo kStrCmdCancel
+
+#define kStrCancelledQuit "Sortida cancel;l.lada"
+
+#define kStrModeConfirmReset "Mode Control : Confirma reset"
+#define kStrModeConfirmInterrupt "Mode Control : Confirma Interrupci;eo"
+#define kStrModeConfirmQuit "Mode Control : Confirma sortida"
+#define kStrModeSpeedControl "Mode Control : Control de velocitat"
+#define kStrModeControlBase "Mode Control (Premi ;laH;la per a l;laajuda)"
+#define kStrModeControlHelp "Mode Control"
+#define kStrModeMessage "Missatge (Premi ;]C;} per continuar)"
+
+#define kStrMenuFile "Fitxer"
+#define kStrMenuSpecial "Especial"
+#define kStrMenuHelp "Ajuda"
+
+#define kStrMenuItemAbout "Sobre ^p"
+#define kStrMenuItemOpen "Obrir imatge de disc"
+#define kStrMenuItemQuit "Sortir"
+#define kStrMenuItemMore "M;eess comandaments"
+
+#define kStrAppMenuItemHide "Ocultar ^p"
+#define kStrAppMenuItemHideOthers "Ocultar la resta"
+#define kStrAppMenuItemShowAll "Mostrar-ho tot"
+#define kStrAppMenuItemQuit "Sortir de ^p"
+
+#define kStrCmdCopyOptions "Copiar variation options"
+#define kStrHaveCopiedOptions "Variation options copiat"
--- /dev/null
+++ b/src/STRCNCZE.h
@@ -1,0 +1,167 @@
+/*
+	STRCNCZE.h
+
+	Copyright (C) 2017 Anonymous, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file;ls see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY;ls without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	STRing CoNstants for CZEch
+
+	These strings were translated by Anonymous.
+*/
+
+#define kStrAboutTitle "O programu"
+#define kStrAboutMessage "Pro zobrazen;ei informac;ei o programu, pou;vzijte p;vr;eikaz ;]A;} v ovl;eadac;eim m;eodu ^p. Pro informace o ovl;eadac;eim m;eodu, pod;eivejte se do ;[V;eice p;vr;eikaz;ru;ll;{ v menu ;[Dal;vs;ei mo;vznosti;{."
+
+#define kStrMoreCommandsTitle "V kontroln;eim m;eodu ^p jsou dostupn;ee dal;vs;ei p;vr;eikazy."
+#define kStrMoreCommandsMessage "pro pou;vzit;ei ovl;eadac;eiho m;eodu stiskn;vete a dr;vzte ;]^c;}. V ovl;eadac;eim m;eodu z;rustanete, dokud nepust;eite ;]^c;}. stiskn;vete ;]H;} v ovl;eadac;eim m;eodu pro zobrazen;ei dostupn;eych p;vr;eikaz;ru."
+
+#define kStrTooManyImagesTitle "P;vr;eili;vs mnoho obraz;ru disk;ru"
+#define kStrTooManyImagesMessage "Tolik obraz;ru disk;ru p;vripojit nezvl;eadnu. zkuste jeden odpojit."
+
+#define kStrImageInUseTitle "Obraz disku je pou;vz;eiv;ean"
+#define kStrImageInUseMessage "Nemohu p;vripojit obraz disku, proto;vze je pou;vz;eiv;ean jinou aplikac;ei nebo otev;vren v ^p."
+
+#define kStrOutOfMemTitle "Nedostatek pam;veti"
+#define kStrOutOfMemMessage "Pro su;vst;ven;ei ^p nen;ei dostatek pam;veti."
+
+#define kStrNoROMTitle "ROM nenalezen"
+#define kStrNoROMMessage "Nemohu naj;eit soubor ROM ;[^r;{. Pro v;eice informac;ei se pod;eivejte na: ;[^w;{."
+
+#define kStrCorruptedROMTitle "Kontroln;ei sou;vcet ROMu selhal"
+#define kStrCorruptedROMMessage "ROM ;[^r;{ m;ru;vze b;eyt po;vskozen."
+
+#define kStrUnsupportedROMTitle "Nepodporovan;ey ROM"
+#define kStrUnsupportedROMMessage "ROM ;[^r;{ se ;eusp;ve;vsn;ve na;vcetl, ale s touto verz;ei ROMu neum;eim pracovat."
+
+#define kStrQuitWarningTitle "Pros;eim vypn;vete emulovan;ey po;vc;eita;vc p;vred zav;vren;eim."
+#define kStrQuitWarningMessage "Pro vynucen;ei zav;vren;ei ^p (riskujete po;vskozen;ei p;vripojen;eych disk;ru),pou;vzijte p;vr;eikaz ;]Q;} ovl;eadac;eiho m;eodu ^p. Pro informace o ovl;eadac;eim m;eodu, pod;eivejte se do ;[V;eice p;vr;eikaz;ru;ll;{ v menu ;[Dal;vs;ei mo;vznosti;{."
+
+#define kStrReportAbnormalTitle "Abnorm;ealn;ei situace"
+#define kStrReportAbnormalMessage "Emulovan;ey po;vc;eite;vc se pokou;vs;ei o operaci, kter;ea nebyla o;vcek;eav;eana p;vri b;ve;vzn;eem pou;vz;eiv;ean;ei."
+
+#define kStrBadArgTitle "Nezn;eam;ey argument"
+#define kStrBadArgMessage "Nerozum;eim jednomu z p;vr;eikazov;eych argument;ru, budu ho ignorovat."
+
+#define kStrOpenFailTitle "Otev;vren;ei selhalo"
+#define kStrOpenFailMessage "Neopda;vrilo se mi otev;vr;eit obraz disku."
+
+#define kStrNoReadROMTitle "Ne;vciteln;ey ROM"
+#define kStrNoReadROMMessage "Na;vsel jsem ROM ;[^r;{, ale nemohu ho p;vre;vc;eist."
+
+#define kStrShortROMTitle "P;vr;eili;vs kr;eatk;ey ROM"
+#define kStrShortROMMessage "ROM ;[^r;{ je krat;vs;ei ne;vz obvykle."
+
+/* state of a boolean option */
+#define kStrOn "on"
+#define kStrOff "off"
+
+/* state of a key */
+#define kStrPressed "stisknuto"
+#define kStrReleased "pu;vst;veno"
+
+/* state of Stopped */
+#define kStrStoppedOn kStrOn
+#define kStrStoppedOff kStrOff
+
+/* About Screen */
+#define kStrProgramInfo "^v"
+#define kStrSponsorIs "^v. Tuto variaci sponzoruje:"
+#define kStrWorkOfMany "Copyright ^y. ^p Obsahuje pr;eaci mnoha lid;ei. Tuto verzi udr;vzuje:"
+#define kStrForMoreInfo "Pro v;eice informac;ei jd;vete na:"
+#define kStrLicense "^p je distribuov;ean poj licenc;ei GNU GPL, verze 2."
+#define kStrDisclaimer " ^p je distribuov;ean s nad;vej;ei, ;vze ude pou;vz;eiv;ean, ale BEZ JAK;eEKOLIV Z;eARUKY;ls t;ee;vz bez implikovan;ee z;earuky OBCHODOVATELNOSTI nebo VHODNOSTI PRO UR;vCIT;eY ;eU;vCEL."
+
+/* Help Screen */
+#define kStrHowToLeaveControl "Pro opu;vst;ven;ei ovl;ead;eac;eiho m;eodu pus;vtte ;]^c;}."
+#define kStrHowToPickACommand "jinak stiskn;vete p;eismeno. Dostupn;ee p;vr;eikazy jsou:"
+#define kStrCmdAbout "O programu (informace o verzi)"
+#define kStrCmdOpenDiskImage "Otev;vr;eit obraz disku"
+#define kStrCmdQuit "Zav;vr;eit"
+#define kStrCmdSpeedControl "Ovl;ead;ean;ei rychlosti;ll (^s)"
+#define kStrCmdMagnifyToggle "P;vribl;ei;vzen;ei (^g)"
+#define kStrCmdFullScrnToggle "Cel;ea obrazovka (^f)"
+#define kStrCmdCtrlKeyToggle "P;vrep;ein;ean;ei emulovan;eeho ;]^m;} (^k)"
+#define kStrCmdReset "Reset"
+#define kStrCmdInterrupt "Vyru;vsit"
+#define kStrCmdHelp "Pomoc (uk;eaz;eat tuto str;eanku)"
+
+/* Speed Control Screen */
+#define kStrCurrentSpeed "Sou;vcasn;ea rychlost: ^s"
+#define kStrSpeedAllOut "Maximum"
+#define kStrSpeedStopped "zastavit (^h)"
+#define kStrSpeedBackToggle "b;ve;vz;vet v pozad;ei (^b)"
+#define kStrSpeedAutoSlowToggle "automatick;ee zpomalen;ei (^l)"
+#define kStrSpeedExit "Zav;vr;eit ovl;ead;ean;ei rychlosti"
+
+#define kStrNewSpeed "Rychlost: ^s"
+#define kStrSpeedValueAllOut kStrSpeedAllOut
+
+#define kStrNewStopped "Je zastaven: ^h."
+#define kStrNewRunInBack "B;ve;vz;ei na pozad;ei: ^b."
+#define kStrNewAutoSlow "Je automaticky zpomalen: ^l."
+
+#define kStrNewMagnify "P;vribl;ei;vzen;ei: ^g."
+
+#define kStrNewFullScreen "Na celou obrazovku: ^f."
+
+#define kStrNewCntrlKey "Emulovan;ey ;]^m;}: ^k."
+
+#define kStrCmdCancel "Storno"
+
+#define kStrConfirmReset "Opravdu chcete resetovat emulovan;ey po;vc;eita;vc? Ztrat;eite neulo;vzen;ee zm;veny a riskujete po;vskozen;ei p;vripojen;eych obraz;ru disk;ru. Stiskn;vete p;eismeno:"
+#define kStrResetDo "resetovat"
+#define kStrResetNo kStrCmdCancel
+
+#define kStrHaveReset "Resetoval jsem emulovan;ey po;vc;eita;vc"
+
+#define kStrCancelledReset "Resetov;ean;ei zru;vseno"
+
+#define kStrConfirmInterrupt "Opravdu chcete vyru;vsit emulovan;ey po;vc;eita;vc? Spust;ei se nainstalovan;ey debugger. Stiskn;vete p;eismeno:"
+#define kStrInterruptDo "vyru;vsit"
+#define kStrInterruptNo kStrCmdCancel
+
+#define kStrHaveInterrupted "Vyru;vsil jsem emulovan;ey po;vc;eita;vc"
+
+#define kStrCancelledInterrupt "Vyru;vsen;ei zru;vseno"
+
+#define kStrConfirmQuit "Opravdu chcete zav;vr;eit ^p? M;veli byste vypnout emulovan;ey po;vc;eita;vc p;vred vypnut;eim pro zabr;ean;ven;ei po;vskozen;ei p;vripojen;eych obraz;ru disk;ru. Stiskn;vete p;eismeno:"
+#define kStrQuitDo "odej;eit"
+#define kStrQuitNo kStrCmdCancel
+
+#define kStrCancelledQuit "Zav;vren;ei zru;vseno"
+
+#define kStrModeConfirmReset " : Confirm Reset"
+#define kStrModeConfirmInterrupt "ovl;ead;eac;ei m;eod : Potvrdit vyru;vsen;ei"
+#define kStrModeConfirmQuit "ovl;ead;eac;ei m;eod : Potvrdit zav;vren;ei"
+#define kStrModeSpeedControl "ovl;ead;eac;ei m;eod : Ovl;ead;ean;ei rychlosti"
+#define kStrModeControlBase "ovl;ead;eac;ei m;eod (stiskn;vete ;]H;} pro pomoc) "
+#define kStrModeControlHelp "ovl;ead;eac;ei m;eod"
+#define kStrModeMessage "Zpr;eava (Stiskn;vete ;]C;} pro pokra;vcov;ean;ei)"
+
+#define kStrMenuFile "Soubor"
+#define kStrMenuSpecial "Dal;vs;ei mo;vznosti"
+#define kStrMenuHelp "Pomoc"
+
+#define kStrMenuItemAbout "O ^p"
+#define kStrMenuItemOpen "Otev;vr;eit obraz disku"
+#define kStrMenuItemQuit "Odej;eit"
+#define kStrMenuItemMore "V;eice p;vr;eikaz;ru"
+
+#define kStrAppMenuItemHide "Skr;eyt ^p"
+#define kStrAppMenuItemHideOthers "Skr;eyt ostatn;ei"
+#define kStrAppMenuItemShowAll "Zobrazit v;vse"
+#define kStrAppMenuItemQuit "Ukon;vcit ^p"
+
+#define kStrCmdCopyOptions "Kop;eirovat variation options"
+#define kStrHaveCopiedOptions "Variation options zkop;eirov;eany"
--- /dev/null
+++ b/src/STRCNDUT.h
@@ -1,0 +1,167 @@
+/*
+	STRCNDUT.h
+
+	Copyright (C) 2006 Luc Pauwels, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	STRing CoNstants for DUTch
+
+	These strings were translated by Luc Pauwels.
+*/
+
+#define kStrAboutTitle "Over ^p"
+#define kStrAboutMessage "Gebruik het ;]A;}-commando van de ^p controlemodus om meer informatie over deze applicatie te tonen. Om meer te weten te komen over de controlemodus, zie ;[Meer Commando;}s;ll;{ in het ;[Speciaal;{ menu."
+
+#define kStrMoreCommandsTitle "Meer commando;}s zijn beschikbaar in de ^p controlemodus."
+#define kStrMoreCommandsMessage "Om naar de controlemodus te gaan, hou de ;]^c;} toets ingedrukt. Je blijft in de controlemodus zolang je de ;]^c;} toets ingedrukt houdt.  Type ;]H;} in de controlemodus om een lijst van beschikbare commando;}s te zien."
+
+#define kStrTooManyImagesTitle "Teveel schijfkopiebestanden"
+#define kStrTooManyImagesMessage "Het maximaal aantal schijfkopiebestanden is in gebruik.  Probeer er ;ee;een te verwijderen."
+
+#define kStrImageInUseTitle "Schijfkopiebestand in gebruik"
+#define kStrImageInUseMessage "Ik kan het schijfkopiebestand niet openen omdat het al in gebruik is door een andere applicatie of omdat het al geopend is in ^p."
+
+#define kStrOutOfMemTitle "Niet genoeg geheugen"
+#define kStrOutOfMemMessage "Er is niet genoeg geheugen beschikbaar om ^p te openen."
+
+#define kStrNoROMTitle "ROM bestand niet gevonden"
+#define kStrNoROMMessage "Ik kan het ROM bestand ;[^r;{ niet vinden. Voor meer informatie, zie ;[^w;{."
+
+#define kStrCorruptedROMTitle "ROM controlegetal verkeerd"
+#define kStrCorruptedROMMessage "Het ROM bestand ;[^r;{ is mogelijk beschadigd."
+
+#define kStrUnsupportedROMTitle "Niet ondersteunde ROM"
+#define kStrUnsupportedROMMessage "Het ROM bestand ;[^r;{ werd succesvol ingeladen, maar ik ondersteun deze ROM versie niet."
+
+#define kStrQuitWarningTitle "Zet de ge;uemuleerde computer uit vooraleer de applicatie te stoppen."
+#define kStrQuitWarningMessage "Om ^p geforceerd te stoppen, met het risico dat het gebruikte schijfkopiebestand beschadigd geraakt, gebruik het ;]Q;} commando van de ^p controlemodus. Om meer te weten te komen over de controlemodus, zie ;[Meer Commando;}s;{ in het ;[Speciaal;{ menu."
+
+#define kStrReportAbnormalTitle "Abnormale situatie"
+#define kStrReportAbnormalMessage "De ge;uemuleerde computer probeert een operatie uit te voeren die onder normale omstandigheden niet kan voorkomen."
+
+#define kStrBadArgTitle "Onbekend argument"
+#define kStrBadArgMessage "Ik herkende ;ee;een van de commandolijn-argumenten niet en heb het genegeerd."
+
+#define kStrOpenFailTitle "Open operatie gefaald"
+#define kStrOpenFailMessage "Ik kon het schijfkopiebestand niet openen."
+
+#define kStrNoReadROMTitle "Het ROM bestand kan niet gelezen worden"
+#define kStrNoReadROMMessage "Ik kon het ROM bestand ;[^r;{vinden, maar ik kon het niet lezen."
+
+#define kStrShortROMTitle "ROM bestand te kort"
+#define kStrShortROMMessage "Het ROM bestand ;[^r;{ is korter dan verwacht."
+
+/* state of a boolean option */
+#define kStrOn "aan"
+#define kStrOff "uit"
+
+/* state of a key */
+#define kStrPressed "ingedrukt"
+#define kStrReleased "losgelaten"
+
+/* state of Stopped */
+#define kStrStoppedOn kStrOn
+#define kStrStoppedOff kStrOff
+
+/* About Screen */
+#define kStrProgramInfo "^v"
+#define kStrSponsorIs "^v. This variation is made for:"
+#define kStrWorkOfMany "Copyright ^y. ^p is het werk van velen. Deze versie wordt onderhouden door:"
+#define kStrForMoreInfo "Voor meer informatie, zie:"
+#define kStrLicense "^p wordt verspreid onder de voorwaarden van de GNU Public License, versie 2."
+#define kStrDisclaimer " ^p wordt verspreid in de hoop dat het bruikbaar is, maar ZONDER ENIGE GARANTIE, zelfs zonder impliciete garanties van VERKOOPBAARHEID noch BRUIKBAARHEID VOOR EEN BEPAALD DOELEINDE."
+
+/* Help Screen */
+#define kStrHowToLeaveControl "Laat de ;]^c;} toets los om de controlemodus te verlaten."
+#define kStrHowToPickACommand "Zoniet, typ een letter.  De beschikbare commando;}s zijn:"
+#define kStrCmdAbout "Over ^p (informatie over deze versie)"
+#define kStrCmdOpenDiskImage "Open schijfkopiebstand;ll"
+#define kStrCmdQuit "Stop"
+#define kStrCmdSpeedControl "Snelheidscontrole;ll (^s)"
+#define kStrCmdMagnifyToggle "Schermvergroting (^g)"
+#define kStrCmdFullScrnToggle "Gebruik het volledig scherm (^f)"
+#define kStrCmdCtrlKeyToggle "Ge;uemuleerde ;]^m;} toets (^k)"
+#define kStrCmdReset "Herstart"
+#define kStrCmdInterrupt "Onderbreek"
+#define kStrCmdHelp "Hulp (toon deze pagina)"
+
+/* Speed Control Screen */
+#define kStrCurrentSpeed "Huidige snelheid: ^s"
+#define kStrSpeedAllOut "Zo snel mogelijk"
+#define kStrSpeedStopped "Stopschakelaar (^h)"
+#define kStrSpeedBackToggle "Schakelaar om in de achtergrond te draaien (^b)"
+#define kStrSpeedAutoSlowToggle "AutoSlow (^l)"
+#define kStrSpeedExit "Verlaat Snelheidscontrole"
+
+#define kStrNewSpeed "Snelheid: ^s"
+#define kStrSpeedValueAllOut kStrSpeedAllOut
+
+#define kStrNewStopped "Stopschakelaar is ^h."
+#define kStrNewRunInBack "In de achtergrond draaien is ^b."
+#define kStrNewAutoSlow "AutoSlow is ^l."
+
+#define kStrNewMagnify "Schermvergroting is ^g."
+
+#define kStrNewFullScreen "Volledig scherm gebruiken is ^f."
+
+#define kStrNewCntrlKey "Ge;uemuleerde ;]^m;} toets ^k."
+
+#define kStrCmdCancel "annuleer"
+
+#define kStrConfirmReset "Bent u er zeker van dat u de ge;uemuleerde computer wilt herstarten?  Werk dat niet bewaard werd zal verloren gaan, en er bestaat een kans dat het gebruikte schijfkopiebestand beschadigd geraakt. Typ een letter:"
+#define kStrResetDo "herstart"
+#define kStrResetNo kStrCmdCancel
+
+#define kStrHaveReset "De ge;uemuleerde computer werd herstart"
+
+#define kStrCancelledReset "Herstart werd geannuleerd"
+
+#define kStrConfirmInterrupt "Bent u er zeker van dat u de ge;uemuleerde computer wilt onderbreken?  Dit zal de eventueel ge;uinstalleerde debugger activeren. Typ een letter:"
+#define kStrInterruptDo "onderbreken"
+#define kStrInterruptNo kStrCmdCancel
+
+#define kStrHaveInterrupted "De ge;uemuleerde computer werd onderbroken"
+
+#define kStrCancelledInterrupt "Onderbreking geannuleerd"
+
+#define kStrConfirmQuit "Bent u er zeker van dat u wilt ^p wilt stoppen?  U zou eerst de ge;uemuleerde computer moeten uitzetten alvorens te stoppen om beschadiging van het gebruikte schijfkopiebestand te vermijden. Typ een letter:"
+#define kStrQuitDo "stop"
+#define kStrQuitNo kStrCmdCancel
+
+#define kStrCancelledQuit "Stoppen geannuleerd"
+
+#define kStrModeConfirmReset "Controlemodus : Bevesting herstarten"
+#define kStrModeConfirmInterrupt "Controlemodus : Bevesting onderbreking"
+#define kStrModeConfirmQuit "Controlemodus : Bevesting stoppen"
+#define kStrModeSpeedControl "Controlemodus : Snelheidscontrole"
+#define kStrModeControlBase "Controlemodus (Typ ;]H;} voor meer hulp)"
+#define kStrModeControlHelp "Controlemodus"
+#define kStrModeMessage "Boodschap (Typ ;]C;} om verder te gaan)"
+
+#define kStrMenuFile "Archief"
+#define kStrMenuSpecial "Speciaal"
+#define kStrMenuHelp "Hulp"
+
+#define kStrMenuItemAbout "Over ^p"
+#define kStrMenuItemOpen "Open schijfkopiebestand"
+#define kStrMenuItemQuit "Stop"
+#define kStrMenuItemMore "Meer Commando;}s"
+
+#define kStrAppMenuItemHide "Verberg ^p"
+#define kStrAppMenuItemHideOthers "Verberg andere"
+#define kStrAppMenuItemShowAll "Toon alles"
+#define kStrAppMenuItemQuit "Stop ^p"
+
+#define kStrCmdCopyOptions "Kopieer variation options"
+#define kStrHaveCopiedOptions "Variation options gekopieerd"
--- /dev/null
+++ b/src/STRCNENG.h
@@ -1,0 +1,167 @@
+/*
+	STRCNENG.h
+
+	Copyright (C) 2006 Paul C. Pratt, Pierre Lemieux
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	STRing CoNstants for ENGlish
+
+	Pierre Lemieux provided some corrections and suggestions.
+*/
+
+#define kStrAboutTitle "About"
+#define kStrAboutMessage "To display information about this program, use the ;]A;} command of the ^p Control Mode. To learn about the Control Mode, see the ;[More Commands;ll;{ item in the ;[Special;{ menu."
+
+#define kStrMoreCommandsTitle "More commands are available in the ^p Control Mode."
+#define kStrMoreCommandsMessage "To enter the Control Mode, press and hold down the ;]^c;} key. You will remain in the Control Mode until you release the ;]^c;} key. Type ;]H;} in the Control Mode to list available commands."
+
+#define kStrTooManyImagesTitle "Too many Disk Images"
+#define kStrTooManyImagesMessage "I can not mount that many Disk Images. Try ejecting one."
+
+#define kStrImageInUseTitle "Disk Image in use"
+#define kStrImageInUseMessage "I can not mount the Disk Image because it is already in use by another application or already open in ^p."
+
+#define kStrOutOfMemTitle "Not enough Memory"
+#define kStrOutOfMemMessage "There is not enough memory available to launch ^p."
+
+#define kStrNoROMTitle "Unable to locate ROM image"
+#define kStrNoROMMessage "I can not find the ROM image file ;[^r;{. For more information, see: ;[^w;{."
+
+#define kStrCorruptedROMTitle "ROM checksum failed"
+#define kStrCorruptedROMMessage "The ROM image file ;[^r;{ may be corrupted."
+
+#define kStrUnsupportedROMTitle "Unsupported ROM"
+#define kStrUnsupportedROMMessage "The ROM image file ;[^r;{ loaded successfully, but I don;}t support this ROM version."
+
+#define kStrQuitWarningTitle "Please shut down the emulated computer before quitting."
+#define kStrQuitWarningMessage "To force ^p to quit, at the risk of corrupting the mounted disk image files, use the ;]Q;} command of the ^p Control Mode. To learn about the Control Mode, see the ;[More Commands;ll;{ item in the ;[Special;{ menu."
+
+#define kStrReportAbnormalTitle "Abnormal Situation"
+#define kStrReportAbnormalMessage "The emulated computer is attempting an operation that wasn;}t expected to happen in normal use."
+
+#define kStrBadArgTitle "Unknown argument"
+#define kStrBadArgMessage "I did not understand one of the command line arguments, and ignored it."
+
+#define kStrOpenFailTitle "Open failed"
+#define kStrOpenFailMessage "I could not open the disk image."
+
+#define kStrNoReadROMTitle "Unable to read ROM image"
+#define kStrNoReadROMMessage "I found the ROM image file ;[^r;{, but I can not read it."
+
+#define kStrShortROMTitle "ROM image too short"
+#define kStrShortROMMessage "The ROM image file ;[^r;{ is shorter than it should be."
+
+/* state of a boolean option */
+#define kStrOn "on"
+#define kStrOff "off"
+
+/* state of a key */
+#define kStrPressed "pressed"
+#define kStrReleased "released"
+
+/* state of Stopped */
+#define kStrStoppedOn kStrOn
+#define kStrStoppedOff kStrOff
+
+/* About Screen */
+#define kStrProgramInfo "^v"
+#define kStrSponsorIs "^v. This variation is made for:"
+#define kStrWorkOfMany "Copyright ^y. ^p contains the work of many people. This version is maintained by:"
+#define kStrForMoreInfo "For more information, see:"
+#define kStrLicense "^p is distributed under the terms of the GNU Public License, version 2."
+#define kStrDisclaimer " ^p is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;ls without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+/* Help Screen */
+#define kStrHowToLeaveControl "To leave the Control Mode, release the ;]^c;} key."
+#define kStrHowToPickACommand "Otherwise, type a letter. Available commands are:"
+#define kStrCmdAbout "About (version information)"
+#define kStrCmdOpenDiskImage "Open disk image;ll"
+#define kStrCmdQuit "Quit"
+#define kStrCmdSpeedControl "Speed control;ll (^s)"
+#define kStrCmdMagnifyToggle "Magnify toggle (^g)"
+#define kStrCmdFullScrnToggle "Full screen toggle (^f)"
+#define kStrCmdCtrlKeyToggle "emulated ;]^m;} Key toggle (^k)"
+#define kStrCmdReset "Reset"
+#define kStrCmdInterrupt "Interrupt"
+#define kStrCmdHelp "Help (show this page)"
+
+/* Speed Control Screen */
+#define kStrCurrentSpeed "Current speed: ^s"
+#define kStrSpeedAllOut "All out"
+#define kStrSpeedStopped "stopped toggle (^h)"
+#define kStrSpeedBackToggle "run in Background toggle (^b)"
+#define kStrSpeedAutoSlowToggle "autosloW toggle (^l)"
+#define kStrSpeedExit "Exit speed control"
+
+#define kStrNewSpeed "Speed: ^s"
+#define kStrSpeedValueAllOut kStrSpeedAllOut
+
+#define kStrNewStopped "Stopped is ^h."
+#define kStrNewRunInBack "Run in background is ^b."
+#define kStrNewAutoSlow "AutoSlow is ^l."
+
+#define kStrNewMagnify "Magnify is ^g."
+
+#define kStrNewFullScreen "Full Screen is ^f."
+
+#define kStrNewCntrlKey "Emulated ;]^m;} key ^k."
+
+#define kStrCmdCancel "cancel"
+
+#define kStrConfirmReset "Are you sure you want to reset the emulated computer? Unsaved changes will be lost, and there is a risk of corrupting the mounted disk image files. Type a letter:"
+#define kStrResetDo "reset"
+#define kStrResetNo kStrCmdCancel
+
+#define kStrHaveReset "Have reset the emulated computer"
+
+#define kStrCancelledReset "Reset cancelled"
+
+#define kStrConfirmInterrupt "Are you sure you want to interrupt the emulated computer? This will invoke any installed debugger. Type a letter:"
+#define kStrInterruptDo "interrupt"
+#define kStrInterruptNo kStrCmdCancel
+
+#define kStrHaveInterrupted "Have interrupted the emulated computer"
+
+#define kStrCancelledInterrupt "Interrupt cancelled"
+
+#define kStrConfirmQuit "Are you sure you want to quit ^p? You should shut down the emulated computer before quitting to prevent corrupting the mounted disk image files. Type a letter:"
+#define kStrQuitDo "quit"
+#define kStrQuitNo kStrCmdCancel
+
+#define kStrCancelledQuit "Quit cancelled"
+
+#define kStrModeConfirmReset "Control Mode : Confirm Reset"
+#define kStrModeConfirmInterrupt "Control Mode : Confirm Interrupt"
+#define kStrModeConfirmQuit "Control Mode : Confirm Quit"
+#define kStrModeSpeedControl "Control Mode : Speed Control"
+#define kStrModeControlBase "Control Mode (Type ;]H;} for help)"
+#define kStrModeControlHelp "Control Mode"
+#define kStrModeMessage "Message (Type ;]C;} to continue)"
+
+#define kStrMenuFile "File"
+#define kStrMenuSpecial "Special"
+#define kStrMenuHelp "Help"
+
+#define kStrMenuItemAbout "About ^p"
+#define kStrMenuItemOpen "Open Disk Image"
+#define kStrMenuItemQuit "Quit"
+#define kStrMenuItemMore "More Commands"
+
+#define kStrAppMenuItemHide "Hide ^p"
+#define kStrAppMenuItemHideOthers "Hide Others"
+#define kStrAppMenuItemShowAll "Show All"
+#define kStrAppMenuItemQuit "Quit ^p"
+
+#define kStrCmdCopyOptions "copy variation options"
+#define kStrHaveCopiedOptions "Variation options copied"
--- /dev/null
+++ b/src/STRCNFRE.h
@@ -1,0 +1,169 @@
+/*
+	STRCNFRE.h
+
+	Copyright (C) 2006 Pierre Lemieux, Ga;uel Coup;ee, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	STRing CoNstants for FREnch
+
+	These strings were translated by Pierre Lemieux, and an earlier
+	version of them was proofread by Ga;uel Coup;ee.
+*/
+
+#define kStrAboutTitle ";`A propos"
+#define kStrAboutMessage "Pour afficher des informations sur ce programme, utilisez la commande A du mode commande de ^p. Pour en savoir plus sur le mode commande, s;eelectionnez l;}article Autres commandes;ll du menu Sp;eecial."
+
+#define kStrMoreCommandsTitle "D;}autres commandes sont disponibles dans le mode commande de ^p."
+#define kStrMoreCommandsMessage "Pour acc;eeder au mode commande, maintenez la touche ^c enfonc;eee. Vous allez demeurer en mode commande jusqu;};`a ce que vous rel;iachiez la touche ^c. Tapez H en mode commande pour afficher la liste des commandes disponibles."
+
+#define kStrTooManyImagesTitle "Images disques trop nombreuses."
+#define kStrTooManyImagesMessage "Je ne peux pas ouvrir un aussi grand nombre d;}images disques. Veuillez en ;eejecter une."
+
+#define kStrImageInUseTitle "Image disque d;eej;`a utilis;eee."
+#define kStrImageInUseMessage "Je ne peux pas ouvrir l;}image disque, car elle est d;eej;`a utilis;eee par une autre application ou d;eej;`a ouverte dans ^p."
+
+#define kStrOutOfMemTitle "M;eemoire insuffisante."
+#define kStrOutOfMemMessage "Il n;}y a plus assez de m;eemoire disponible pour lancer ^p"
+
+#define kStrNoROMTitle "ROM introuvable."
+#define kStrNoROMMessage "Je n;}arrive pas ;`a trouver le fichier image de la ROM intitul;ee ;[^r;{. Pour plus d;}information, voir : ;[^w;{."
+
+#define kStrCorruptedROMTitle "Somme de contr;iole incorrecte."
+#define kStrCorruptedROMMessage "Le fichier image de la ROM intitul;ee ;[^r;{ est peut-;ietre endommag;ee."
+
+#define kStrUnsupportedROMTitle "ROM non support;eee."
+#define kStrUnsupportedROMMessage "Le chargement du fichier image de la ROM intitul;ee ;[^r;{ a r;eeussi, mais je ne supporte pas cette version de la ROM."
+
+#define kStrQuitWarningTitle "Veuillez ;eeteindre l;}ordinateur virtuel avant de quitter."
+#define kStrQuitWarningMessage "Pour forcer ^p ;`a quitter, au risque d;}endommager les images disques ouvertes, tapez Q en mode commande. Pour en savoir plus sur le mode commande de ^p, s;eelectionnez l;}article Autres commandes;ll du menu Sp;eecial."
+
+#define kStrReportAbnormalTitle "Situation anormale."
+#define kStrReportAbnormalMessage "L;}ordinateur virtuel tente d;}effectuer une op;eeration qui n;};eetait pas pr;eevue dans le cadre d;}un usage normal."
+
+#define kStrBadArgTitle "Argument inconnu."
+#define kStrBadArgMessage "J;}ai ignor;ee l;}un des arguments de la ligne de commande, que je ne comprenais pas."
+
+#define kStrOpenFailTitle "Tentative d;}ouverture infructueuse."
+#define kStrOpenFailMessage "Je n;}ai pas r;eeussi ;`a ouvrir l;}image disque."
+
+#define kStrNoReadROMTitle "ROM illisible."
+#define kStrNoReadROMMessage "J;}ai bien trouv;ee le fichier image de la ROM intitul;ee ;[^r;{, mais je n;}arrive pas ;`a le lire."
+
+#define kStrShortROMTitle "ROM trop courte."
+#define kStrShortROMMessage "Le fichier image de la ROM intitul;ee ;[^r;{ est plus court qu;}il ne le devrait."
+
+/* state of a boolean option */
+#define kStrOn "activ;ee"
+#define kStrOff "d;eesactiv;ee"
+
+/* state of a key */
+#define kStrPressed "enfonc;eee"
+#define kStrReleased "rel;iach;eee"
+
+/* state of Stopped */
+#define kStrStoppedOn "activ;eee"
+#define kStrStoppedOff "d;eesactiv;eee"
+
+/* About Screen */
+#define kStrProgramInfo "^v"
+#define kStrSponsorIs "^v. This variation is made for:"
+#define kStrWorkOfMany "copyright ^y. ^p est le fruit du travail de nombreuses personnes. La maintenance de cette version est assur;eee par :"
+#define kStrForMoreInfo "Pour de plus amples informations, voir :"
+#define kStrLicense "^p est distribu;ee au titre des clauses de la Licence publique g;een;eerale GNU, version 2."
+#define kStrDisclaimer " ^p est distribu;ee dans l;}espoir qu;}il sera utile, mais SANS AUCUNE GARANTIE, sans m;ieme une garantie implicite de COMMERCIABILIT;eE ou DE CONFORMIT;eE ;`A UNE UTILISATION PARTICULI;`ERE."
+
+/* Help Screen */
+#define kStrHowToLeaveControl "Pour quitter le mode commande, rel;iachez la touche ^c."
+#define kStrHowToPickACommand "Sinon, choisissez l;}une des commandes ci-dessous en tapant la lettre correspondante :"
+#define kStrCmdAbout ";`A propos (de cette version du logiciel)"
+#define kStrCmdOpenDiskImage "Ouvrir une image disque;ll"
+#define kStrCmdQuit "Quitter"
+#define kStrCmdSpeedControl "R;eeglage de la vitesse;ll (^s)"
+#define kStrCmdMagnifyToggle "Agrandissement (^g)"
+#define kStrCmdFullScrnToggle "Plein ;eecran (^f)"
+#define kStrCmdCtrlKeyToggle "Touche ^m virtuelle (^k)"
+#define kStrCmdReset "R;eeinitialisation"
+#define kStrCmdInterrupt "Interruption"
+#define kStrCmdHelp "Aide (affiche cette page)"
+
+/* Speed Control Screen */
+#define kStrCurrentSpeed "Vitesse courante : ^s"
+#define kStrSpeedAllOut "Vitesse maximale"
+#define kStrSpeedStopped "Pause (^h)"
+#define kStrSpeedBackToggle "Fonctionnement en arri;`ere-plan (^b)"
+#define kStrSpeedAutoSlowToggle "AutoSlow (^l)"
+#define kStrSpeedExit "Quitter cette page"
+
+#define kStrNewSpeed "Vitesse : ^s"
+#define kStrSpeedValueAllOut "maximale"
+
+#define kStrNewStopped "Pause ^h."
+#define kStrNewRunInBack "Fonctionnement en arri;`ere-plan ^b."
+#define kStrNewAutoSlow "AutoSlow ^l."
+
+#define kStrNewMagnify "Agrandissement ^g."
+
+#define kStrNewFullScreen "Mode plein ;eecran ^f."
+
+#define kStrNewCntrlKey "Touche ^m virtuelle ^k."
+
+#define kStrCmdCancel "Annuler"
+
+#define kStrConfirmReset "Souhaitez-vous vraiment r;eeinitialiser l;}ordinateur virtuel ? Vous allez perdre les modifications non enregistr;eees et vous risquez d;}endommager les images disques ouvertes."
+#define kStrResetDo "R;eeinitialiser"
+#define kStrResetNo kStrCmdCancel
+
+#define kStrHaveReset "Vous avez r;eeinitialis;ee l;}ordinateur virtuel."
+
+#define kStrCancelledReset "R;eeinitialisation annul;eee."
+
+#define kStrConfirmInterrupt "Souhaitez-vous vraiment interrompre l;}ordinateur virtuel ? Cela va d;eeclencher le d;eebogueur (s;}il y en a un d;}install;ee)."
+#define kStrInterruptDo "Interrompre"
+#define kStrInterruptNo kStrCmdCancel
+
+#define kStrHaveInterrupted "Vous avez interrompu l;}ordinateur virtuel."
+
+#define kStrCancelledInterrupt "Interruption annul;eee."
+
+#define kStrConfirmQuit "Souhaitez-vous vraiment quitter ^p ? Vous devriez ;eeteindre l;}ordinateur virtuel avant de quitter, pour ;eeviter d;}endommager les images disques ouvertes."
+#define kStrQuitDo kStrCmdQuit
+#define kStrQuitNo kStrCmdCancel
+
+#define kStrCancelledQuit "Commande Quitter annul;eee."
+
+#define kStrModeConfirmReset "Mode commande : confirmation de la r;eeinitialisation"
+#define kStrModeConfirmInterrupt "Mode commande : confirmation de l;}interruption"
+#define kStrModeConfirmQuit "Mode commande : confirmation de la commande Quitter"
+#define kStrModeSpeedControl "Mode commande : r;eeglage de la vitesse"
+#define kStrModeControlBase "Mode commande (Tapez H pour afficher l;}aide.)"
+#define kStrModeControlHelp "Mode commande"
+#define kStrModeMessage "Message (Tapez C pour continuer.)"
+
+#define kStrMenuFile "Fichier"
+#define kStrMenuSpecial "Sp;eecial"
+#define kStrMenuHelp "Aide"
+
+#define kStrMenuItemAbout ";`A propos de ^p"
+#define kStrMenuItemOpen "Ouvrir une image disque"
+#define kStrMenuItemQuit "Quitter"
+#define kStrMenuItemMore "Autres commandes"
+
+#define kStrAppMenuItemHide "Masquer ^p"
+#define kStrAppMenuItemHideOthers "Masquer les autres"
+#define kStrAppMenuItemShowAll "Tout afficher"
+#define kStrAppMenuItemQuit "Quitter ^p"
+
+#define kStrCntrlKyName "Contr;iole"
+#define kStrCmdCopyOptions "Copier variation options"
+#define kStrHaveCopiedOptions "Variation options copi;eees"
--- /dev/null
+++ b/src/STRCNGER.h
@@ -1,0 +1,169 @@
+/*
+	STRCNGER.h
+
+	Copyright (C) 2006 Paul C. Pratt, Detlef Kahner
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	STRing CoNstants for GERman
+
+	Translated by Detlef Kahner
+*/
+
+#define kStrAboutTitle ";uUber ^p"
+#define kStrAboutMessage "Mehr Informationen zu ^p erhalten Sie ;uuber die Taste ;]A;} im Kontrollmodus. Informationen zum Kontrollmodus erhalten Sie ;uuber den Men;uubefehl ;[Mehr Befehle;ll;{ im Spezialmen;uu."
+
+#define kStrMoreCommandsTitle "Mehr Befehle sind im Kontrollmodus abrufbar."
+#define kStrMoreCommandsMessage "Um den Kontrollmodus von ^p aufzurufen, dr;uucken Sie die ;]^c;}-Taste und lassen diese gedr;uuckt. Sie verbleiben im Kontrollmodus, solange Sie diese Taste gedr;uuckt halten. Eine Liste verf;uugbarer Befehle erhalten Sie w;uahrenddessen durch Dr;uucken der Taste ;]H;}."
+
+#define kStrTooManyImagesTitle "Zuviele Disketten-Images."
+#define kStrTooManyImagesMessage "Soviele Images k;uonnen nicht gemountet sein. Bitte werfen Sie einige aus."
+
+#define kStrImageInUseTitle "Disketten-Image bereits in Gebrauch."
+#define kStrImageInUseMessage "Disketten-Image kann nicht gemountet werden, weil es entweder bereits in ^p gemountet ist oder von einem anderen Programm (z. B. dem Finder) verwendet wird."
+
+#define kStrOutOfMemTitle "Zuwenig Arbeitsspeicher."
+#define kStrOutOfMemMessage "Es ist nicht gen;uugend Arbeitsspeicher vorhanden, um ^p zu starten."
+
+#define kStrNoROMTitle "ROM nicht gefunden."
+#define kStrNoROMMessage "Das ROM namens ;[^r;{ kann nicht gefunden werden. Mehr Informationen hier: ;[^w;{"
+
+#define kStrCorruptedROMTitle "ROM-Pr;uufsumme fehlgeschlagen."
+#define kStrCorruptedROMMessage "Das ROM ;[^r;{ ist m;uoglicherweise besch;uadigt."
+
+#define kStrUnsupportedROMTitle "ROM wird nicht unterst;uutzt."
+#define kStrUnsupportedROMMessage "Das ROM ;[^r;{ wurde erfolgreich geladen, aber diese Version von ^p unterst;uutzt es nicht."
+
+#define kStrQuitWarningTitle "Bitte fahren Sie das emulierte MacOS herunter, bevor Sie ^p beenden."
+#define kStrQuitWarningMessage "Um ^p sofort zu beenden, aber Besch;uadigungen an den gemounteten Disketten-Images in Kauf zu nehmen, dr;uucken Sie die Taste ;]Q;} innerhalb des Kontrollmodus. Zugriff zum Kontrollmodus von ^p erhalten Sie, indem Sie die ;]^c;}-Taste gedr;uuckt halten."
+
+#define kStrReportAbnormalTitle "Unerwartete Situation"
+#define kStrReportAbnormalMessage "Der emulierte Rechner hat versucht, eine Operation durchzuf;uuhren, die im Rahmen eines normalen Gebrauches nicht vorgesehen war."
+
+#define kStrBadArgTitle "Unbekannter Befehl."
+#define kStrBadArgMessage "Befehlseingabe nicht verstanden und deshalb ignoriert."
+
+#define kStrOpenFailTitle ";uOffnen fehlgeschlagen."
+#define kStrOpenFailMessage "Das Disk-Image konnte nicht ge;uoffnet werden."
+
+#define kStrNoReadROMTitle "ROM nicht lesbar."
+#define kStrNoReadROMMessage "Das ROM namens ;[^r;{ wurde gefunden, kann aber von dieser Version von ^p nicht verwendet werden."
+
+#define kStrShortROMTitle "ROM-Image zu klein."
+#define kStrShortROMMessage "Das ROM ;[^r;{ ist kleiner als erwartet."
+
+/* state of a boolean option */
+#define kStrOn "an"
+#define kStrOff "aus"
+
+/* state of a key */
+#define kStrPressed "gedr;uuckt"
+#define kStrReleased "losgelassen"
+
+/* state of Stopped */
+#define kStrStoppedOn kStrOn
+#define kStrStoppedOff kStrOff
+
+/* About Screen */
+#define kStrProgramInfo "^v"
+#define kStrSponsorIs "^v. This variation is made for:"
+#define kStrWorkOfMany "Copyright ^y. ^p enth;ualt die Arbeit mehrerer Personen. Diese Version wird gepflegt von:"
+#define kStrForMoreInfo "Mehr Informationen:"
+#define kStrLicense "^p wird unter den Bestimmungen der GNU Public License, Version 2, verbreitet."
+#define kStrDisclaimer " ^p wird angeboten in der Hoffnung, brauchbar zu sein, aber OHNE JEDE GARANTIE;ls gleichfalls ohne garantierte EIGNUNG ZU EINEM BESTIMMTEN ZWECK."
+
+/* Help Screen */
+#define kStrHowToLeaveControl "Um den Kontrollmodus zu verlassen, lassen Sie ;]^c;} los."
+#define kStrHowToPickACommand "Anderenfalls dr;uucken Sie einen dieser Buchstaben:"
+#define kStrCmdAbout "Informationen zu dieser Version"
+#define kStrCmdOpenDiskImage "Disketten-Image ;uoffnen;ll"
+#define kStrCmdQuit "Beenden"
+#define kStrCmdSpeedControl "Geschwindigkeitskontrolle;ll (^s)"
+#define kStrCmdMagnifyToggle "Vergr;uosserung (^g)"
+#define kStrCmdFullScrnToggle "Vollbild (^f)"
+#define kStrCmdCtrlKeyToggle "Emulierte ;]^m;}-Taste (^k)"
+#define kStrCmdReset "Neustarten (Reset durchf;uuhren)"
+#define kStrCmdInterrupt "Interrupt"
+#define kStrCmdHelp "Hilfe (zeigt diese Befehlsliste)"
+
+/* Speed Control Screen */
+#define kStrCurrentSpeed "Momentane Geschwindigkeit: ^s"
+#define kStrSpeedAllOut "H;uochstgeschwindigkeit"
+#define kStrSpeedStopped "^p jetzt anhalten (^h)"
+#define kStrSpeedBackToggle "^p im Hintergrund anhalten (^b)"
+#define kStrSpeedAutoSlowToggle "AutoSlow (^l)"
+#define kStrSpeedExit "Geschwindigkeits-Einstellungen verlassen"
+
+#define kStrNewSpeed "Neue Geschwindigkeit: ^s"
+#define kStrSpeedValueAllOut kStrSpeedAllOut
+
+#define kStrNewStopped "^p ist jetzt angehalten (^h)"
+#define kStrNewRunInBack "^p anhalten, wenn nicht aktiv (^b)"
+#define kStrNewAutoSlow "AutoSlow (^l)"
+
+#define kStrNewMagnify "Vergr;uo;serung ist ^g"
+
+#define kStrNewFullScreen "Vollbildmodus ist ^f"
+
+#define kStrNewCntrlKey "Emulierte ;]^m;}-Taste ^k"
+
+#define kStrCmdCancel "Abbrechen"
+
+#define kStrConfirmReset "Wollen Sie den emulierten Rechner wirklich neustarten? Ungesicherte ;uAnderungen werden verlorengehen und gemountete Disketten-Images k;uonnen besch;uadigt werden. Dr;uucken Sie einen dieser Buchstaben:"
+#define kStrResetDo "^p neustarten"
+#define kStrResetNo "Nicht neustarten"
+
+#define kStrHaveReset "Emulierter Rechner wurde zur;uuckgesetzt."
+
+#define kStrCancelledReset "Neustart wird nicht durchgef;uuhrt"
+
+#define kStrConfirmInterrupt "Interrupt f;uur diesen emulierten Rechner ausf;uuhren? Dies ruft alle implementierten Debugger auf. Dr;uucken Sie einen dieser Buchstaben:"
+#define kStrInterruptDo "Interrupt ausf;uuhren"
+#define kStrInterruptNo "Interrupt nicht ausf;uuhren"
+
+#define kStrHaveInterrupted "Interrupt wurde durchgef;uuhrt"
+
+#define kStrCancelledInterrupt "Interrupt wird nicht ausgef;uuhrt"
+
+#define kStrConfirmQuit "Wollen Sie ^p wirklich beenden? Sie sollten zuvor den emulierten Rechner herunterfahren, um Besch;uadigungen an gemounteten Disketten-Images zu vermeiden. Dr;uucken Sie einen dieser Buchstaben:"
+#define kStrQuitDo kStrCmdQuit
+#define kStrQuitNo "Nicht beenden"
+
+#define kStrCancelledQuit "^p wird nicht beendet"
+
+#define kStrModeConfirmReset "Kontrollmodus : Neustarten von ^p best;uatigen"
+#define kStrModeConfirmInterrupt "Kontrollmodus : Interrupt best;uatigen"
+#define kStrModeConfirmQuit "Kontrollmodus : Beenden von ^p best;uatigen"
+#define kStrModeSpeedControl "Kontrollmodus : Geschwindigkeitskontrolle"
+#define kStrModeControlBase "Kontrollmodus (Tippen Sie ;]H;}, um Hilfe zu erhalten)"
+#define kStrModeControlHelp "Kontrollmodus"
+#define kStrModeMessage "Mitteilung (Tippen Sie ;]C;}, um fortzusetzen)"
+
+#define kStrMenuFile "Ablage"
+#define kStrMenuFile_win "Datei"
+#define kStrMenuSpecial "Spezial"
+#define kStrMenuHelp "Hilfe"
+
+#define kStrMenuItemAbout ";uUber ^p"
+#define kStrMenuItemOpen "Disketten-Image ;uoffnen"
+#define kStrMenuItemQuit "Beenden"
+#define kStrMenuItemMore "Mehr Befehle"
+
+#define kStrAppMenuItemHide "^p ausblenden"
+#define kStrAppMenuItemHideOthers "Andere ausblenden"
+#define kStrAppMenuItemShowAll "Alle einblenden"
+#define kStrAppMenuItemQuit "^p beenden"
+
+#define kStrCntrlKyName "Control"
+#define kStrCmdCopyOptions "Variation options kopieren"
+#define kStrHaveCopiedOptions "Variation options kopiert"
--- /dev/null
+++ b/src/STRCNITA.h
@@ -1,0 +1,170 @@
+/*
+	STRCNITA.h
+
+	Copyright (C) 2006 Paul C. Pratt, Fabio Concas, Gianluca Abbiati
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	STRing CoNstants for ITAlian
+
+	These strings were originally translated by Fabio Concas, who
+	hasn't been heard from lately, and modifications were
+	needed for version 2.8.1. Gianluca Abbiati agreed to look
+	at it, and made numerous changes for version 2.8.2.
+*/
+
+#define kStrAboutTitle "Informazioni"
+#define kStrAboutMessage "Per visualizzare le informazioni su questo programma usa il comando ;]A;} dalla Modalit;`a Controllo di ^p. Per informazioni sulla Modalit;`a Controllo, vedi ;[Ulteriori Comandi;ll;{ nel men;`u ;[Speciale;{."
+
+#define kStrMoreCommandsTitle "Ulteriori comandi sono disponibili nella Modalit;`a Controllo di ^p."
+#define kStrMoreCommandsMessage "Per entrare nella Modalit;`a Controllo, premi e tieni premuto il tasto ;]^c;}. La Modalit;`a Controllo rester;`a attiva fino a che il tasto ;]^c;} non verr;`a rilasciato. Digita ;]H;} nella Modalit;`a Controllo per avere la lista dei comandi disponibili."
+
+#define kStrTooManyImagesTitle "Troppe Immagini Disco."
+#define kStrTooManyImagesMessage "Non posso montare altre Immagini Disco. Prova ad espellerne una."
+
+#define kStrImageInUseTitle "Immagine Disco in uso."
+#define kStrImageInUseMessage "Non posso montare l;}Immagine Disco perch;ee ;`e utilizzata da un;}altra applicazione."
+
+#define kStrOutOfMemTitle "Memoria insufficiente."
+#define kStrOutOfMemMessage "Non c;};`e abbastanza memoria per avviare ^p."
+
+#define kStrNoROMTitle "Impossibile trovare l;}immagine della ROM."
+#define kStrNoROMMessage "Non trovo il file immagine della ROM ;[^r;{. Per maggiori informazioni, vedi: ;[^w;{"
+
+#define kStrCorruptedROMTitle "Checksum della ROM fallita."
+#define kStrCorruptedROMMessage "L;}immagine della ROM ;[^r;{ potrebbe essere danneggiata."
+
+#define kStrUnsupportedROMTitle "ROM non supportata."
+#define kStrUnsupportedROMMessage "Il file immagine della ROM ;[^r;{ ;`e stato caricato, ma ^p non supporta ancora questa ROM."
+
+#define kStrQuitWarningTitle "Dovresti spegnere la macchina emulata prima di uscire."
+#define kStrQuitWarningMessage "Per forzare l;}uscita da ^p (col rischio di danneggiare le immagini disco montate), usa il comando ;]Q;} dalla Modalit;`a Controllo di ^p. Per informazioni sulla Modalit;`a Controllo, vedi ;[Ulteriori Comandi;ll;{ nel men;`u ;[Speciale;{."
+
+#define kStrReportAbnormalTitle "Situazione Anomala"
+#define kStrReportAbnormalMessage "La macchina emulata sta tentando un;}operazione inaspettata nell;}uso normale."
+
+#define kStrBadArgTitle "Argomento sconosciuto."
+#define kStrBadArgMessage "Non comprendo uno dei parametri della riga di comando, lo ignoro."
+
+#define kStrOpenFailTitle "Apertura fallita."
+#define kStrOpenFailMessage "Non posso aprire l;}immagine disco."
+
+#define kStrNoReadROMTitle "Non posso leggere l;}immagine della ROM."
+#define kStrNoReadROMMessage "Ho trovato l;}immagine della ROM ;[^r;{, ma non posso leggerla."
+
+#define kStrShortROMTitle "L;}immagine della ROM ;`e troppo piccola."
+#define kStrShortROMMessage "Il file immagine della ROM ;[^r;{ ;`e pi;`u piccolo di quanto dovrebbe essere."
+
+/* state of a boolean option */
+#define kStrOn "attivo"
+#define kStrOff "inattivo"
+
+/* state of a key */
+#define kStrPressed "premuto"
+#define kStrReleased "rilasciato"
+
+/* state of Stopped */
+#define kStrStoppedOn kStrOn
+#define kStrStoppedOff kStrOff
+
+/* About Screen */
+#define kStrProgramInfo "^v"
+#define kStrSponsorIs "^v. This variation is made for:"
+#define kStrWorkOfMany "Copyright ^y. ^p contiene il lavoro di molte persone. Questa versione ;`e mantenuta da:"
+#define kStrForMoreInfo "Per maggiori informazioni, vedi:"
+#define kStrLicense "^p ;`e distribuito secondo i termini della Licenza Pubblica GNU, versione 2."
+#define kStrDisclaimer " ^p ;`e distribuito con la speranza che sia utile, ma SENZA ALCUNA GARANZIA;ls compresa la garanzia implicita di COMMERCIABILIT;`A o IDONEIT;`A PER UN QUALSIASI SCOPO."
+
+/* Help Screen */
+#define kStrHowToLeaveControl "Per uscire dalla Modalit;`a Controllo, rilascia il tasto ;]^c;}."
+#define kStrHowToPickACommand "Altrimenti premi una lettera. I comandi disponibili sono:"
+#define kStrCmdAbout "Informazioni (informazioni sulla versione)"
+#define kStrCmdOpenDiskImage "Apri immagine disco;ll"
+#define kStrCmdQuit "Esci"
+#define kStrCmdSpeedControl "Controllo velocit;`a;ll (^s)"
+#define kStrCmdMagnifyToggle "Ingrandimento (^g)"
+#define kStrCmdFullScrnToggle "Schermo intero (^f)"
+#define kStrCmdCtrlKeyToggle "Tasto ;]^m;} emulato (^k)"
+#define kStrCmdReset "Reset"
+#define kStrCmdInterrupt "Interrupt"
+#define kStrCmdHelp "Aiuto (mostra questo messaggio)"
+
+/* Speed Control Screen */
+#define kStrCurrentSpeed "Velocit;`a attuale: ^s"
+#define kStrSpeedAllOut "Massima velocit;`a"
+#define kStrSpeedStopped "Stop (^h)"
+#define kStrSpeedBackToggle "Funzionamento in background (^b)"
+#define kStrSpeedAutoSlowToggle "AutoSlow (^l)"
+#define kStrSpeedExit "Esci da Controllo Velocit;`a"
+
+#define kStrNewSpeed "Velocit;`a: ^s"
+#define kStrSpeedValueAllOut "Massima"
+
+#define kStrNewStopped "Lo stop ;`e ^h"
+#define kStrNewRunInBack "Il funzionamento in background ;`e ^b"
+#define kStrNewAutoSlow "AutoSlow ;`e ^l."
+
+#define kStrNewMagnify "L;laingrandimento ;`e ^g"
+
+#define kStrNewFullScreen "Lo schermo intero ;`e ^f"
+
+#define kStrNewCntrlKey "Il tasto ;]^m;} emulato ;`e ^k"
+
+#define kStrCmdCancel "Annulla"
+
+#define kStrConfirmReset "Sei sicuro di voler resettare la macchina emulata? Le modifiche non salvate andranno perse e le immagini disco montate potrebbero venire danneggiate. Premi una lettera:"
+#define kStrResetDo kStrCmdReset
+#define kStrResetNo kStrCmdCancel
+
+#define kStrHaveReset "La macchina emulata ;`e stata resettata"
+
+#define kStrCancelledReset "Reset annullato"
+
+#define kStrConfirmInterrupt "Sei sicuro di voler eseguire l;laInterrupt della macchina emulata? Questo avvier;`a il debugger installato nel tuo sistema. Premi una lettera:"
+#define kStrInterruptDo kStrCmdInterrupt
+#define kStrInterruptNo kStrCmdCancel
+
+#define kStrHaveInterrupted "Interrupt della macchina emulata eseguito"
+
+#define kStrCancelledInterrupt "Interrupt annullato"
+
+#define kStrConfirmQuit "Sei sicuro di voler uscire? Dovresti spegnere la macchina emulata prima di uscire da ^p per prevenire potenziali danni alle immagini disco montate. Premi una lettera:"
+#define kStrQuitDo kStrCmdQuit
+#define kStrQuitNo kStrCmdCancel
+
+#define kStrCancelledQuit "Uscita annullata"
+
+#define kStrModeConfirmReset "Modalit;`a Controllo : Conferma Riavviare"
+#define kStrModeConfirmInterrupt "Modalit;`a Controllo : Conferma l;}Interrupt"
+#define kStrModeConfirmQuit "Modalit;`a Controllo : Conferma Uscire"
+#define kStrModeSpeedControl "Modalit;`a Controllo : Controllo Velocit;`a"
+#define kStrModeControlBase "Modalit;`a Controllo (Digita ;]H;} per l;}aiuto)"
+#define kStrModeControlHelp "Modalit;`a Controllo"
+#define kStrModeMessage "Messaggio (Digita ;]C;} per continuare)"
+
+#define kStrMenuFile "Archivio"
+#define kStrMenuSpecial "Speciale"
+#define kStrMenuHelp "Aiuto"
+
+#define kStrMenuItemAbout "Informazioni su ^p"
+#define kStrMenuItemOpen "Apri Immagine Disco"
+#define kStrMenuItemQuit "Esci"
+#define kStrMenuItemMore "Altri Comandi"
+
+#define kStrAppMenuItemHide "Nascondi ^p"
+#define kStrAppMenuItemHideOthers "Nascondi altre"
+#define kStrAppMenuItemShowAll "Mostra tutte"
+#define kStrAppMenuItemQuit "Esci da ^p"
+
+#define kStrCmdCopyOptions "Copia variation options"
+#define kStrHaveCopiedOptions "Variation options copiate"
--- /dev/null
+++ b/src/STRCNPOL.h
@@ -1,0 +1,168 @@
+/*
+	STRCNPOL.h
+
+	Copyright (C) 2012 Przemys;dlaw Buczkowski, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	STRing CoNstants for POLish
+
+	These strings were translated by Przemys;dlaw Buczkowski.
+*/
+
+#define kStrAboutTitle "O programie;ll"
+#define kStrAboutMessage "Aby obejrze;ec informacje o tym programie u;dzyj komendy ;]A;} w ^p Trybie Kontroli. Aby dowiedzie;ec si;de wi;decej o tym trybie kliknij przycisk ;[Wi;decej komend;ll;{ w menu ;[Specjalne;{."
+
+#define kStrMoreCommandsTitle "Wi;decej komend jest dost;depnych w ^p Trybie Kontroli."
+#define kStrMoreCommandsMessage "Aby wej;es;ec w Tryb Kontroli przytrzymaj przycisk ^c. Pozostaniesz w Trybie Kontroli dop;eoki nie pu;escisz tego klawisza. Kliknij H aby wy;eswietli;ec Pomoc."
+
+#define kStrTooManyImagesTitle "Za du;dzo obraz;eow dysk;eow"
+#define kStrTooManyImagesMessage "Nie mog;de zamontowa;ec tylu dysk;eow. Odmontowywanie jednego."
+
+#define kStrImageInUseTitle "Obraz w u;dzyciu"
+#define kStrImageInUseMessage "Nie mog;de zamontowa;ec tego dysku poniewa;dz jest on u;dzywany przez inn;da aplikacj;de lub uruchomiony w ^p."
+
+#define kStrOutOfMemTitle "Za ma;dlo pami;deci"
+#define kStrOutOfMemMessage "Mam za ma;dlo pami;deci aby uruchomi;ec ^p."
+
+#define kStrNoROMTitle "Nie uda;dlo si;de zlokalizowa;ec ROMu"
+#define kStrNoROMMessage "Nie mog;de znale;ez;ec ROMu ;[^r;{. Aby dowiedzie;ec si;de wi;decej, zobacz: ;[^w;{."
+
+#define kStrCorruptedROMTitle "ROM uszkodzony"
+#define kStrCorruptedROMMessage "Plik ROMu ;[^r;{ mo;dze by;ec uszkodzony."
+
+#define kStrUnsupportedROMTitle "Niewspierany ROM"
+#define kStrUnsupportedROMMessage "ROM ;[^r;{ zosta;dl za;dladowany, ale nie obs;dluguj;de tej wersji."
+
+#define kStrQuitWarningTitle "Prosz;de wy;dl;daczy;ec emulowany komputer przed wyj;esciem."
+#define kStrQuitWarningMessage "Aby wymusi;ec wyj;escie ryzykuj;dac uszkodzenie obraz;eow dysk;eow u;dzyj komendy ;]Q;} w Trybie Kontroli. Aby dowiedzie;ec si;de wi;decej o tym trybie kliknij przycisk ;[Wi;decej komend;ll;{ w menu ;[Specjalne;{."
+
+#define kStrReportAbnormalTitle "Nienormalne polecenie"
+#define kStrReportAbnormalMessage "Emulowany komputer pr;eobowa;dl zrobi;ec co;es, co nie powinno si;de zdarzy;ec."
+
+#define kStrBadArgTitle "Z;dly argument"
+#define kStrBadArgMessage "Nie zrozumia;dlem podanego argumentu."
+
+#define kStrOpenFailTitle "B;dl;dad otwierania"
+#define kStrOpenFailMessage "Nie mog;de otworzy;ec obrazu dysku."
+
+#define kStrNoReadROMTitle "Nieudane otwarcie ROMu"
+#define kStrNoReadROMMessage "Znalaz;dlem plik ROMu ;[^r;{, ale nie mog;de go otworzy;ec."
+
+#define kStrShortROMTitle "Za ma;dly ROM"
+#define kStrShortROMMessage "Plik ROMu ;[^r;{ jest mniejszy ni;dz powinien by;ec."
+
+/* state of a boolean option */
+#define kStrOn "w;dl;daczone"
+#define kStrOff "wy;dl;daczone"
+
+/* state of a key */
+#define kStrPressed "wci;esni;dety"
+#define kStrReleased "puszczony"
+
+/* state of Stopped */
+#define kStrStoppedOn kStrOn
+#define kStrStoppedOff kStrOff
+
+/* About Screen */
+#define kStrProgramInfo "^v"
+#define kStrSponsorIs "^v. This variation is made for:"
+#define kStrWorkOfMany "Copyright ^y. ^p jest wynikiem pracy wielu os;eob. Ta wersja jest zarz;dadzana przez:"
+#define kStrForMoreInfo "Po wi;decej informacji zobacz:"
+#define kStrLicense "^p jest dystrybuowany na licencji GNU General Public License 2."
+#define kStrDisclaimer " ^p is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;ls without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+/* Help Screen */
+#define kStrHowToLeaveControl "Aby opu;esci;ec Tryb Kontroli pu;es;ec klawisz ^c."
+#define kStrHowToPickACommand "Naci;esnij liter;de. Dost;depne komendy to:"
+#define kStrCmdAbout "O programie (szczeg;eo;dly wersji);ll"
+#define kStrCmdOpenDiskImage "Otw;eorz obraz dysku;ll"
+#define kStrCmdQuit "Wyjd;ez"
+#define kStrCmdSpeedControl "Kontrola szybko;esci;ll (^s)"
+#define kStrCmdMagnifyToggle "Skalowanie (^g)"
+#define kStrCmdFullScrnToggle "Pe;dlny ekran (^f)"
+#define kStrCmdCtrlKeyToggle "Emulowany klawisz ^m (^k)"
+#define kStrCmdReset "Reset"
+#define kStrCmdInterrupt "Przerwanie"
+#define kStrCmdHelp "Pomoc (ta strona)"
+
+/* Speed Control Screen */
+#define kStrCurrentSpeed "Obecna pr;dedko;es;ec: ^s"
+#define kStrSpeedAllOut "Ca;dla naprz;eod!"
+#define kStrSpeedStopped "Zatrzymanie (^h)"
+#define kStrSpeedBackToggle "Uruchamianie w tle (^b)"
+#define kStrSpeedAutoSlowToggle "AutoSlow (^l)"
+#define kStrSpeedExit "Wyj;escie z kontroli pr;dedko;esci"
+
+#define kStrNewSpeed "Pr;dedko;es;ec: ^s"
+#define kStrSpeedValueAllOut kStrSpeedAllOut
+
+#define kStrNewStopped "Zatrzymanie jest ^h."
+#define kStrNewRunInBack "Uruchomienie w tle ^b."
+#define kStrNewAutoSlow "AutoSlow jest ^g."
+
+#define kStrNewMagnify "Powi;dekszenie jest ^g."
+
+#define kStrNewFullScreen "Pe;dlny ekran jest ^f."
+
+#define kStrNewCntrlKey "Emulowany klawiszem ^m jest ^k."
+
+#define kStrCmdCancel "anuluj"
+
+#define kStrConfirmReset "Czy na pewno chcesz zresetowa;ec emulator? Zmiany nie zostan;da zapisane, istnieje ryzyko uszkodzenia obraz;eow dysk;eow. Podaj liter;de:"
+#define kStrResetDo "reset"
+#define kStrResetNo kStrCmdCancel
+
+#define kStrHaveReset "Zresetowano komputer."
+
+#define kStrCancelledReset "Reset anulowany."
+
+#define kStrConfirmInterrupt "Czy jeste;es pewny aby wywo;dla;ec przerwanie emulatora? Podaj liter;de:"
+#define kStrInterruptDo "przerwanie"
+#define kStrInterruptNo kStrCmdCancel
+
+#define kStrHaveInterrupted "Wywo;dlano przerwanie komputera."
+
+#define kStrCancelledInterrupt "Przerwanie anulowane."
+
+#define kStrConfirmQuit "Czy na pewno chcesz wy;dl;daczy;ec komputer ^p? Zmiany nie zostan;da zapisane, istnieje ryzyko uszkodzenia obraz;eow dysk;eow. Podaj liter;de:"
+#define kStrQuitDo "wyjd;ez"
+#define kStrQuitNo kStrCmdCancel
+
+#define kStrCancelledQuit "Wyj;escie anulowane"
+
+#define kStrModeConfirmReset "Tryb Kontroli : Potwierd;ez reset"
+#define kStrModeConfirmInterrupt "Tryb Kontroli : Potwierd;ez przerwanie"
+#define kStrModeConfirmQuit "Tryb Kontroli : Potwierd;ez wyj;escie"
+#define kStrModeSpeedControl "Tryb Kontroli : Kontrola pr;dedko;esci"
+#define kStrModeControlBase "Tryb Kontroli (wci;esnij ;]H;} po pomoc)"
+#define kStrModeControlHelp "Tryb Kontroli"
+#define kStrModeMessage "Wiadomo;es;ec (kliknij ;]C;} aby kontynuowa;ec)"
+
+#define kStrMenuFile "Plik"
+#define kStrMenuSpecial "Specjalne"
+#define kStrMenuHelp "Pomoc"
+
+#define kStrMenuItemAbout "O;ll ^p"
+#define kStrMenuItemOpen "Otw;eorz obraz dysku"
+#define kStrMenuItemQuit "Pomoc"
+#define kStrMenuItemMore "Wi;decej komend"
+
+#define kStrAppMenuItemHide "Ukryj ^p"
+#define kStrAppMenuItemHideOthers "Ukryj pozosta;dle"
+#define kStrAppMenuItemShowAll "Poka;dz wszystkie"
+#define kStrAppMenuItemQuit "Zako;encz ^p"
+
+#define kStrCntrlKyName "Control"
+#define kStrCmdCopyOptions "Kopiuj variation options"
+#define kStrHaveCopiedOptions "Variation options kopiowane"
--- /dev/null
+++ b/src/STRCNPTB.h
@@ -1,0 +1,211 @@
+/*
+	STRCNPTB.h
+
+	Copyright (C) 2017 Mauricio, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	STRing CoNstants for PorTuguese-Brazilian
+
+	These strings were translated by Mauricio.
+*/
+
+#define kStrAboutTitle "Sobre"
+
+#define kStrAboutMessage "Para exibir informa;c;noes sobre este programa, use o comando ;]A;} do Modo de Controle ^p. Para saber mais sobre o Modo de Controle, consulte o item ;[Mais Comandos;ll;{ no menu ;[Especial;{."
+
+#define kStrMoreCommandsTitle "Mais comandos est;nao dispon;eiveis no Modo de Controle ^p."
+
+#define kStrMoreCommandsMessage "Para entrar no Modo de Controle, pressione e mantenha pressionada a tecla ;]^c;}, voc;ie permanecer;ea no Modo de Controle at;ee que voc;ie solte a tecla ;]^c;}. Digite 'H' no Modo de Controle para listar os comandos dispon;eiveis."
+
+#define kStrTooManyImagesTitle "Imagens de Disco excedidas"
+
+#define kStrTooManyImagesMessage "N;nao consigo montar tantas Imagens de Disco. Tente ejetar alguma."
+
+#define kStrImageInUseTitle "Imagem de Disco em uso"
+
+#define kStrImageInUseMessage "N;nao consigo montar a imagem de disco porque ela j;ea est;ea em uso por outro aplicativo ou j;ea est;ea aberta em ^p."
+
+#define kStrOutOfMemTitle "Mem;eoria insuficiente"
+
+#define kStrOutOfMemMessage "N;nao h;ea mem;eoria suficiente dispon;eivel para iniciar ^p."
+
+#define kStrNoROMTitle "N;nao ;ee poss;eivel localizar a imagem ROM"
+
+#define kStrNoROMMessage "N;nao consigo encontrar o arquivo de imagem ROM ;[^r;{. Para obter mais informa;c;noes, consulte: ;[^w;{."
+
+#define kStrCorruptedROMTitle "Falha no checksum da ROM"
+
+#define kStrCorruptedROMMessage "O arquivo de imagem ROM ;[^r;{ pode estar corrompido."
+
+#define kStrUnsupportedROMTitle "ROM n;nao suportada"
+
+#define kStrUnsupportedROMMessage "O arquivo de imagem ROM ;[^r;{ foi carregado com ;iexito, mas n;nao suportamos esta vers;nao ROM."
+
+#define kStrQuitWarningTitle "Por favor, desligue o computador emulado antes de fechar."
+
+#define kStrQuitWarningMessage "To force ^p to quit, at the risk of corrupting the mounted disk image files, use the ;]Q;} command of the ^p Control Mode. To learn about the Control Mode, see the ;[More Commands;ll;{ item in the ;[Special;{ menu."
+
+#define kStrReportAbnormalTitle "Situa;c;nao Anormal"
+
+#define kStrReportAbnormalMessage "O computador emulado est;ea tentando uma opera;c;nao que n;nao era esperada para acontecer em uso normal."
+
+#define kStrBadArgTitle "Argumento desconhecido"
+
+#define kStrBadArgMessage "Eu n;nao entendi um dos argumentos da linha de comando e ignorei-o."
+
+#define kStrOpenFailTitle "Falha ao abrir"
+
+#define kStrOpenFailMessage "N;nao consegui abrir a imagem do disco."
+
+#define kStrNoReadROMTitle "N;nao ;ee poss;eivel ler a imagem ROM"
+
+#define kStrNoReadROMMessage "Eu encontrei o arquivo de imagem ROM ;[^r;{, mas n;nao consigo l;ie-lo."
+
+#define kStrShortROMTitle "Imagem da ROM muito pequena"
+
+#define kStrShortROMMessage "O arquivo de imagem ROM ;[^r;{ ;ee menor do que deveria ser."
+
+/* state of a boolean option */
+#define kStrOn "Ligado"
+#define kStrOff "Desligado"
+
+/* state of a key */
+#define kStrPressed "Ligada"
+#define kStrReleased "Desligada"
+
+/* state of Stopped */
+#define kStrStoppedOn kStrOn
+#define kStrStoppedOff kStrOff
+
+/* About Screen */
+#define kStrProgramInfo "^v"
+
+#define kStrSponsorIs "^v. Esta varia;c;nao ;ee patrocinada por:"
+
+#define kStrWorkOfMany "Copyright ^y. ^p cont;eem o trabalho de muitas pessoas. Esta vers;nao ;ee mantida por:"
+
+#define kStrForMoreInfo "Para obter mais informa;c;noes, consulte:"
+
+#define kStrLicense "^p ;ee distribu;eido sob os termos da Licen;ca P;eublica GNU, vers;nao 2."
+
+#define kStrDisclaimer " ^p ;ee distribu;eido com a esperan;ca de que ser;ea ;eutil, mas SEM NENHUMA GARANTIA, sem sequer a garantia impl;eicita de COMERCIALIZA;C;nAO ou ADEQUA;C;nAO A UM DETERMINADO PROP;eOSITO."
+
+/* Help Screen */
+#define kStrHowToLeaveControl "Para sair do modo de controle, solte a tecla ;]^c;}."
+
+#define kStrHowToPickACommand "Caso contr;eario, digite uma letra. Comandos dispon;eiveis:"
+
+#define kStrCmdAbout "Sobre (informa;c;noes sobre a vers;nao)"
+
+#define kStrCmdOpenDiskImage "Abrir imagem de disco;ll"
+
+#define kStrCmdQuit "Sair"
+
+#define kStrCmdSpeedControl "Controle de velocidade;ll (^s)"
+
+#define kStrCmdMagnifyToggle "Zoom (^g)"
+
+#define kStrCmdFullScrnToggle "Tela Cheia (^f)"
+
+#define kStrCmdCtrlKeyToggle "Alternar Tecla ;]^m;} emulada (^k)"
+
+#define kStrCmdReset "Reiniciar"
+
+#define kStrCmdInterrupt "Interromper"
+
+#define kStrCmdHelp "Ajuda (mostrar esta p;eagina)"
+
+/* Speed Control Screen */
+#define kStrCurrentSpeed "Velocidade atual: ^s"
+
+#define kStrSpeedAllOut "Toda a velocidade"
+
+#define kStrSpeedStopped "parado (^h)"
+
+#define kStrSpeedBackToggle "Rodar em Segundo Plano (^b)"
+
+#define kStrSpeedAutoSlowToggle "Lentid;nao Autom;eatica (^l)"
+
+#define kStrSpeedExit "Sair do controle de velocidade"
+
+#define kStrNewSpeed "Velocidade: ^s"
+
+#define kStrSpeedValueAllOut kStrSpeedAllOut
+
+#define kStrNewStopped "Parado est;ea ^h."
+
+#define kStrNewRunInBack "Rodar em segundo plano est;ea ^b."
+
+#define kStrNewAutoSlow "Lentid;nao Autom;eatica est;ea ^l."
+
+#define kStrNewMagnify "Zoom est;ea ^g."
+
+#define kStrNewFullScreen "Tela Cheia est;ea ^f."
+
+#define kStrNewCntrlKey "Emula;c;nao da tecla ;]^m;} ^k."
+
+#define kStrCmdCancel "cancelar"
+
+#define kStrConfirmReset "Tem certeza de que deseja reiniciar o computador emulado? As altera;c;noes n;nao salvas ser;nao perdidas e h;ea o risco de corromper os arquivos de imagem de disco montados. Digite uma letra:"
+
+#define kStrResetDo "reiniciar"
+
+#define kStrResetNo kStrCmdCancel
+
+#define kStrHaveReset "Reiniciar o computador emulado"
+
+#define kStrCancelledReset "Reinicializa;c;nao cancelada"
+
+#define kStrConfirmInterrupt "Tem certeza de que deseja interromper o computador emulado? Isso invocar;ea qualquer depurador instalado. Digite uma letra:"
+
+#define kStrInterruptDo "Interromper"
+
+#define kStrInterruptNo kStrCmdCancel
+
+#define kStrHaveInterrupted "Interrompeu o computador emulado"
+
+#define kStrCancelledInterrupt "Interrup;c;nao cancelada"
+
+#define kStrConfirmQuit "Tem certeza de que deseja sair ^p? Voc;ie deve desligar o computador emulado antes de sair para evitar corromper os arquivos de imagem de disco montados. Digite uma letra:"
+
+#define kStrQuitDo "sair"
+
+#define kStrQuitNo kStrCmdCancel
+
+#define kStrCancelledQuit "Opera;c;nao cancelada"
+
+#define kStrModeConfirmReset "Modo de Controle : Confirmar Reinicializa;c;nao"
+#define kStrModeConfirmInterrupt "Modo de Controle : Confirmar Interrup;c;nao"
+#define kStrModeConfirmQuit "Modo de Controle : Confirmar Sair"
+#define kStrModeSpeedControl "Modo de Controle : Controle de Velocidade"
+#define kStrModeControlBase "Modo de Controle (Digite ;]H;} para obter ajuda)"
+#define kStrModeControlHelp "Modo de Controle"
+#define kStrModeMessage "Message (Digite ;]C;} para continuar)"
+
+#define kStrMenuFile "Arquivo"
+#define kStrMenuSpecial "Especial"
+#define kStrMenuHelp "Ajuda"
+
+#define kStrMenuItemAbout "Sobre ^p"
+#define kStrMenuItemOpen "Open Disk Image"
+#define kStrMenuItemQuit "Sair"
+#define kStrMenuItemMore "Mais Comandos"
+
+#define kStrAppMenuItemHide "Esconder ^p"
+#define kStrAppMenuItemHideOthers "Esconder Outras"
+#define kStrAppMenuItemShowAll "Mostrar Todas"
+#define kStrAppMenuItemQuit "Sair ^p"
+
+#define kStrCmdCopyOptions "Copiar variation options"
+#define kStrHaveCopiedOptions "Variation options copiadas"
--- /dev/null
+++ b/src/STRCNSPA.h
@@ -1,0 +1,167 @@
+/*
+	STRCNSPA.h
+
+	Copyright (C) 2006 Chir, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	STRing CoNstants for SPAnish
+
+	These strings were translated by Chir.
+*/
+
+#define kStrAboutTitle "Acerca de"
+#define kStrAboutMessage "Para mostrar informaci;eon acerca de este programa, use el comando ;]A;} del ^p Modo Control. Para saber m;eas acerca del Modo Control, vea ;[Mas Comandos;ll;{ en el menu ;[Especial;{ ."
+
+#define kStrMoreCommandsTitle "M;eas comandos est;ean disponibles en el modo de control de ^p ."
+#define kStrMoreCommandsMessage "Para entrar en el modo de control, mantenga pulsada la tecla ;]^c;} . Seguir;ea en el modo control hasta que suelte la tecla ;]^c;} . Pulse ;]H;} en el modo control para listar los comandos disponibles."
+
+#define kStrTooManyImagesTitle "Demasiadas im;eagenes de disco"
+#define kStrTooManyImagesMessage "No se pueden montar tantas im;eagenes de disco. Intente sacar alguna."
+
+#define kStrImageInUseTitle "Imagen disco en uso"
+#define kStrImageInUseMessage "No se puede montar la imagen disco porque ya est;ea en uso por otra aplicaci;eon, o ya abierta en ^p."
+
+#define kStrOutOfMemTitle "Memoria insuficiente"
+#define kStrOutOfMemMessage "No hay suficiente memoria disponible para lanzar ^p."
+
+#define kStrNoROMTitle "Imposible localizar la imagen ROM"
+#define kStrNoROMMessage "No se encuentra la imagen del fichero ROM ;[^r;{. Para m;eas informaci;eon, ver: ;[^w;{."
+
+#define kStrCorruptedROMTitle "El control checksum de la ROM ha fracasado"
+#define kStrCorruptedROMMessage "El fichero de imagen ROM ;[^r;{ puede estar corrompido."
+
+#define kStrUnsupportedROMTitle "ROM no soportada"
+#define kStrUnsupportedROMMessage "Fichero de imagen ROM ;[^r;{ cargado con ;eexito, pero esa versi;eon no est;ea soportada."
+
+#define kStrQuitWarningTitle "Por favor, apague el ordenador emulado antes de salir."
+#define kStrQuitWarningMessage "Para forzar ^p salir, con riesgo de corrupci;eon en las im;eagenes de discos montadas, use el comando ;]Q;} del ^p Modo Control. Para saber m;eas acerca del Modo Control, vea ;[Mas Comandos;ll;{ en el menu ;[Especial;{ ."
+
+#define kStrReportAbnormalTitle "Situaci;eon anormal"
+#define kStrReportAbnormalMessage "El ordenador emulado intenta hacer una operaci;eon no esperada en un uso normal."
+
+#define kStrBadArgTitle "Argumento desconocido"
+#define kStrBadArgMessage "No se comprendi;eo alguno de los argumentos de la linea de comandos, y se ignor;eo."
+
+#define kStrOpenFailTitle "Apertura fracasada"
+#define kStrOpenFailMessage "No se pudo abrir la imagen disco."
+
+#define kStrNoReadROMTitle "No se puede abrir la imagen ROM"
+#define kStrNoReadROMMessage "Se encontr;eo el fichero de imagen ROM ;[^r;{, pero no se pudo leer."
+
+#define kStrShortROMTitle "Imagen ROM demasiado corta"
+#define kStrShortROMMessage "El fichero de imagen ROM ;[^r;{ es m;eas corto de lo que deber;eia."
+
+/* state of a boolean option */
+#define kStrOn "activado"
+#define kStrOff "desactivado"
+
+/* state of a key */
+#define kStrPressed "pulsada"
+#define kStrReleased "soltada"
+
+/* state of Stopped */
+#define kStrStoppedOn kStrOn
+#define kStrStoppedOff kStrOff
+
+/* About Screen */
+#define kStrProgramInfo "^v"
+#define kStrSponsorIs "^v. This variation is made for:"
+#define kStrWorkOfMany "Copyright ^y. ^p contiene el trabajo de muchas personas. Esta versi;eon es mantenida por:"
+#define kStrForMoreInfo "Para m;eas informaci;eon, vea:"
+#define kStrLicense "^p es distribuido bajo los t;eerminos de la licencia p;eublica GNU, versi;eon 2."
+#define kStrDisclaimer " ^p es distribuido con la esperanza de ser ;eutil, pero SIN NINGUNA GARANTIA;ls incluso sin la garant;eia impl;eicita de MERCANTIBILIDAD O ADECUACION PARA UN USO PARTICULAR."
+
+/* Help Screen */
+#define kStrHowToLeaveControl "Para salir del Modo Control, suelte la tecla ;]^c;} ."
+#define kStrHowToPickACommand "Sin;eo, pulse una letra. Los comandos disponibles son:"
+#define kStrCmdAbout "Acerca de (informaci;eon sobre versi;eon)"
+#define kStrCmdOpenDiskImage "Abrir imagen disco;ll"
+#define kStrCmdQuit "Salir"
+#define kStrCmdSpeedControl "Control de velocidad;ll (^s)"
+#define kStrCmdMagnifyToggle "Magnificaci;eon (^g)"
+#define kStrCmdFullScrnToggle "Pantalla completa (^f)"
+#define kStrCmdCtrlKeyToggle "Toggle emulaci;eon tecla ;]^m;} (^k)"
+#define kStrCmdReset "Reset"
+#define kStrCmdInterrupt "Interrumpir"
+#define kStrCmdHelp "Ayuda (mostrar esta p;eagina)"
+
+/* Speed Control Screen */
+#define kStrCurrentSpeed "Velocidad actual: ^s"
+#define kStrSpeedAllOut "M;eaxima velocidad"
+#define kStrSpeedStopped "Stop (^h)"
+#define kStrSpeedBackToggle "Ejecutar en segundo plano (^b)"
+#define kStrSpeedAutoSlowToggle "AutoSlow (^l)"
+#define kStrSpeedExit "Salir del control de velocidad"
+
+#define kStrNewSpeed "Velocidad: ^s"
+#define kStrSpeedValueAllOut kStrSpeedAllOut
+
+#define kStrNewStopped "Stop est;ea ^h."
+#define kStrNewRunInBack "Ejecutar en segundo plano est;ea ^b."
+#define kStrNewAutoSlow "AutoSlow est;ea ^l."
+
+#define kStrNewMagnify "Magnificaci;eon est;ea ^g."
+
+#define kStrNewFullScreen "Pantalla completa est;ea ^f."
+
+#define kStrNewCntrlKey "Emulado tecla ;]^m;} ^k."
+
+#define kStrCmdCancel "cancelar"
+
+#define kStrConfirmReset "Est;ea seguro de desear reiniciar el ordenador emulado? Los cambios no salvados se perderan, y existe riesgo de corrupci;eon en las im;eagenes de discos montadas. Pulse una tecla:"
+#define kStrResetDo "reset"
+#define kStrResetNo kStrCmdCancel
+
+#define kStrHaveReset "Se ha reiniciado el ordenador emulado"
+
+#define kStrCancelledReset "Reset cancelado"
+
+#define kStrConfirmInterrupt "Est;ea seguro de desear interrumpir el ordenador emulado? Esto invocar;ea cualquier debugger instalado. Pulse una tecla:"
+#define kStrInterruptDo "interrumpir"
+#define kStrInterruptNo kStrCmdCancel
+
+#define kStrHaveInterrupted "Se ha interrumpido el ordenador emulado"
+
+#define kStrCancelledInterrupt "Interrupci;eon cancelada"
+
+#define kStrConfirmQuit "Est;ea seguro de desear salir de ^p? Deber;eia apagar el ordenador emulado antes de salir, para evitar corrupciones en las im;eagenes de discos montadas. Pulse una tecla:"
+#define kStrQuitDo "salir"
+#define kStrQuitNo kStrCmdCancel
+
+#define kStrCancelledQuit "Salida cancelada"
+
+#define kStrModeConfirmReset "Modo Control : Confirmar reset"
+#define kStrModeConfirmInterrupt "Modo Control : Confirmar Interrupci;eon"
+#define kStrModeConfirmQuit "Modo Control : Confirmar salida"
+#define kStrModeSpeedControl "Modo Control : Control de velocidad"
+#define kStrModeControlBase "Modo Control (Pulse ;]H;} para la ayuda)"
+#define kStrModeControlHelp "Modo Control"
+#define kStrModeMessage "Mensaje (Pulse ;]C;} para continuar)"
+
+#define kStrMenuFile "Fichero"
+#define kStrMenuSpecial "Especial"
+#define kStrMenuHelp "Ayuda"
+
+#define kStrMenuItemAbout "Acerca de ^p"
+#define kStrMenuItemOpen "Abrir imagen disco"
+#define kStrMenuItemQuit "Salir"
+#define kStrMenuItemMore "M;eas comandos"
+
+#define kStrAppMenuItemHide "Ocultar ^p"
+#define kStrAppMenuItemHideOthers "Ocultar otros"
+#define kStrAppMenuItemShowAll "Mostrar todo"
+#define kStrAppMenuItemQuit "Salir de ^p"
+
+#define kStrCmdCopyOptions "Copiar variation options"
+#define kStrHaveCopiedOptions "Variation options copiadas"
--- /dev/null
+++ b/src/STRCNSRL.h
@@ -1,0 +1,184 @@
+/*
+	STRCNSRL.h
+
+	Copyright (C) 2018 SerbXenomorph, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file;ls see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY;ls without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	STRing CoNstants for SeRbian Latin
+
+	Converted from Serbian Cyrillic by 3 different online
+	converters, which all gave identical results.
+
+	comment from Serbian Cyrillic source follows:
+*/
+
+/*
+	STRing CoNstants for SeRbian Cyrillic
+	Translated by SerbXenomorph
+	- If no support Unicode/UTF-8, etc. support, online cyrillic to latin convertor will be enough.
+	- I have made some suggestions in the comments to avoid string repetition.
+*/
+
+#define kStrAboutTitle "O programu"
+#define kStrAboutMessage "Da bi se pokazale informacije o programu, koristite ;]A;} komandu moda kontrole ^p . Da saznate vi;vse o kontrolnom modu, vidite ;[Jo;vs komandi;ll;{ u ;[Special;{ meniju."
+
+#define kStrMoreCommandsTitle "Vi;vse komanda je dostupno u modu kontrole ^p."
+#define kStrMoreCommandsMessage "Da bi ste u;vsli u kontrolni mod, pretisnite taster ;]^c;}. osta;ecete u njemu dok ga ne pustite. Pretisnite ;]H;} da prika;vzete listu dostupnih komandi."
+
+#define kStrTooManyImagesTitle "Previ;vse diskovnih datoteka"
+#define kStrTooManyImagesMessage "Ne mogu montirati toliko diskovnih datoteka. Izbacite jednu."
+
+#define kStrImageInUseTitle "Diskovna datoteka se koristi"
+#define kStrImageInUseMessage "Ne mogu montirati diskovnu datoteku ^p kako se ve;ec koristi u drugom programu."
+
+#define kStrOutOfMemTitle "Nema dovoljno memorije"
+#define kStrOutOfMemMessage "Nema dovoljno memorije da bi se pokrenuo ^p."
+/*
+	This can possibly be defined as ("%s  da bi se pokrenuo ^p.", kStrOutOfMemTitle) to avoid duplicated string, if used in a printf() like function.
+*/
+
+#define kStrNoROMTitle "Ne mogu na;eci ROM datoteku"
+#define kStrNoROMMessage "Ne mogu na;eci ROM datoteku ;[^r;{. Za vi;vse informacija, vidite: ;[^w;{."
+/*
+	Same for this
+*/
+
+#define kStrCorruptedROMTitle "ROM provera neuspe;vsna"
+#define kStrCorruptedROMMessage "ROM datoteka ;[^r;{ je mo;vzda o;vste;ecena."
+
+#define kStrUnsupportedROMTitle "Nepodr;vzani ROM"
+#define kStrUnsupportedROMMessage "ROM datoteka ;[^r;{ se u;vcitala uspe;vsno, ali ne podr;vzavam ROM verziju."
+
+#define kStrQuitWarningTitle "Molimo ugasite emulisani kompjuter pre nego ;vsto iza;ddete iz programa."
+#define kStrQuitWarningMessage "Da biste prisilili ^p da iza;dde, sa rizikom da se diskovni fajlovi o;vstete, koristi ;]Q;} komandu kontrolnog moda ^p. Da saznate vi;vse o kontrolnom modu, vidite ;[Jo;vs komandi;ll;{ u ;[Special;{ meniju."
+
+#define kStrReportAbnormalTitle "Abnormalna situacija"
+#define kStrReportAbnormalMessage "Emulisani ra;vcunar je poku;vsao operaciju koja ne bi trebalo de se izvr;vsi pri normalnom kori;vs;ecenju."
+
+#define kStrBadArgTitle "Nepoznati argument"
+#define kStrBadArgMessage "Nisam razumeo jedan od argumenata komandne linije, i ignorisao ga."
+
+#define kStrOpenFailTitle "Otvaranje neuspe;vsno"
+#define kStrOpenFailMessage "Nisam mogao otvoriti diskovnu datoteku."
+
+#define kStrNoReadROMTitle "ROM datoteka ne;vcitljiva"
+#define kStrNoReadROMMessage "Prona;vsao sam ROM datoteku ;[^r;{, ali je ne mogu pro;vcitati."
+
+#define kStrShortROMTitle "ROM datoteka prekratka"
+#define kStrShortROMMessage "ROM datoteka ;[^r;{ je kra;eca nego ;vsto bi trebala da bude."
+
+/* state of a boolean option */
+#define kStrOn "Vklju;vcen"
+#define kStrOff "Isklju;vcen"
+
+/* state of a key */
+#define kStrPressed "pritisnut"
+#define kStrReleased "pu;vsten"
+
+/* state of Stopped */
+#define kStrStoppedOn kStrOn
+#define kStrStoppedOff kStrOff
+
+/* About Screen */
+#define kStrProgramInfo "^v"
+#define kStrSponsorIs "^v. Ova varijacija je napravljena za:"
+#define kStrWorkOfMany "Za;vsti;eceno autorskim pravima ^y. ^p sadr;vzi rad mnogo ljudi. Ovu verziju odr;vzava:"
+#define kStrForMoreInfo "Za vi;vse informacija, vidite:"
+#define kStrLicense "^p je distribuiran pod nalozima GNU javne licence, verzije 2."
+#define kStrDisclaimer " ^p je distribuiran u nadi da ;ece biti koristan, ali BeZ GaRaNcIjE.;ls  ;vcak i BeZ UtR;vzIvOsTi ili PrIkLaDnOsTi Za OdRe;dDeNu SvRhU."
+
+/* Help Screen */
+#define kStrHowToLeaveControl "da biste iza;vsli iz kontrolnog moda, pustite taster ;]^c;}."
+#define kStrHowToPickACommand "U drugom slu;vcaju, otkucajte slovo. Dostupne komande su:"
+#define kStrCmdAbout "O programu (informacije o verziji)"
+#define kStrCmdOpenDiskImage "Otvori diskovnu datoteku;ll"
+#define kStrCmdQuit "Iza;ddi"
+#define kStrCmdSpeedControl "Kontrola brzine;ll (^s)"
+#define kStrCmdMagnifyToggle "Prekida;vc lupe (^g)"
+#define kStrCmdFullScrnToggle "Prekida;vc re;vzima celog ekrana (^f)"
+#define kStrCmdCtrlKeyToggle "Prekida;vc emulisanog tastera ;]^m;} (^k)"
+#define kStrCmdReset "Resetuj"
+#define kStrCmdInterrupt "Prekid"
+#define kStrCmdHelp "Pomo;ec (poka;vzi ovu stranu)"
+
+/* Speed Control Screen */
+#define kStrCurrentSpeed "Trenutna brzina: ^s"
+#define kStrSpeedAllOut "Potpuna"
+#define kStrSpeedStopped "Prekida;vc zaustavljanja (^h)"
+#define kStrSpeedBackToggle "Prekida;vc rada u pozadini (^b)"
+#define kStrSpeedAutoSlowToggle "Prekida;vc automatskog usporavanja emulacije (^l)" /*Remove the "emulacije" if not enough space to display*/
+#define kStrSpeedExit "Iza;ddi iz kontrole brzine"
+
+#define kStrNewSpeed "Brzina: ^s"
+#define kStrSpeedValueAllOut kStrSpeedAllOut
+
+#define kStrNewStopped "Zaustavljeno jest ^h."
+#define kStrNewRunInBack "Pusti u pozadini jest ^b."
+#define kStrNewAutoSlow "automatsko usporavanje jest ^l."
+
+#define kStrNewMagnify "Pribli;vzi je ^g."
+
+#define kStrNewFullScreen "Ceo ekran je ^f."
+
+#define kStrNewCntrlKey "Emulisani taster ;]^m;} je ^k."
+
+#define kStrCmdCancel "odbij"
+
+#define kStrConfirmReset "Da li ste sigurni da ;vzelite resetovati emulirani kompjuter? nesa;vcuvane izmene ;ece biti izgubljene, i postoji rizik o;vste;ecivanja diskovnih datoteka. Otkucaj slovo:"
+#define kStrResetDo "resetuj"
+#define kStrResetNo kStrCmdCancel
+
+#define kStrHaveReset "Emulisani kompjuter resetovan"
+
+#define kStrCancelledReset "Resetovanje odbijeno"
+
+#define kStrConfirmInterrupt "Da li ste sigurni da ;vzelite prekinuti emulisani ra;vcunar? Ovo ;ece pokrenuti rad bilo kog instaliranog debagera. Otkucajte slovo:"
+#define kStrInterruptDo "prekini"
+#define kStrInterruptNo kStrCmdCancel
+
+#define kStrHaveInterrupted "Emulisani kompjuter prekinut"
+
+#define kStrCancelledInterrupt "Prekid odbijen"
+
+#define kStrConfirmQuit "Da li ste sigurni da ;vzelite iza;eci ^p? Trebali biste ugasiti emulisani ra;vcunar pre izlaska da biste preventisali korupciju montiranih diskovnih fajlova. Otkucajte slovo:"
+#define kStrQuitDo "iza;ddi"
+#define kStrQuitNo kStrCmdCancel
+
+#define kStrCancelledQuit "Izlazak odbijen"
+
+#define kStrModeConfirmReset "Kontrolni mod : Potvrdi resetovanje"
+#define kStrModeConfirmInterrupt "Kontrolni mod : Potvrdi prekid"
+#define kStrModeConfirmQuit "Kontrolni mod : Potvrdi izlazak"
+#define kStrModeSpeedControl "Kontrolni mod : Kontrola brzine"
+#define kStrModeControlBase "Kontrolni mod (Otkucaj ;]H;} za pomo;ec)"
+#define kStrModeControlHelp "Kontrolni mod"
+/* Same suggestion above for "Kontrolni mod". This may be used in other languages. */
+#define kStrModeMessage "Poruka (Otkucaj ;]C;} da nastavi;vs)"
+
+#define kStrMenuFile "Fajl"
+#define kStrMenuSpecial "Special"
+#define kStrMenuHelp "Pomo;ec"
+
+#define kStrMenuItemAbout "O ^p"
+#define kStrMenuItemOpen "Otvori diskovnu datoteku"
+#define kStrMenuItemQuit "Iza;ddi"
+#define kStrMenuItemMore "Vi;vse komandi"
+
+#define kStrAppMenuItemHide "Sakrij ^p"
+#define kStrAppMenuItemHideOthers "Sakrij ostale"
+#define kStrAppMenuItemShowAll "Prika;vzi sve"
+#define kStrAppMenuItemQuit "Iza;ddi ^p"
+
+#define kStrCmdCopyOptions "Kopiraj variation options"
+#define kStrHaveCopiedOptions "Variation options kopirane"
--- /dev/null
+++ b/src/SYSDEPNS.h
@@ -1,0 +1,152 @@
+/*
+	SYSDEPNS.h
+
+	Copyright (C) 2006 Bernd Schmidt, Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	SYStem DEPeNdencies.
+*/
+
+#ifdef SYSDEPNS_H
+#error "header already included"
+#else
+#define SYSDEPNS_H
+#endif
+
+#include "CNFGGLOB.h"
+
+
+typedef ui3b *ui3p;
+typedef ui4b *ui4p;
+typedef ui5b *ui5p;
+
+/*
+	Largest efficiently supported
+	representation types. uimr should be
+	large enough to hold number of elements
+	of any array we will deal with.
+*/
+typedef ui5r uimr;
+typedef si5r simr;
+
+#define blnr ui3r
+#define trueblnr 1
+#define falseblnr 0
+
+#define nullpr ((void *) 0)
+
+#define anyp ui3p
+
+/* pascal string, single byte characters */
+#define ps3p ui3p
+
+#ifndef MayInline
+#define MayInline
+#endif
+
+#ifndef MayNotInline
+#define MayNotInline
+#endif
+
+#ifndef my_reg_call
+#define my_reg_call
+#endif
+
+#ifndef my_osglu_call
+#define my_osglu_call
+#endif
+
+#define LOCALVAR static
+#ifdef AllFiles
+#define GLOBALVAR LOCALVAR
+#define EXPORTVAR(t, v)
+#else
+#define GLOBALVAR
+#define EXPORTVAR(t, v) extern t v;
+#endif
+
+#define LOCALFUNC static MayNotInline
+#define FORWARDFUNC LOCALFUNC
+#ifdef AllFiles
+#define GLOBALFUNC LOCALFUNC
+#define EXPORTFUNC LOCALFUNC
+#else
+#define GLOBALFUNC MayNotInline
+#define EXPORTFUNC extern
+#endif
+#define IMPORTFUNC EXPORTFUNC
+#define TYPEDEFFUNC typedef
+
+#define LOCALPROC LOCALFUNC void
+#define GLOBALPROC GLOBALFUNC void
+#define EXPORTPROC EXPORTFUNC void
+#define IMPORTPROC IMPORTFUNC void
+#define FORWARDPROC FORWARDFUNC void
+#define TYPEDEFPROC TYPEDEFFUNC void
+
+#define LOCALINLINEFUNC static MayInline
+#define LOCALINLINEPROC LOCALINLINEFUNC void
+
+#define LOCALFUNCUSEDONCE LOCALINLINEFUNC
+#define LOCALPROCUSEDONCE LOCALINLINEPROC
+
+#define GLOBALOSGLUFUNC GLOBALFUNC my_osglu_call
+#define EXPORTOSGLUFUNC EXPORTFUNC my_osglu_call
+#define GLOBALOSGLUPROC GLOBALFUNC my_osglu_call void
+#define EXPORTOSGLUPROC EXPORTFUNC my_osglu_call void
+	/*
+		For functions in operating system glue that
+		are called by rest of program.
+	*/
+
+/*
+	best type for ui4r that is probably in register
+	(when compiler messes up otherwise)
+*/
+
+#ifndef BigEndianUnaligned
+#define BigEndianUnaligned 0
+#endif
+
+#ifndef LittleEndianUnaligned
+#define LittleEndianUnaligned 0
+#endif
+
+#ifndef ui3rr
+#define ui3rr ui3r
+#endif
+
+#ifndef ui4rr
+#define ui4rr ui4r
+#endif
+
+#ifndef si5rr
+#define si5rr si5r
+#endif
+
+#ifndef my_align_8
+#define my_align_8
+#endif
+
+#ifndef my_cond_rare
+#define my_cond_rare(x) (x)
+#endif
+
+#ifndef Have_ASR
+#define Have_ASR 0
+#endif
+
+#ifndef HaveMySwapUi5r
+#define HaveMySwapUi5r 0
+#endif
--- /dev/null
+++ b/src/VIA2EMDV.c
@@ -1,0 +1,1224 @@
+/*
+	VIA2EMDV.c
+
+	Copyright (C) 2008 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Versatile Interface Adapter EMulated DEVice
+
+	Emulates the VIA found in the Mac Plus.
+
+	This code adapted from vMac by Philip Cummins.
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+
+#include "MYOSGLUE.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+#endif
+
+#include "VIA2EMDV.h"
+
+/*
+	ReportAbnormalID unused 0x0510 - 0x05FF
+*/
+
+#ifdef VIA2_iA0_ChangeNtfy
+IMPORTPROC VIA2_iA0_ChangeNtfy(void);
+#endif
+
+#ifdef VIA2_iA1_ChangeNtfy
+IMPORTPROC VIA2_iA1_ChangeNtfy(void);
+#endif
+
+#ifdef VIA2_iA2_ChangeNtfy
+IMPORTPROC VIA2_iA2_ChangeNtfy(void);
+#endif
+
+#ifdef VIA2_iA3_ChangeNtfy
+IMPORTPROC VIA2_iA3_ChangeNtfy(void);
+#endif
+
+#ifdef VIA2_iA4_ChangeNtfy
+IMPORTPROC VIA2_iA4_ChangeNtfy(void);
+#endif
+
+#ifdef VIA2_iA5_ChangeNtfy
+IMPORTPROC VIA2_iA5_ChangeNtfy(void);
+#endif
+
+#ifdef VIA2_iA6_ChangeNtfy
+IMPORTPROC VIA2_iA6_ChangeNtfy(void);
+#endif
+
+#ifdef VIA2_iA7_ChangeNtfy
+IMPORTPROC VIA2_iA7_ChangeNtfy(void);
+#endif
+
+#ifdef VIA2_iB0_ChangeNtfy
+IMPORTPROC VIA2_iB0_ChangeNtfy(void);
+#endif
+
+#ifdef VIA2_iB1_ChangeNtfy
+IMPORTPROC VIA2_iB1_ChangeNtfy(void);
+#endif
+
+#ifdef VIA2_iB2_ChangeNtfy
+IMPORTPROC VIA2_iB2_ChangeNtfy(void);
+#endif
+
+#ifdef VIA2_iB3_ChangeNtfy
+IMPORTPROC VIA2_iB3_ChangeNtfy(void);
+#endif
+
+#ifdef VIA2_iB4_ChangeNtfy
+IMPORTPROC VIA2_iB4_ChangeNtfy(void);
+#endif
+
+#ifdef VIA2_iB5_ChangeNtfy
+IMPORTPROC VIA2_iB5_ChangeNtfy(void);
+#endif
+
+#ifdef VIA2_iB6_ChangeNtfy
+IMPORTPROC VIA2_iB6_ChangeNtfy(void);
+#endif
+
+#ifdef VIA2_iB7_ChangeNtfy
+IMPORTPROC VIA2_iB7_ChangeNtfy(void);
+#endif
+
+#ifdef VIA2_iCB2_ChangeNtfy
+IMPORTPROC VIA2_iCB2_ChangeNtfy(void);
+#endif
+
+#define Ui3rPowOf2(p) (1 << (p))
+#define Ui3rTestBit(i, p) (((i) & Ui3rPowOf2(p)) != 0)
+
+#define VIA2_ORA_CanInOrOut (VIA2_ORA_CanIn | VIA2_ORA_CanOut)
+
+#if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 7)
+#ifdef VIA2_iA7
+#error "VIA2_iA7 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 6)
+#ifdef VIA2_iA6
+#error "VIA2_iA6 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 5)
+#ifdef VIA2_iA5
+#error "VIA2_iA5 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 4)
+#ifdef VIA2_iA4
+#error "VIA2_iA4 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 3)
+#ifdef VIA2_iA3
+#error "VIA2_iA3 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 2)
+#ifdef VIA2_iA2
+#error "VIA2_iA2 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 1)
+#ifdef VIA2_iA1
+#error "VIA2_iA1 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA2_ORA_CanInOrOut, 0)
+#ifdef VIA2_iA0
+#error "VIA2_iA0 defined but not used"
+#endif
+#endif
+
+#define VIA2_ORB_CanInOrOut (VIA2_ORB_CanIn | VIA2_ORB_CanOut)
+
+#if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 7)
+#ifdef VIA2_iB7
+#error "VIA2_iB7 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 6)
+#ifdef VIA2_iB6
+#error "VIA2_iB6 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 5)
+#ifdef VIA2_iB5
+#error "VIA2_iB5 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 4)
+#ifdef VIA2_iB4
+#error "VIA2_iB4 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 3)
+#ifdef VIA2_iB3
+#error "VIA2_iB3 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 2)
+#ifdef VIA2_iB2
+#error "VIA2_iB2 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 1)
+#ifdef VIA2_iB1
+#error "VIA2_iB1 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA2_ORB_CanInOrOut, 0)
+#ifdef VIA2_iB0
+#error "VIA2_iB0 defined but not used"
+#endif
+#endif
+
+typedef struct {
+	ui5b T1C_F;  /* Timer 1 Counter Fixed Point */
+	ui5b T2C_F;  /* Timer 2 Counter Fixed Point */
+	ui3b ORB;    /* Buffer B */
+	/* ui3b ORA_H;     Buffer A with Handshake */
+	ui3b DDR_B;  /* Data Direction Register B */
+	ui3b DDR_A;  /* Data Direction Register A */
+	ui3b T1L_L;  /* Timer 1 Latch Low */
+	ui3b T1L_H;  /* Timer 1 Latch High */
+	ui3b T2L_L;  /* Timer 2 Latch Low */
+	ui3b SR;     /* Shift Register */
+	ui3b ACR;    /* Auxiliary Control Register */
+	ui3b PCR;    /* Peripheral Control Register */
+	ui3b IFR;    /* Interrupt Flag Register */
+	ui3b IER;    /* Interrupt Enable Register */
+	ui3b ORA;    /* Buffer A */
+} VIA2_Ty;
+
+LOCALVAR VIA2_Ty VIA2_D;
+
+#define kIntCA2 0 /* One_Second */
+#define kIntCA1 1 /* Vertical_Blanking */
+#define kIntSR 2 /* Keyboard_Data_Ready */
+#define kIntCB2 3 /* Keyboard_Data */
+#define kIntCB1 4 /* Keyboard_Clock */
+#define kIntT2 5 /* Timer_2 */
+#define kIntT1 6 /* Timer_1 */
+
+#define VIA2_dolog (dbglog_HAVE && 0)
+
+/* VIA2_Get_ORA : VIA Get Port A Data */
+/*
+	This function queries VIA Port A interfaced hardware
+	about their status
+*/
+
+LOCALFUNC ui3b VIA2_Get_ORA(ui3b Selection)
+{
+	ui3b Value = (~ VIA2_ORA_CanIn) & Selection & VIA2_ORA_FloatVal;
+
+#if Ui3rTestBit(VIA2_ORA_CanIn, 7)
+	if (Ui3rTestBit(Selection, 7)) {
+		Value |= (VIA2_iA7 << 7);
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORA_CanIn, 6)
+	if (Ui3rTestBit(Selection, 6)) {
+		Value |= (VIA2_iA6 << 6);
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORA_CanIn, 5)
+	if (Ui3rTestBit(Selection, 5)) {
+		Value |= (VIA2_iA5 << 5);
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORA_CanIn, 4)
+	if (Ui3rTestBit(Selection, 4)) {
+		Value |= (VIA2_iA4 << 4);
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORA_CanIn, 3)
+	if (Ui3rTestBit(Selection, 3)) {
+		Value |= (VIA2_iA3 << 3);
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORA_CanIn, 2)
+	if (Ui3rTestBit(Selection, 2)) {
+		Value |= (VIA2_iA2 << 2);
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORA_CanIn, 1)
+	if (Ui3rTestBit(Selection, 1)) {
+		Value |= (VIA2_iA1 << 1);
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORA_CanIn, 0)
+	if (Ui3rTestBit(Selection, 0)) {
+		Value |= (VIA2_iA0 << 0);
+	}
+#endif
+
+	return Value;
+}
+
+/* VIA2_Get_ORB : VIA Get Port B Data */
+/*
+	This function queries VIA Port B interfaced hardware
+	about their status
+*/
+
+LOCALFUNC ui3b VIA2_Get_ORB(ui3b Selection)
+{
+	ui3b Value = (~ VIA2_ORB_CanIn) & Selection & VIA2_ORB_FloatVal;
+
+#if Ui3rTestBit(VIA2_ORB_CanIn, 7)
+	if (Ui3rTestBit(Selection, 7)) {
+		Value |= (VIA2_iB7 << 7);
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORB_CanIn, 6)
+	if (Ui3rTestBit(Selection, 6)) {
+		Value |= (VIA2_iB6 << 6);
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORB_CanIn, 5)
+	if (Ui3rTestBit(Selection, 5)) {
+		Value |= (VIA2_iB5 << 5);
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORB_CanIn, 4)
+	if (Ui3rTestBit(Selection, 4)) {
+		Value |= (VIA2_iB4 << 4);
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORB_CanIn, 3)
+	if (Ui3rTestBit(Selection, 3)) {
+		Value |= (VIA2_iB3 << 3);
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORB_CanIn, 2)
+	if (Ui3rTestBit(Selection, 2)) {
+		Value |= (VIA2_iB2 << 2);
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORB_CanIn, 1)
+	if (Ui3rTestBit(Selection, 1)) {
+		Value |= (VIA2_iB1 << 1);
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORB_CanIn, 0)
+	if (Ui3rTestBit(Selection, 0)) {
+		Value |= (VIA2_iB0 << 0);
+	}
+#endif
+
+	return Value;
+}
+
+#define ViaORcheckBit(p, x) \
+	(Ui3rTestBit(Selection, p) && \
+	((v = (Data >> p) & 1) != x))
+
+LOCALPROC VIA2_Put_ORA(ui3b Selection, ui3b Data)
+{
+#if 0 != VIA2_ORA_CanOut
+	ui3b v;
+#endif
+
+#if Ui3rTestBit(VIA2_ORA_CanOut, 7)
+	if (ViaORcheckBit(7, VIA2_iA7)) {
+		VIA2_iA7 = v;
+#ifdef VIA2_iA7_ChangeNtfy
+		VIA2_iA7_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORA_CanOut, 6)
+	if (ViaORcheckBit(6, VIA2_iA6)) {
+		VIA2_iA6 = v;
+#ifdef VIA2_iA6_ChangeNtfy
+		VIA2_iA6_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORA_CanOut, 5)
+	if (ViaORcheckBit(5, VIA2_iA5)) {
+		VIA2_iA5 = v;
+#ifdef VIA2_iA5_ChangeNtfy
+		VIA2_iA5_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORA_CanOut, 4)
+	if (ViaORcheckBit(4, VIA2_iA4)) {
+		VIA2_iA4 = v;
+#ifdef VIA2_iA4_ChangeNtfy
+		VIA2_iA4_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORA_CanOut, 3)
+	if (ViaORcheckBit(3, VIA2_iA3)) {
+		VIA2_iA3 = v;
+#ifdef VIA2_iA3_ChangeNtfy
+		VIA2_iA3_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORA_CanOut, 2)
+	if (ViaORcheckBit(2, VIA2_iA2)) {
+		VIA2_iA2 = v;
+#ifdef VIA2_iA2_ChangeNtfy
+		VIA2_iA2_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORA_CanOut, 1)
+	if (ViaORcheckBit(1, VIA2_iA1)) {
+		VIA2_iA1 = v;
+#ifdef VIA2_iA1_ChangeNtfy
+		VIA2_iA1_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORA_CanOut, 0)
+	if (ViaORcheckBit(0, VIA2_iA0)) {
+		VIA2_iA0 = v;
+#ifdef VIA2_iA0_ChangeNtfy
+		VIA2_iA0_ChangeNtfy();
+#endif
+	}
+#endif
+}
+
+LOCALPROC VIA2_Put_ORB(ui3b Selection, ui3b Data)
+{
+#if 0 != VIA2_ORB_CanOut
+	ui3b v;
+#endif
+
+#if Ui3rTestBit(VIA2_ORB_CanOut, 7)
+	if (ViaORcheckBit(7, VIA2_iB7)) {
+		VIA2_iB7 = v;
+#ifdef VIA2_iB7_ChangeNtfy
+		VIA2_iB7_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORB_CanOut, 6)
+	if (ViaORcheckBit(6, VIA2_iB6)) {
+		VIA2_iB6 = v;
+#ifdef VIA2_iB6_ChangeNtfy
+		VIA2_iB6_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORB_CanOut, 5)
+	if (ViaORcheckBit(5, VIA2_iB5)) {
+		VIA2_iB5 = v;
+#ifdef VIA2_iB5_ChangeNtfy
+		VIA2_iB5_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORB_CanOut, 4)
+	if (ViaORcheckBit(4, VIA2_iB4)) {
+		VIA2_iB4 = v;
+#ifdef VIA2_iB4_ChangeNtfy
+		VIA2_iB4_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORB_CanOut, 3)
+	if (ViaORcheckBit(3, VIA2_iB3)) {
+		VIA2_iB3 = v;
+#ifdef VIA2_iB3_ChangeNtfy
+		VIA2_iB3_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORB_CanOut, 2)
+	if (ViaORcheckBit(2, VIA2_iB2)) {
+		VIA2_iB2 = v;
+#ifdef VIA2_iB2_ChangeNtfy
+		VIA2_iB2_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORB_CanOut, 1)
+	if (ViaORcheckBit(1, VIA2_iB1)) {
+		VIA2_iB1 = v;
+#ifdef VIA2_iB1_ChangeNtfy
+		VIA2_iB1_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA2_ORB_CanOut, 0)
+	if (ViaORcheckBit(0, VIA2_iB0)) {
+		VIA2_iB0 = v;
+#ifdef VIA2_iB0_ChangeNtfy
+		VIA2_iB0_ChangeNtfy();
+#endif
+	}
+#endif
+}
+
+LOCALPROC VIA2_SetDDR_A(ui3b Data)
+{
+	ui3b floatbits = VIA2_D.DDR_A & ~ Data;
+	ui3b unfloatbits = Data & ~ VIA2_D.DDR_A;
+
+	if (floatbits != 0) {
+		VIA2_Put_ORA(floatbits, VIA2_ORA_FloatVal);
+	}
+	VIA2_D.DDR_A = Data;
+	if (unfloatbits != 0) {
+		VIA2_Put_ORA(unfloatbits, VIA2_D.ORA);
+	}
+	if ((Data & ~ VIA2_ORA_CanOut) != 0) {
+		ReportAbnormalID(0x0501,
+			"Set VIA2_D.DDR_A unexpected direction");
+	}
+}
+
+LOCALPROC VIA2_SetDDR_B(ui3b Data)
+{
+	ui3b floatbits = VIA2_D.DDR_B & ~ Data;
+	ui3b unfloatbits = Data & ~ VIA2_D.DDR_B;
+
+	if (floatbits != 0) {
+		VIA2_Put_ORB(floatbits, VIA2_ORB_FloatVal);
+	}
+	VIA2_D.DDR_B = Data;
+	if (unfloatbits != 0) {
+		VIA2_Put_ORB(unfloatbits, VIA2_D.ORB);
+	}
+	if ((Data & ~ VIA2_ORB_CanOut) != 0) {
+		ReportAbnormalID(0x0502,
+			"Set VIA2_D.DDR_B unexpected direction");
+	}
+}
+
+
+LOCALPROC VIA2_CheckInterruptFlag(void)
+{
+	ui3b NewInterruptRequest =
+		((VIA2_D.IFR & VIA2_D.IER) != 0) ? 1 : 0;
+
+	if (NewInterruptRequest != VIA2_InterruptRequest) {
+		VIA2_InterruptRequest = NewInterruptRequest;
+#ifdef VIA2_interruptChngNtfy
+		VIA2_interruptChngNtfy();
+#endif
+	}
+}
+
+
+LOCALVAR ui3b VIA2_T1_Active = 0;
+LOCALVAR ui3b VIA2_T2_Active = 0;
+
+LOCALVAR blnr VIA2_T1IntReady = falseblnr;
+
+LOCALPROC VIA2_Clear(void)
+{
+	VIA2_D.ORA   = 0; VIA2_D.DDR_A = 0;
+	VIA2_D.ORB   = 0; VIA2_D.DDR_B = 0;
+	VIA2_D.T1L_L = VIA2_D.T1L_H = 0x00;
+	VIA2_D.T2L_L = 0x00;
+	VIA2_D.T1C_F = 0;
+	VIA2_D.T2C_F = 0;
+	VIA2_D.SR = VIA2_D.ACR = 0x00;
+	VIA2_D.PCR   = VIA2_D.IFR   = VIA2_D.IER   = 0x00;
+	VIA2_T1_Active = VIA2_T2_Active = 0x00;
+	VIA2_T1IntReady = falseblnr;
+}
+
+GLOBALPROC VIA2_Zap(void)
+{
+	VIA2_Clear();
+	VIA2_InterruptRequest = 0;
+}
+
+GLOBALPROC VIA2_Reset(void)
+{
+	VIA2_SetDDR_A(0);
+	VIA2_SetDDR_B(0);
+
+	VIA2_Clear();
+
+	VIA2_CheckInterruptFlag();
+}
+
+LOCALPROC VIA2_SetInterruptFlag(ui3b VIA_Int)
+{
+	VIA2_D.IFR |= ((ui3b)1 << VIA_Int);
+	VIA2_CheckInterruptFlag();
+}
+
+LOCALPROC VIA2_ClrInterruptFlag(ui3b VIA_Int)
+{
+	VIA2_D.IFR &= ~ ((ui3b)1 << VIA_Int);
+	VIA2_CheckInterruptFlag();
+}
+
+#ifdef _VIA_Debug
+#include <stdio.h>
+#endif
+
+GLOBALPROC VIA2_ShiftInData(ui3b v)
+{
+	/*
+		external hardware generates 8 pulses on CB1,
+		writes 8 bits to CB2
+	*/
+	ui3b ShiftMode = (VIA2_D.ACR & 0x1C) >> 2;
+
+	if (ShiftMode != 3) {
+#if ExtraAbnormalReports
+		if (ShiftMode == 0) {
+			/* happens on reset */
+		} else {
+			ReportAbnormalID(0x0503, "VIA Not ready to shift in");
+				/*
+					Observed (rarely) in Crystal Quest played
+					at 1x speed in "-t mc64".
+				*/
+		}
+#endif
+	} else {
+		VIA2_D.SR = v;
+		VIA2_SetInterruptFlag(kIntSR);
+		VIA2_SetInterruptFlag(kIntCB1);
+	}
+}
+
+GLOBALFUNC ui3b VIA2_ShiftOutData(void)
+{
+	/*
+		external hardware generates 8 pulses on CB1,
+		reads 8 bits from CB2
+	*/
+	if (((VIA2_D.ACR & 0x1C) >> 2) != 7) {
+		ReportAbnormalID(0x0504, "VIA Not ready to shift out");
+		return 0;
+	} else {
+		VIA2_SetInterruptFlag(kIntSR);
+		VIA2_SetInterruptFlag(kIntCB1);
+		VIA2_iCB2 = (VIA2_D.SR & 1);
+		return VIA2_D.SR;
+	}
+}
+
+#define CyclesPerViaTime (10 * kMyClockMult)
+#define CyclesScaledPerViaTime (kCycleScale * CyclesPerViaTime)
+
+LOCALVAR blnr VIA2_T1Running = trueblnr;
+LOCALVAR iCountt VIA2_T1LastTime = 0;
+
+GLOBALPROC VIA2_DoTimer1Check(void)
+{
+	if (VIA2_T1Running) {
+		iCountt NewTime = GetCuriCount();
+		iCountt deltaTime = (NewTime - VIA2_T1LastTime);
+		if (deltaTime != 0) {
+			ui5b Temp = VIA2_D.T1C_F; /* Get Timer 1 Counter */
+			ui5b deltaTemp =
+				(deltaTime / CyclesPerViaTime) << (16 - kLn2CycleScale);
+					/* may overflow */
+			ui5b NewTemp = Temp - deltaTemp;
+			if ((deltaTime > (0x00010000UL * CyclesScaledPerViaTime))
+				|| ((Temp <= deltaTemp) && (Temp != 0)))
+			{
+				if ((VIA2_D.ACR & 0x40) != 0) { /* Free Running? */
+					/* Reload Counter from Latches */
+					ui4b v = (VIA2_D.T1L_H << 8) + VIA2_D.T1L_L;
+					ui4b ntrans = 1 + ((v == 0) ? 0 :
+						(((deltaTemp - Temp) / v) >> 16));
+					NewTemp += (((ui5b)v * ntrans) << 16);
+#if Ui3rTestBit(VIA2_ORB_CanOut, 7)
+					if ((VIA2_D.ACR & 0x80) != 0) { /* invert ? */
+						if ((ntrans & 1) != 0) {
+							VIA2_iB7 ^= 1;
+#ifdef VIA2_iB7_ChangeNtfy
+							VIA2_iB7_ChangeNtfy();
+#endif
+						}
+					}
+#endif
+					VIA2_SetInterruptFlag(kIntT1);
+#if VIA2_dolog && 1
+					dbglog_WriteNote("VIA2 Timer 1 Interrupt");
+#endif
+				} else {
+					if (VIA2_T1_Active == 1) {
+						VIA2_T1_Active = 0;
+						VIA2_SetInterruptFlag(kIntT1);
+#if VIA2_dolog && 1
+						dbglog_WriteNote("VIA2 Timer 1 Interrupt");
+#endif
+					}
+				}
+			}
+
+			VIA2_D.T1C_F = NewTemp;
+			VIA2_T1LastTime = NewTime;
+		}
+
+		VIA2_T1IntReady = falseblnr;
+		if ((VIA2_D.IFR & (1 << kIntT1)) == 0) {
+			if (((VIA2_D.ACR & 0x40) != 0) || (VIA2_T1_Active == 1)) {
+				ui5b NewTemp = VIA2_D.T1C_F; /* Get Timer 1 Counter */
+				ui5b NewTimer;
+#ifdef _VIA_Debug
+				fprintf(stderr, "posting Timer1Check, %d, %d\n",
+					Temp, GetCuriCount());
+#endif
+				if (NewTemp == 0) {
+					NewTimer = (0x00010000UL * CyclesScaledPerViaTime);
+				} else {
+					NewTimer =
+						(1 + (NewTemp >> (16 - kLn2CycleScale)))
+							* CyclesPerViaTime;
+				}
+				ICT_add(kICT_VIA2_Timer1Check, NewTimer);
+				VIA2_T1IntReady = trueblnr;
+			}
+		}
+	}
+}
+
+LOCALPROC CheckT1IntReady(void)
+{
+	if (VIA2_T1Running) {
+		blnr NewT1IntReady = falseblnr;
+
+		if ((VIA2_D.IFR & (1 << kIntT1)) == 0) {
+			if (((VIA2_D.ACR & 0x40) != 0) || (VIA2_T1_Active == 1)) {
+				NewT1IntReady = trueblnr;
+			}
+		}
+
+		if (VIA2_T1IntReady != NewT1IntReady) {
+			VIA2_T1IntReady = NewT1IntReady;
+			if (NewT1IntReady) {
+				VIA2_DoTimer1Check();
+			}
+		}
+	}
+}
+
+GLOBALFUNC ui4b VIA2_GetT1InvertTime(void)
+{
+	ui4b v;
+
+	if ((VIA2_D.ACR & 0xC0) == 0xC0) {
+		v = (VIA2_D.T1L_H << 8) + VIA2_D.T1L_L;
+	} else {
+		v = 0;
+	}
+	return v;
+}
+
+LOCALVAR blnr VIA2_T2Running = trueblnr;
+LOCALVAR blnr VIA2_T2C_ShortTime = falseblnr;
+LOCALVAR iCountt VIA2_T2LastTime = 0;
+
+GLOBALPROC VIA2_DoTimer2Check(void)
+{
+	if (VIA2_T2Running) {
+		iCountt NewTime = GetCuriCount();
+		ui5b Temp = VIA2_D.T2C_F; /* Get Timer 2 Counter */
+		iCountt deltaTime = (NewTime - VIA2_T2LastTime);
+		ui5b deltaTemp = (deltaTime / CyclesPerViaTime)
+			<< (16 - kLn2CycleScale); /* may overflow */
+		ui5b NewTemp = Temp - deltaTemp;
+		if (VIA2_T2_Active == 1) {
+			if ((deltaTime > (0x00010000UL * CyclesScaledPerViaTime))
+				|| ((Temp <= deltaTemp) && (Temp != 0)))
+			{
+				VIA2_T2C_ShortTime = falseblnr;
+				VIA2_T2_Active = 0;
+				VIA2_SetInterruptFlag(kIntT2);
+#if VIA2_dolog && 1
+				dbglog_WriteNote("VIA2 Timer 2 Interrupt");
+#endif
+			} else {
+				ui5b NewTimer;
+#ifdef _VIA_Debug
+				fprintf(stderr, "posting Timer2Check, %d, %d\n",
+					Temp, GetCuriCount());
+#endif
+				if (NewTemp == 0) {
+					NewTimer = (0x00010000UL * CyclesScaledPerViaTime);
+				} else {
+					NewTimer = (1 + (NewTemp >> (16 - kLn2CycleScale)))
+						* CyclesPerViaTime;
+				}
+				ICT_add(kICT_VIA2_Timer2Check, NewTimer);
+			}
+		}
+		VIA2_D.T2C_F = NewTemp;
+		VIA2_T2LastTime = NewTime;
+	}
+}
+
+#define kORB    0x00
+#define kORA_H  0x01
+#define kDDR_B  0x02
+#define kDDR_A  0x03
+#define kT1C_L  0x04
+#define kT1C_H  0x05
+#define kT1L_L  0x06
+#define kT1L_H  0x07
+#define kT2_L   0x08
+#define kT2_H   0x09
+#define kSR     0x0A
+#define kACR    0x0B
+#define kPCR    0x0C
+#define kIFR    0x0D
+#define kIER    0x0E
+#define kORA    0x0F
+
+GLOBALFUNC ui5b VIA2_Access(ui5b Data, blnr WriteMem, CPTR addr)
+{
+	switch (addr) {
+		case kORB   :
+#if VIA2_CB2modesAllowed != 0x01
+			if ((VIA2_D.PCR & 0xE0) == 0)
+#endif
+			{
+				VIA2_ClrInterruptFlag(kIntCB2);
+			}
+			VIA2_ClrInterruptFlag(kIntCB1);
+			if (WriteMem) {
+				VIA2_D.ORB = Data;
+				VIA2_Put_ORB(VIA2_D.DDR_B, VIA2_D.ORB);
+			} else {
+				Data = (VIA2_D.ORB & VIA2_D.DDR_B)
+					| VIA2_Get_ORB(~ VIA2_D.DDR_B);
+			}
+#if VIA2_dolog && 1
+			dbglog_Access("VIA2_Access kORB", Data, WriteMem);
+#endif
+			break;
+		case kDDR_B :
+			if (WriteMem) {
+				VIA2_SetDDR_B(Data);
+			} else {
+				Data = VIA2_D.DDR_B;
+			}
+#if VIA2_dolog && 1
+			dbglog_Access("VIA2_Access kDDR_B", Data, WriteMem);
+#endif
+			break;
+		case kDDR_A :
+			if (WriteMem) {
+				VIA2_SetDDR_A(Data);
+			} else {
+				Data = VIA2_D.DDR_A;
+			}
+#if VIA2_dolog && 1
+			dbglog_Access("VIA2_Access kDDR_A", Data, WriteMem);
+#endif
+			break;
+		case kT1C_L :
+			if (WriteMem) {
+				VIA2_D.T1L_L = Data;
+			} else {
+				VIA2_ClrInterruptFlag(kIntT1);
+				VIA2_DoTimer1Check();
+				Data = (VIA2_D.T1C_F & 0x00FF0000) >> 16;
+			}
+#if VIA2_dolog && 1
+			dbglog_Access("VIA2_Access kT1C_L", Data, WriteMem);
+#endif
+			break;
+		case kT1C_H :
+			if (WriteMem) {
+				VIA2_D.T1L_H = Data;
+				VIA2_ClrInterruptFlag(kIntT1);
+				VIA2_D.T1C_F = (Data << 24) + (VIA2_D.T1L_L << 16);
+				if ((VIA2_D.ACR & 0x40) == 0) {
+					VIA2_T1_Active = 1;
+				}
+				VIA2_T1LastTime = GetCuriCount();
+				VIA2_DoTimer1Check();
+			} else {
+				VIA2_DoTimer1Check();
+				Data = (VIA2_D.T1C_F & 0xFF000000) >> 24;
+			}
+#if VIA2_dolog && 1
+			dbglog_Access("VIA2_Access kT1C_H", Data, WriteMem);
+#endif
+			break;
+		case kT1L_L :
+			if (WriteMem) {
+				VIA2_D.T1L_L = Data;
+			} else {
+				Data = VIA2_D.T1L_L;
+			}
+#if VIA2_dolog && 1
+			dbglog_Access("VIA2_Access kT1L_L", Data, WriteMem);
+#endif
+			break;
+		case kT1L_H :
+			if (WriteMem) {
+				VIA2_D.T1L_H = Data;
+			} else {
+				Data = VIA2_D.T1L_H;
+			}
+#if VIA2_dolog && 1
+			dbglog_Access("VIA2_Access kT1L_H", Data, WriteMem);
+#endif
+			break;
+		case kT2_L  :
+			if (WriteMem) {
+				VIA2_D.T2L_L = Data;
+			} else {
+				VIA2_ClrInterruptFlag(kIntT2);
+				VIA2_DoTimer2Check();
+				Data = (VIA2_D.T2C_F & 0x00FF0000) >> 16;
+			}
+#if VIA2_dolog && 1
+			dbglog_Access("VIA2_Access kT2_L", Data, WriteMem);
+#endif
+			break;
+		case kT2_H  :
+			if (WriteMem) {
+				VIA2_D.T2C_F = (Data << 24) + (VIA2_D.T2L_L << 16);
+				VIA2_ClrInterruptFlag(kIntT2);
+				VIA2_T2_Active = 1;
+
+				if ((VIA2_D.T2C_F < (128UL << 16))
+					&& (VIA2_D.T2C_F != 0))
+				{
+					VIA2_T2C_ShortTime = trueblnr;
+					VIA2_T2Running = trueblnr;
+					/*
+						Running too many instructions during
+						a short timer interval can crash when
+						playing sounds in System 7. So
+						in this case don't let timer pause.
+					*/
+				}
+				VIA2_T2LastTime = GetCuriCount();
+				VIA2_DoTimer2Check();
+			} else {
+				VIA2_DoTimer2Check();
+				Data = (VIA2_D.T2C_F & 0xFF000000) >> 24;
+			}
+#if VIA2_dolog && 1
+			dbglog_Access("VIA2_Access kT2_H", Data, WriteMem);
+#endif
+			break;
+		case kSR:
+#ifdef _VIA_Debug
+			fprintf(stderr, "VIA2_D.SR: %d, %d, %d\n",
+				WriteMem, ((VIA2_D.ACR & 0x1C) >> 2), Data);
+#endif
+			if (WriteMem) {
+				VIA2_D.SR = Data;
+			}
+			VIA2_ClrInterruptFlag(kIntSR);
+			switch ((VIA2_D.ACR & 0x1C) >> 2) {
+				case 3 : /* Shifting In */
+					break;
+				case 6 : /* shift out under o2 clock */
+					if ((! WriteMem) || (VIA2_D.SR != 0)) {
+						ReportAbnormalID(0x0505,
+							"VIA shift mode 6, non zero");
+					} else {
+#ifdef _VIA_Debug
+						fprintf(stderr, "posting Foo2Task\n");
+#endif
+						if (VIA2_iCB2 != 0) {
+							VIA2_iCB2 = 0;
+#ifdef VIA2_iCB2_ChangeNtfy
+							VIA2_iCB2_ChangeNtfy();
+#endif
+						}
+					}
+#if 0 /* possibly should do this. seems not to affect anything. */
+					VIA2_SetInterruptFlag(kIntSR); /* don't wait */
+#endif
+					break;
+				case 7 : /* Shifting Out */
+					break;
+			}
+			if (! WriteMem) {
+				Data = VIA2_D.SR;
+			}
+#if VIA2_dolog && 1
+			dbglog_Access("VIA2_Access kSR", Data, WriteMem);
+#endif
+			break;
+		case kACR:
+			if (WriteMem) {
+#if 1
+				if ((VIA2_D.ACR & 0x10) != ((ui3b)Data & 0x10)) {
+					/* shift direction has changed */
+					if ((Data & 0x10) == 0) {
+						/*
+							no longer an output,
+							set data to float value
+						*/
+						if (VIA2_iCB2 == 0) {
+							VIA2_iCB2 = 1;
+#ifdef VIA2_iCB2_ChangeNtfy
+							VIA2_iCB2_ChangeNtfy();
+#endif
+						}
+					}
+				}
+#endif
+				VIA2_D.ACR = Data;
+				if ((VIA2_D.ACR & 0x20) != 0) {
+					/* Not pulse counting? */
+					ReportAbnormalID(0x0506,
+						"Set VIA2_D.ACR T2 Timer pulse counting");
+				}
+				switch ((VIA2_D.ACR & 0xC0) >> 6) {
+					/* case 1: happens in early System 6 */
+					case 2:
+						ReportAbnormalID(0x0507,
+							"Set VIA2_D.ACR T1 Timer mode 2");
+						break;
+				}
+				CheckT1IntReady();
+				switch ((VIA2_D.ACR & 0x1C) >> 2) {
+					case 0: /* this isn't sufficient */
+						VIA2_ClrInterruptFlag(kIntSR);
+						break;
+					case 1:
+					case 2:
+					case 4:
+					case 5:
+						ReportAbnormalID(0x0508,
+							"Set VIA2_D.ACR shift mode 1,2,4,5");
+						break;
+					default:
+						break;
+				}
+				if ((VIA2_D.ACR & 0x03) != 0) {
+					ReportAbnormalID(0x0509,
+						"Set VIA2_D.ACR T2 Timer latching enabled");
+				}
+			} else {
+				Data = VIA2_D.ACR;
+			}
+#if VIA2_dolog && 1
+			dbglog_Access("VIA2_Access kACR", Data, WriteMem);
+#endif
+			break;
+		case kPCR:
+			if (WriteMem) {
+				VIA2_D.PCR = Data;
+#define Ui3rSetContains(s, i) (((s) & (1 << (i))) != 0)
+				if (! Ui3rSetContains(VIA2_CB2modesAllowed,
+					(VIA2_D.PCR >> 5) & 0x07))
+				{
+					ReportAbnormalID(0x050A,
+						"Set VIA2_D.PCR CB2 Control mode?");
+				}
+				if ((VIA2_D.PCR & 0x10) != 0) {
+					ReportAbnormalID(0x050B,
+						"Set VIA2_D.PCR CB1 INTERRUPT CONTROL?");
+				}
+				if (! Ui3rSetContains(VIA2_CA2modesAllowed,
+					(VIA2_D.PCR >> 1) & 0x07))
+				{
+					ReportAbnormalID(0x050C,
+						"Set VIA2_D.PCR CA2 INTERRUPT CONTROL?");
+				}
+				if ((VIA2_D.PCR & 0x01) != 0) {
+					ReportAbnormalID(0x050D,
+						"Set VIA2_D.PCR CA1 INTERRUPT CONTROL?");
+				}
+			} else {
+				Data = VIA2_D.PCR;
+			}
+#if VIA2_dolog && 1
+			dbglog_Access("VIA2_Access kPCR", Data, WriteMem);
+#endif
+			break;
+		case kIFR:
+			if (WriteMem) {
+				VIA2_D.IFR = VIA2_D.IFR & ((~ Data) & 0x7F);
+					/* Clear Flag Bits */
+				VIA2_CheckInterruptFlag();
+				CheckT1IntReady();
+			} else {
+				Data = VIA2_D.IFR;
+				if ((VIA2_D.IFR & VIA2_D.IER) != 0) {
+					Data |= 0x80;
+				}
+			}
+#if VIA2_dolog && 1
+			dbglog_Access("VIA2_Access kIFR", Data, WriteMem);
+#endif
+			break;
+		case kIER   :
+			if (WriteMem) {
+				if ((Data & 0x80) == 0) {
+					VIA2_D.IER = VIA2_D.IER & ((~ Data) & 0x7F);
+						/* Clear Enable Bits */
+#if 0 != VIA2_IER_Never0
+					/*
+						of course, will be 0 initially,
+						this just checks not cleared later.
+					*/
+					if ((Data & VIA2_IER_Never0) != 0) {
+						ReportAbnormalID(0x050E, "IER Never0 clr");
+					}
+#endif
+				} else {
+					VIA2_D.IER = VIA2_D.IER | (Data & 0x7F);
+						/* Set Enable Bits */
+#if 0 != VIA2_IER_Never1
+					if ((VIA2_D.IER & VIA2_IER_Never1) != 0) {
+						ReportAbnormalID(0x050F, "IER Never1 set");
+					}
+#endif
+				}
+				VIA2_CheckInterruptFlag();
+			} else {
+				Data = VIA2_D.IER | 0x80;
+			}
+#if VIA2_dolog && 1
+			dbglog_Access("VIA2_Access kIER", Data, WriteMem);
+#endif
+			break;
+		case kORA   :
+		case kORA_H :
+			if ((VIA2_D.PCR & 0xE) == 0) {
+				VIA2_ClrInterruptFlag(kIntCA2);
+			}
+			VIA2_ClrInterruptFlag(kIntCA1);
+			if (WriteMem) {
+				VIA2_D.ORA = Data;
+				VIA2_Put_ORA(VIA2_D.DDR_A, VIA2_D.ORA);
+			} else {
+				Data = (VIA2_D.ORA & VIA2_D.DDR_A)
+					| VIA2_Get_ORA(~ VIA2_D.DDR_A);
+			}
+#if VIA2_dolog && 1
+			dbglog_Access("VIA2_Access kORA", Data, WriteMem);
+#endif
+			break;
+	}
+	return Data;
+}
+
+GLOBALPROC VIA2_ExtraTimeBegin(void)
+{
+	if (VIA2_T1Running) {
+		VIA2_DoTimer1Check(); /* run up to this moment */
+		VIA2_T1Running = falseblnr;
+	}
+	if (VIA2_T2Running & (! VIA2_T2C_ShortTime)) {
+		VIA2_DoTimer2Check(); /* run up to this moment */
+		VIA2_T2Running = falseblnr;
+	}
+}
+
+GLOBALPROC VIA2_ExtraTimeEnd(void)
+{
+	if (! VIA2_T1Running) {
+		VIA2_T1Running = trueblnr;
+		VIA2_T1LastTime = GetCuriCount();
+		VIA2_DoTimer1Check();
+	}
+	if (! VIA2_T2Running) {
+		VIA2_T2Running = trueblnr;
+		VIA2_T2LastTime = GetCuriCount();
+		VIA2_DoTimer2Check();
+	}
+}
+
+/* VIA Interrupt Interface */
+
+#ifdef VIA2_iCA1_PulseNtfy
+GLOBALPROC VIA2_iCA1_PulseNtfy(void)
+{
+	VIA2_SetInterruptFlag(kIntCA1);
+}
+#endif
+
+#ifdef VIA2_iCA2_PulseNtfy
+GLOBALPROC VIA2_iCA2_PulseNtfy(void)
+{
+	VIA2_SetInterruptFlag(kIntCA2);
+}
+#endif
+
+#ifdef VIA2_iCB1_PulseNtfy
+GLOBALPROC VIA2_iCB1_PulseNtfy(void)
+{
+	VIA2_SetInterruptFlag(kIntCB1);
+}
+#endif
+
+#ifdef VIA2_iCB2_PulseNtfy
+GLOBALPROC VIA2_iCB2_PulseNtfy(void)
+{
+	VIA2_SetInterruptFlag(kIntCB2);
+}
+#endif
--- /dev/null
+++ b/src/VIA2EMDV.h
@@ -1,0 +1,48 @@
+/*
+	VIA2EMDV.h
+
+	Copyright (C) 2004 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef VIA2EMDV_H
+#error "header already included"
+#else
+#define VIA2EMDV_H
+#endif
+
+EXPORTPROC VIA2_Zap(void);
+EXPORTPROC VIA2_Reset(void);
+
+EXPORTFUNC ui5b VIA2_Access(ui5b Data, blnr WriteMem, CPTR addr);
+
+EXPORTPROC VIA2_ExtraTimeBegin(void);
+EXPORTPROC VIA2_ExtraTimeEnd(void);
+#ifdef VIA2_iCA1_PulseNtfy
+EXPORTPROC VIA2_iCA1_PulseNtfy(void);
+#endif
+#ifdef VIA2_iCA2_PulseNtfy
+EXPORTPROC VIA2_iCA2_PulseNtfy(void);
+#endif
+#ifdef VIA2_iCB1_PulseNtfy
+EXPORTPROC VIA2_iCB1_PulseNtfy(void);
+#endif
+#ifdef VIA2_iCB2_PulseNtfy
+EXPORTPROC VIA2_iCB2_PulseNtfy(void);
+#endif
+EXPORTPROC VIA2_DoTimer1Check(void);
+EXPORTPROC VIA2_DoTimer2Check(void);
+
+EXPORTFUNC ui4b VIA2_GetT1InvertTime(void);
+
+EXPORTPROC VIA2_ShiftInData(ui3b v);
+EXPORTFUNC ui3b VIA2_ShiftOutData(void);
--- /dev/null
+++ b/src/VIAEMDEV.c
@@ -1,0 +1,1224 @@
+/*
+	VIAEMDEV.c
+
+	Copyright (C) 2008 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	Versatile Interface Adapter EMulated DEVice
+
+	Emulates the VIA found in the Mac Plus.
+
+	This code adapted from vMac by Philip Cummins.
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+
+#include "MYOSGLUE.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+#endif
+
+#include "VIAEMDEV.h"
+
+/*
+	ReportAbnormalID unused 0x0410 - 0x04FF
+*/
+
+#ifdef VIA1_iA0_ChangeNtfy
+IMPORTPROC VIA1_iA0_ChangeNtfy(void);
+#endif
+
+#ifdef VIA1_iA1_ChangeNtfy
+IMPORTPROC VIA1_iA1_ChangeNtfy(void);
+#endif
+
+#ifdef VIA1_iA2_ChangeNtfy
+IMPORTPROC VIA1_iA2_ChangeNtfy(void);
+#endif
+
+#ifdef VIA1_iA3_ChangeNtfy
+IMPORTPROC VIA1_iA3_ChangeNtfy(void);
+#endif
+
+#ifdef VIA1_iA4_ChangeNtfy
+IMPORTPROC VIA1_iA4_ChangeNtfy(void);
+#endif
+
+#ifdef VIA1_iA5_ChangeNtfy
+IMPORTPROC VIA1_iA5_ChangeNtfy(void);
+#endif
+
+#ifdef VIA1_iA6_ChangeNtfy
+IMPORTPROC VIA1_iA6_ChangeNtfy(void);
+#endif
+
+#ifdef VIA1_iA7_ChangeNtfy
+IMPORTPROC VIA1_iA7_ChangeNtfy(void);
+#endif
+
+#ifdef VIA1_iB0_ChangeNtfy
+IMPORTPROC VIA1_iB0_ChangeNtfy(void);
+#endif
+
+#ifdef VIA1_iB1_ChangeNtfy
+IMPORTPROC VIA1_iB1_ChangeNtfy(void);
+#endif
+
+#ifdef VIA1_iB2_ChangeNtfy
+IMPORTPROC VIA1_iB2_ChangeNtfy(void);
+#endif
+
+#ifdef VIA1_iB3_ChangeNtfy
+IMPORTPROC VIA1_iB3_ChangeNtfy(void);
+#endif
+
+#ifdef VIA1_iB4_ChangeNtfy
+IMPORTPROC VIA1_iB4_ChangeNtfy(void);
+#endif
+
+#ifdef VIA1_iB5_ChangeNtfy
+IMPORTPROC VIA1_iB5_ChangeNtfy(void);
+#endif
+
+#ifdef VIA1_iB6_ChangeNtfy
+IMPORTPROC VIA1_iB6_ChangeNtfy(void);
+#endif
+
+#ifdef VIA1_iB7_ChangeNtfy
+IMPORTPROC VIA1_iB7_ChangeNtfy(void);
+#endif
+
+#ifdef VIA1_iCB2_ChangeNtfy
+IMPORTPROC VIA1_iCB2_ChangeNtfy(void);
+#endif
+
+#define Ui3rPowOf2(p) (1 << (p))
+#define Ui3rTestBit(i, p) (((i) & Ui3rPowOf2(p)) != 0)
+
+#define VIA1_ORA_CanInOrOut (VIA1_ORA_CanIn | VIA1_ORA_CanOut)
+
+#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 7)
+#ifdef VIA1_iA7
+#error "VIA1_iA7 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 6)
+#ifdef VIA1_iA6
+#error "VIA1_iA6 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 5)
+#ifdef VIA1_iA5
+#error "VIA1_iA5 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 4)
+#ifdef VIA1_iA4
+#error "VIA1_iA4 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 3)
+#ifdef VIA1_iA3
+#error "VIA1_iA3 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 2)
+#ifdef VIA1_iA2
+#error "VIA1_iA2 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 1)
+#ifdef VIA1_iA1
+#error "VIA1_iA1 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 0)
+#ifdef VIA1_iA0
+#error "VIA1_iA0 defined but not used"
+#endif
+#endif
+
+#define VIA1_ORB_CanInOrOut (VIA1_ORB_CanIn | VIA1_ORB_CanOut)
+
+#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 7)
+#ifdef VIA1_iB7
+#error "VIA1_iB7 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 6)
+#ifdef VIA1_iB6
+#error "VIA1_iB6 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 5)
+#ifdef VIA1_iB5
+#error "VIA1_iB5 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 4)
+#ifdef VIA1_iB4
+#error "VIA1_iB4 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 3)
+#ifdef VIA1_iB3
+#error "VIA1_iB3 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 2)
+#ifdef VIA1_iB2
+#error "VIA1_iB2 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 1)
+#ifdef VIA1_iB1
+#error "VIA1_iB1 defined but not used"
+#endif
+#endif
+
+#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 0)
+#ifdef VIA1_iB0
+#error "VIA1_iB0 defined but not used"
+#endif
+#endif
+
+typedef struct {
+	ui5b T1C_F;  /* Timer 1 Counter Fixed Point */
+	ui5b T2C_F;  /* Timer 2 Counter Fixed Point */
+	ui3b ORB;    /* Buffer B */
+	/* ui3b ORA_H;     Buffer A with Handshake */
+	ui3b DDR_B;  /* Data Direction Register B */
+	ui3b DDR_A;  /* Data Direction Register A */
+	ui3b T1L_L;  /* Timer 1 Latch Low */
+	ui3b T1L_H;  /* Timer 1 Latch High */
+	ui3b T2L_L;  /* Timer 2 Latch Low */
+	ui3b SR;     /* Shift Register */
+	ui3b ACR;    /* Auxiliary Control Register */
+	ui3b PCR;    /* Peripheral Control Register */
+	ui3b IFR;    /* Interrupt Flag Register */
+	ui3b IER;    /* Interrupt Enable Register */
+	ui3b ORA;    /* Buffer A */
+} VIA1_Ty;
+
+LOCALVAR VIA1_Ty VIA1_D;
+
+#define kIntCA2 0 /* One_Second */
+#define kIntCA1 1 /* Vertical_Blanking */
+#define kIntSR 2 /* Keyboard_Data_Ready */
+#define kIntCB2 3 /* Keyboard_Data */
+#define kIntCB1 4 /* Keyboard_Clock */
+#define kIntT2 5 /* Timer_2 */
+#define kIntT1 6 /* Timer_1 */
+
+#define VIA1_dolog (dbglog_HAVE && 0)
+
+/* VIA1_Get_ORA : VIA Get Port A Data */
+/*
+	This function queries VIA Port A interfaced hardware
+	about their status
+*/
+
+LOCALFUNC ui3b VIA1_Get_ORA(ui3b Selection)
+{
+	ui3b Value = (~ VIA1_ORA_CanIn) & Selection & VIA1_ORA_FloatVal;
+
+#if Ui3rTestBit(VIA1_ORA_CanIn, 7)
+	if (Ui3rTestBit(Selection, 7)) {
+		Value |= (VIA1_iA7 << 7);
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORA_CanIn, 6)
+	if (Ui3rTestBit(Selection, 6)) {
+		Value |= (VIA1_iA6 << 6);
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORA_CanIn, 5)
+	if (Ui3rTestBit(Selection, 5)) {
+		Value |= (VIA1_iA5 << 5);
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORA_CanIn, 4)
+	if (Ui3rTestBit(Selection, 4)) {
+		Value |= (VIA1_iA4 << 4);
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORA_CanIn, 3)
+	if (Ui3rTestBit(Selection, 3)) {
+		Value |= (VIA1_iA3 << 3);
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORA_CanIn, 2)
+	if (Ui3rTestBit(Selection, 2)) {
+		Value |= (VIA1_iA2 << 2);
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORA_CanIn, 1)
+	if (Ui3rTestBit(Selection, 1)) {
+		Value |= (VIA1_iA1 << 1);
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORA_CanIn, 0)
+	if (Ui3rTestBit(Selection, 0)) {
+		Value |= (VIA1_iA0 << 0);
+	}
+#endif
+
+	return Value;
+}
+
+/* VIA1_Get_ORB : VIA Get Port B Data */
+/*
+	This function queries VIA Port B interfaced hardware
+	about their status
+*/
+
+LOCALFUNC ui3b VIA1_Get_ORB(ui3b Selection)
+{
+	ui3b Value = (~ VIA1_ORB_CanIn) & Selection & VIA1_ORB_FloatVal;
+
+#if Ui3rTestBit(VIA1_ORB_CanIn, 7)
+	if (Ui3rTestBit(Selection, 7)) {
+		Value |= (VIA1_iB7 << 7);
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORB_CanIn, 6)
+	if (Ui3rTestBit(Selection, 6)) {
+		Value |= (VIA1_iB6 << 6);
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORB_CanIn, 5)
+	if (Ui3rTestBit(Selection, 5)) {
+		Value |= (VIA1_iB5 << 5);
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORB_CanIn, 4)
+	if (Ui3rTestBit(Selection, 4)) {
+		Value |= (VIA1_iB4 << 4);
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORB_CanIn, 3)
+	if (Ui3rTestBit(Selection, 3)) {
+		Value |= (VIA1_iB3 << 3);
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORB_CanIn, 2)
+	if (Ui3rTestBit(Selection, 2)) {
+		Value |= (VIA1_iB2 << 2);
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORB_CanIn, 1)
+	if (Ui3rTestBit(Selection, 1)) {
+		Value |= (VIA1_iB1 << 1);
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORB_CanIn, 0)
+	if (Ui3rTestBit(Selection, 0)) {
+		Value |= (VIA1_iB0 << 0);
+	}
+#endif
+
+	return Value;
+}
+
+#define ViaORcheckBit(p, x) \
+	(Ui3rTestBit(Selection, p) && \
+	((v = (Data >> p) & 1) != x))
+
+LOCALPROC VIA1_Put_ORA(ui3b Selection, ui3b Data)
+{
+#if 0 != VIA1_ORA_CanOut
+	ui3b v;
+#endif
+
+#if Ui3rTestBit(VIA1_ORA_CanOut, 7)
+	if (ViaORcheckBit(7, VIA1_iA7)) {
+		VIA1_iA7 = v;
+#ifdef VIA1_iA7_ChangeNtfy
+		VIA1_iA7_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORA_CanOut, 6)
+	if (ViaORcheckBit(6, VIA1_iA6)) {
+		VIA1_iA6 = v;
+#ifdef VIA1_iA6_ChangeNtfy
+		VIA1_iA6_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORA_CanOut, 5)
+	if (ViaORcheckBit(5, VIA1_iA5)) {
+		VIA1_iA5 = v;
+#ifdef VIA1_iA5_ChangeNtfy
+		VIA1_iA5_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORA_CanOut, 4)
+	if (ViaORcheckBit(4, VIA1_iA4)) {
+		VIA1_iA4 = v;
+#ifdef VIA1_iA4_ChangeNtfy
+		VIA1_iA4_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORA_CanOut, 3)
+	if (ViaORcheckBit(3, VIA1_iA3)) {
+		VIA1_iA3 = v;
+#ifdef VIA1_iA3_ChangeNtfy
+		VIA1_iA3_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORA_CanOut, 2)
+	if (ViaORcheckBit(2, VIA1_iA2)) {
+		VIA1_iA2 = v;
+#ifdef VIA1_iA2_ChangeNtfy
+		VIA1_iA2_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORA_CanOut, 1)
+	if (ViaORcheckBit(1, VIA1_iA1)) {
+		VIA1_iA1 = v;
+#ifdef VIA1_iA1_ChangeNtfy
+		VIA1_iA1_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORA_CanOut, 0)
+	if (ViaORcheckBit(0, VIA1_iA0)) {
+		VIA1_iA0 = v;
+#ifdef VIA1_iA0_ChangeNtfy
+		VIA1_iA0_ChangeNtfy();
+#endif
+	}
+#endif
+}
+
+LOCALPROC VIA1_Put_ORB(ui3b Selection, ui3b Data)
+{
+#if 0 != VIA1_ORB_CanOut
+	ui3b v;
+#endif
+
+#if Ui3rTestBit(VIA1_ORB_CanOut, 7)
+	if (ViaORcheckBit(7, VIA1_iB7)) {
+		VIA1_iB7 = v;
+#ifdef VIA1_iB7_ChangeNtfy
+		VIA1_iB7_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORB_CanOut, 6)
+	if (ViaORcheckBit(6, VIA1_iB6)) {
+		VIA1_iB6 = v;
+#ifdef VIA1_iB6_ChangeNtfy
+		VIA1_iB6_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORB_CanOut, 5)
+	if (ViaORcheckBit(5, VIA1_iB5)) {
+		VIA1_iB5 = v;
+#ifdef VIA1_iB5_ChangeNtfy
+		VIA1_iB5_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORB_CanOut, 4)
+	if (ViaORcheckBit(4, VIA1_iB4)) {
+		VIA1_iB4 = v;
+#ifdef VIA1_iB4_ChangeNtfy
+		VIA1_iB4_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORB_CanOut, 3)
+	if (ViaORcheckBit(3, VIA1_iB3)) {
+		VIA1_iB3 = v;
+#ifdef VIA1_iB3_ChangeNtfy
+		VIA1_iB3_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORB_CanOut, 2)
+	if (ViaORcheckBit(2, VIA1_iB2)) {
+		VIA1_iB2 = v;
+#ifdef VIA1_iB2_ChangeNtfy
+		VIA1_iB2_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORB_CanOut, 1)
+	if (ViaORcheckBit(1, VIA1_iB1)) {
+		VIA1_iB1 = v;
+#ifdef VIA1_iB1_ChangeNtfy
+		VIA1_iB1_ChangeNtfy();
+#endif
+	}
+#endif
+
+#if Ui3rTestBit(VIA1_ORB_CanOut, 0)
+	if (ViaORcheckBit(0, VIA1_iB0)) {
+		VIA1_iB0 = v;
+#ifdef VIA1_iB0_ChangeNtfy
+		VIA1_iB0_ChangeNtfy();
+#endif
+	}
+#endif
+}
+
+LOCALPROC VIA1_SetDDR_A(ui3b Data)
+{
+	ui3b floatbits = VIA1_D.DDR_A & ~ Data;
+	ui3b unfloatbits = Data & ~ VIA1_D.DDR_A;
+
+	if (floatbits != 0) {
+		VIA1_Put_ORA(floatbits, VIA1_ORA_FloatVal);
+	}
+	VIA1_D.DDR_A = Data;
+	if (unfloatbits != 0) {
+		VIA1_Put_ORA(unfloatbits, VIA1_D.ORA);
+	}
+	if ((Data & ~ VIA1_ORA_CanOut) != 0) {
+		ReportAbnormalID(0x0401,
+			"Set VIA1_D.DDR_A unexpected direction");
+	}
+}
+
+LOCALPROC VIA1_SetDDR_B(ui3b Data)
+{
+	ui3b floatbits = VIA1_D.DDR_B & ~ Data;
+	ui3b unfloatbits = Data & ~ VIA1_D.DDR_B;
+
+	if (floatbits != 0) {
+		VIA1_Put_ORB(floatbits, VIA1_ORB_FloatVal);
+	}
+	VIA1_D.DDR_B = Data;
+	if (unfloatbits != 0) {
+		VIA1_Put_ORB(unfloatbits, VIA1_D.ORB);
+	}
+	if ((Data & ~ VIA1_ORB_CanOut) != 0) {
+		ReportAbnormalID(0x0402,
+			"Set VIA1_D.DDR_B unexpected direction");
+	}
+}
+
+
+LOCALPROC VIA1_CheckInterruptFlag(void)
+{
+	ui3b NewInterruptRequest =
+		((VIA1_D.IFR & VIA1_D.IER) != 0) ? 1 : 0;
+
+	if (NewInterruptRequest != VIA1_InterruptRequest) {
+		VIA1_InterruptRequest = NewInterruptRequest;
+#ifdef VIA1_interruptChngNtfy
+		VIA1_interruptChngNtfy();
+#endif
+	}
+}
+
+
+LOCALVAR ui3b VIA1_T1_Active = 0;
+LOCALVAR ui3b VIA1_T2_Active = 0;
+
+LOCALVAR blnr VIA1_T1IntReady = falseblnr;
+
+LOCALPROC VIA1_Clear(void)
+{
+	VIA1_D.ORA   = 0; VIA1_D.DDR_A = 0;
+	VIA1_D.ORB   = 0; VIA1_D.DDR_B = 0;
+	VIA1_D.T1L_L = VIA1_D.T1L_H = 0x00;
+	VIA1_D.T2L_L = 0x00;
+	VIA1_D.T1C_F = 0;
+	VIA1_D.T2C_F = 0;
+	VIA1_D.SR = VIA1_D.ACR = 0x00;
+	VIA1_D.PCR   = VIA1_D.IFR   = VIA1_D.IER   = 0x00;
+	VIA1_T1_Active = VIA1_T2_Active = 0x00;
+	VIA1_T1IntReady = falseblnr;
+}
+
+GLOBALPROC VIA1_Zap(void)
+{
+	VIA1_Clear();
+	VIA1_InterruptRequest = 0;
+}
+
+GLOBALPROC VIA1_Reset(void)
+{
+	VIA1_SetDDR_A(0);
+	VIA1_SetDDR_B(0);
+
+	VIA1_Clear();
+
+	VIA1_CheckInterruptFlag();
+}
+
+LOCALPROC VIA1_SetInterruptFlag(ui3b VIA_Int)
+{
+	VIA1_D.IFR |= ((ui3b)1 << VIA_Int);
+	VIA1_CheckInterruptFlag();
+}
+
+LOCALPROC VIA1_ClrInterruptFlag(ui3b VIA_Int)
+{
+	VIA1_D.IFR &= ~ ((ui3b)1 << VIA_Int);
+	VIA1_CheckInterruptFlag();
+}
+
+#ifdef _VIA_Debug
+#include <stdio.h>
+#endif
+
+GLOBALPROC VIA1_ShiftInData(ui3b v)
+{
+	/*
+		external hardware generates 8 pulses on CB1,
+		writes 8 bits to CB2
+	*/
+	ui3b ShiftMode = (VIA1_D.ACR & 0x1C) >> 2;
+
+	if (ShiftMode != 3) {
+#if ExtraAbnormalReports
+		if (ShiftMode == 0) {
+			/* happens on reset */
+		} else {
+			ReportAbnormalID(0x0403, "VIA Not ready to shift in");
+				/*
+					Observed (rarely) in Crystal Quest played
+					at 1x speed in "-t mc64".
+				*/
+		}
+#endif
+	} else {
+		VIA1_D.SR = v;
+		VIA1_SetInterruptFlag(kIntSR);
+		VIA1_SetInterruptFlag(kIntCB1);
+	}
+}
+
+GLOBALFUNC ui3b VIA1_ShiftOutData(void)
+{
+	/*
+		external hardware generates 8 pulses on CB1,
+		reads 8 bits from CB2
+	*/
+	if (((VIA1_D.ACR & 0x1C) >> 2) != 7) {
+		ReportAbnormalID(0x0404, "VIA Not ready to shift out");
+		return 0;
+	} else {
+		VIA1_SetInterruptFlag(kIntSR);
+		VIA1_SetInterruptFlag(kIntCB1);
+		VIA1_iCB2 = (VIA1_D.SR & 1);
+		return VIA1_D.SR;
+	}
+}
+
+#define CyclesPerViaTime (10 * kMyClockMult)
+#define CyclesScaledPerViaTime (kCycleScale * CyclesPerViaTime)
+
+LOCALVAR blnr VIA1_T1Running = trueblnr;
+LOCALVAR iCountt VIA1_T1LastTime = 0;
+
+GLOBALPROC VIA1_DoTimer1Check(void)
+{
+	if (VIA1_T1Running) {
+		iCountt NewTime = GetCuriCount();
+		iCountt deltaTime = (NewTime - VIA1_T1LastTime);
+		if (deltaTime != 0) {
+			ui5b Temp = VIA1_D.T1C_F; /* Get Timer 1 Counter */
+			ui5b deltaTemp =
+				(deltaTime / CyclesPerViaTime) << (16 - kLn2CycleScale);
+					/* may overflow */
+			ui5b NewTemp = Temp - deltaTemp;
+			if ((deltaTime > (0x00010000UL * CyclesScaledPerViaTime))
+				|| ((Temp <= deltaTemp) && (Temp != 0)))
+			{
+				if ((VIA1_D.ACR & 0x40) != 0) { /* Free Running? */
+					/* Reload Counter from Latches */
+					ui4b v = (VIA1_D.T1L_H << 8) + VIA1_D.T1L_L;
+					ui4b ntrans = 1 + ((v == 0) ? 0 :
+						(((deltaTemp - Temp) / v) >> 16));
+					NewTemp += (((ui5b)v * ntrans) << 16);
+#if Ui3rTestBit(VIA1_ORB_CanOut, 7)
+					if ((VIA1_D.ACR & 0x80) != 0) { /* invert ? */
+						if ((ntrans & 1) != 0) {
+							VIA1_iB7 ^= 1;
+#ifdef VIA1_iB7_ChangeNtfy
+							VIA1_iB7_ChangeNtfy();
+#endif
+						}
+					}
+#endif
+					VIA1_SetInterruptFlag(kIntT1);
+#if VIA1_dolog && 1
+					dbglog_WriteNote("VIA1 Timer 1 Interrupt");
+#endif
+				} else {
+					if (VIA1_T1_Active == 1) {
+						VIA1_T1_Active = 0;
+						VIA1_SetInterruptFlag(kIntT1);
+#if VIA1_dolog && 1
+						dbglog_WriteNote("VIA1 Timer 1 Interrupt");
+#endif
+					}
+				}
+			}
+
+			VIA1_D.T1C_F = NewTemp;
+			VIA1_T1LastTime = NewTime;
+		}
+
+		VIA1_T1IntReady = falseblnr;
+		if ((VIA1_D.IFR & (1 << kIntT1)) == 0) {
+			if (((VIA1_D.ACR & 0x40) != 0) || (VIA1_T1_Active == 1)) {
+				ui5b NewTemp = VIA1_D.T1C_F; /* Get Timer 1 Counter */
+				ui5b NewTimer;
+#ifdef _VIA_Debug
+				fprintf(stderr, "posting Timer1Check, %d, %d\n",
+					Temp, GetCuriCount());
+#endif
+				if (NewTemp == 0) {
+					NewTimer = (0x00010000UL * CyclesScaledPerViaTime);
+				} else {
+					NewTimer =
+						(1 + (NewTemp >> (16 - kLn2CycleScale)))
+							* CyclesPerViaTime;
+				}
+				ICT_add(kICT_VIA1_Timer1Check, NewTimer);
+				VIA1_T1IntReady = trueblnr;
+			}
+		}
+	}
+}
+
+LOCALPROC CheckT1IntReady(void)
+{
+	if (VIA1_T1Running) {
+		blnr NewT1IntReady = falseblnr;
+
+		if ((VIA1_D.IFR & (1 << kIntT1)) == 0) {
+			if (((VIA1_D.ACR & 0x40) != 0) || (VIA1_T1_Active == 1)) {
+				NewT1IntReady = trueblnr;
+			}
+		}
+
+		if (VIA1_T1IntReady != NewT1IntReady) {
+			VIA1_T1IntReady = NewT1IntReady;
+			if (NewT1IntReady) {
+				VIA1_DoTimer1Check();
+			}
+		}
+	}
+}
+
+GLOBALFUNC ui4b VIA1_GetT1InvertTime(void)
+{
+	ui4b v;
+
+	if ((VIA1_D.ACR & 0xC0) == 0xC0) {
+		v = (VIA1_D.T1L_H << 8) + VIA1_D.T1L_L;
+	} else {
+		v = 0;
+	}
+	return v;
+}
+
+LOCALVAR blnr VIA1_T2Running = trueblnr;
+LOCALVAR blnr VIA1_T2C_ShortTime = falseblnr;
+LOCALVAR iCountt VIA1_T2LastTime = 0;
+
+GLOBALPROC VIA1_DoTimer2Check(void)
+{
+	if (VIA1_T2Running) {
+		iCountt NewTime = GetCuriCount();
+		ui5b Temp = VIA1_D.T2C_F; /* Get Timer 2 Counter */
+		iCountt deltaTime = (NewTime - VIA1_T2LastTime);
+		ui5b deltaTemp = (deltaTime / CyclesPerViaTime)
+			<< (16 - kLn2CycleScale); /* may overflow */
+		ui5b NewTemp = Temp - deltaTemp;
+		if (VIA1_T2_Active == 1) {
+			if ((deltaTime > (0x00010000UL * CyclesScaledPerViaTime))
+				|| ((Temp <= deltaTemp) && (Temp != 0)))
+			{
+				VIA1_T2C_ShortTime = falseblnr;
+				VIA1_T2_Active = 0;
+				VIA1_SetInterruptFlag(kIntT2);
+#if VIA1_dolog && 1
+				dbglog_WriteNote("VIA1 Timer 2 Interrupt");
+#endif
+			} else {
+				ui5b NewTimer;
+#ifdef _VIA_Debug
+				fprintf(stderr, "posting Timer2Check, %d, %d\n",
+					Temp, GetCuriCount());
+#endif
+				if (NewTemp == 0) {
+					NewTimer = (0x00010000UL * CyclesScaledPerViaTime);
+				} else {
+					NewTimer = (1 + (NewTemp >> (16 - kLn2CycleScale)))
+						* CyclesPerViaTime;
+				}
+				ICT_add(kICT_VIA1_Timer2Check, NewTimer);
+			}
+		}
+		VIA1_D.T2C_F = NewTemp;
+		VIA1_T2LastTime = NewTime;
+	}
+}
+
+#define kORB    0x00
+#define kORA_H  0x01
+#define kDDR_B  0x02
+#define kDDR_A  0x03
+#define kT1C_L  0x04
+#define kT1C_H  0x05
+#define kT1L_L  0x06
+#define kT1L_H  0x07
+#define kT2_L   0x08
+#define kT2_H   0x09
+#define kSR     0x0A
+#define kACR    0x0B
+#define kPCR    0x0C
+#define kIFR    0x0D
+#define kIER    0x0E
+#define kORA    0x0F
+
+GLOBALFUNC ui5b VIA1_Access(ui5b Data, blnr WriteMem, CPTR addr)
+{
+	switch (addr) {
+		case kORB   :
+#if VIA1_CB2modesAllowed != 0x01
+			if ((VIA1_D.PCR & 0xE0) == 0)
+#endif
+			{
+				VIA1_ClrInterruptFlag(kIntCB2);
+			}
+			VIA1_ClrInterruptFlag(kIntCB1);
+			if (WriteMem) {
+				VIA1_D.ORB = Data;
+				VIA1_Put_ORB(VIA1_D.DDR_B, VIA1_D.ORB);
+			} else {
+				Data = (VIA1_D.ORB & VIA1_D.DDR_B)
+					| VIA1_Get_ORB(~ VIA1_D.DDR_B);
+			}
+#if VIA1_dolog && 1
+			dbglog_Access("VIA1_Access kORB", Data, WriteMem);
+#endif
+			break;
+		case kDDR_B :
+			if (WriteMem) {
+				VIA1_SetDDR_B(Data);
+			} else {
+				Data = VIA1_D.DDR_B;
+			}
+#if VIA1_dolog && 1
+			dbglog_Access("VIA1_Access kDDR_B", Data, WriteMem);
+#endif
+			break;
+		case kDDR_A :
+			if (WriteMem) {
+				VIA1_SetDDR_A(Data);
+			} else {
+				Data = VIA1_D.DDR_A;
+			}
+#if VIA1_dolog && 1
+			dbglog_Access("VIA1_Access kDDR_A", Data, WriteMem);
+#endif
+			break;
+		case kT1C_L :
+			if (WriteMem) {
+				VIA1_D.T1L_L = Data;
+			} else {
+				VIA1_ClrInterruptFlag(kIntT1);
+				VIA1_DoTimer1Check();
+				Data = (VIA1_D.T1C_F & 0x00FF0000) >> 16;
+			}
+#if VIA1_dolog && 1
+			dbglog_Access("VIA1_Access kT1C_L", Data, WriteMem);
+#endif
+			break;
+		case kT1C_H :
+			if (WriteMem) {
+				VIA1_D.T1L_H = Data;
+				VIA1_ClrInterruptFlag(kIntT1);
+				VIA1_D.T1C_F = (Data << 24) + (VIA1_D.T1L_L << 16);
+				if ((VIA1_D.ACR & 0x40) == 0) {
+					VIA1_T1_Active = 1;
+				}
+				VIA1_T1LastTime = GetCuriCount();
+				VIA1_DoTimer1Check();
+			} else {
+				VIA1_DoTimer1Check();
+				Data = (VIA1_D.T1C_F & 0xFF000000) >> 24;
+			}
+#if VIA1_dolog && 1
+			dbglog_Access("VIA1_Access kT1C_H", Data, WriteMem);
+#endif
+			break;
+		case kT1L_L :
+			if (WriteMem) {
+				VIA1_D.T1L_L = Data;
+			} else {
+				Data = VIA1_D.T1L_L;
+			}
+#if VIA1_dolog && 1
+			dbglog_Access("VIA1_Access kT1L_L", Data, WriteMem);
+#endif
+			break;
+		case kT1L_H :
+			if (WriteMem) {
+				VIA1_D.T1L_H = Data;
+			} else {
+				Data = VIA1_D.T1L_H;
+			}
+#if VIA1_dolog && 1
+			dbglog_Access("VIA1_Access kT1L_H", Data, WriteMem);
+#endif
+			break;
+		case kT2_L  :
+			if (WriteMem) {
+				VIA1_D.T2L_L = Data;
+			} else {
+				VIA1_ClrInterruptFlag(kIntT2);
+				VIA1_DoTimer2Check();
+				Data = (VIA1_D.T2C_F & 0x00FF0000) >> 16;
+			}
+#if VIA1_dolog && 1
+			dbglog_Access("VIA1_Access kT2_L", Data, WriteMem);
+#endif
+			break;
+		case kT2_H  :
+			if (WriteMem) {
+				VIA1_D.T2C_F = (Data << 24) + (VIA1_D.T2L_L << 16);
+				VIA1_ClrInterruptFlag(kIntT2);
+				VIA1_T2_Active = 1;
+
+				if ((VIA1_D.T2C_F < (128UL << 16))
+					&& (VIA1_D.T2C_F != 0))
+				{
+					VIA1_T2C_ShortTime = trueblnr;
+					VIA1_T2Running = trueblnr;
+					/*
+						Running too many instructions during
+						a short timer interval can crash when
+						playing sounds in System 7. So
+						in this case don't let timer pause.
+					*/
+				}
+				VIA1_T2LastTime = GetCuriCount();
+				VIA1_DoTimer2Check();
+			} else {
+				VIA1_DoTimer2Check();
+				Data = (VIA1_D.T2C_F & 0xFF000000) >> 24;
+			}
+#if VIA1_dolog && 1
+			dbglog_Access("VIA1_Access kT2_H", Data, WriteMem);
+#endif
+			break;
+		case kSR:
+#ifdef _VIA_Debug
+			fprintf(stderr, "VIA1_D.SR: %d, %d, %d\n",
+				WriteMem, ((VIA1_D.ACR & 0x1C) >> 2), Data);
+#endif
+			if (WriteMem) {
+				VIA1_D.SR = Data;
+			}
+			VIA1_ClrInterruptFlag(kIntSR);
+			switch ((VIA1_D.ACR & 0x1C) >> 2) {
+				case 3 : /* Shifting In */
+					break;
+				case 6 : /* shift out under o2 clock */
+					if ((! WriteMem) || (VIA1_D.SR != 0)) {
+						ReportAbnormalID(0x0405,
+							"VIA shift mode 6, non zero");
+					} else {
+#ifdef _VIA_Debug
+						fprintf(stderr, "posting Foo2Task\n");
+#endif
+						if (VIA1_iCB2 != 0) {
+							VIA1_iCB2 = 0;
+#ifdef VIA1_iCB2_ChangeNtfy
+							VIA1_iCB2_ChangeNtfy();
+#endif
+						}
+					}
+#if 0 /* possibly should do this. seems not to affect anything. */
+					VIA1_SetInterruptFlag(kIntSR); /* don't wait */
+#endif
+					break;
+				case 7 : /* Shifting Out */
+					break;
+			}
+			if (! WriteMem) {
+				Data = VIA1_D.SR;
+			}
+#if VIA1_dolog && 1
+			dbglog_Access("VIA1_Access kSR", Data, WriteMem);
+#endif
+			break;
+		case kACR:
+			if (WriteMem) {
+#if 1
+				if ((VIA1_D.ACR & 0x10) != ((ui3b)Data & 0x10)) {
+					/* shift direction has changed */
+					if ((Data & 0x10) == 0) {
+						/*
+							no longer an output,
+							set data to float value
+						*/
+						if (VIA1_iCB2 == 0) {
+							VIA1_iCB2 = 1;
+#ifdef VIA1_iCB2_ChangeNtfy
+							VIA1_iCB2_ChangeNtfy();
+#endif
+						}
+					}
+				}
+#endif
+				VIA1_D.ACR = Data;
+				if ((VIA1_D.ACR & 0x20) != 0) {
+					/* Not pulse counting? */
+					ReportAbnormalID(0x0406,
+						"Set VIA1_D.ACR T2 Timer pulse counting");
+				}
+				switch ((VIA1_D.ACR & 0xC0) >> 6) {
+					/* case 1: happens in early System 6 */
+					case 2:
+						ReportAbnormalID(0x0407,
+							"Set VIA1_D.ACR T1 Timer mode 2");
+						break;
+				}
+				CheckT1IntReady();
+				switch ((VIA1_D.ACR & 0x1C) >> 2) {
+					case 0: /* this isn't sufficient */
+						VIA1_ClrInterruptFlag(kIntSR);
+						break;
+					case 1:
+					case 2:
+					case 4:
+					case 5:
+						ReportAbnormalID(0x0408,
+							"Set VIA1_D.ACR shift mode 1,2,4,5");
+						break;
+					default:
+						break;
+				}
+				if ((VIA1_D.ACR & 0x03) != 0) {
+					ReportAbnormalID(0x0409,
+						"Set VIA1_D.ACR T2 Timer latching enabled");
+				}
+			} else {
+				Data = VIA1_D.ACR;
+			}
+#if VIA1_dolog && 1
+			dbglog_Access("VIA1_Access kACR", Data, WriteMem);
+#endif
+			break;
+		case kPCR:
+			if (WriteMem) {
+				VIA1_D.PCR = Data;
+#define Ui3rSetContains(s, i) (((s) & (1 << (i))) != 0)
+				if (! Ui3rSetContains(VIA1_CB2modesAllowed,
+					(VIA1_D.PCR >> 5) & 0x07))
+				{
+					ReportAbnormalID(0x040A,
+						"Set VIA1_D.PCR CB2 Control mode?");
+				}
+				if ((VIA1_D.PCR & 0x10) != 0) {
+					ReportAbnormalID(0x040B,
+						"Set VIA1_D.PCR CB1 INTERRUPT CONTROL?");
+				}
+				if (! Ui3rSetContains(VIA1_CA2modesAllowed,
+					(VIA1_D.PCR >> 1) & 0x07))
+				{
+					ReportAbnormalID(0x040C,
+						"Set VIA1_D.PCR CA2 INTERRUPT CONTROL?");
+				}
+				if ((VIA1_D.PCR & 0x01) != 0) {
+					ReportAbnormalID(0x040D,
+						"Set VIA1_D.PCR CA1 INTERRUPT CONTROL?");
+				}
+			} else {
+				Data = VIA1_D.PCR;
+			}
+#if VIA1_dolog && 1
+			dbglog_Access("VIA1_Access kPCR", Data, WriteMem);
+#endif
+			break;
+		case kIFR:
+			if (WriteMem) {
+				VIA1_D.IFR = VIA1_D.IFR & ((~ Data) & 0x7F);
+					/* Clear Flag Bits */
+				VIA1_CheckInterruptFlag();
+				CheckT1IntReady();
+			} else {
+				Data = VIA1_D.IFR;
+				if ((VIA1_D.IFR & VIA1_D.IER) != 0) {
+					Data |= 0x80;
+				}
+			}
+#if VIA1_dolog && 1
+			dbglog_Access("VIA1_Access kIFR", Data, WriteMem);
+#endif
+			break;
+		case kIER   :
+			if (WriteMem) {
+				if ((Data & 0x80) == 0) {
+					VIA1_D.IER = VIA1_D.IER & ((~ Data) & 0x7F);
+						/* Clear Enable Bits */
+#if 0 != VIA1_IER_Never0
+					/*
+						of course, will be 0 initially,
+						this just checks not cleared later.
+					*/
+					if ((Data & VIA1_IER_Never0) != 0) {
+						ReportAbnormalID(0x040E, "IER Never0 clr");
+					}
+#endif
+				} else {
+					VIA1_D.IER = VIA1_D.IER | (Data & 0x7F);
+						/* Set Enable Bits */
+#if 0 != VIA1_IER_Never1
+					if ((VIA1_D.IER & VIA1_IER_Never1) != 0) {
+						ReportAbnormalID(0x040F, "IER Never1 set");
+					}
+#endif
+				}
+				VIA1_CheckInterruptFlag();
+			} else {
+				Data = VIA1_D.IER | 0x80;
+			}
+#if VIA1_dolog && 1
+			dbglog_Access("VIA1_Access kIER", Data, WriteMem);
+#endif
+			break;
+		case kORA   :
+		case kORA_H :
+			if ((VIA1_D.PCR & 0xE) == 0) {
+				VIA1_ClrInterruptFlag(kIntCA2);
+			}
+			VIA1_ClrInterruptFlag(kIntCA1);
+			if (WriteMem) {
+				VIA1_D.ORA = Data;
+				VIA1_Put_ORA(VIA1_D.DDR_A, VIA1_D.ORA);
+			} else {
+				Data = (VIA1_D.ORA & VIA1_D.DDR_A)
+					| VIA1_Get_ORA(~ VIA1_D.DDR_A);
+			}
+#if VIA1_dolog && 1
+			dbglog_Access("VIA1_Access kORA", Data, WriteMem);
+#endif
+			break;
+	}
+	return Data;
+}
+
+GLOBALPROC VIA1_ExtraTimeBegin(void)
+{
+	if (VIA1_T1Running) {
+		VIA1_DoTimer1Check(); /* run up to this moment */
+		VIA1_T1Running = falseblnr;
+	}
+	if (VIA1_T2Running & (! VIA1_T2C_ShortTime)) {
+		VIA1_DoTimer2Check(); /* run up to this moment */
+		VIA1_T2Running = falseblnr;
+	}
+}
+
+GLOBALPROC VIA1_ExtraTimeEnd(void)
+{
+	if (! VIA1_T1Running) {
+		VIA1_T1Running = trueblnr;
+		VIA1_T1LastTime = GetCuriCount();
+		VIA1_DoTimer1Check();
+	}
+	if (! VIA1_T2Running) {
+		VIA1_T2Running = trueblnr;
+		VIA1_T2LastTime = GetCuriCount();
+		VIA1_DoTimer2Check();
+	}
+}
+
+/* VIA Interrupt Interface */
+
+#ifdef VIA1_iCA1_PulseNtfy
+GLOBALPROC VIA1_iCA1_PulseNtfy(void)
+{
+	VIA1_SetInterruptFlag(kIntCA1);
+}
+#endif
+
+#ifdef VIA1_iCA2_PulseNtfy
+GLOBALPROC VIA1_iCA2_PulseNtfy(void)
+{
+	VIA1_SetInterruptFlag(kIntCA2);
+}
+#endif
+
+#ifdef VIA1_iCB1_PulseNtfy
+GLOBALPROC VIA1_iCB1_PulseNtfy(void)
+{
+	VIA1_SetInterruptFlag(kIntCB1);
+}
+#endif
+
+#ifdef VIA1_iCB2_PulseNtfy
+GLOBALPROC VIA1_iCB2_PulseNtfy(void)
+{
+	VIA1_SetInterruptFlag(kIntCB2);
+}
+#endif
--- /dev/null
+++ b/src/VIAEMDEV.h
@@ -1,0 +1,48 @@
+/*
+	VIAEMDEV.h
+
+	Copyright (C) 2004 Philip Cummins, Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef VIAEMDEV_H
+#error "header already included"
+#else
+#define VIAEMDEV_H
+#endif
+
+EXPORTPROC VIA1_Zap(void);
+EXPORTPROC VIA1_Reset(void);
+
+EXPORTFUNC ui5b VIA1_Access(ui5b Data, blnr WriteMem, CPTR addr);
+
+EXPORTPROC VIA1_ExtraTimeBegin(void);
+EXPORTPROC VIA1_ExtraTimeEnd(void);
+#ifdef VIA1_iCA1_PulseNtfy
+EXPORTPROC VIA1_iCA1_PulseNtfy(void);
+#endif
+#ifdef VIA1_iCA2_PulseNtfy
+EXPORTPROC VIA1_iCA2_PulseNtfy(void);
+#endif
+#ifdef VIA1_iCB1_PulseNtfy
+EXPORTPROC VIA1_iCB1_PulseNtfy(void);
+#endif
+#ifdef VIA1_iCB2_PulseNtfy
+EXPORTPROC VIA1_iCB2_PulseNtfy(void);
+#endif
+EXPORTPROC VIA1_DoTimer1Check(void);
+EXPORTPROC VIA1_DoTimer2Check(void);
+
+EXPORTFUNC ui4b VIA1_GetT1InvertTime(void);
+
+EXPORTPROC VIA1_ShiftInData(ui3b v);
+EXPORTFUNC ui3b VIA1_ShiftOutData(void);
--- /dev/null
+++ b/src/VIDEMDEV.c
@@ -1,0 +1,1004 @@
+/*
+	VIDEMDEV.c
+
+	Copyright (C) 2008 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+/*
+	VIDeo card EMulated DEVice
+
+	Emulation of video card for Macintosh II.
+
+	Written referring to:
+		Sample firmware code in "Designing Cards and Drivers
+		for Macintosh II and Macintosh SE", Apple Computer,
+		page 8-20.
+
+		Basilisk II source code, especially slot_rom.cpp
+*/
+
+#ifndef AllFiles
+#include "SYSDEPNS.h"
+#include "MYOSGLUE.h"
+#include "ENDIANAC.h"
+#include "EMCONFIG.h"
+#include "GLOBGLUE.h"
+#include "MINEM68K.h"
+#include "SONYEMDV.h"
+#endif
+
+#include "VIDEMDEV.h"
+
+/*
+	ReportAbnormalID unused 0x0A08 - 0x0AFF
+*/
+
+#define VID_dolog (dbglog_HAVE && 0)
+
+LOCALVAR const ui3b VidDrvr_contents[] = {
+0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x2A, 0x00, 0x00, 0x00, 0xE2, 0x00, 0xEC,
+0x00, 0xB6, 0x15, 0x2E, 0x44, 0x69, 0x73, 0x70,
+0x6C, 0x61, 0x79, 0x5F, 0x56, 0x69, 0x64, 0x65,
+0x6F, 0x5F, 0x53, 0x61, 0x6D, 0x70, 0x6C, 0x65,
+0x00, 0x00, 0x24, 0x48, 0x26, 0x49, 0x70, 0x04,
+0xA4, 0x40, 0x70, 0x04, 0xA7, 0x22, 0x66, 0x00,
+0x00, 0x50, 0x27, 0x48, 0x00, 0x14, 0xA0, 0x29,
+0x49, 0xFA, 0x00, 0x4A, 0x70, 0x10, 0xA7, 0x1E,
+0x66, 0x00, 0x00, 0x3E, 0x31, 0x7C, 0x00, 0x06,
+0x00, 0x04, 0x21, 0x4C, 0x00, 0x08, 0x21, 0x4B,
+0x00, 0x0C, 0x70, 0x00, 0x10, 0x2B, 0x00, 0x28,
+0xA0, 0x75, 0x66, 0x24, 0x22, 0x6B, 0x00, 0x14,
+0x22, 0x51, 0x22, 0x88, 0x3F, 0x3C, 0x00, 0x01,
+0x55, 0x4F, 0x3F, 0x3C, 0x00, 0x03, 0x41, 0xFA,
+0x00, 0x9C, 0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F,
+0xDE, 0xFC, 0x00, 0x0A, 0x70, 0x00, 0x60, 0x02,
+0x70, 0xE9, 0x4E, 0x75, 0x2F, 0x08, 0x55, 0x4F,
+0x3F, 0x3C, 0x00, 0x04, 0x41, 0xFA, 0x00, 0x7E,
+0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x50, 0x4F,
+0x20, 0x29, 0x00, 0x2A, 0xE1, 0x98, 0x02, 0x40,
+0x00, 0x0F, 0x20, 0x78, 0x0D, 0x28, 0x4E, 0x90,
+0x20, 0x5F, 0x70, 0x01, 0x4E, 0x75, 0x2F, 0x0B,
+0x26, 0x69, 0x00, 0x14, 0x42, 0x67, 0x55, 0x4F,
+0x3F, 0x3C, 0x00, 0x03, 0x41, 0xFA, 0x00, 0x4E,
+0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0xDE, 0xFC,
+0x00, 0x0A, 0x20, 0x53, 0x20, 0x50, 0xA0, 0x76,
+0x20, 0x4B, 0xA0, 0x23, 0x70, 0x00, 0x26, 0x5F,
+0x4E, 0x75, 0x2F, 0x08, 0x55, 0x4F, 0x3F, 0x3C,
+0x00, 0x06, 0x60, 0x08, 0x2F, 0x08, 0x55, 0x4F,
+0x3F, 0x3C, 0x00, 0x05, 0x41, 0xFA, 0x00, 0x1E,
+0x2F, 0x18, 0x20, 0x50, 0x20, 0x8F, 0x5C, 0x4F,
+0x30, 0x1F, 0x20, 0x5F, 0x08, 0x28, 0x00, 0x09,
+0x00, 0x06, 0x67, 0x02, 0x4E, 0x75, 0x20, 0x78,
+0x08, 0xFC, 0x4E, 0xD0
+};
+
+LOCALPROC ChecksumSlotROM(void)
+{
+	/* Calculate CRC */
+	/* assuming check sum field initialized to zero */
+	int i;
+	ui3p p = VidROM;
+	ui5b crc = 0;
+
+	for (i = kVidROM_Size; --i >= 0; ) {
+		crc = ((crc << 1) | (crc >> 31)) + *p++;
+	}
+	do_put_mem_long(p - 12, crc);
+}
+
+LOCALVAR ui3p pPatch;
+
+LOCALPROC PatchAByte(ui3b v)
+{
+	*pPatch++ = v;
+}
+
+LOCALPROC PatchAWord(ui4r v)
+{
+	PatchAByte(v >> 8);
+	PatchAByte(v & 0x00FF);
+}
+
+LOCALPROC PatchALong(ui5r v)
+{
+	PatchAWord(v >> 16);
+	PatchAWord(v & 0x0000FFFF);
+}
+
+#if 0
+LOCALPROC PatchAOSLstEntry0(ui3r Id, ui5r Offset)
+{
+	PatchALong((Id << 24) | (Offset & 0x00FFFFFF));
+}
+#endif
+
+LOCALPROC PatchAOSLstEntry(ui3r Id, ui3p Offset)
+{
+	PatchALong((Id << 24) | ((Offset - pPatch) & 0x00FFFFFF));
+}
+
+LOCALFUNC ui3p ReservePatchOSLstEntry(void)
+{
+	ui3p v = pPatch;
+	pPatch += 4;
+	return v;
+}
+
+LOCALPROC PatchAReservedOSLstEntry(ui3p p, ui3r Id)
+{
+	ui3p pPatchSave = pPatch;
+	pPatch = p;
+	PatchAOSLstEntry(Id, pPatchSave);
+	pPatch = pPatchSave;
+}
+
+LOCALPROC PatchADatLstEntry(ui3r Id, ui5r Data)
+{
+	PatchALong((Id << 24) | (Data & 0x00FFFFFF));
+}
+
+LOCALPROC PatchAnEndOfLst(void)
+{
+	PatchADatLstEntry(0xFF /* endOfList */, 0x00000000);
+}
+
+GLOBALFUNC blnr Vid_Init(void)
+{
+	int i;
+	ui5r UsedSoFar;
+
+	ui3p pAt_sRsrcDir;
+	ui3p pTo_sRsrc_Board;
+	ui3p pTo_BoardType;
+	ui3p pTo_BoardName;
+	ui3p pTo_VenderInfo;
+	ui3p pTo_VendorID;
+	ui3p pTo_RevLevel;
+	ui3p pTo_PartNum;
+	ui3p pTo_sRsrc_Video;
+	ui3p pTo_VideoType;
+	ui3p pTo_VideoName;
+	ui3p pTo_MinorBase;
+	ui3p pTo_MinorLength;
+#if 0
+	ui3p pTo_MajorBase;
+	ui3p pTo_MajorLength;
+#endif
+	ui3p pTo_VidDrvrDir;
+	ui3p pTo_sMacOS68020;
+	ui3p pTo_OneBitMode;
+	ui3p pTo_OneVidParams;
+#if 0 != vMacScreenDepth
+	ui3p pTo_ColorBitMode = nullpr;
+	ui3p pTo_ColorVidParams;
+#endif
+
+	pPatch = VidROM;
+
+	pAt_sRsrcDir = pPatch;
+	pTo_sRsrc_Board = ReservePatchOSLstEntry();
+	pTo_sRsrc_Video = ReservePatchOSLstEntry();
+	PatchAnEndOfLst();
+
+	PatchAReservedOSLstEntry(pTo_sRsrc_Board, 0x01 /* sRsrc_Board */);
+	pTo_BoardType = ReservePatchOSLstEntry();
+	pTo_BoardName = ReservePatchOSLstEntry();
+	PatchADatLstEntry(0x20 /* BoardId */, 0x0000764D);
+		/* 'vM', for Mini vMac */
+	pTo_VenderInfo = ReservePatchOSLstEntry();
+	PatchAnEndOfLst();
+
+	PatchAReservedOSLstEntry(pTo_BoardType, 0x01 /* sRsrcType */);
+	PatchAWord(0x0001);
+	PatchAWord(0x0000);
+	PatchAWord(0x0000);
+	PatchAWord(0x0000);
+
+	PatchAReservedOSLstEntry(pTo_BoardName, 0x02 /* sRsrcName */);
+	/*
+		'Mini vMac video card' as ascii c string
+		(null terminated), and
+		zero padded to end aligned long.
+	*/
+	PatchALong(0x4D696E69);
+	PatchALong(0x20764D61);
+	PatchALong(0x63207669);
+	PatchALong(0x64656F20);
+	PatchALong(0x63617264);
+	PatchALong(0x00000000);
+
+	PatchAReservedOSLstEntry(pTo_VenderInfo, 0x24 /* vendorInfo */);
+
+	pTo_VendorID = ReservePatchOSLstEntry();
+	pTo_RevLevel = ReservePatchOSLstEntry();
+	pTo_PartNum = ReservePatchOSLstEntry();
+	PatchAnEndOfLst();
+
+	PatchAReservedOSLstEntry(pTo_VendorID, 0x01 /* vendorId */);
+	/*
+		'Paul C. Pratt' as ascii c string
+		(null terminated), and
+		zero padded to end aligned long.
+	*/
+	PatchALong(0x5061756C);
+	PatchALong(0x20432E20);
+	PatchALong(0x50726174);
+	PatchALong(0x74000000);
+
+	PatchAReservedOSLstEntry(pTo_RevLevel, 0x03 /* revLevel */);
+	/*
+		'1.0' as ascii c string
+		(null terminated), and
+		zero padded to end aligned long.
+	*/
+	PatchALong(0x312E3000);
+
+	PatchAReservedOSLstEntry(pTo_PartNum, 0x04 /* partNum */);
+	/*
+		'TFB-1' as ascii c string
+		(null terminated), and
+		zero padded to end aligned long.
+	*/
+	PatchALong(0x5446422D);
+	PatchALong(0x31000000);
+
+	PatchAReservedOSLstEntry(pTo_sRsrc_Video, 0x80 /* sRsrc_Video */);
+
+	pTo_VideoType = ReservePatchOSLstEntry();
+	pTo_VideoName = ReservePatchOSLstEntry();
+	pTo_VidDrvrDir = ReservePatchOSLstEntry();
+	PatchADatLstEntry(0x08 /* sRsrcHWDevId */, 0x00000001);
+	pTo_MinorBase = ReservePatchOSLstEntry();
+	pTo_MinorLength = ReservePatchOSLstEntry();
+#if 0
+	pTo_MajorBase = ReservePatchOSLstEntry();
+	pTo_MajorLength = ReservePatchOSLstEntry();
+#endif
+	pTo_OneBitMode = ReservePatchOSLstEntry();
+#if 0 != vMacScreenDepth
+	if (ColorModeWorks) {
+		pTo_ColorBitMode = ReservePatchOSLstEntry();
+	}
+#endif
+	PatchAnEndOfLst();
+
+	PatchAReservedOSLstEntry(pTo_VideoType, 0x01 /* sRsrcType */);
+
+	PatchAWord(0x0003); /* catDisplay */
+	PatchAWord(0x0001); /* typVideo */
+	PatchAWord(0x0001); /* drSwApple */
+	PatchAWord(0x0001); /* drHwTFB */
+
+	PatchAReservedOSLstEntry(pTo_VideoName, 0x02 /* sRsrcName */);
+	/*
+		'Display_Video_Apple_TFB' as ascii c string
+		(null terminated), and
+		zero padded to end aligned long.
+	*/
+	PatchALong(0x44697370);
+	PatchALong(0x6C61795F);
+	PatchALong(0x56696465);
+	PatchALong(0x6F5F4170);
+	PatchALong(0x706C655F);
+	PatchALong(0x54464200);
+
+	PatchAReservedOSLstEntry(pTo_MinorBase, 0x0A /* MinorBaseOS */);
+	PatchALong(0x00000000);
+
+	PatchAReservedOSLstEntry(pTo_MinorLength, 0x0B /* MinorLength */);
+	PatchALong(kVidMemRAM_Size);
+
+#if 0
+	PatchAReservedOSLstEntry(pTo_MajorBase, 0x0C /* MinorBaseOS */);
+	PatchALong(0x00000000);
+
+	PatchAReservedOSLstEntry(pTo_MajorLength, 0x0D /* MinorLength */);
+	PatchALong(kVidMemRAM_Size);
+#endif
+
+	PatchAReservedOSLstEntry(pTo_VidDrvrDir, 0x04 /* sRsrcDrvrDir */);
+	pTo_sMacOS68020 = ReservePatchOSLstEntry();
+	PatchAnEndOfLst();
+
+	PatchAReservedOSLstEntry(pTo_sMacOS68020, 0x02 /* sMacOS68020 */);
+
+	PatchALong(4 + sizeof(VidDrvr_contents) + 8);
+	MyMoveBytes((ui3p)VidDrvr_contents,
+		pPatch, sizeof(VidDrvr_contents));
+	pPatch += sizeof(VidDrvr_contents);
+	PatchAWord(kcom_callcheck);
+	PatchAWord(kExtnVideo);
+	PatchALong(kExtn_Block_Base);
+
+	PatchAReservedOSLstEntry(pTo_OneBitMode, 0x80 /* oneBitMode */);
+	pTo_OneVidParams = ReservePatchOSLstEntry();
+	PatchADatLstEntry(0x03 /* mVidParams */, 0x00000001);
+	PatchADatLstEntry(0x04 /* mDevType */, 0x00000000);
+	PatchAnEndOfLst();
+
+	PatchAReservedOSLstEntry(pTo_OneVidParams, 0x01 /* mVidParams */);
+	PatchALong(0x0000002E); /* physical Block Size */
+	PatchALong(0x00000000); /* defmBaseOffset */
+	PatchAWord(vMacScreenWidth / 8);
+		/* (Bounds.R-Bounds.L)*PixelSize/8 */
+	PatchAWord(0x0000); /* Bounds.T */
+	PatchAWord(0x0000); /* Bounds.L */
+	PatchAWord(vMacScreenHeight); /* Bounds.B */
+	PatchAWord(vMacScreenWidth); /* Bounds.R */
+	PatchAWord(0x0000); /* bmVersion */
+	PatchAWord(0x0000); /* packType not used */
+	PatchALong(0x00000000); /* packSize not used */
+	PatchALong(0x00480000); /* bmHRes */
+	PatchALong(0x00480000); /* bmVRes */
+	PatchAWord(0x0000); /* bmPixelType */
+	PatchAWord(0x0001); /* bmPixelSize */
+	PatchAWord(0x0001); /* bmCmpCount */
+	PatchAWord(0x0001); /* bmCmpSize */
+	PatchALong(0x00000000); /* bmPlaneBytes */
+
+#if 0 != vMacScreenDepth
+	if (ColorModeWorks) {
+
+		PatchAReservedOSLstEntry(pTo_ColorBitMode, 0x81);
+		pTo_ColorVidParams = ReservePatchOSLstEntry();
+		PatchADatLstEntry(0x03 /* mVidParams */, 0x00000001);
+		PatchADatLstEntry(0x04 /* mDevType */,
+			(vMacScreenDepth < 4) ? 0x00000000 : 0x00000002);
+			/* 2 for direct devices, according to Basilisk II */
+		PatchAnEndOfLst();
+
+		PatchAReservedOSLstEntry(pTo_ColorVidParams, 0x01);
+		PatchALong(0x0000002E); /* physical Block Size */
+		PatchALong(0x00000000); /* defmBaseOffset */
+		PatchAWord(vMacScreenByteWidth);
+		PatchAWord(0x0000); /* Bounds.T */
+		PatchAWord(0x0000); /* Bounds.L */
+		PatchAWord(vMacScreenHeight); /* Bounds.B */
+		PatchAWord(vMacScreenWidth); /* Bounds.R */
+		PatchAWord(0x0000); /* bmVersion */
+		PatchAWord(0x0000); /* packType not used */
+		PatchALong(0x00000000); /* packSize not used */
+		PatchALong(0x00480000); /* bmHRes */
+		PatchALong(0x00480000); /* bmVRes */
+		PatchAWord((vMacScreenDepth < 4) ? 0x0000 : 0x0010);
+			/* bmPixelType */
+		PatchAWord(1 << vMacScreenDepth); /* bmPixelSize */
+		PatchAWord((vMacScreenDepth < 4) ? 0x0001 : 0x0003);
+			/* bmCmpCount */
+#if 4 == vMacScreenDepth
+		PatchAWord(0x0005); /* bmCmpSize */
+#elif 5 == vMacScreenDepth
+		PatchAWord(0x0008); /* bmCmpSize */
+#else
+		PatchAWord(1 << vMacScreenDepth); /* bmCmpSize */
+#endif
+		PatchALong(0x00000000); /* bmPlaneBytes */
+
+	}
+#endif
+
+	UsedSoFar = (pPatch - VidROM) + 20;
+	if (UsedSoFar > kVidROM_Size) {
+		ReportAbnormalID(0x0A01, "kVidROM_Size to small");
+		return falseblnr;
+	}
+
+	for (i = kVidROM_Size - UsedSoFar; --i >= 0; ) {
+		PatchAByte(0);
+	}
+
+	pPatch = (kVidROM_Size - 20) + VidROM;
+	PatchALong((pAt_sRsrcDir - pPatch) & 0x00FFFFFF);
+	PatchALong(/* 0x0000041E */ kVidROM_Size);
+	PatchALong(0x00000000);
+	PatchAByte(0x01);
+	PatchAByte(0x01);
+	PatchALong(0x5A932BC7);
+	PatchAByte(0x00);
+	PatchAByte(0x0F);
+
+	ChecksumSlotROM();
+
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+	CLUT_reds[0] = 0xFFFF;
+	CLUT_greens[0] = 0xFFFF;
+	CLUT_blues[0] = 0xFFFF;
+	CLUT_reds[CLUT_size - 1] = 0;
+	CLUT_greens[CLUT_size - 1] = 0;
+	CLUT_blues[CLUT_size - 1] = 0;
+#endif
+
+	return trueblnr;
+}
+
+IMPORTPROC Vid_VBLinterrupt_PulseNotify(void);
+
+GLOBALPROC Vid_Update(void)
+{
+	if (! Vid_VBLintunenbl) {
+		Vid_VBLinterrupt = 0;
+		Vid_VBLinterrupt_PulseNotify();
+	}
+}
+
+LOCALFUNC ui4r Vid_GetMode(void)
+{
+	return
+#if 0 != vMacScreenDepth
+		UseColorMode ? 129 :
+#endif
+		128;
+}
+
+LOCALFUNC tMacErr Vid_SetMode(ui4r v)
+{
+#if 0 == vMacScreenDepth
+	UnusedParam(v);
+#else
+	if (UseColorMode != ((v != 128) && ColorModeWorks)) {
+		UseColorMode = ! UseColorMode;
+		ColorMappingChanged = trueblnr;
+	}
+#endif
+	return mnvm_noErr;
+}
+
+GLOBALFUNC ui4r Vid_Reset(void)
+{
+#if 0 != vMacScreenDepth
+	UseColorMode = falseblnr;
+#endif
+	return 128;
+}
+
+#define kCmndVideoFeatures 1
+#define kCmndVideoGetIntEnbl 2
+#define kCmndVideoSetIntEnbl 3
+#define kCmndVideoClearInt 4
+#define kCmndVideoStatus 5
+#define kCmndVideoControl 6
+
+#define CntrlParam_csCode 0x1A /* control/status code [word] */
+#define CntrlParam_csParam 0x1C /* operation-defined parameters */
+
+#define VDPageInfo_csMode 0
+#define VDPageInfo_csData 2
+#define VDPageInfo_csPage 6
+#define VDPageInfo_csBaseAddr 8
+
+#define VDSetEntryRecord_csTable 0
+#define VDSetEntryRecord_csStart 4
+#define VDSetEntryRecord_csCount 6
+
+#define VDGammaRecord_csGTable 0
+
+#define VidBaseAddr 0xF9900000
+	/* appears to be completely ignored */
+
+LOCALVAR blnr UseGrayTones = falseblnr;
+
+LOCALPROC FillScreenWithGrayPattern(void)
+{
+	int i;
+	int j;
+	ui5b *p1 = (ui5b *)VidMem;
+
+#if 0 != vMacScreenDepth
+	if (UseColorMode) {
+#if 1 == vMacScreenDepth
+		ui5b pat = 0xCCCCCCCC;
+#elif 2 == vMacScreenDepth
+		ui5b pat = 0xF0F0F0F0;
+#elif 3 == vMacScreenDepth
+		ui5b pat = 0xFF00FF00;
+#elif 4 == vMacScreenDepth
+		ui5b pat = 0x00007FFF;
+#elif 5 == vMacScreenDepth
+		ui5b pat = 0x00000000;
+#endif
+		for (i = vMacScreenHeight; --i >= 0; ) {
+			for (j = vMacScreenByteWidth >> 2; --j >= 0; ) {
+				*p1++ = pat;
+#if 5 == vMacScreenDepth
+				pat = (~ pat) & 0x00FFFFFF;
+#endif
+			}
+			pat = (~ pat)
+#if 4 == vMacScreenDepth
+				& 0x7FFF7FFF
+#elif 5 == vMacScreenDepth
+				& 0x00FFFFFF
+#endif
+				;
+		}
+	} else
+#endif
+	{
+		ui5b pat = 0xAAAAAAAA;
+
+		for (i = vMacScreenHeight; --i >= 0; ) {
+			for (j = vMacScreenMonoByteWidth >> 2; --j >= 0; ) {
+				*p1++ = pat;
+			}
+			pat = ~ pat;
+		}
+	}
+}
+
+GLOBALPROC ExtnVideo_Access(CPTR p)
+{
+	tMacErr result = mnvm_controlErr;
+
+	switch (get_vm_word(p + ExtnDat_commnd)) {
+		case kCmndVersion:
+#if VID_dolog
+			dbglog_WriteNote("Video_Access kCmndVersion");
+#endif
+			put_vm_word(p + ExtnDat_version, 1);
+			result = mnvm_noErr;
+			break;
+		case kCmndVideoGetIntEnbl:
+#if VID_dolog
+			dbglog_WriteNote("Video_Access kCmndVideoGetIntEnbl");
+#endif
+			put_vm_word(p + 8,
+				Vid_VBLintunenbl ? 0 : 1);
+			result = mnvm_noErr;
+			break;
+		case kCmndVideoSetIntEnbl:
+#if VID_dolog
+			dbglog_WriteNote("Video_Access kCmndVideoSetIntEnbl");
+#endif
+			Vid_VBLintunenbl =
+				(0 == get_vm_word(p + 8))
+					? 1 : 0;
+			result = mnvm_noErr;
+			break;
+		case kCmndVideoClearInt:
+#if VID_dolog && 0 /* frequent */
+			dbglog_WriteNote("Video_Access kCmndVideoClearInt");
+#endif
+			Vid_VBLinterrupt = 1;
+			result = mnvm_noErr;
+			break;
+		case kCmndVideoControl:
+			{
+				CPTR CntrlParams = get_vm_long(p + 8);
+				CPTR csParam =
+					get_vm_long(CntrlParams + CntrlParam_csParam);
+				ui4r csCode =
+					get_vm_word(CntrlParams + CntrlParam_csCode);
+
+				switch (csCode) {
+					case 0: /* VidReset */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoControl, VidReset");
+#endif
+						put_vm_word(csParam + VDPageInfo_csMode,
+							Vid_GetMode());
+						put_vm_word(csParam + VDPageInfo_csPage, 0);
+							/* page is always 0 */
+						put_vm_long(csParam + VDPageInfo_csBaseAddr,
+							VidBaseAddr);
+
+						result = mnvm_noErr;
+						break;
+					case 1: /* KillIO */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoControl, KillIO");
+#endif
+						result = mnvm_noErr;
+						break;
+					case 2: /* SetVidMode */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoControl, "
+							"SetVidMode");
+#endif
+						if (0 != get_vm_word(
+							csParam + VDPageInfo_csPage))
+						{
+							/* return mnvm_controlErr, page must be 0 */
+							ReportAbnormalID(0x0A02,
+								"SetVidMode not page 0");
+						} else {
+							result = Vid_SetMode(get_vm_word(
+								csParam + VDPageInfo_csMode));
+							put_vm_long(csParam + VDPageInfo_csBaseAddr,
+								VidBaseAddr);
+						}
+						break;
+					case 3: /* SetEntries */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoControl, "
+							"SetEntries");
+#endif
+#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4)
+						if (UseColorMode) {
+							CPTR csTable = get_vm_long(
+								csParam + VDSetEntryRecord_csTable);
+							ui4r csStart = get_vm_word(
+								csParam + VDSetEntryRecord_csStart);
+							ui4r csCount = 1 + get_vm_word(
+								csParam + VDSetEntryRecord_csCount);
+
+							if (((ui4r) 0xFFFF) == csStart) {
+								int i;
+
+								result = mnvm_noErr;
+								for (i = 0; i < csCount; ++i) {
+									ui4r j = get_vm_word(csTable + 0);
+									if (j == 0) {
+										/* ignore input, leave white */
+									} else
+									if (j == CLUT_size - 1) {
+										/* ignore input, leave black */
+									} else
+									if (j >= CLUT_size) {
+										/* out of range */
+										result = mnvm_paramErr;
+									} else
+									{
+										ui4r r =
+											get_vm_word(csTable + 2);
+										ui4r g =
+											get_vm_word(csTable + 4);
+										ui4r b =
+											get_vm_word(csTable + 6);
+										CLUT_reds[j] = r;
+										CLUT_greens[j] = g;
+										CLUT_blues[j] = b;
+									}
+									csTable += 8;
+								}
+								ColorMappingChanged = trueblnr;
+							} else
+							if (csStart + csCount < csStart) {
+								/* overflow */
+								result = mnvm_paramErr;
+							} else
+							if (csStart + csCount > CLUT_size) {
+								result = mnvm_paramErr;
+							} else
+							{
+								int i;
+
+								for (i = 0; i < csCount; ++i) {
+									int j = i + csStart;
+
+									if (j == 0) {
+										/* ignore input, leave white */
+									} else
+									if (j == CLUT_size - 1) {
+										/* ignore input, leave black */
+									} else
+									{
+										ui4r r =
+											get_vm_word(csTable + 2);
+										ui4r g =
+											get_vm_word(csTable + 4);
+										ui4r b =
+											get_vm_word(csTable + 6);
+										CLUT_reds[j] = r;
+										CLUT_greens[j] = g;
+										CLUT_blues[j] = b;
+									}
+									csTable += 8;
+								}
+								ColorMappingChanged = trueblnr;
+								result = mnvm_noErr;
+							}
+						} else
+#endif
+						{
+							/* not implemented */
+						}
+						break;
+					case 4: /* SetGamma */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoControl, SetGamma");
+#endif
+						{
+#if 0
+							CPTR csTable = get_vm_long(
+								csParam + VDGammaRecord_csGTable);
+							/* not implemented */
+#endif
+						}
+#if 0
+						ReportAbnormalID(0x0A03,
+							"Video_Access SetGamma not implemented");
+#else
+						result = mnvm_noErr;
+#endif
+						break;
+					case 5: /* GrayScreen */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoControl, "
+							"GrayScreen");
+#endif
+						{
+#if 0
+							ui4r csPage = get_vm_word(
+								csParam + VDPageInfo_csPage);
+							/* not implemented */
+#endif
+							FillScreenWithGrayPattern();
+							result = mnvm_noErr;
+						}
+						break;
+					case 6: /* SetGray */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoControl, SetGray");
+#endif
+						{
+							ui3r csMode = get_vm_byte(
+								csParam + VDPageInfo_csMode);
+								/*
+									"Designing Cards and Drivers" book
+									says this is a word, but it seems
+									to be a byte.
+								*/
+
+							UseGrayTones = (csMode != 0);
+							result = mnvm_noErr;
+						}
+						break;
+					case 9: /* SetDefaultMode */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoControl, "
+							"SetDefaultMode");
+#endif
+						/* not handled yet */
+						/*
+							seen when close Monitors control panel
+							in system 7.5.5
+						*/
+						break;
+					case 16: /* SavePreferredConfiguration */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoControl, "
+							"SavePreferredConfiguration");
+#endif
+						/* not handled yet */
+						/*
+							seen when close Monitors control panel
+							in system 7.5.5
+						*/
+						break;
+					default:
+						ReportAbnormalID(0x0A04,
+							"kCmndVideoControl, unknown csCode");
+#if dbglog_HAVE
+						dbglog_writelnNum("csCode", csCode);
+#endif
+						break;
+				}
+			}
+			break;
+		case kCmndVideoStatus:
+			{
+				CPTR CntrlParams = get_vm_long(p + 8);
+				CPTR csParam = get_vm_long(
+					CntrlParams + CntrlParam_csParam);
+				ui4r csCode = get_vm_word(
+					CntrlParams + CntrlParam_csCode);
+
+				result = mnvm_statusErr;
+				switch (csCode) {
+					case 2: /* GetMode */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoStatus, GetMode");
+#endif
+						put_vm_word(csParam + VDPageInfo_csMode,
+							Vid_GetMode());
+						put_vm_word(csParam + VDPageInfo_csPage, 0);
+							/* page is always 0 */
+						put_vm_long(csParam + VDPageInfo_csBaseAddr,
+							VidBaseAddr);
+						result = mnvm_noErr;
+						break;
+					case 3: /* GetEntries */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoStatus, "
+							"GetEntries");
+#endif
+						{
+#if 0
+							CPTR csTable = get_vm_long(
+								csParam + VDSetEntryRecord_csTable);
+							put_vm_word(
+								csParam + VDSetEntryRecord_csStart,
+								csStart);
+							put_vm_word(
+								csParam + VDSetEntryRecord_csCount,
+								csCount);
+#endif
+							ReportAbnormalID(0x0A05,
+								"GetEntries not implemented");
+						}
+						break;
+					case 4: /* GetPages */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoStatus, GetPages");
+#endif
+						put_vm_word(csParam + VDPageInfo_csPage, 1);
+							/* always 1 page */
+						result = mnvm_noErr;
+						break;
+					case 5: /* GetPageAddr */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoStatus,"
+							" GetPageAddr");
+#endif
+						{
+							ui4r csPage = get_vm_word(
+								csParam + VDPageInfo_csPage);
+							if (0 != csPage) {
+								/*
+									return mnvm_statusErr,
+									page must be 0
+								*/
+							} else {
+								put_vm_long(
+									csParam + VDPageInfo_csBaseAddr,
+									VidBaseAddr);
+								result = mnvm_noErr;
+							}
+						}
+						break;
+					case 6: /* GetGray */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoStatus, GetGray");
+#endif
+						put_vm_word(csParam + VDPageInfo_csMode,
+							UseGrayTones ? 0x0100 : 0);
+							/*
+								"Designing Cards and Drivers" book
+								says this is a word, but it seems
+								to be a byte.
+							*/
+						result = mnvm_noErr;
+						break;
+					case 8: /* GetGamma */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoStatus, "
+							"GetGamma");
+#endif
+						/* not handled yet */
+						/*
+							seen when close Monitors control panel
+							in system 7.5.5
+						*/
+						break;
+					case 9: /* GetDefaultMode */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoStatus, "
+							"GetDefaultMode");
+#endif
+						/* not handled yet */
+						/* seen in System 7.5.5 boot */
+						break;
+					case 10: /* GetCurrentMode */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoStatus, "
+							"GetCurrentMode");
+#endif
+#if 0
+						put_vm_word(csParam + VDPageInfo_csMode,
+							Vid_GetMode());
+						put_vm_long(csParam + VDPageInfo_csData, 0);
+							/* what is this ? */
+						put_vm_word(csParam + VDPageInfo_csPage, 0);
+							/* page is always 0 */
+						put_vm_long(csParam + VDPageInfo_csBaseAddr,
+							VidBaseAddr);
+
+						result = mnvm_noErr;
+#endif
+						break;
+					case 12: /* GetConnection */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoStatus, "
+							"GetConnection");
+#endif
+						/* not handled yet */
+						/* seen in System 7.5.5 boot */
+						break;
+					case 13: /* GetCurrentMode */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoStatus, "
+							"GetCurrentMode");
+#endif
+						/* not handled yet */
+						/* seen in System 7.5.5 boot */
+						break;
+					case 14: /* GetModeBaseAddress */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoStatus, "
+							"GetModeBaseAddress");
+#endif
+						/* not handled yet */
+						/*
+							seen in System 7.5.5 Monitors control panel
+						*/
+						break;
+					case 16: /* GetPreferredConfiguration */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoStatus, "
+							"GetPreferredConfiguration");
+#endif
+						/* not handled yet */
+						/* seen in System 7.5.5 boot */
+						break;
+					case 17: /* GetNextResolution */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoStatus, "
+							"GetNextResolution");
+#endif
+						/* not handled yet */
+						/*
+							seen in System 7.5.5 monitors control panel
+							option button
+						*/
+						break;
+					case 18: /* GetVideoParameters */
+#if VID_dolog
+						dbglog_WriteNote(
+							"Video_Access kCmndVideoStatus, "
+							"GetVideoParameters");
+#endif
+						/* not handled yet */
+						/* seen in System 7.5.5 boot */
+						break;
+					default:
+						ReportAbnormalID(0x0A06,
+							"Video_Access kCmndVideoStatus, "
+								"unknown csCode");
+#if dbglog_HAVE
+						dbglog_writelnNum("csCode", csCode);
+#endif
+						break;
+				}
+			}
+			break;
+		default:
+			ReportAbnormalID(0x0A07,
+				"Video_Access, unknown commnd");
+			break;
+	}
+
+	put_vm_word(p + ExtnDat_result, result);
+}
--- /dev/null
+++ b/src/VIDEMDEV.h
@@ -1,0 +1,27 @@
+/*
+	VIDEMDEV.h
+
+	Copyright (C) 2008 Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#ifdef VIDEMDEV_H
+#error "header already included"
+#else
+#define VIDEMDEV_H
+#endif
+
+EXPORTFUNC blnr Vid_Init(void);
+EXPORTFUNC ui4r Vid_Reset(void);
+EXPORTPROC Vid_Update(void);
+
+EXPORTPROC ExtnVideo_Access(CPTR p);
--- /dev/null
+++ b/src/main.r
@@ -1,0 +1,55 @@
+/*
+	main.r
+
+	Copyright (C) 2003 Philip Cummins, Richard F. Bannister,
+		Paul C. Pratt
+
+	You can redistribute this file and/or modify it under the terms
+	of version 2 of the GNU General Public License as published by
+	the Free Software Foundation.  You should have received a copy
+	of the license along with this file; see the file COPYING.
+
+	This file is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	license for more details.
+*/
+
+#include "CNFGRSRC.h"
+
+/* Alerts Constants */
+
+#define kMyStandardAlert 128
+
+resource 'DITL' (kMyStandardAlert, purgeable) {
+	{ /* array DITLarray: 2 elements */
+		/* [1] */
+		{177, 293, 197, 351},
+		Button {
+			enabled,
+			"OK"
+		},
+		/* [2] */
+		{10, 72, 162, 353},
+		StaticText {
+			disabled,
+			"^0\n\n^1^2^3"
+		}
+	}
+};
+
+resource 'ALRT' (kMyStandardAlert, "Non Fatal Error", purgeable) {
+	{40, 43, 249, 405},
+	kMyStandardAlert,
+	{ /* array: 4 elements */
+		/* [1] */
+		OK, visible, sound1,
+		/* [2] */
+		OK, visible, sound1,
+		/* [3] */
+		OK, visible, sound1,
+		/* [4] */
+		OK, visible, sound1
+	},
+	alertPositionMainScreen
+};