diff -rcN STonX-0.6.4/INSTALL STonX-0.6.5/INSTALL
*** STonX-0.6.4/INSTALL	Mon Jan 22 00:23:30 1996
--- STonX-0.6.5/INSTALL	Thu Jan  1 01:00:00 1970
***************
*** 1,98 ****
- INSTALLATION INSTRUCTIONS
- =========================
- 
- In order to compile STonX, you will need the following:
- 
-  * A C compiler, preferably GNU C (but some ANSI C compilers, like DEC's
-   will do)
- 
-  * The M4 macro processor
- 
-  * a `csh'-compatible shell (to run the shell script m4_to_c.csh)
- 
-  * X11R5 or R6 libraries
-  
- These will suffice to get you started (unless I've forgotten something). 
- 
- 
- CONFIGURATION
- =============
- 
- STonX uses a "configure" script generated by the GNU Autoconf program in order
- to determine system-dependent configuration parameters. Invoke the script
- by typing
- 
- 	./configure
- 
- or, alternatively, 
- 
- 	sh configure
- 
- if the former doesn't work.
- 
- This will generate a `Makefile', link `config.h' to the appropriate file from
- the `config' subdirectory and generate dependencies for the Makefile. It will
- also generate some more sources.
- 
- If the `configure' script fails, please contact me at nino@complang.tuwien.ac.at
- and send me the output it generated. 
- 
- 
- ADDITIONAL CONFIGURATION OPTIONS
- ================================
- 
- After generating the Makefile, look at the file `options.h' (sparsely commented)
- and see if there is anything you want to change. The only options that you might
- need to change are TOS_1 (set to 1 is you have a TOS 1.0, 1.2 or 1.4 image)
- and SMALL (check if this is defined in the `config.h' as well), which should
- be set to 1 if your system has less than 16MB physical memory or if linking
- fails otherwise (it will result in an emulator which emulates 4MB RAM instead
- of 14MB, and takes up approximately 9MB swap space instead of 17MB).
- 
- 
- COMPILING
- =========
- 
- To compile, simply type 
- 	
- 	make
- 
- at the shell prompt. If you don't copy your TOS image to the directory
- containing the sources named `tos.img' before this point, the `make' process
- will stop after STonX has been linked and tell you to do it now. The TOS image
- is needed at this point in order to generate the Atari system fonts in .pcf
- format. You don't need to do this if you don't want to use the Xlib-VDI
- driver. After copying the TOS image, simply type `make' again to continue. The
- fonts will be extracted from the TOS image and installed temporarily in the
- `data' subdirectory. See the `INSTALLING' section for how to install them
- permanently.
- 
- After STonX has been compiled and linked successfully, you can start it
- by typing
- 
- 	./stonx
- 
- The command-line options can be listed with the `-h' option (`./stonx -h').
- 
- 
- INSTALLING
- ==========
- 
- At the moment, STonX can only be run from the directory containing the TOS
- image, i.e. there is no automatic system-wide installation. 
- 
- The system fonts should be installed in a place where the X server can find
- them. Examine your default font path with the `xset' command:
- 
- 	xset q
- 
- This will print (among other things) the current font path. If you copy
- the files ending in `.pcf' from the `data' subdirectory to one of the
- directories in the font path, go to that directory and do a 
- 
- 	mkfontdir .; xset fp rehash
- 
- the fonts will be installed permanently. Note that if you run STonX on a 
- different computer than the one handling your X display, you will have to
- install the fonts on the latter.
- 
--- 0 ----
diff -rcN STonX-0.6.4/Makefile.in STonX-0.6.5/Makefile.in
*** STonX-0.6.4/Makefile.in	Mon Jan 22 00:23:45 1996
--- STonX-0.6.5/Makefile.in	Fri Feb  9 19:06:25 1996
***************
*** 18,27 ****
--- 18,32 ----
  
  # X11 library path
  XLIBS=@X_LIBS@
+ SFLAGS=
  # MONITOR=1:
  #Linux:
  #XLIBS=@X_LIBS@ -L../../binutils-2.4 -lopcodes -lbfd -liberty -lncurses
  
+ #Linux SVGALIB support :
+ #XLIBS=@X_LIBS@ -lvgagl -lvga 
+ #SFLAGS=-DUSE_SVGALIB
+ 
  DEF= @def@ -DINLINE=@inline@
  
  # Compiler
***************
*** 31,40 ****
  # Preprocessor
  CPP=@CPP@
  
! CFLAGS= $(INC) $(DEF) $(OPT)
! OBJ=cpu.o monitor.o io.o main.o native.o screen.o utils.o hw.o ikbd.o debug.o\
  	prof.o xlib_vdi.o  blitter.o mem.o audio.o serial.o\
! 	parallel.o gemdos.o error.o ui.o mfp.o
  
  MOREOBJ= code0000.o code0300.o code0600.o code0900.o code1200.o code1500.o
  
--- 36,45 ----
  # Preprocessor
  CPP=@CPP@
  
! CFLAGS= $(INC) $(DEF) $(OPT) $(SFLAGS)
! OBJ=cpu.o monitor.o io.o main.o native.o utils.o hw.o ikbd.o debug.o\
  	prof.o xlib_vdi.o  blitter.o mem.o audio.o serial.o\
! 	parallel.o gemdos.o error.o ui.o mfp.o x.o svga.o screen.o 
  
  MOREOBJ= code0000.o code0300.o code0600.o code0900.o code1200.o code1500.o
  
***************
*** 47,54 ****
  	xlib_aes.h blitter.c audio.c serial.c parallel.c mem.c \
  	serial.h options.h missing.h gemdos.h COPYING configure.in\
  	cartridge.S error.c 68000.def gen.c gendefs.m4 gendefs.h emulator.h\
! 	amdefs.h genhead.c ui.c m4_to_c.csh cpu.h Keysyms.G atari/*\
! 	README INSTALL
  
  DEPSRC=$(CSRC) $(MOREOBJ:.o=.c)
  
--- 52,58 ----
  	xlib_aes.h blitter.c audio.c serial.c parallel.c mem.c \
  	serial.h options.h missing.h gemdos.h COPYING configure.in\
  	cartridge.S error.c 68000.def gen.c gendefs.m4 gendefs.h emulator.h\
! 	amdefs.h genhead.c ui.c m4_to_c.csh cpu.h Keysyms.G atari/*
  
  DEPSRC=$(CSRC) $(MOREOBJ:.o=.c)
  
diff -rcN STonX-0.6.4/README STonX-0.6.5/README
*** STonX-0.6.4/README	Tue Jan 16 23:52:45 1996
--- STonX-0.6.5/README	Thu Jan  1 01:00:00 1970
***************
*** 1,327 ****
- (note: this file has been obsoleted by the html documentation, which is being
- written, to some extent. It is not properly maintained, sorry)
- 
-       _____   _________           
-      /     \      |                  \     /
-      |            |                   \   /
-      \_____       |    ___    ___      \ /     ( ST on  )
-            \      |   /   \ |/   \     / \     ( Unix/X )
-            |      |   |   | |    |    /   \
-      \_____/      |   \___/ |    |  /      \
-       
- 
-                        VERSION 0.6 
- 
-               (C) 1995 by Marinos Yannikos
-                (nino@complang.tuwien.ac.at)
-       (http://www.complang.tuwien.ac.at/nino/home.html)
- 
- 	          ALL RIGHTS RESERVED
-  THIS PROGRAM IS PROVIDED "AS IS" WITHOUT A WARRANTY OF ANY KIND
- 
- 
-       See the file `COPYING' for licensing information
- 
-          Last change to this file: December 21, 1995
- 
- This file is separated into 4 sections:
- 
-   1.  About STonX (general description)
-   2.  Frequently Asked Questions
-   3.  The Future 
-   4.  History
- 
- --------------------------------------------------------------------------------
- 
-  1. ABOUT STonX
-  ##############
- 
- Copyright information
- ~~~~~~~~~~~~~~~~~~~~~
- STonX is free software and distributed under the GNU License. Read the file
- COPYING for details.
- 
- Intruduction
- ~~~~~~~~~~~~
- STonX is a software emulator, which runs on Unix workstations with the X Window
- system, and emulates an Atari ST computer. `Software emulator' means, that the
- system components, including the 68000 microprocessor, are emulated in software.
- This approach has the advantage, that it can be used regardless of the hardware
- the emulator runs on. Unfortunately, it also has the disadvantage that it is
- very slow.
- 
- Why use an emulator?
- ~~~~~~~~~~~~~~~~~~~~
- An emulator's sole purpose is to allow software written for a particular
- computer system to be used on other systems. A software emulator in particular
- is *not* useful for keeping your old programs while changing your hardware,
- except if the new hardware ist several orders of magnitude faster than the
- old one. 
- 
- What can STonX do?
- ~~~~~~~~~~~~~~~~~~
- As you may have guessed already, it is nearly impossible to emulate a computer
- system to its full extent. STonX was initially meant to be a very `low-level'
- emulator, meaning that it should be able to deal with hardware register 
- accesses and similar things, which it does quite well at the moment. A different
- approach would have been to disallow direct hardware access, and support only
- "clean" programs, like most GEM applications for example. At this time, STonX
- can cope with hardware accesses quite well (see below for limitations), and
- I hope to be able to finish the VDI driver for X in the near future, so that
- "clean" applications can use the graphics capabilities and speed of your X
- display.
- 
- Here is a list of the emulated system components:
- 
- * M68000 CPU     Everything (I hope) except Trace-Mode and correct bus- and
-                  address-error stack frames.
- 
- * MFP            Only the necessary parts to get TOS to run (Timer C and
-                  VBL). The MFP interrupt priorities are completely bogus,
-                  as are the other interrupts in the system, for efficiency
-                  reasons and lack of a complete MFP emulation, mainly.
- 
- * IKBD           Only keyboard keycodes and (incomplete) relative mouse mode.
- 
- * Shifter        ST Shifter, the STE support is not yet complete (the possible
-                  word-alignment of the screen would cause problems with the
-                  ST-Low and -Mid to ZPixmap conversion routines). 
- 
- * Disk-I/O       Still very limited. A general FDC/HDC-Emulation would probably
-                  not make sense, except for a few games. A GEMDOS-Driver for
-                  the Unix FS would be very useful. The native interface
-                  (opcode $a0ff, see 'faketos.c') will be helpful in implementing
-                  this.
- 
- * Mega ST(E)     Still buggy, haven't had time to correct it. It gets the hour
-   Clock Chip     wrong sometimes, and the alarm timer is not implemented (among
-                  other things).
- 
- * YM2149 sound   Available on several Unix platforms
-   chip
- 
- * Serial &       Not very useful yet, but enough for testing some
-   parallel ports telecommunication software
- 
- 
- The Xlib-VDI Driver
- ~~~~~~~~~~~~~~~~~~~
- As of version 0.3, the VDI is already quite usable. Note that the fonts used
- are all X fonts (BDF format), and must be installed properly. This is done in
- the Makefile (make fonts). The program `tosfonts' extracts the system fonts
- from the `tos.img' file (which you're going to need anyway), and installs
- them in the `data' subdirectory (see `data/makefonts.sh'). It also installs
- Latin-1 versions of these fonts so that you can use them for you XTerm windows!
- 
- Not that although it only implements monochrome routines, the Xlib-VDI Driver
- only runs on 8-bit color displays at the moment (sorry).
- 
- --------------------------------------------------------------------------------
- 
-  2. FREQUENTLY ASKED QUESTIONS
-  #############################
- 
- Q: Why can't I compile STonX on my Computer with Zintorola 86060 processor and
-    Sluggix 0.8 Beta O.S.?
- A: If you have GNU-C and X11R5/6 for this system, and STonX still won't compile,
-    please let me know as soon as possible, I will try to fix it.
- 
- Q: How do I leave the emulator `gently'?
- A: Press all 3 mouse buttons together
- 
- Q: What do all the warnings mean?
- A: Some keycodes can not be generated, because no mapping is defined for
-    them in `Keysyms'. Have a look at that file, and then do a `xmodmap -pke'
-    to find suitable Keysyms for mapping the missing ST-Keycodes to.
- 
- Q: Why doesn't STonX work on my X display?
- A: Currently, STonX is very choosy about X displays - it requires an 8 bit
-    display with PseudoColor visual capabilities. Building a version for
-    monochrome displays might be possible by defining -DMONO=1 in the Makefile,
-    but don't bet on it.
- 
- Q: Why do the graphics look funny / why are the letters reversed?
- A: Because I've merged the modifications for little-endian frame buffers
-    without testing it afterwards. Please let me know if this happens!
- 
- Q: Why does the emulator window go blank, and then my system starts swapping
-    for ages until I finally turn it off?
- A: STonX requires approximately 17MB memory, and during the initialization of
-    TOS it is quickly accessed linearly, so you should have at least 20MB
-    physical memory. You can try to add -DSMALL at the end of the DEF definition
-    in the Makefile and recompile everything. This will give create a version of
-    STonX which uses only 9MB of memory and emulates a 4MB ST. This option
-    has not been tested thoroughly, but seems to work.
- 
- Q: What TOS versions does STonX work with? Where do I get TOS images?
- A: I tried it with TOS 2.06, other versions haven't been tested, but TOS 
-    versions which support plain STs should work with it. At the moment, you
-    can only use TOS ROM images which normally begin at $E00000 in memory
-    (256K ROMs). TOS is copyrighted, so it would be illegal to distribute
-    a TOS image with STonX. To make a TOS image just copy 256K of memory
-    from $E00000 to a file and put it in the STonX directory with the name
-    `tos.img'.
- 
- Q: What's `cartridge.img' for?
- A: This is an cartridge image which installs the BIOS level disk routines.
-    It is necessary, since there is no FDC emulation (yet). If there was one,
-    the disk routines from TOS could be used.
- 
- Q: How do I get the emulator to load a program?
- A: The emulator can't deal with single programs, only with disks and disk 
-    images. If you want to load a disk in a format your Unix box can read,
-    you can try the option -disk a:/dev/rfd0 (or replace /dev/rfd0 with
-    whatever designates the raw floppy disk device on your system) to load
-    directly from disk. This works on Suns. If you want to load a disk
-    with a strange format (10 or 11 sectors etc.), you need to make a disk
-    image on the ST, and load that disk image onto your Unix disk. To make
-    a disk image, copy all sectors from the disk to a file (e.g. sectors
-    0-1599 on a 80/10/2 disk). Then, use the option -a:File (replace File with
-    the name of the disk image). You can also map several files/disks to 
-    TOS drives at the same time, e.g. by using -c:File for drive C. Remember
-    that you always map something to drive A though.
- 
- Q: Program XXX doesn't run, what should I do?
- A: If the program is known to run with the TOS you are using with STonX, 
-    and if it doesn't (or shouldn't) use any of the system components not
-    yet emulated (see section 1), and if you're getting a 2 bomb bus error,
-    it probably accesses a memory location which is not documented, but 
-    exists in STs. Please rebuild STonX with -DDEBUG=1, run the program
-    again, wait until the crash, and look at the end of DEBUGFILE for a
-    message like "pc=<A> sr=<B> BUS ERROR -> <C>". At the previous line,
-    there should be a description of the offending memory access. Please
-    inform me about it! Note that you're looking at the wrong BUS ERROR
-    message if you got 2 bombs on the screen and <C> above does not begin
-    with `2'.
- 
- Q: Why are the locations of the ST and X mouse cursors different?
- A: Because the emulator has (at the moment) no way to tell where the
-    emulated system keeps its mouse cursor positions in memory. When you
-    enter the emulator window, you can freeze the ST mouse cursor with the
-    right mouse button, move to it with the X cursor, and press the right
-    mouse button again to "pick it up". A better solution is in the works...
- 
- Q: Why do some keys seem to 'hang' e.g. in Megaroids?
- A: Because the interrupt priorities are bogus, and in some cases data from
-    the IKBD may be lost. 
- 
- Q: Why can't the mouse be switched off (e.g. in games)?
- A: Because the emulated IKBD doesn't (yet) understand any commands
- 
- Q: Where can I get the newest version of STonX? 
- A: Probably at ftp.complang.tuwien.ac.at/pub/nino/ or 
-    http://www.complang.tuwien.ac.at/nino/
-    Don't bet on it though! :-) 
- 
- Q: Why do benchmark programs show much better values than what they should?
- A: Because Timer C, which is often used for measuring time, is running at
-    a lower frequency than the usual 200Hz. Look at the output to stderr when
-    starting STonX, it will tell you the actual frequency. If it is e.g. 50Hz,
-    the values reported by benchmark programs will be 4 x higher than they
-    should be.
- 
- Q: When will the VDI driver be finished?
- A: If I knew the answer, I'd probably never have started... :-)
- 
- Q: What can I do to speed up the development of STonX?
- A: You can try to bribe me with any amount of money, any type of hardware or
-    software for the Atari ST or SunOS 4.1 (no pirated stuff please).
-    A nice postcard might suffice too. :-)
- 
- --------------------------------------------------------------------------------
- 
-  3. THE FUTURE
-  #############
- 
- Things left to do:
- - Finish the VDI driver
- - Speed up the emulation with little-endian hosts
- - Maybe write a FDC emulation
- - Optimize a bit more
- - Complete the IKBD emulation (esp. Joystick)
- - Fix the bug in the clock chip emulation
- (etc. etc.)
- 
- --------------------------------------------------------------------------------
- 
-  4. HISTORY
-  ##########
- 
- In the beginning there were absurd plans, long sleepless nights, and incredible
- boredom.
- 
- First version with a version number - Version 0.1 Alpha (Apr 11 1995)
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- - Added -refresh option
- - Wrote an `Autoconf' script
- - Removed the Xlib calls from the signal handler
- - Use sigaction() instead of signal() (Thanks to Des Herriott for the hint!)
- - Added global register variable declarations for SGIs (untested)
- - Fixed bug in colormap handling which bloated up the Xserver if colormap
-   changed frequently
- - Fixed bug which caused bus errors at naughty accesses to $ff8206
-   (Grav2 runs now! ;-))
- - The keyboard auto repeat is now only turned off if the X mouse pointer is
-   inside the emulator window
- - Merged some patches for little-endian machines and little-endian frame buffers
-   (untested)
- 
- Version 0.2 Alpha (Apr 13 1995)
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- - Fixed invalid initialisation of sigset_t variable in hw.c
- - Fixed problem with multiple keycodes mapped to the same Keysym.
-   This prevented e.g. a keyboard reset with the usual combination if both the
-   normal and the Keypad Del key were mapped to the "Delete" keysym.
- - Fixed description of 8th change above. :-) (on -> off)
- - Changed the default frequencies to something more reasonable
- - Implemented (simple) VDI input functions
- - It is now possible to switch between the `old style' window and the VDI
-   window at runtime. This feature may disappear in the future.
- - X events are now processed at every VBL, not at every screen update
- - The `old style' window is not updated if the X pointer is in the VDI
-   window
- - Added -DSMALL for people with less memory and/or patience
- - Added a chmod +w Makefile to Makefile.in (make depend rule)
- - Changed stricmp() to strncasecmp()
- 
- Version 0.3 Alpha (Apr 15 1995)
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- - Fixed 12 bit FAT assumption and Media-Change bug, large diskfiles work now
- - Improved the VDI driver, now it looks almost exactly like TOS VDI
- - Wrote programs to help convert GEM Bitmap Fonts to BDF format
- 
- Version 0.4 Beta (Jul 25 1995)
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- - first public release
- - Integrated Griff's blitter emulator
- - The VDI driver redraws at expose events now
- - The VDI driver works with monochrome displays now, and -DMONO has been 
-   eliminated
- - Little-endian fixes for the VDI driver and fnttobdf
- - Linux port and assembly support
- - Emulation is a bit faster now for some instructions
- - Condition codes N,Z are now evaluated lazily (this makes STonX incompatible
-   with the real 68000 in some rare cases, but I haven't seen code that uses
-   this)
- 
- Version 0.5 (Nov 30 1995)
- ~~~~~~~~~~~~~~~~~~~~~~~~~
- - Integrated sound, serial and parallel port support
- - Fixed a few bugs, e.g. the one that caused the Alpha console crash
- - Added colormap sharing (#define NEWCOLOR 1 in screen.c)
- - Added a Unix filesystem interface (option -fs, file gemdos.c)
- - More assembly support for x86
- - mkfonts.sh is now a /bin/sh script
- - TOS 1.X support where X=0,2,4. Executing programs over the Unix filesystem
-   interface may not work with TOS <1.4 (sorry)
- - Timer C is now optionally 200Hz
- 
- Version 0.6 (Dec 21, 1995)
- ~~~~~~~~~~~~~~~~~~~~~~~~~~
- - Emulation code has been almost completely rewritten, resulting in 
-   1) 20-80% speed increase, 65% on my Linux PC and 80% on our Alphas
-   2) Less memory and more time needed to compile cpu.c 
-   3) More easily maintainable code
- - experimental implementation of the -size option
- - added Griff's patches to main.c to read options from a $HOME/.stonxrc file
- 
--- 0 ----
diff -rcN STonX-0.6.4/audio.c STonX-0.6.5/audio.c
*** STonX-0.6.4/audio.c	Sun Jan 21 19:21:42 1996
--- STonX-0.6.5/audio.c	Fri Feb  9 19:19:56 1996
***************
*** 9,15 ****
   *	Last Updated : November 15th 1995. 
   */
  
! #include "defs.h"
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
--- 9,17 ----
   *	Last Updated : November 15th 1995. 
   */
  
! #include "main.h"
! #include "tosdefs.h"
! #include "mem.h"
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
***************
*** 17,25 ****
  #include <signal.h>
  #include <sys/types.h>
  #include <sys/time.h>
- #include "main.h"
- #include "tosdefs.h"
- #include "mem.h"
  
  #ifdef STONX_AUDIO_LINUX
  #define HAVE_AUDIO
--- 19,24 ----
***************
*** 32,43 ****
  #include <unistd.h>
  #define LINUX_DEFAULT_FREQ (22050)
  
! /* this adds low latency sound for VOXWARE 3 - enjoy! */
  
! #if defined(SNDCTL_DSP_SETFRAGMENT) && defined(SNDCTL_DSP_GETOSPACE)
  #define LINUX_AUDIO_VOXWARE3 
  #endif
- 
  #endif
  
  
--- 31,42 ----
  #include <unistd.h>
  #define LINUX_DEFAULT_FREQ (22050)
  
! /* this adds low latency sound for VOXWARE 3 - enjoy! 
! */
  
! #if defined(SNDCTL_DSP_SETFRAGMENT) 
  #define LINUX_AUDIO_VOXWARE3 
  #endif
  #endif
  
  
***************
*** 106,116 ****
--- 105,117 ----
  #define DEC_DEFAULT_BUFFERSIZE (2048)
  #endif
  
+ #define DEBUG_SND 0
  
  #define STATIC static
  
  static void init_noise(void);
  static void init_envelope(void);
+ static void init_cliptable(void);
  
  /*
   *	Unix audio vars.
***************
*** 218,331 ****
  	&Envelope1111
  };
  
! STATIC unsigned int SquarewaveW[16] =
! { 	0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,
  }; 
! 
  STATIC unsigned char envs[16][ENV_SIZE*4];
! STATIC unsigned char Noise_Table[NOISE_SIZE];
! STATIC unsigned char STE_voice[MAX_SAMPLES];
! STATIC unsigned char YM_voice1[MAX_SAMPLES];
! STATIC unsigned char YM_voice2[MAX_SAMPLES];
! STATIC unsigned char YM_voice3[MAX_SAMPLES];
! STATIC unsigned char Envelope[MAX_SAMPLES];
! STATIC unsigned char Noise[MAX_SAMPLES];
  
  /*
   * Hardware Register emulation functions 
   */ 
    
- STATIC B ff8800,ff8801,ff8802,ff8803;
- 
  B LOAD_B_ff8800(void) 
  { 	
! 	/*fprintf(stderr,"Load $ff8800 - current selected : %d\n",YM_select & 15);*/
! 	switch (YM_select & 15)
  	{	case 0:  
  			return Snd.YM_ChannelA.finetune;
- 			break;	
  		case 1:
  			return Snd.YM_ChannelA.crsetune;
- 			break;	
  		case 2:  
  			return Snd.YM_ChannelB.finetune;
- 			break;	
  		case 3:
  			return Snd.YM_ChannelB.crsetune;
- 			break;	
  		case 4:  
  			return Snd.YM_ChannelC.finetune;
- 			break;	
  		case 5:
  			return Snd.YM_ChannelC.crsetune;
- 			break;	
  		case 6:
  			return Snd.YM_NoiseControl;
- 			break;
  		case 7:
  			return Snd.YM_MixerControl;
- 			break;
  		case 8:
  			return Snd.YM_ChannelA.amplitude;
- 			break;
  		case 9:
  			return Snd.YM_ChannelB.amplitude;
- 			break;
  		case 10:
  			return Snd.YM_ChannelC.amplitude;
- 			break;
  		case 11:
  			return Snd.YM_Envelope_fine_period;
- 			break;
  		case 12:
  			return Snd.YM_Envelope_crse_period;
- 			break;
  		case 13:
  			return Snd.YM_Envelope_shape;
- 			break;
  		case 14:
  			return Snd.IO_PortA & 0xf8;
- 			break;
  		case 15:
  			return Snd.IO_PortB;
  	}
  }
  
  B LOAD_B_ff8801(void)
! {	return ff8801;
  }
  
  B LOAD_B_ff8802(void)
! {	return ff8802;
  }
  
  B LOAD_B_ff8803(void)
! {	return ff8803;
  }
  
  void STORE_B_ff8800(B v)
  {	
  	/*fprintf(stderr,"Store $ff8800 : %d\n",v);*/
! 	ff8800 = YM_select = v;
  }
  
  void STORE_B_ff8801(B v)
  {	
  	/*fprintf(stderr,"Store $ff8801 : %d\n",v);*/
! 	ff8801=v;
  }
  
  void STORE_B_ff8802(B v)
  {	
  	/*fprintf(stderr,"Store $ff8802 : %d\n",v);*/
! 	ff8802 = v;	
! 	switch (YM_select & 0x0f)
  	{	case 0:  
  			Snd.YM_ChannelA.finetune=v & 0xff;
  			break;	
  		case 1:
! 			Snd.YM_ChannelA.crsetune=v & 0x0f;
! 			break;	
  		case 2:  
  			Snd.YM_ChannelB.finetune=v & 0xff;
  			break;	
--- 219,320 ----
  	&Envelope1111
  };
  
! STATIC int SquarewaveW[16] =
! { 	-128,-128,-128,-128,-128,-128,-128,-128,	
! 	+127,+127,+127,+127,+127,+127,+127,+127
  }; 
! STATIC int *clip_tab;
! STATIC int clip_table[512];
  STATIC unsigned char envs[16][ENV_SIZE*4];
! STATIC char Noise_Table[NOISE_SIZE];
! STATIC int Envelope[MAX_SAMPLES];
! STATIC int Noise[MAX_SAMPLES];
! STATIC int mix_buffer[MAX_SAMPLES];
  
  /*
   * Hardware Register emulation functions 
   */ 
    
  B LOAD_B_ff8800(void) 
  { 	
! 	/*fprintf(stderr,"Load $ff8800 - current selected : %d\n",YM_select);*/
! 	switch (YM_select)
  	{	case 0:  
  			return Snd.YM_ChannelA.finetune;
  		case 1:
  			return Snd.YM_ChannelA.crsetune;
  		case 2:  
  			return Snd.YM_ChannelB.finetune;
  		case 3:
  			return Snd.YM_ChannelB.crsetune;
  		case 4:  
  			return Snd.YM_ChannelC.finetune;
  		case 5:
  			return Snd.YM_ChannelC.crsetune;
  		case 6:
  			return Snd.YM_NoiseControl;
  		case 7:
  			return Snd.YM_MixerControl;
  		case 8:
  			return Snd.YM_ChannelA.amplitude;
  		case 9:
  			return Snd.YM_ChannelB.amplitude;
  		case 10:
  			return Snd.YM_ChannelC.amplitude;
  		case 11:
  			return Snd.YM_Envelope_fine_period;
  		case 12:
  			return Snd.YM_Envelope_crse_period;
  		case 13:
  			return Snd.YM_Envelope_shape;
  		case 14:
  			return Snd.IO_PortA & 0xf8;
  		case 15:
  			return Snd.IO_PortB;
  	}
  }
  
  B LOAD_B_ff8801(void)
! {	return 0xff;			/* checked : always returns 0xff */
  }
  
  B LOAD_B_ff8802(void)
! {	return 0;
  }
  
  B LOAD_B_ff8803(void)
! {	return 0xff;			/* checked : always returns 0xff */
  }
  
  void STORE_B_ff8800(B v)
  {	
  	/*fprintf(stderr,"Store $ff8800 : %d\n",v);*/
! 	YM_select = v & 15;
  }
  
  void STORE_B_ff8801(B v)
  {	
  	/*fprintf(stderr,"Store $ff8801 : %d\n",v);*/
! 
! 	/* should this do what 8800 does??? on a Falcon it seems to!!! */
  }
  
  void STORE_B_ff8802(B v)
  {	
  	/*fprintf(stderr,"Store $ff8802 : %d\n",v);*/
! 	switch (YM_select)
  	{	case 0:  
  			Snd.YM_ChannelA.finetune=v & 0xff;
+ #if (DEBUG_SND)
+ 			fprintf(stderr,"Channel A fine tune:%d\n",(UL) v);
+ #endif
  			break;	
  		case 1:
! 			Snd.YM_ChannelA.crsetune=v & 0x0f; 
! #if (DEBUG_SND)
! 			fprintf(stderr,"Channel A course tune:%d\n",(UL)v);
! #endif
! 			break;					
  		case 2:  
  			Snd.YM_ChannelB.finetune=v & 0xff;
  			break;	
***************
*** 343,367 ****
  			break;
  		case 7:
  			Snd.YM_MixerControl=v & 0xff;
  			break;
  		case 8:
  			Snd.YM_ChannelA.amplitude=v & 0x1f;
  			break;
  		case 9:
  			Snd.YM_ChannelB.amplitude=v & 0x1f;
  			break;
  		case 10:
  			Snd.YM_ChannelC.amplitude=v & 0x1f;
  			break;
  		case 11:
  			Snd.YM_Envelope_fine_period=v & 0xff;
  			break;
  		case 12:
  			Snd.YM_Envelope_crse_period=v & 0xff;
! 			Snd.YM_flag = 1;
  			break;
  		case 13:
  			Snd.YM_Envelope_shape=v & 0x0f;
  			break;
  		case 14:
  			Snd.IO_PortA = v;
--- 332,380 ----
  			break;
  		case 7:
  			Snd.YM_MixerControl=v & 0xff;
+ #if (DEBUG_SND)
+ 			fprintf(stderr,"Mixer Control:%d\n",(UL) v);
+ #endif
  			break;
  		case 8:
  			Snd.YM_ChannelA.amplitude=v & 0x1f;
+ #if (DEBUG_SND)
+ 			if (Snd.YM_ChannelA.amplitude & 0x10)
+ 				fprintf(stderr,"Channel A Enveloping ON:%d\n",v);
+ #endif
  			break;
  		case 9:
  			Snd.YM_ChannelB.amplitude=v & 0x1f;
+ #if (DEBUG_SND)
+ 			if (Snd.YM_ChannelB.amplitude & 0x10)
+ 				fprintf(stderr,"Channel B Enveloping ON:%d\n",v);
+ #endif
  			break;
  		case 10:
  			Snd.YM_ChannelC.amplitude=v & 0x1f;
+ #if (DEBUG_SND)
+ 			if (Snd.YM_ChannelC.amplitude & 0x10)
+ 				fprintf(stderr,"Channel C Enveloping ON:\n");
+ #endif
  			break;
  		case 11:
  			Snd.YM_Envelope_fine_period=v & 0xff;
+ #if (DEBUG_SND)
+ 			fprintf(stderr,"Fine envelope:%d\n",(UL) v);
+ #endif
  			break;
  		case 12:
  			Snd.YM_Envelope_crse_period=v & 0xff;
! #if (DEBUG_SND)
! 			fprintf(stderr,"Course envelope:%d\n",(UL) v);
! #endif
  			break;
  		case 13:
  			Snd.YM_Envelope_shape=v & 0x0f;
+ #if (DEBUG_SND)
+ 			fprintf(stderr,"Envelope shape set/trigger :%d\n",v);
+ #endif
+ 			Snd.YM_flag = 1;
  			break;
  		case 14:
  			Snd.IO_PortA = v;
***************
*** 375,393 ****
  
  void STORE_B_ff8803(B v)
  {	/*fprintf(stderr,"Store $ff8803 : %d\n",v);*/
! 	ff8803=v;
  }
  
  /* 
   *	Generate a single YM 2149 Voice.
   */
  
! void generate_YM_voice(YM_Voice *YM,unsigned char *V,unsigned int *Current_IntFrac,int TONE_MASK)
  { 	
  	int i;
  	unsigned int F=*Current_IntFrac;
  	unsigned int YM_freq;
  	unsigned int tune = YM->finetune + (YM->crsetune<<8);
  	if (tune)
  	{	float t  = ((float)FREQ_base*65536*256*16) / tune;
  		YM_freq = (unsigned int) t;
--- 388,410 ----
  
  void STORE_B_ff8803(B v)
  {	/*fprintf(stderr,"Store $ff8803 : %d\n",v);*/
! 
! 	
  }
  
+ static int amp_tab[16]= { 	 0, 1, 1, 2, 3,  4,  5,  7,	
+ 				12,20,28,44,70,110,165,255	};
  /* 
   *	Generate a single YM 2149 Voice.
   */
  
! static void generate_YM_voice(YM_Voice *YM,unsigned int *Current_IntFrac,int TONE_MASK)
  { 	
  	int i;
  	unsigned int F=*Current_IntFrac;
  	unsigned int YM_freq;
  	unsigned int tune = YM->finetune + (YM->crsetune<<8);
+ 	int *V = mix_buffer;
  	if (tune)
  	{	float t  = ((float)FREQ_base*65536*256*16) / tune;
  		YM_freq = (unsigned int) t;
***************
*** 399,448 ****
  	{	
  		if (Snd.YM_MixerControl & TONE_MASK)
  		{	
! 			if (Snd.YM_MixerControl & (TONE_MASK<<3))
! 			{	/* Has Envelope, No TONE, No Noise */	
! 				for (i = 0 ; i < samples_to_generate  ; i++)
! 					 V[i] = 0; 
! 			} else
  			{	/* Has Envelope,No Tone, Has Noise */ 
  				for (i = 0 ; i < samples_to_generate  ; i++)
! 					V[i] = ((unsigned int) (Noise[i]*Envelope[i]) >> 8);
  			}
  		} else
  		{	
  			if (Snd.YM_MixerControl & (TONE_MASK<<3))
  			{ /* Has Envelope,Has Tone, No Noise */
  				for (i = 0 ; i < samples_to_generate ; i++,F+=YM_freq)
! 					V[i] = ( (unsigned int) SquarewaveW[(F) >> 28] * Envelope[i]) >> 8;
  			} else
  			{ /* Has Envelope,Has Tone and Noise */ 
  				for (i = 0 ; i < samples_to_generate  ; i++,F+=YM_freq)
! 					V[i] = ( (unsigned int) (SquarewaveW[(F) >> 28] ^ Noise[i]) * Envelope[i]) >> 8;
   			}
  		}
  	} else				/* voice using amplitude */
! 	{	unsigned int amp = (YM->amplitude) * 16;
  		if (Snd.YM_MixerControl & TONE_MASK)
  		{	
! 			if (Snd.YM_MixerControl & (TONE_MASK<<3))
! 			{	/* No Envelope, No Tone, No Noise */	
! 				for (i = 0 ; i < samples_to_generate  ; i++)
! 					 V[i] = 0;
! 			} else
  			{	/* No Envelope, No Tone, Has Noise */ 
  				for (i = 0 ; i < samples_to_generate  ; i++)
! 					V[i] = ( (unsigned int) Noise[i] * amp) >> 8;
  			}	
  		} else
  		{	
  			if (Snd.YM_MixerControl & (TONE_MASK<<3))
  			{ /* No Envelope, Has Tone, No Noise */
  				for (i = 0 ; i < samples_to_generate ; i++,F+=YM_freq)
! 					V[i] = ( (unsigned int) SquarewaveW[(F) >> 28] * amp) >> 8; 
  			} else
  			{ /* No Envelope, Has Tone, Has Noise */ 
  				for (i = 0 ; i < samples_to_generate  ; i++,F+=YM_freq)
! 					V[i] = ( (unsigned int) (SquarewaveW[(F) >> 28] ^ Noise[i]) * amp) >> 8;
  			} 
  		} 
  	}	 
--- 416,462 ----
  	{	
  		if (Snd.YM_MixerControl & TONE_MASK)
  		{	
! 			if (!(Snd.YM_MixerControl & (TONE_MASK<<3)))
  			{	/* Has Envelope,No Tone, Has Noise */ 
  				for (i = 0 ; i < samples_to_generate  ; i++)
! 					V[i] = clip_tab[V[i]+((Noise[i]*Envelope[i])>>8)];
  			}
  		} else
  		{	
  			if (Snd.YM_MixerControl & (TONE_MASK<<3))
  			{ /* Has Envelope,Has Tone, No Noise */
  				for (i = 0 ; i < samples_to_generate ; i++,F+=YM_freq)
! 					V[i] = clip_tab[V[i]+((SquarewaveW[F>>28]*Envelope[i])>>8)];
  			} else
  			{ /* Has Envelope,Has Tone and Noise */ 
  				for (i = 0 ; i < samples_to_generate  ; i++,F+=YM_freq)
! 					V[i] = clip_tab[V[i]+((clip_tab[SquarewaveW[F>>28]+Noise[i]]*Envelope[i])>>8)];
   			}
  		}
  	} else				/* voice using amplitude */
! 	{	
! #if (1)
! 		int amp = amp_tab[YM->amplitude];
! #else
! 		int amp = (YM->amplitude) * 16;
! #endif
  		if (Snd.YM_MixerControl & TONE_MASK)
  		{	
! 			if (!(Snd.YM_MixerControl & (TONE_MASK<<3)))
  			{	/* No Envelope, No Tone, Has Noise */ 
  				for (i = 0 ; i < samples_to_generate  ; i++)
! 					V[i] = clip_tab[V[i]+((Noise[i]*amp)>>8)];
  			}	
  		} else
  		{	
  			if (Snd.YM_MixerControl & (TONE_MASK<<3))
  			{ /* No Envelope, Has Tone, No Noise */
  				for (i = 0 ; i < samples_to_generate ; i++,F+=YM_freq)
! 					V[i] = clip_tab[V[i]+((SquarewaveW[F>>28]*amp)>>8)]; 
  			} else
  			{ /* No Envelope, Has Tone, Has Noise */ 
  				for (i = 0 ; i < samples_to_generate  ; i++,F+=YM_freq)
! 					V[i] = clip_tab[V[i]+((clip_tab[SquarewaveW[F>>28]+Noise[i]]*amp)>>8)];
  			} 
  		} 
  	}	 
***************
*** 465,470 ****
--- 479,485 ----
  	FD_ZERO(&ex_fds);
  	init_noise();
  	init_envelope();
+ 	init_cliptable();
  	Audio.machine_audio_open(); 
  	while (1)
  	{	
***************
*** 505,514 ****
  			} else
  				Noise_Freq = 0;
  			for (i = 0 ; i < samples_to_generate ; i++,Noise_IntFrac+=Noise_Freq)
! 				Noise[i] = Noise_Table[(Noise_IntFrac >> 16) & (NOISE_SIZE-1)];
  		}
  
! 		if ( (Snd.YM_ChannelA.amplitude & 0x10) || (Snd.YM_ChannelB.amplitude & 0x010) || (Snd.YM_ChannelC.amplitude & 0x010) ) 
  		{	/* Generate Frequency Shifted Envelope */
  			unsigned char *Env= &envs[Snd.YM_Envelope_shape][0];
  			unsigned int env_period = (Snd.YM_Envelope_crse_period<<8) + Snd.YM_Envelope_fine_period;
--- 520,529 ----
  			} else
  				Noise_Freq = 0;
  			for (i = 0 ; i < samples_to_generate ; i++,Noise_IntFrac+=Noise_Freq)
! 				Noise[i] = (int) Noise_Table[(Noise_IntFrac >> 16) & (NOISE_SIZE-1)];
  		}
  
! 		if ( (Snd.YM_ChannelA.amplitude & 0x10) || (Snd.YM_ChannelB.amplitude & 0x10) || (Snd.YM_ChannelC.amplitude & 0x10) ) 
  		{	/* Generate Frequency Shifted Envelope */
  			unsigned char *Env= &envs[Snd.YM_Envelope_shape][0];
  			unsigned int env_period = (Snd.YM_Envelope_crse_period<<8) + Snd.YM_Envelope_fine_period;
***************
*** 519,525 ****
  				Env_Freq = 0;
  
  			for (i = 0 ; i < samples_to_generate ; i++)
! 			{	Envelope[i] =  Env[Env_IntFrac>>16];
  				Env_IntFrac += Env_Freq;
  				/* this is particularly crap... */
  				while (Env_IntFrac >= ((ENV_SIZE*4)<<16)) 
--- 534,540 ----
  				Env_Freq = 0;
  
  			for (i = 0 ; i < samples_to_generate ; i++)
! 			{	Envelope[i] =  amp_tab[Env[Env_IntFrac>>16]>>4];
  				Env_IntFrac += Env_Freq;
  				/* this is particularly crap... */
  				while (Env_IntFrac >= ((ENV_SIZE*4)<<16)) 
***************
*** 527,542 ****
  			}
  		}
  
! 		generate_YM_voice(&Snd.YM_ChannelA,YM_voice1,&YM_voice1_IntFrac,1);
! 		generate_YM_voice(&Snd.YM_ChannelB,YM_voice2,&YM_voice2_IntFrac,2);
! 		generate_YM_voice(&Snd.YM_ChannelC,YM_voice3,&YM_voice3_IntFrac,4);
  
  		if (audio_samplebits == 8)
! 		{	unsigned char *buf = (unsigned char *) audio_buffer;
  			for (i = 0 ; i < samples_to_generate ; i++)
! 			{	unsigned int v = ( (unsigned int)YM_voice1[i]+(unsigned int)YM_voice2[i]+(unsigned int) YM_voice3[i]);
! 				buf[i] = v>>2; 
! 			}
  #ifdef STONX_AUDIO_DEC
          		mmeProcessCallbacks();
        			{	MMRESULT	status;
--- 542,556 ----
  			}
  		}
  
! 		bzero(mix_buffer,samples_to_generate*sizeof(int)); 
  
+ 		generate_YM_voice(&Snd.YM_ChannelA,&YM_voice1_IntFrac,1); 
+ 		generate_YM_voice(&Snd.YM_ChannelB,&YM_voice2_IntFrac,2);
+ 		generate_YM_voice(&Snd.YM_ChannelC,&YM_voice3_IntFrac,4);
  		if (audio_samplebits == 8)
! 		{	char *buf = (char *) audio_buffer;
  			for (i = 0 ; i < samples_to_generate ; i++)
! 				buf[i] = mix_buffer[i]^0x80;
  #ifdef STONX_AUDIO_DEC
          		mmeProcessCallbacks();
        			{	MMRESULT	status;
***************
*** 551,557 ****
  			}
  
  #else
- 
  			write(devAudio,audio_buffer,samples_to_generate); 
  
  #endif
--- 565,570 ----
***************
*** 560,574 ****
  			UW *buf = (UW *) audio_buffer;
  #ifdef STONX_AUDIO_SGI
  			for (i = 0 ; i < samples_to_generate ; i++)
! 			{	unsigned int v = ( (unsigned int)YM_voice1[i]+(unsigned int)YM_voice2[i]+(unsigned int) YM_voice3[i]);
! 				buf[i] = (v<<6) ^ 0x8000; 
! 			}
  			ALwritesamps(port,audio_buffer, (samples_to_generate) );
  #else
  			for (i = 0 ; i < samples_to_generate ; i++) 
! 			{	unsigned int v = ( (unsigned int)YM_voice1[i]+(unsigned int)YM_voice2[i]+(unsigned int) YM_voice3[i]);
! 				buf[i] = (v<<6); 
! 			}
  			write(devAudio,audio_buffer,samples_to_generate*2); 
  #endif
  		}
--- 573,583 ----
  			UW *buf = (UW *) audio_buffer;
  #ifdef STONX_AUDIO_SGI
  			for (i = 0 ; i < samples_to_generate ; i++)
! 				buf[i] = (mix_buffer[i]<<6); 
  			ALwritesamps(port,audio_buffer, (samples_to_generate) );
  #else
  			for (i = 0 ; i < samples_to_generate ; i++) 
! 				buf[i] = (mix_buffer[i]<<6)^0x8000; 
  			write(devAudio,audio_buffer,samples_to_generate*2); 
  #endif
  		}
***************
*** 595,600 ****
--- 604,621 ----
  }
  #endif
  
+ /* 
+  *	Init clip table 
+  */
+ 
+ void init_cliptable(void)
+ {	int i;	
+ 	for (i=0 ; i < 512 ; i++)
+ 	{	int j = i - 256;	
+ 		clip_table[i]= j<-128 ? -128 : j>127 ? 127 : j; 
+ 	}
+ 	clip_tab = &clip_table[256];
+ }
  
  /*
   *	Create a 'noise' sample.
***************
*** 604,610 ****
  {	int i;
  	srand(0xa354e767);
  	for (i = 0 ; i < NOISE_SIZE ; i++)
! 		Noise_Table[i] = (rand() & 0xff);
  }
  
  /*
--- 625,631 ----
  {	int i;
  	srand(0xa354e767);
  	for (i = 0 ; i < NOISE_SIZE ; i++)
! 		Noise_Table[i] = (rand() & 0xff)-128;
  }
  
  /*
diff -rcN STonX-0.6.4/blitter.c STonX-0.6.5/blitter.c
*** STonX-0.6.4/blitter.c	Fri Jan 19 00:45:37 1996
--- STonX-0.6.5/blitter.c	Fri Feb  9 19:09:50 1996
***************
*** 4,17 ****
   * COPYING for details
   *
   *	Blitter Emulator,
!  *	Martin Griffiths, 1995.
   *	
   * 	Here lies the Atari Blitter Emulator - The 'Blitter' chip is found in  
   *	the STE/MegaSTE and provides a very fast BitBlit in hardware.
   *
!  *	The hardware registers for this chip lie at addresses $ff8a30 - $ff8a3c,
!  *	however we only need to actively deal with address $ff8a3c, since all
!  *	other hardware registers can be treated as normal memory. 
   *	
   */
  
--- 4,16 ----
   * COPYING for details
   *
   *	Blitter Emulator,
!  *	Martin Griffiths, 1995/96.
   *	
   * 	Here lies the Atari Blitter Emulator - The 'Blitter' chip is found in  
   *	the STE/MegaSTE and provides a very fast BitBlit in hardware.
   *
!  *	The hardware registers for this chip lie at addresses $ff8a00 - $ff8a3c,
!  * 	There seems to be a mirror for $ff8a30 used in TOS 1.02 at $ff7f30.
   *	
   */
  
***************
*** 20,62 ****
  #include <stdlib.h>
  #include "mem.h"
  
  static UW halftone_ram[16];
  
  #define HOP_OPS(_fn_name,_op,_do_source_shift,_get_source_data,_shifted_hopd_data, _do_halftone_inc) \
  static void _fn_name (void)						\
! {	int y_count    = LM_UW(MEM(0xff8a38));				\
! 	int x_count    = LM_UW(MEM(0xff8a36));				\
! 	unsigned int line_num   = LM_UB(MEM(0xff8a3c));			\
! 	unsigned int skew       = LM_UB(MEM(0xff8a3d));			\
! 	int source_x_inc = (int) LM_W(MEM(0xff8a20));			\
! 	int source_y_inc = (int) LM_W(MEM(0xff8a22));			\
! 	int dest_x_inc = (int) LM_W(MEM(0xff8a2e));			\
! 	int dest_y_inc = (int) LM_W(MEM(0xff8a30));			\
! 	UW end_mask_1 = LM_UW(MEM(0xff8a28));				\
! 	UW end_mask_2 = LM_UW(MEM(0xff8a2a));				\
! 	UW end_mask_3 = LM_UW(MEM(0xff8a2c));				\
! 	register int source_addr  = LM_UL(MEM(0xff8a24))  & (MEM_MASK-1);	\
! 	register int dest_addr  = LM_UL(MEM(0xff8a32)) & (MEM_MASK-1);	\
! 	register unsigned int source_buffer,dst_data,opd_data;		\
! 	int x,y,NFSR,FXSR;     						\
! 	int halftone_curroffset,halftone_direction;			\
! 	NFSR = (skew & 0x40) != 0;					\
! 	FXSR = (skew & 0x80) != 0;					\
! 	skew &= 15;							\
! 	if (LM_UB(MEM(0xff8a3a)) & 1) 					\
! 	{	for (x = 0 ; x < 16 ; x++)				\
! 		halftone_ram[x] = LM_UW(MEM(0xff8a00+(x*2)));		\
! 		if (line_num & 0x20) 		 			\
! 			halftone_curroffset = skew;			\
! 		else							\
! 			halftone_curroffset = line_num & 15; 		\
! 		if (dest_y_inc >= 0)					\
! 			halftone_direction = 1;				\
! 		else 							\
! 			halftone_direction = -1;			\
! 	}								\
! 	for (y=0 ; y<y_count ; y++) 					\
! 	{	if (FXSR) 						\
  		{ 	_do_source_shift; 				\
  			_get_source_data;				\
  			source_addr += source_x_inc; 			\
--- 19,96 ----
  #include <stdlib.h>
  #include "mem.h"
  
+ #if (0)
+ {        fprintf(stderr,"Source Address:%X\n",source_addr);		\
+         fprintf(stderr,"  Dest Address:%X\n",dest_addr);		\
+         fprintf(stderr,"       X count:%X\n",x_count);			\
+         fprintf(stderr,"       Y count:%X\n",y_count);			\
+         fprintf(stderr,"  Source X inc:%X\n",source_x_inc);		\
+         fprintf(stderr,"    Dest X inc:%X\n",dest_x_inc);		\
+         fprintf(stderr,"  Source Y inc:%X\n",source_y_inc);		\
+         fprintf(stderr,"    Dest Y inc:%X\n",dest_y_inc);		\
+         fprintf(stderr,"HOP:%2X    OP:%X\n",hop,op);			\
+         fprintf(stderr,"   source SKEW:%X\n",skewreg);			\
+         fprintf(stderr,"     endmask 1:%X\n",end_mask_1);		\
+         fprintf(stderr,"     endmask 2:%X\n",end_mask_2);		\
+         fprintf(stderr,"     endmask 3:%X\n",end_mask_3);		\
+         fprintf(stderr,"       linenum:%X\n",line_num);			\
+         if (NFSR) fprintf(stderr,"NFSR is Set!\n");			\
+         if (FXSR) fprintf(stderr,"FXSR is Set!\n");			\
+ }
+ #endif
+ 
  static UW halftone_ram[16];
+ static UW end_mask_1,end_mask_2,end_mask_3;
+ static UB NFSR,FXSR; 
+ static UW x_count,y_count;
+ static UB hop,op,line_num,skewreg;
+ static unsigned int dest_addr_reg=0;
+ static int halftone_curroffset,halftone_direction;
+ static int source_x_inc, source_y_inc, dest_x_inc, dest_y_inc;
+ 
+ void load_halftone_ram(void)
+ {
+ 	halftone_ram[0] = LM_UW(MEM(0xff8a00));	
+ 	halftone_ram[1] = LM_UW(MEM(0xff8a02));	
+ 	halftone_ram[2] = LM_UW(MEM(0xff8a04));	
+ 	halftone_ram[3] = LM_UW(MEM(0xff8a06));	
+ 	halftone_ram[4] = LM_UW(MEM(0xff8a08));	
+ 	halftone_ram[5] = LM_UW(MEM(0xff8a0a));	
+ 	halftone_ram[6] = LM_UW(MEM(0xff8a0c));	
+ 	halftone_ram[7] = LM_UW(MEM(0xff8a0e));	
+ 	halftone_ram[8] = LM_UW(MEM(0xff8a10));	
+ 	halftone_ram[9] = LM_UW(MEM(0xff8a12));	
+ 	halftone_ram[10] = LM_UW(MEM(0xff8a14));	
+ 	halftone_ram[11] = LM_UW(MEM(0xff8a16));	
+ 	halftone_ram[12] = LM_UW(MEM(0xff8a18));	
+ 	halftone_ram[13] = LM_UW(MEM(0xff8a1a));	
+ 	halftone_ram[14] = LM_UW(MEM(0xff8a1c));	
+ 	halftone_ram[15] = LM_UW(MEM(0xff8a1e));	
+ 	if (line_num & 0x20) 		 			
+ 		halftone_curroffset = skewreg & 15;			
+ 	else							
+ 		halftone_curroffset = line_num & 15; 		
+ 	if (dest_y_inc >= 0)					
+ 		halftone_direction = 1;				
+ 	else 							
+ 		halftone_direction = -1;			
+ 
+ }
  
  #define HOP_OPS(_fn_name,_op,_do_source_shift,_get_source_data,_shifted_hopd_data, _do_halftone_inc) \
  static void _fn_name (void)						\
! { 	register int source_addr  = LM_UL(MEM(0xff8a24))  & (MEM_MASK-1);\
! 	register int dest_addr = dest_addr_reg & (MEM_MASK-1);		\
! 	register unsigned int skew       = skewreg & 15;		\
! 	register unsigned int source_buffer;				\
! 	source_x_inc = (int) LM_W(MEM(0xff8a20));			\
! 	source_y_inc = (int) LM_W(MEM(0xff8a22)); 			\
! 	dest_x_inc = (int) LM_W(MEM(0xff8a2e)); 			\
! 	dest_y_inc = (int) LM_W(MEM(0xff8a30)); 			\
! 	if (hop & 1) load_halftone_ram();				\
! 	do 								\
! 	{	register UW x,dst_data,opd_data;			\
! 		if (FXSR) 						\
  		{ 	_do_source_shift; 				\
  			_get_source_data;				\
  			source_addr += source_x_inc; 			\
***************
*** 89,99 ****
  		source_addr += source_y_inc;				\
  		dest_addr += dest_y_inc;				\
  		_do_halftone_inc;					\
! 	}								\
  	SM_UL(MEM(0xff8a24), source_addr); 				\
! 	SM_UL(MEM(0xff8a32), dest_addr);				\
! 	SM_B(MEM(0xff8a3c),line_num & ~0x80);				\
! 	SM_UW(MEM(0xff8a38),0);						\
  }
  
  HOP_OPS(_HOP_0_OP_00_N,(0), source_buffer >>=16, , 0xffff, )	 
--- 123,131 ----
  		source_addr += source_y_inc;				\
  		dest_addr += dest_y_inc;				\
  		_do_halftone_inc;					\
! 	} while (--y_count > 0);					\
  	SM_UL(MEM(0xff8a24), source_addr); 				\
! 	dest_addr_reg = dest_addr;					\
  }
  
  HOP_OPS(_HOP_0_OP_00_N,(0), source_buffer >>=16, , 0xffff, )	 
***************
*** 248,259 ****
  	_HOP_3_OP_00_P, _HOP_3_OP_01_P, _HOP_3_OP_02_P, _HOP_3_OP_03_P, _HOP_3_OP_04_P, _HOP_3_OP_05_P, _HOP_3_OP_06_P, _HOP_3_OP_07_P, _HOP_3_OP_08_P, _HOP_3_OP_09_P, _HOP_3_OP_10_P, _HOP_3_OP_11_P, _HOP_3_OP_12_P, _HOP_3_OP_13_P, _HOP_3_OP_14_P, _HOP_3_OP_15_P,
  };
  
- B LOAD_B_ff8a3c(void)
- {	return LM_B(MEM(0xff8a3c));
- }
  
  /* This seems to be a mirror for $ff8a30 used in TOS 1.02
   */
  void STORE_B_ff7f30(B v)
  {
  	SM_B(MEM(0xff8a30),v);
--- 280,289 ----
  	_HOP_3_OP_00_P, _HOP_3_OP_01_P, _HOP_3_OP_02_P, _HOP_3_OP_03_P, _HOP_3_OP_04_P, _HOP_3_OP_05_P, _HOP_3_OP_06_P, _HOP_3_OP_07_P, _HOP_3_OP_08_P, _HOP_3_OP_09_P, _HOP_3_OP_10_P, _HOP_3_OP_11_P, _HOP_3_OP_12_P, _HOP_3_OP_13_P, _HOP_3_OP_14_P, _HOP_3_OP_15_P,
  };
  
  
  /* This seems to be a mirror for $ff8a30 used in TOS 1.02
   */
+ 
  void STORE_B_ff7f30(B v)
  {
  	SM_B(MEM(0xff8a30),v);
***************
*** 265,283 ****
  	SM_B(MEM(0xff7f31),v);
  }
  
  void STORE_B_ff8a3c(B v)
  {	
! 	SM_B(MEM(0xff8a3c),v);
! 	if ((LM_UW(MEM(0xff8a38)) !=0) && (v & 0x80)) /* Busy bit set and lines to blit? */
  		flags |= F_BLIT;	
  }
  
  
  void Do_Blit(void)
  { 	
  	if (LM_W(MEM(0xff8a20)) < 0)		/* source_x_inc < 0 */
! 		do_hop_op_N[LM_UB(MEM(0xff8a3a)) & 3][LM_UB(MEM(0xff8a3b)) & 15]();
  	else
! 		do_hop_op_P[LM_UB(MEM(0xff8a3a)) & 3][LM_UB(MEM(0xff8a3b)) & 15]();
! 
  }
--- 295,479 ----
  	SM_B(MEM(0xff7f31),v);
  }
  
+ B LOAD_B_ff8a28(B v)
+ {	return (end_mask_1 >> 8) & 0xff;
+ }
+ 
+ B LOAD_B_ff8a29(B v)
+ {	return end_mask_1 & 0xff;
+ }
+ 
+ B LOAD_B_ff8a2a(B v)
+ {	return (end_mask_2 >> 8) & 0xff;
+ }
+ 
+ B LOAD_B_ff8a2b(B v)
+ {	return end_mask_2 & 0xff;
+ }
+ 
+ B LOAD_B_ff8a2c(B v)
+ {	return (end_mask_3 >> 8) & 0xff;
+ }
+ 
+ B LOAD_B_ff8a2d(B v)
+ {	return end_mask_3 & 0xff;
+ }
+ 
+ B LOAD_B_ff8a32(B v)
+ {	return (0);
+ }
+ 
+ B LOAD_B_ff8a33(B v)
+ {	return (dest_addr_reg >> 16) & 0xff;
+ }
+ 
+ B LOAD_B_ff8a34(B v)
+ {	return (dest_addr_reg >> 8) & 0xff;
+ }
+ 
+ B LOAD_B_ff8a35(B v)
+ {	return (dest_addr_reg) & 0xff;
+ }
+ 
+ B LOAD_B_ff8a36(B v)
+ {	return (x_count >> 8) & 0xff;
+ }
+ 
+ B LOAD_B_ff8a37(B v)
+ {	return (x_count) & 0xff;
+ }
+ 
+ B LOAD_B_ff8a38(B v)
+ {	return (y_count >> 8) & 0xff;
+ }
+ 
+ B LOAD_B_ff8a39(B v)
+ {	return (y_count) & 0xff;
+ }
+ 
+ B LOAD_B_ff8a3a(B v)
+ {	return (B) hop;
+ }
+ 
+ B LOAD_B_ff8a3b(B v)
+ {	return (B) op;
+ }
+ 
+ B LOAD_B_ff8a3c(void)
+ {	return (B) line_num & 0x3f;
+ }
+ 
+ B LOAD_B_ff8a3d(B v)
+ {	return (B) skewreg;
+ }
+ 
+ void STORE_B_ff8a32(B v)
+ {	
+ #if (0)
+ 	fprintf(stderr,"write : ff8a32 : %X\n",v);
+ #endif
+ }
+ 
+ void STORE_B_ff8a33(B v)
+ {	dest_addr_reg &= 0x00ffff;
+ 	dest_addr_reg |= (v&0xff) << 16;
+ #if (0)
+ 	fprintf(stderr,"write : ff8a33 : %X\n",v);
+ #endif
+ }
+ 
+ void STORE_B_ff8a34(B v)
+ {	dest_addr_reg &= 0xff00ff;
+ 	dest_addr_reg |= (v&0xff) << 8;
+ #if (0)
+ 	fprintf(stderr,"write : ff8a34: %X\n",v);
+ #endif
+ }
+ 
+ void STORE_B_ff8a35(B v)
+ {	dest_addr_reg &= 0xffff00;
+ 	dest_addr_reg |= (v & 0xfe);
+ #if (0)
+ 	fprintf(stderr,"write : ff8a35 : %X\n",v);
+ #endif
+ }
+ 
+ void STORE_B_ff8a28(B v)
+ {	end_mask_1 &= 0x00ff;
+ 	end_mask_1 |= (v&0xff) << 8;
+ }
+ 
+ void STORE_B_ff8a29(B v)
+ {	end_mask_1 &= 0xff00;
+ 	end_mask_1 |= (v&0xff);
+ }
+ 
+ void STORE_B_ff8a2a(B v)
+ {	end_mask_2 &= 0x00ff;
+ 	end_mask_2 |= (v&0xff) << 8;
+ }
+ 
+ void STORE_B_ff8a2b(B v)
+ {	end_mask_2 &= 0xff00;
+ 	end_mask_2 |= (v&0xff);
+ }
+ 
+ void STORE_B_ff8a2c(B v)
+ {	end_mask_3 &= 0x00ff;
+ 	end_mask_3 |= (v&0xff) << 8;
+ }
+ 
+ void STORE_B_ff8a2d(B v)
+ {	end_mask_3 &= 0xff00;
+ 	end_mask_3 |= (v&0xff);
+ }
+ 
+ void STORE_B_ff8a36(B v)
+ {	x_count &= 0x00ff;
+ 	x_count |= (v&0xff) << 8;
+ }
+ 
+ void STORE_B_ff8a37(B v)
+ {	x_count &= 0xff00;
+ 	x_count |= (v&0xff);
+ }
+ 
+ void STORE_B_ff8a38(B v)
+ {	y_count &= 0x00ff;
+ 	y_count |= (v&0xff) << 8;
+ }
+ 
+ void STORE_B_ff8a39(B v)
+ {	y_count &= 0xff00;
+ 	y_count |= (v&0xff);
+ }
+ 
+ void STORE_B_ff8a3a(B v)
+ {	hop = v & 3;	/* h/ware reg masks out the top 6 bits! */
+ }
+ 
+ void STORE_B_ff8a3b(B v)
+ {	op = v & 15;	/* h/ware reg masks out the top 4 bits! */	
+ }
+ 
  void STORE_B_ff8a3c(B v)
  {	
! 	if ((y_count !=0) && (v & 0x80)) /* Busy bit set and lines to blit? */
  		flags |= F_BLIT;	
+ 	line_num   = (UB) v;	
  }
  
+ void STORE_B_ff8a3d(B v)
+ {	
+ 	NFSR = (v & 0x40) != 0;					
+ 	FXSR = (v & 0x80) != 0;					
+ 	skewreg = (unsigned char) v & 0xcf;	/* h/ware reg mask %11001111 !*/	
+ }
  
  void Do_Blit(void)
  { 	
  	if (LM_W(MEM(0xff8a20)) < 0)		/* source_x_inc < 0 */
! 		do_hop_op_N[hop][op]();
  	else
! 		do_hop_op_P[hop][op]();
  }
diff -rcN STonX-0.6.4/configure STonX-0.6.5/configure
*** STonX-0.6.4/configure	Tue Jan 16 05:51:45 1996
--- STonX-0.6.5/configure	Fri Feb  9 19:02:26 1996
***************
*** 400,406 ****
  fi
  
  
! version="0.6.4"
  
  echo "#define VERSION \"$version\"">version.h
  #### PROGRAMS
--- 400,406 ----
  fi
  
  
! version="0.6.5"
  
  echo "#define VERSION \"$version\"">version.h
  #### PROGRAMS
diff -rcN STonX-0.6.4/configure.in STonX-0.6.5/configure.in
*** STonX-0.6.4/configure.in	Tue Jan 16 05:51:41 1996
--- STonX-0.6.5/configure.in	Fri Feb  9 19:02:20 1996
***************
*** 1,5 ****
  AC_INIT(defs.h)
! version="0.6.4"
  AC_SUBST(version)
  echo "#define VERSION \"$version\"">version.h
  #### PROGRAMS
--- 1,5 ----
  AC_INIT(defs.h)
! version="0.6.5"
  AC_SUBST(version)
  echo "#define VERSION \"$version\"">version.h
  #### PROGRAMS
diff -rcN STonX-0.6.4/cpu.c STonX-0.6.5/cpu.c
*** STonX-0.6.4/cpu.c	Mon Jan 22 01:45:11 1996
--- STonX-0.6.5/cpu.c	Fri Feb  9 19:27:19 1996
***************
*** 574,580 ****
  	}
  	else if ((flags & F_VBL) && IPL_OK(4))
  	{
! 		shifter();
  		EXCEPTION(T_VBL);
  		SET_IPL(5);
  		flags &= ~F_VBL;
--- 574,580 ----
  	}
  	else if ((flags & F_VBL) && IPL_OK(4))
  	{
! 		machine.screen_shifter();
  		EXCEPTION(T_VBL);
  		SET_IPL(5);
  		flags &= ~F_VBL;
diff -rcN STonX-0.6.4/docs/INSTALL STonX-0.6.5/docs/INSTALL
*** STonX-0.6.4/docs/INSTALL	Thu Jan  1 01:00:00 1970
--- STonX-0.6.5/docs/INSTALL	Tue Jan 16 23:38:20 1996
***************
*** 0 ****
--- 1,98 ----
+ INSTALLATION INSTRUCTIONS
+ =========================
+ 
+ In order to compile STonX, you will need the following:
+ 
+  * A C compiler, preferably GNU C (but some ANSI C compilers, like DEC's
+   will do)
+ 
+  * The M4 macro processor
+ 
+  * a `csh'-compatible shell (to run the shell script m4_to_c.csh)
+ 
+  * X11R5 or R6 libraries
+  
+ These will suffice to get you started (unless I've forgotten something). 
+ 
+ 
+ CONFIGURATION
+ =============
+ 
+ STonX uses a "configure" script generated by Cygnus' Autoconf program in order
+ to determine system-dependent configuration parameters. Invoke the script
+ by typing
+ 
+ 	./configure
+ 
+ or, alternatively, 
+ 
+ 	sh configure
+ 
+ if the former doesn't work.
+ 
+ This will generate a `Makefile', link `config.h' to the appropriate file from
+ the `config' subdirectory and generate dependencies for the Makefile. It will
+ also generate some more sources.
+ 
+ If the `configure' script fails, please contact me at nino@complang.tuwien.ac.at
+ and send me the output it generated. 
+ 
+ 
+ ADDITIONAL CONFIGURATION OPTIONS
+ ================================
+ 
+ After generating the Makefile, look at the file `options.h' (sparsely commented)
+ and see if there is anything you want to change. The only options that you might
+ need to change are TOS_1 (set to 1 is you have a TOS 1.0, 1.2 or 1.4 image)
+ and SMALL (check if this is defined in the `config.h' as well), which should
+ be set to 1 if your system has less than 16MB physical memory or if linking
+ fails otherwise (it will result in an emulator which emulates 4MB RAM instead
+ of 14MB, and takes up approximately 9MB swap space instead of 17MB).
+ 
+ 
+ COMPILING
+ =========
+ 
+ To compile, simply type 
+ 	
+ 	make
+ 
+ at the shell prompt. If you don't copy your TOS image to the directory
+ containing the sources named `tos.img' before this point, the `make' process
+ will stop after STonX has been linked and tell you to do it now. The TOS image
+ is needed at this point in order to generate the Atari system fonts in .pcf
+ format. You don't need to do this if you don't want to use the Xlib-VDI
+ driver. After copying the TOS image, simply type `make' again to continue. The
+ fonts will be extracted from the TOS image and installed temporarily in the
+ `data' subdirectory. See the `INSTALLING' section for how to install them
+ permanently.
+ 
+ After STonX has been compiled and linked successfully, you can start it
+ by typing
+ 
+ 	./stonx
+ 
+ The command-line options can be listed with the `-h' option (`./stonx -h').
+ 
+ 
+ INSTALLING
+ ==========
+ 
+ At the moment, STonX can only be run from the directory containing the TOS
+ image, i.e. there is no automatic system-wide installation. 
+ 
+ The system fonts should be installed in a place where the X server can find
+ them. Examine your default font path with the `xset' command:
+ 
+ 	xset q
+ 
+ This will print (among other things) the current font path. If you copy
+ the files ending in `.pcf' from the `data' subdirectory to one of the
+ directories in the font path, go to that directory and do a 
+ 
+ 	mkfontdir .; xset fp rehash
+ 
+ the fonts will be installed permanently. Note that if you run STonX on a 
+ different computer than the one handling your X display, you will have to
+ install the fonts on the latter.
+ 
diff -rcN STonX-0.6.4/docs/README STonX-0.6.5/docs/README
*** STonX-0.6.4/docs/README	Thu Jan  1 01:00:00 1970
--- STonX-0.6.5/docs/README	Tue Jan 16 23:52:45 1996
***************
*** 0 ****
--- 1,327 ----
+ (note: this file has been obsoleted by the html documentation, which is being
+ written, to some extent. It is not properly maintained, sorry)
+ 
+       _____   _________           
+      /     \      |                  \     /
+      |            |                   \   /
+      \_____       |    ___    ___      \ /     ( ST on  )
+            \      |   /   \ |/   \     / \     ( Unix/X )
+            |      |   |   | |    |    /   \
+      \_____/      |   \___/ |    |  /      \
+       
+ 
+                        VERSION 0.6 
+ 
+               (C) 1995 by Marinos Yannikos
+                (nino@complang.tuwien.ac.at)
+       (http://www.complang.tuwien.ac.at/nino/home.html)
+ 
+ 	          ALL RIGHTS RESERVED
+  THIS PROGRAM IS PROVIDED "AS IS" WITHOUT A WARRANTY OF ANY KIND
+ 
+ 
+       See the file `COPYING' for licensing information
+ 
+          Last change to this file: December 21, 1995
+ 
+ This file is separated into 4 sections:
+ 
+   1.  About STonX (general description)
+   2.  Frequently Asked Questions
+   3.  The Future 
+   4.  History
+ 
+ --------------------------------------------------------------------------------
+ 
+  1. ABOUT STonX
+  ##############
+ 
+ Copyright information
+ ~~~~~~~~~~~~~~~~~~~~~
+ STonX is free software and distributed under the GNU License. Read the file
+ COPYING for details.
+ 
+ Intruduction
+ ~~~~~~~~~~~~
+ STonX is a software emulator, which runs on Unix workstations with the X Window
+ system, and emulates an Atari ST computer. `Software emulator' means, that the
+ system components, including the 68000 microprocessor, are emulated in software.
+ This approach has the advantage, that it can be used regardless of the hardware
+ the emulator runs on. Unfortunately, it also has the disadvantage that it is
+ very slow.
+ 
+ Why use an emulator?
+ ~~~~~~~~~~~~~~~~~~~~
+ An emulator's sole purpose is to allow software written for a particular
+ computer system to be used on other systems. A software emulator in particular
+ is *not* useful for keeping your old programs while changing your hardware,
+ except if the new hardware ist several orders of magnitude faster than the
+ old one. 
+ 
+ What can STonX do?
+ ~~~~~~~~~~~~~~~~~~
+ As you may have guessed already, it is nearly impossible to emulate a computer
+ system to its full extent. STonX was initially meant to be a very `low-level'
+ emulator, meaning that it should be able to deal with hardware register 
+ accesses and similar things, which it does quite well at the moment. A different
+ approach would have been to disallow direct hardware access, and support only
+ "clean" programs, like most GEM applications for example. At this time, STonX
+ can cope with hardware accesses quite well (see below for limitations), and
+ I hope to be able to finish the VDI driver for X in the near future, so that
+ "clean" applications can use the graphics capabilities and speed of your X
+ display.
+ 
+ Here is a list of the emulated system components:
+ 
+ * M68000 CPU     Everything (I hope) except Trace-Mode and correct bus- and
+                  address-error stack frames.
+ 
+ * MFP            Only the necessary parts to get TOS to run (Timer C and
+                  VBL). The MFP interrupt priorities are completely bogus,
+                  as are the other interrupts in the system, for efficiency
+                  reasons and lack of a complete MFP emulation, mainly.
+ 
+ * IKBD           Only keyboard keycodes and (incomplete) relative mouse mode.
+ 
+ * Shifter        ST Shifter, the STE support is not yet complete (the possible
+                  word-alignment of the screen would cause problems with the
+                  ST-Low and -Mid to ZPixmap conversion routines). 
+ 
+ * Disk-I/O       Still very limited. A general FDC/HDC-Emulation would probably
+                  not make sense, except for a few games. A GEMDOS-Driver for
+                  the Unix FS would be very useful. The native interface
+                  (opcode $a0ff, see 'faketos.c') will be helpful in implementing
+                  this.
+ 
+ * Mega ST(E)     Still buggy, haven't had time to correct it. It gets the hour
+   Clock Chip     wrong sometimes, and the alarm timer is not implemented (among
+                  other things).
+ 
+ * YM2149 sound   Available on several Unix platforms
+   chip
+ 
+ * Serial &       Not very useful yet, but enough for testing some
+   parallel ports telecommunication software
+ 
+ 
+ The Xlib-VDI Driver
+ ~~~~~~~~~~~~~~~~~~~
+ As of version 0.3, the VDI is already quite usable. Note that the fonts used
+ are all X fonts (BDF format), and must be installed properly. This is done in
+ the Makefile (make fonts). The program `tosfonts' extracts the system fonts
+ from the `tos.img' file (which you're going to need anyway), and installs
+ them in the `data' subdirectory (see `data/makefonts.sh'). It also installs
+ Latin-1 versions of these fonts so that you can use them for you XTerm windows!
+ 
+ Not that although it only implements monochrome routines, the Xlib-VDI Driver
+ only runs on 8-bit color displays at the moment (sorry).
+ 
+ --------------------------------------------------------------------------------
+ 
+  2. FREQUENTLY ASKED QUESTIONS
+  #############################
+ 
+ Q: Why can't I compile STonX on my Computer with Zintorola 86060 processor and
+    Sluggix 0.8 Beta O.S.?
+ A: If you have GNU-C and X11R5/6 for this system, and STonX still won't compile,
+    please let me know as soon as possible, I will try to fix it.
+ 
+ Q: How do I leave the emulator `gently'?
+ A: Press all 3 mouse buttons together
+ 
+ Q: What do all the warnings mean?
+ A: Some keycodes can not be generated, because no mapping is defined for
+    them in `Keysyms'. Have a look at that file, and then do a `xmodmap -pke'
+    to find suitable Keysyms for mapping the missing ST-Keycodes to.
+ 
+ Q: Why doesn't STonX work on my X display?
+ A: Currently, STonX is very choosy about X displays - it requires an 8 bit
+    display with PseudoColor visual capabilities. Building a version for
+    monochrome displays might be possible by defining -DMONO=1 in the Makefile,
+    but don't bet on it.
+ 
+ Q: Why do the graphics look funny / why are the letters reversed?
+ A: Because I've merged the modifications for little-endian frame buffers
+    without testing it afterwards. Please let me know if this happens!
+ 
+ Q: Why does the emulator window go blank, and then my system starts swapping
+    for ages until I finally turn it off?
+ A: STonX requires approximately 17MB memory, and during the initialization of
+    TOS it is quickly accessed linearly, so you should have at least 20MB
+    physical memory. You can try to add -DSMALL at the end of the DEF definition
+    in the Makefile and recompile everything. This will give create a version of
+    STonX which uses only 9MB of memory and emulates a 4MB ST. This option
+    has not been tested thoroughly, but seems to work.
+ 
+ Q: What TOS versions does STonX work with? Where do I get TOS images?
+ A: I tried it with TOS 2.06, other versions haven't been tested, but TOS 
+    versions which support plain STs should work with it. At the moment, you
+    can only use TOS ROM images which normally begin at $E00000 in memory
+    (256K ROMs). TOS is copyrighted, so it would be illegal to distribute
+    a TOS image with STonX. To make a TOS image just copy 256K of memory
+    from $E00000 to a file and put it in the STonX directory with the name
+    `tos.img'.
+ 
+ Q: What's `cartridge.img' for?
+ A: This is an cartridge image which installs the BIOS level disk routines.
+    It is necessary, since there is no FDC emulation (yet). If there was one,
+    the disk routines from TOS could be used.
+ 
+ Q: How do I get the emulator to load a program?
+ A: The emulator can't deal with single programs, only with disks and disk 
+    images. If you want to load a disk in a format your Unix box can read,
+    you can try the option -disk a:/dev/rfd0 (or replace /dev/rfd0 with
+    whatever designates the raw floppy disk device on your system) to load
+    directly from disk. This works on Suns. If you want to load a disk
+    with a strange format (10 or 11 sectors etc.), you need to make a disk
+    image on the ST, and load that disk image onto your Unix disk. To make
+    a disk image, copy all sectors from the disk to a file (e.g. sectors
+    0-1599 on a 80/10/2 disk). Then, use the option -a:File (replace File with
+    the name of the disk image). You can also map several files/disks to 
+    TOS drives at the same time, e.g. by using -c:File for drive C. Remember
+    that you always map something to drive A though.
+ 
+ Q: Program XXX doesn't run, what should I do?
+ A: If the program is known to run with the TOS you are using with STonX, 
+    and if it doesn't (or shouldn't) use any of the system components not
+    yet emulated (see section 1), and if you're getting a 2 bomb bus error,
+    it probably accesses a memory location which is not documented, but 
+    exists in STs. Please rebuild STonX with -DDEBUG=1, run the program
+    again, wait until the crash, and look at the end of DEBUGFILE for a
+    message like "pc=<A> sr=<B> BUS ERROR -> <C>". At the previous line,
+    there should be a description of the offending memory access. Please
+    inform me about it! Note that you're looking at the wrong BUS ERROR
+    message if you got 2 bombs on the screen and <C> above does not begin
+    with `2'.
+ 
+ Q: Why are the locations of the ST and X mouse cursors different?
+ A: Because the emulator has (at the moment) no way to tell where the
+    emulated system keeps its mouse cursor positions in memory. When you
+    enter the emulator window, you can freeze the ST mouse cursor with the
+    right mouse button, move to it with the X cursor, and press the right
+    mouse button again to "pick it up". A better solution is in the works...
+ 
+ Q: Why do some keys seem to 'hang' e.g. in Megaroids?
+ A: Because the interrupt priorities are bogus, and in some cases data from
+    the IKBD may be lost. 
+ 
+ Q: Why can't the mouse be switched off (e.g. in games)?
+ A: Because the emulated IKBD doesn't (yet) understand any commands
+ 
+ Q: Where can I get the newest version of STonX? 
+ A: Probably at ftp.complang.tuwien.ac.at/pub/nino/ or 
+    http://www.complang.tuwien.ac.at/nino/
+    Don't bet on it though! :-) 
+ 
+ Q: Why do benchmark programs show much better values than what they should?
+ A: Because Timer C, which is often used for measuring time, is running at
+    a lower frequency than the usual 200Hz. Look at the output to stderr when
+    starting STonX, it will tell you the actual frequency. If it is e.g. 50Hz,
+    the values reported by benchmark programs will be 4 x higher than they
+    should be.
+ 
+ Q: When will the VDI driver be finished?
+ A: If I knew the answer, I'd probably never have started... :-)
+ 
+ Q: What can I do to speed up the development of STonX?
+ A: You can try to bribe me with any amount of money, any type of hardware or
+    software for the Atari ST or SunOS 4.1 (no pirated stuff please).
+    A nice postcard might suffice too. :-)
+ 
+ --------------------------------------------------------------------------------
+ 
+  3. THE FUTURE
+  #############
+ 
+ Things left to do:
+ - Finish the VDI driver
+ - Speed up the emulation with little-endian hosts
+ - Maybe write a FDC emulation
+ - Optimize a bit more
+ - Complete the IKBD emulation (esp. Joystick)
+ - Fix the bug in the clock chip emulation
+ (etc. etc.)
+ 
+ --------------------------------------------------------------------------------
+ 
+  4. HISTORY
+  ##########
+ 
+ In the beginning there were absurd plans, long sleepless nights, and incredible
+ boredom.
+ 
+ First version with a version number - Version 0.1 Alpha (Apr 11 1995)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ - Added -refresh option
+ - Wrote an `Autoconf' script
+ - Removed the Xlib calls from the signal handler
+ - Use sigaction() instead of signal() (Thanks to Des Herriott for the hint!)
+ - Added global register variable declarations for SGIs (untested)
+ - Fixed bug in colormap handling which bloated up the Xserver if colormap
+   changed frequently
+ - Fixed bug which caused bus errors at naughty accesses to $ff8206
+   (Grav2 runs now! ;-))
+ - The keyboard auto repeat is now only turned off if the X mouse pointer is
+   inside the emulator window
+ - Merged some patches for little-endian machines and little-endian frame buffers
+   (untested)
+ 
+ Version 0.2 Alpha (Apr 13 1995)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ - Fixed invalid initialisation of sigset_t variable in hw.c
+ - Fixed problem with multiple keycodes mapped to the same Keysym.
+   This prevented e.g. a keyboard reset with the usual combination if both the
+   normal and the Keypad Del key were mapped to the "Delete" keysym.
+ - Fixed description of 8th change above. :-) (on -> off)
+ - Changed the default frequencies to something more reasonable
+ - Implemented (simple) VDI input functions
+ - It is now possible to switch between the `old style' window and the VDI
+   window at runtime. This feature may disappear in the future.
+ - X events are now processed at every VBL, not at every screen update
+ - The `old style' window is not updated if the X pointer is in the VDI
+   window
+ - Added -DSMALL for people with less memory and/or patience
+ - Added a chmod +w Makefile to Makefile.in (make depend rule)
+ - Changed stricmp() to strncasecmp()
+ 
+ Version 0.3 Alpha (Apr 15 1995)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ - Fixed 12 bit FAT assumption and Media-Change bug, large diskfiles work now
+ - Improved the VDI driver, now it looks almost exactly like TOS VDI
+ - Wrote programs to help convert GEM Bitmap Fonts to BDF format
+ 
+ Version 0.4 Beta (Jul 25 1995)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ - first public release
+ - Integrated Griff's blitter emulator
+ - The VDI driver redraws at expose events now
+ - The VDI driver works with monochrome displays now, and -DMONO has been 
+   eliminated
+ - Little-endian fixes for the VDI driver and fnttobdf
+ - Linux port and assembly support
+ - Emulation is a bit faster now for some instructions
+ - Condition codes N,Z are now evaluated lazily (this makes STonX incompatible
+   with the real 68000 in some rare cases, but I haven't seen code that uses
+   this)
+ 
+ Version 0.5 (Nov 30 1995)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ - Integrated sound, serial and parallel port support
+ - Fixed a few bugs, e.g. the one that caused the Alpha console crash
+ - Added colormap sharing (#define NEWCOLOR 1 in screen.c)
+ - Added a Unix filesystem interface (option -fs, file gemdos.c)
+ - More assembly support for x86
+ - mkfonts.sh is now a /bin/sh script
+ - TOS 1.X support where X=0,2,4. Executing programs over the Unix filesystem
+   interface may not work with TOS <1.4 (sorry)
+ - Timer C is now optionally 200Hz
+ 
+ Version 0.6 (Dec 21, 1995)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ - Emulation code has been almost completely rewritten, resulting in 
+   1) 20-80% speed increase, 65% on my Linux PC and 80% on our Alphas
+   2) Less memory and more time needed to compile cpu.c 
+   3) More easily maintainable code
+ - experimental implementation of the -size option
+ - added Griff's patches to main.c to read options from a $HOME/.stonxrc file
+ 
diff -rcN STonX-0.6.4/docs/RELEASE_NOTES STonX-0.6.5/docs/RELEASE_NOTES
*** STonX-0.6.4/docs/RELEASE_NOTES	Mon Jan 22 00:25:05 1996
--- STonX-0.6.5/docs/RELEASE_NOTES	Fri Feb  9 19:15:33 1996
***************
*** 1,29 ****
! Release notes for version 0.6.4
  ===============================
  
! This version has many improvements over 0.6.3, as well as many new features.
! The most important new features are:
! 
! - Arbitrary screen sizes in all graphics modes, both with and without -vdi
! - Colour VDI driver (i.e. resolutions like 1024x768x16 are possible now with
!   the VDI driver). Only tested with TOS 2.05 and 2.06.
! - `chunky' update for the TOS window (only those parts of the screen that have
!   changed are updated). This makes it possible to use -vbl 2 -refresh 1 on
!   most systems.
! - New mouse handling in the TOS window, now only the TOS mouse cursor is 
!   displayed, and the invisible (toggle with the right mouse button) X 
!   mouse cursor is warped to the TOS mouse cursor's position whenever you
!   enter the TOS window
! - New blitter.c (compiles with much less memory)
! - Better sound support for DEC and Linux (very good VOXWARE 3 support)
! - The emulation code compiles with less memory and temporary file space,
!   since it has been split up into several files
! 
! On the other hand, the -vdi code is probably broken again for some displays
! where black/white are swapped. Also, the colour rasterops are still buggy and
! the TOS fonts are screwed up in the TOS VDI window if -size and -vdi are
! used to make a colour screen with a resolution with more than 400 lines.
! 
! This is probably the last version before 0.7, which will only be bugfixed
! and optimized (colour rasterops in xlib_vdi.c) compared to 0.6.4.
! 
--- 1,9 ----
! Release notes for version 0.6.5
  ===============================
  
! - Linux SVGALIB support (-svga), allows the emulator to run fullscreen (should
!   also work on DEC Alpha's running Linux)
! - Audio improvements (volume and mixing corrections) 
! - Blitter speedups and bug fixes
! - Portability improvements (it should now be easy to port STonX to other 
!   platforms i.e. Mac/Windows/Dos etc)
diff -rcN STonX-0.6.4/ikbd.c STonX-0.6.5/ikbd.c
*** STonX-0.6.4/ikbd.c	Thu Jan 18 03:56:40 1996
--- STonX-0.6.5/ikbd.c	Fri Feb  9 19:01:44 1996
***************
*** 7,12 ****
--- 7,13 ----
  #include "debug.h"
  #include "mem.h"
  #include "ikbd.h"
+ #include "screen.h"
  #include <X11/Xlib.h>
  #include <X11/keysym.h>
  #include <stdio.h>
***************
*** 16,225 ****
  #define KB_DEBUG 0
  #define KEYMAP_HARDCODED 0
  
- /* These are the ST keycodes as reported by the IKBD:
-  */
- #define ST_ESC		0x01
- #define ST_1		0x02
- #define ST_2		0x03
- #define ST_3		0x04
- #define ST_4		0x05
- #define ST_5		0x06
- #define ST_6		0x07
- #define ST_7		0x08
- #define ST_8		0x09
- #define ST_9		0x0a
- #define ST_0		0x0b
- #define ST_MINUS	0x0c
- #define ST_EQUAL	0x0d
- #define ST_BS		0x0e
- #define ST_TAB		0x0f
- #define ST_Q		0x10
- #define ST_W		0x11
- #define ST_E		0x12
- #define ST_R		0x13
- #define ST_T		0x14
- #define ST_Y		0x15
- #define ST_U		0x16
- #define ST_I		0x17
- #define ST_O		0x18
- #define ST_P		0x19
- #define ST_SQ_OPEN	0x1a	/* [ */
- #define ST_SQ_CLOSE 0x1b	/* ] */
- #define ST_RETURN	0x1c
- #define ST_CONTROL	0x1d
- #define ST_A		0x1e
- #define ST_S		0x1f
- #define ST_D		0x20
- #define ST_F		0x21
- #define ST_G		0x22
- #define ST_H		0x23
- #define ST_J		0x24
- #define ST_K		0x25
- #define ST_L		0x26
- #define ST_SEMIC	0x27	/* ; */
- #define ST_APOST	0x28	/* ' */
- #define ST_GRAVE	0x29	/* ` */
- #define ST_LSH		0x2a	/* left shift */
- #define ST_BACKSL	0x2b	/* \ */
- #define ST_Z		0x2c
- #define ST_X		0x2d
- #define ST_C		0x2e
- #define ST_V		0x2f
- #define ST_B		0x30
- #define ST_N		0x31
- #define ST_M		0x32
- #define ST_COMMA	0x33
- #define ST_DOT		0x34
- #define ST_SLASH	0x35
- #define ST_RSH		0x36	/* right shift */
- #define ST_ALT		0x38
- #define ST_SPACE	0x39
- #define ST_CAPSLOCK	0x3a
- #define ST_F1		0x3b
- #define ST_F2		0x3c
- #define ST_F3		0x3d
- #define ST_F4		0x3e
- #define ST_F5		0x3f
- #define ST_F6		0x40
- #define ST_F7		0x41
- #define ST_F8		0x42
- #define ST_F9		0x43
- #define ST_F10		0x44
- #define ST_HOME		0x47
- #define ST_UP		0x48
- #define ST_KP_MINUS 0x4a
- #define ST_LEFT		0x4b
- #define ST_RIGHT	0x4d
- #define ST_KP_PLUS	0x4e
- #define ST_DOWN		0x50
- #define ST_INSERT	0x52
- #define ST_DELETE	0x53
- #define ST_ISO		0x60	/* The 'Atari' Key */
- #define ST_UNDO		0x61
- #define ST_HELP		0x62
- #define ST_KP_OPEN	0x63	/* Keypad ( */
- #define ST_KP_CLOSE 0x64	/* Keypad ) */
- #define ST_KP_DIV	0x65	/* Keypad / */
- #define ST_KP_MULT	0x66	/* Keypad * */
- #define ST_KP_7		0x67
- #define ST_KP_8		0x68
- #define ST_KP_9		0x69
- #define ST_KP_4		0x6a
- #define ST_KP_5		0x6b
- #define ST_KP_6		0x6c
- #define ST_KP_1		0x6d
- #define ST_KP_2		0x6e
- #define ST_KP_3		0x6f
- #define ST_KP_0		0x70
- #define ST_KP_DOT	0x71	/* Keypad . */
- #define ST_KP_ENTER 0x72
- 
- struct
- {
- 	int c;
- 	char *s;
- } st_keysyms[] =
- {
- 	{ST_1, "ST_1"},
- 	{ST_2, "ST_2"},
- 	{ST_3, "ST_3"},
- 	{ST_4, "ST_4"},
- 	{ST_5, "ST_5"},
- 	{ST_6, "ST_6"},
- 	{ST_7, "ST_7"},
- 	{ST_8, "ST_8"},
- 	{ST_9, "ST_9"},
- 	{ST_0, "ST_0"},
- 	{ST_F1, "ST_F1"},
- 	{ST_F2, "ST_F2"},
- 	{ST_F3, "ST_F3"},
- 	{ST_F4, "ST_F4"},
- 	{ST_F5, "ST_F5"},
- 	{ST_F6, "ST_F6"},
- 	{ST_F7, "ST_F7"},
- 	{ST_F8, "ST_F8"},
- 	{ST_F9, "ST_F9"},
- 	{ST_F10, "ST_F10"},
- 	{ST_A, "ST_A"},
- 	{ST_B, "ST_B"},
- 	{ST_C, "ST_C"},
- 	{ST_D, "ST_D"},
- 	{ST_E, "ST_E"},
- 	{ST_F, "ST_F"},
- 	{ST_G, "ST_G"},
- 	{ST_H, "ST_H"},
- 	{ST_I, "ST_I"},
- 	{ST_J, "ST_J"},
- 	{ST_K, "ST_K"},
- 	{ST_L, "ST_L"},
- 	{ST_M, "ST_M"},
- 	{ST_N, "ST_N"},
- 	{ST_O, "ST_O"},
- 	{ST_P, "ST_P"},
- 	{ST_Q, "ST_Q"},
- 	{ST_R, "ST_R"},
- 	{ST_S, "ST_S"},
- 	{ST_T, "ST_T"},
- 	{ST_U, "ST_U"},
- 	{ST_V, "ST_V"},
- 	{ST_W, "ST_W"},
- 	{ST_X, "ST_X"},
- 	{ST_Y, "ST_Y"},
- 	{ST_Z, "ST_Z"},
- 	{ST_SPACE, "ST_SPACE"},
- 	{ST_ALT, "ST_ALT"},
- 	{ST_ESC, "ST_ESC"},
- 	{ST_MINUS, "ST_MINUS"},
- 	{ST_EQUAL, "ST_EQUAL"},
- 	{ST_GRAVE, "ST_GRAVE"},
- 	{ST_BS, "ST_BS"},
- 	{ST_DELETE, "ST_DELETE"},
- 	{ST_ISO, "ST_ISO"},
- 	{ST_INSERT, "ST_INSERT"},
- 	{ST_TAB, "ST_TAB"},
- 	{ST_SQ_OPEN, "ST_SQ_OPEN"},
- 	{ST_SQ_CLOSE, "ST_SQ_CLOSE"},
- 	{ST_UP, "ST_UP"},
- 	{ST_LEFT, "ST_LEFT"},
- 	{ST_RIGHT, "ST_RIGHT"},
- 	{ST_DOWN, "ST_DOWN"},
- 	{ST_CONTROL, "ST_CONTROL"},
- 	{ST_LSH, "ST_LSH"},
- 	{ST_RSH, "ST_RSH"},
- 	{ST_CAPSLOCK, "ST_CAPSLOCK"},
- 	{ST_SEMIC, "ST_SEMIC"},
- 	{ST_APOST, "ST_APOST"},
- 	{ST_BACKSL, "ST_BACKSL"},
- 	{ST_COMMA, "ST_COMMA"},
- 	{ST_DOT, "ST_DOT"},
- 	{ST_SLASH, "ST_SLASH"},
- 	{ST_RETURN, "ST_RETURN"},
- 	{ST_KP_ENTER, "ST_KP_ENTER"},
- 	{ST_KP_MINUS, "ST_KP_MINUS"},
- 	{ST_KP_PLUS, "ST_KP_PLUS"},
- 	{ST_HELP, "ST_HELP"},
- 	{ST_UNDO, "ST_UNDO"},
- 	{ST_KP_OPEN, "ST_KP_OPEN"},
- 	{ST_KP_CLOSE, "ST_KP_CLOSE"},
- 	{ST_KP_DIV, "ST_KP_DIV"},
- 	{ST_KP_MULT, "ST_KP_MULT"},
- 	{ST_KP_DOT, "ST_KP_DOT"},
- 	{ST_KP_0, "ST_KP_0"},
- 	{ST_KP_1, "ST_KP_1"},
- 	{ST_KP_2, "ST_KP_2"},
- 	{ST_KP_3, "ST_KP_3"},
- 	{ST_KP_4, "ST_KP_4"},
- 	{ST_KP_5, "ST_KP_5"},
- 	{ST_KP_6, "ST_KP_6"},
- 	{ST_KP_7, "ST_KP_7"},
- 	{ST_KP_8, "ST_KP_8"},
- 	{ST_KP_9, "ST_KP_9"},
- 	{ST_HOME, "ST_HOME"},
- };
- 
- #define NUM_STK (sizeof(st_keysyms)/sizeof(st_keysyms[0]))
- static char mapped[NUM_STK];
- 
  /* special codes sent by the IKBD: */
  #define IKBD_STATUS		0xf6
  #define IKBD_ABS_MOUSE	0xf7
--- 17,22 ----
***************
*** 286,294 ****
  #endif
  extern int kmin, kmax;
  
- #define ST_UNDEF	(-1)
- 
- 
  /* This is the keycode translation table. It is dependent on your kind of X
   * terminal, and on the mapping you want to use for the ST keys.
   * To make your own table, you'll need to examine the `xmodmap -pke' output
--- 83,88 ----
***************
*** 728,811 ****
  	}
  }
  
- char *kdefsfile = "Keysyms";
  void init_ikbd(void)
! {
! 	int i, l=0, j;
! 	FILE *f;
! 	char b[1000], x[1000], y[1000];
! 	keycodes = (int *)malloc(sizeof(int)*(kmax+1));
! 	for (i=0; i<=kmax; i++)
! 		keycodes[i] = ST_UNDEF;
! 	verbose && 
! 	fprintf (stderr, "Reading keycode mappings from `%s'...\n", kdefsfile);
! 	f = fopen(kdefsfile, "r");
! 	if (f == NULL)
! 	{
! 		fprintf(stderr,"FATAL error: File `%s' not found - exiting...\n",
! 			kdefsfile);
! 		exit(1);
! 	}
! 	while (fgets(b, 1000, f) != NULL)
! 	{
! 		l++;
! 		if (b[0] == '#') continue;
! 		if (sscanf(b, "%s %s", x, y) < 2)
! 		{
! 			verbose && 
! 				fprintf (stderr, "Malformed line %d in file %s, ignoring it\n",
! 						l, kdefsfile);
! 		}
! 		else 
! 		{
! 			int q;
! 			int ok=0, u;
! 			for (j=kmin; j<=kmax; j++)
! 			{
! #if KB_DEBUG
! 				if (*x == 'F')
! 				{
! 					fprintf (stderr, "x=<%s>, ksyms[%d]=<%s>, cmp=%d\n",
! 						x,j-kmin,ksyms[j-kmin],(ksyms[j-kmin]==NULL?999:strcasecmp(x,ksyms[j-kmin])));
! 				}
! #endif
! 				if (ksyms[j-kmin] != NULL && strcasecmp (x, ksyms[j-kmin]) == 0)
! 				{
! 					q = /*XKeysymToKeycode(display,
! 						XStringToKeysym(ksyms[*/ j /* -kmin ]))*/; 
! 					for (u=0; u<sizeof(st_keysyms)/sizeof(st_keysyms[0]); u++)
! 					{
! 						if (strcasecmp (y, st_keysyms[u].s) == 0)
! 						{
! 							keycodes[q] = st_keysyms[u].c;
! 							mapped[u] = 1;
! 							break;
! 						}
! 					}
! 					if (u == sizeof(st_keysyms)/sizeof(st_keysyms[0]))
! 					{
! 						fprintf (stderr,
! 							"Error: Illegal ST-Keysym in %s, line %d `%s'\n",
! 							kdefsfile, l, y);
! 						exit(1);
! 					}
! 					ok=1;
! 				}
! 			}
! 			if (!ok)
! 			{
! 				verbose &&
! 				fprintf (stderr,"Warning: unknown KeySym in %s, line %d `%s'\n",
! 								kdefsfile, l, x);
! 				continue;
! 			}
! 		}
! 	}
! 	for (i=0; i<NUM_STK; i++)
! 	{
! 		if (!mapped[i] && verbose)
! 			fprintf (stderr, "Warning: %s not mapped!\n", st_keysyms[i].s);
! 	}
  	SM_UB(MEM(0xfffc00),0x0e);
  }
  
--- 522,529 ----
  	}
  }
  
  void init_ikbd(void)
! {	machine.init_keys();
  	SM_UB(MEM(0xfffc00),0x0e);
  }
  
diff -rcN STonX-0.6.4/ikbd.h STonX-0.6.5/ikbd.h
*** STonX-0.6.4/ikbd.h	Tue Dec 12 05:22:57 1995
--- STonX-0.6.5/ikbd.h	Fri Feb  9 19:01:46 1996
***************
*** 12,15 ****
--- 12,116 ----
  void ikbd_force (void);
  void ikbd_adjust (int dx,int dy);
  
+ #define ST_UNDEF	(-1)
+ 
+ /* These are the ST keycodes as reported by the IKBD:
+  */
+ 
+ #define ST_ESC		0x01
+ #define ST_1		0x02
+ #define ST_2		0x03
+ #define ST_3		0x04
+ #define ST_4		0x05
+ #define ST_5		0x06
+ #define ST_6		0x07
+ #define ST_7		0x08
+ #define ST_8		0x09
+ #define ST_9		0x0a
+ #define ST_0		0x0b
+ #define ST_MINUS	0x0c
+ #define ST_EQUAL	0x0d
+ #define ST_BS		0x0e
+ #define ST_TAB		0x0f
+ #define ST_Q		0x10
+ #define ST_W		0x11
+ #define ST_E		0x12
+ #define ST_R		0x13
+ #define ST_T		0x14
+ #define ST_Y		0x15
+ #define ST_U		0x16
+ #define ST_I		0x17
+ #define ST_O		0x18
+ #define ST_P		0x19
+ #define ST_SQ_OPEN	0x1a	/* [ */
+ #define ST_SQ_CLOSE 0x1b	/* ] */
+ #define ST_RETURN	0x1c
+ #define ST_CONTROL	0x1d
+ #define ST_A		0x1e
+ #define ST_S		0x1f
+ #define ST_D		0x20
+ #define ST_F		0x21
+ #define ST_G		0x22
+ #define ST_H		0x23
+ #define ST_J		0x24
+ #define ST_K		0x25
+ #define ST_L		0x26
+ #define ST_SEMIC	0x27	/* ; */
+ #define ST_APOST	0x28	/* ' */
+ #define ST_GRAVE	0x29	/* ` */
+ #define ST_LSH		0x2a	/* left shift */
+ #define ST_BACKSL	0x2b	/* \ */
+ #define ST_Z		0x2c
+ #define ST_X		0x2d
+ #define ST_C		0x2e
+ #define ST_V		0x2f
+ #define ST_B		0x30
+ #define ST_N		0x31
+ #define ST_M		0x32
+ #define ST_COMMA	0x33
+ #define ST_DOT		0x34
+ #define ST_SLASH	0x35
+ #define ST_RSH		0x36	/* right shift */
+ #define ST_ALT		0x38
+ #define ST_SPACE	0x39
+ #define ST_CAPSLOCK	0x3a
+ #define ST_F1		0x3b
+ #define ST_F2		0x3c
+ #define ST_F3		0x3d
+ #define ST_F4		0x3e
+ #define ST_F5		0x3f
+ #define ST_F6		0x40
+ #define ST_F7		0x41
+ #define ST_F8		0x42
+ #define ST_F9		0x43
+ #define ST_F10		0x44
+ #define ST_HOME		0x47
+ #define ST_UP		0x48
+ #define ST_KP_MINUS 0x4a
+ #define ST_LEFT		0x4b
+ #define ST_RIGHT	0x4d
+ #define ST_KP_PLUS	0x4e
+ #define ST_DOWN		0x50
+ #define ST_INSERT	0x52
+ #define ST_DELETE	0x53
+ #define ST_ISO		0x60	/* The 'Atari' Key */
+ #define ST_UNDO		0x61
+ #define ST_HELP		0x62
+ #define ST_KP_OPEN	0x63	/* Keypad ( */
+ #define ST_KP_CLOSE 0x64	/* Keypad ) */
+ #define ST_KP_DIV	0x65	/* Keypad / */
+ #define ST_KP_MULT	0x66	/* Keypad * */
+ #define ST_KP_7		0x67
+ #define ST_KP_8		0x68
+ #define ST_KP_9		0x69
+ #define ST_KP_4		0x6a
+ #define ST_KP_5		0x6b
+ #define ST_KP_6		0x6c
+ #define ST_KP_1		0x6d
+ #define ST_KP_2		0x6e
+ #define ST_KP_3		0x6f
+ #define ST_KP_0		0x70
+ #define ST_KP_DOT	0x71	/* Keypad . */
+ #define ST_KP_ENTER 0x72
+ 
  #endif /* IKBD_H */
diff -rcN STonX-0.6.4/io.c STonX-0.6.5/io.c
*** STonX-0.6.4/io.c	Mon Jan 22 01:43:16 1996
--- STonX-0.6.5/io.c	Fri Feb  9 19:24:07 1996
***************
*** 15,20 ****
--- 15,21 ----
  #include "mem.h"
  #include "main.h"
  #include "serial.h"
+ #include "screen.h"
  
  #define SERIAL_DEV "/dev/ttyS1"
  #define BOOTSECTOR 0
***************
*** 172,178 ****
  #if 0
  	fprintf(stderr,"Shiftmode set\n");
  #endif
! 	shifter();
  }
  
  void set_vbase (UL n)
--- 173,179 ----
  #if 0
  	fprintf(stderr,"Shiftmode set\n");
  #endif
! 	machine.screen_shifter();
  }
  
  void set_vbase (UL n)
diff -rcN STonX-0.6.4/iotab1.c STonX-0.6.5/iotab1.c
*** STonX-0.6.4/iotab1.c	Fri Jan 19 00:42:59 1996
--- STonX-0.6.5/iotab1.c	Fri Feb  9 19:11:11 1996
***************
*** 19,24 ****
--- 19,42 ----
  B LOAD_B_ff8923(void);
  B LOAD_B_ff8924(void);
  B LOAD_B_ff8925(void);
+ B LOAD_B_ff8a28(void);
+ B LOAD_B_ff8a29(void);
+ B LOAD_B_ff8a2a(void);
+ B LOAD_B_ff8a2b(void);
+ B LOAD_B_ff8a2c(void);
+ B LOAD_B_ff8a2d(void);
+ B LOAD_B_ff8a32(void);
+ B LOAD_B_ff8a33(void);
+ B LOAD_B_ff8a34(void);
+ B LOAD_B_ff8a35(void);
+ B LOAD_B_ff8a36(void);
+ B LOAD_B_ff8a37(void);
+ B LOAD_B_ff8a38(void);
+ B LOAD_B_ff8a39(void);
+ B LOAD_B_ff8a3a(void);
+ B LOAD_B_ff8a3b(void);
+ B LOAD_B_ff8a3c(void);
+ B LOAD_B_ff8a3d(void);
  B (* IOTAB1_funcs_LOAD[])(void)={
  LOAD_B_ff8200,
  LOAD_B_ff8202,
***************
*** 39,44 ****
--- 57,80 ----
  LOAD_B_ff8923,
  LOAD_B_ff8924,
  LOAD_B_ff8925,
+ LOAD_B_ff8a28,
+ LOAD_B_ff8a29,
+ LOAD_B_ff8a2a,
+ LOAD_B_ff8a2b,
+ LOAD_B_ff8a2c,
+ LOAD_B_ff8a2d,
+ LOAD_B_ff8a32,
+ LOAD_B_ff8a33,
+ LOAD_B_ff8a34,
+ LOAD_B_ff8a35,
+ LOAD_B_ff8a36,
+ LOAD_B_ff8a37,
+ LOAD_B_ff8a38,
+ LOAD_B_ff8a39,
+ LOAD_B_ff8a3a,
+ LOAD_B_ff8a3b,
+ LOAD_B_ff8a3c,
+ LOAD_B_ff8a3d,
  };
  UB IOTAB1_flags_LOAD[]={
  1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
***************
*** 181,188 ****
  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,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,
--- 217,224 ----
  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,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,21,22,23,24,25,26,1,1,1,1,27,28,
! 29,30,31,32,33,34,35,36,37,38,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,
***************
*** 303,309 ****
--- 339,362 ----
  void STORE_B_ff8801(B v);
  void STORE_B_ff8802(B v);
  void STORE_B_ff8803(B v);
+ void STORE_B_ff8a28(B v);
+ void STORE_B_ff8a29(B v);
+ void STORE_B_ff8a2a(B v);
+ void STORE_B_ff8a2b(B v);
+ void STORE_B_ff8a2c(B v);
+ void STORE_B_ff8a2d(B v);
+ void STORE_B_ff8a32(B v);
+ void STORE_B_ff8a33(B v);
+ void STORE_B_ff8a34(B v);
+ void STORE_B_ff8a35(B v);
+ void STORE_B_ff8a36(B v);
+ void STORE_B_ff8a37(B v);
+ void STORE_B_ff8a38(B v);
+ void STORE_B_ff8a39(B v);
+ void STORE_B_ff8a3a(B v);
+ void STORE_B_ff8a3b(B v);
  void STORE_B_ff8a3c(B v);
+ void STORE_B_ff8a3d(B v);
  void (* IOTAB1_funcs_STORE[])(B v)={
  STORE_B_ff7f30,
  STORE_B_ff7f31,
***************
*** 325,331 ****
--- 378,401 ----
  STORE_B_ff8801,
  STORE_B_ff8802,
  STORE_B_ff8803,
+ STORE_B_ff8a28,
+ STORE_B_ff8a29,
+ STORE_B_ff8a2a,
+ STORE_B_ff8a2b,
+ STORE_B_ff8a2c,
+ STORE_B_ff8a2d,
+ STORE_B_ff8a32,
+ STORE_B_ff8a33,
+ STORE_B_ff8a34,
+ STORE_B_ff8a35,
+ STORE_B_ff8a36,
+ STORE_B_ff8a37,
+ STORE_B_ff8a38,
+ STORE_B_ff8a39,
+ STORE_B_ff8a3a,
+ STORE_B_ff8a3b,
  STORE_B_ff8a3c,
+ STORE_B_ff8a3d,
  };
  UB IOTAB1_flags_STORE[]={
  2,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
***************
*** 468,475 ****
  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,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,22,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,
--- 538,545 ----
  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,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,22,23,24,25,26,27,1,1,1,1,28,29,
! 30,31,32,33,34,35,36,37,38,39,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,
diff -rcN STonX-0.6.4/main.c STonX-0.6.5/main.c
*** STonX-0.6.4/main.c	Thu Jan 18 03:56:40 1996
--- STonX-0.6.5/main.c	Fri Feb  9 19:01:58 1996
***************
*** 42,47 ****
--- 42,49 ----
  int got_drive=0;
  int chunky=0;
  extern char *kdefsfile;
+ Machine_Specific machine;
+ 
  void process_args (int argc, char *argv[], int is_rc)
  {
  	int i, u=0;
***************
*** 75,80 ****
--- 77,92 ----
  		{
  			priv_cmap=1;
  		}
+ #ifdef	USE_SVGALIB
+ 		else if (EQ(x,"svga"))
+ 		{
+ 			machine.screen_open = svga_screen_open;
+ 			machine.screen_close = svga_screen_close;
+ 			machine.screen_shifter = svga_screen_shifter;
+ 			machine.init_keys = svga_init_keys;
+ 			
+ 		}
+ #endif
  		else if (EQ(x,"chunky"))
  		{
  			chunky=1;
***************
*** 203,208 ****
--- 215,223 ----
  " -warmboot                 Attempt to simulate a warm-boot\n"
  " -private                  Use private colormap (speeds -color up)\n"
  " -cconws                   Redirect GEMDOS Cconws() function to terminal\n"
+ #ifdef	USE_SVGALIB
+ " -svga                     Use Linux SVGALIB instead of X\n"	
+ #endif
  " -vdi                      Use xlib-VDI\n\n"
  "Example: %s -disk a:Disk -color -usec 10000 -vbl 10 -refresh 2 -timer-c 1\n"
  "will use `Disk' for drive A:, boot in color mode, and run Timer C at "
***************
*** 270,275 ****
--- 285,296 ----
  main (int argc, char *argv[])
  {
  	flags = 0;
+ 
+ 	machine.screen_open = x_screen_open;
+ 	machine.screen_close = x_screen_close;
+ 	machine.screen_shifter = x_screen_shifter;
+ 	machine.init_keys = x_init_keys;
+ 
  	printf ("STonX Version " VERSION "\n(c) 1995 Marinos Yannikos and Martin D. Griffiths\n\n"
  	"*** This program is free software, and comes with NO WARRANTY! ***\n\n"
  	"**************** Read the file COPYING for details ***************\n\n");
***************
*** 340,346 ****
  #if CARTRIDGE
  	load_file ("cartridge.img", MEM(0xfa0000));
  #endif
! 	init_screen();
  	if (audio) audio_open();
  	init_hardware();
  	init_ikbd();
--- 361,367 ----
  #if CARTRIDGE
  	load_file ("cartridge.img", MEM(0xfa0000));
  #endif
! 	machine.screen_open();
  	if (audio) audio_open();
  	init_hardware();
  	init_ikbd();
***************
*** 358,364 ****
  #if MONITOR
  	kill_monitor();
  #endif
! 	screen_clean_up();
  	if (parallel_dev != NULL) done_parallel();
  	if (audio) audio_close();
  	exit_debug();
--- 379,385 ----
  #if MONITOR
  	kill_monitor();
  #endif
! 	machine.screen_close();
  	if (parallel_dev != NULL) done_parallel();
  	if (audio) audio_close();
  	exit_debug();
diff -rcN STonX-0.6.4/mem.c STonX-0.6.5/mem.c
*** STonX-0.6.4/mem.c	Mon Jan 22 01:30:17 1996
--- STonX-0.6.5/mem.c	Fri Feb  9 19:23:44 1996
***************
*** 35,41 ****
  		SM_UL(MEM(0x4ba),16000);
  		SM_UL(MEM(0x436),new_top);
  		SM_UL(MEM(0x42e),LM_UL(MEM(0x436)));
! #if 1
  		fprintf(stderr,"phystop is now %lx\n",LM_UL(MEM(0x42e)));
  #endif
  		SM_UL(MEM(0x44e),LM_UL(MEM(0x42e)));
--- 35,41 ----
  		SM_UL(MEM(0x4ba),16000);
  		SM_UL(MEM(0x436),new_top);
  		SM_UL(MEM(0x42e),LM_UL(MEM(0x436)));
! #if 0
  		fprintf(stderr,"phystop is now %lx\n",LM_UL(MEM(0x42e)));
  #endif
  		SM_UL(MEM(0x44e),LM_UL(MEM(0x42e)));
***************
*** 62,65 ****
--- 62,71 ----
  #endif
  		SM_UL(MEM(0x4ba),16000);
  	}
+ }
+ 
+ void mc68000_reset(void)
+ {	/* pc = TOSSTART; ????
+ 	sr = 0x2700;
+ 	*/
  }
diff -rcN STonX-0.6.4/options.h STonX-0.6.5/options.h
*** STonX-0.6.4/options.h	Mon Jan 22 00:30:22 1996
--- STonX-0.6.5/options.h	Fri Feb  9 19:35:56 1996
***************
*** 14,20 ****
  #endif
  
  /* Set this to 1 if you're going to use a TOS 1.X */
! #define TOS_1 0
  
  /* Draw everything to a pixmap as well in the Xlib-VDI driver so we can 
   * redraw at exposure events?
--- 14,20 ----
  #endif
  
  /* Set this to 1 if you're going to use a TOS 1.X */
! #define TOS_1 0 
  
  /* Draw everything to a pixmap as well in the Xlib-VDI driver so we can 
   * redraw at exposure events?
diff -rcN STonX-0.6.4/screen.c STonX-0.6.5/screen.c
*** STonX-0.6.4/screen.c	Mon Jan 22 00:45:28 1996
--- STonX-0.6.5/screen.c	Fri Feb  9 19:01:39 1996
***************
*** 4,644 ****
   * COPYING for details
   */
  #include "defs.h"
! #include "tosdefs.h"
! #include "debug.h"
! #include "ikbd.h"
! #include "main.h"
! #include "missing.h"
! #include "onexit.h"
  #include "screen.h"
- #include "xlib_vdi.h"
  #include <stdio.h>
  #include <string.h>
- #include <sys/param.h>
- #include <sys/times.h>
- #include <time.h>
- #include <X11/Xos.h>
- #include <X11/Xatom.h>
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <X11/cursorfont.h>
- 
- #ifndef CLK_TCK
- #define CLK_TCK HZ
- #endif
- 
- #define GCURX 0x25a
- #define GCURY 0x258
- 
- #define GRABMODE 0
- #define HIDEMODE 1
- #define REDRAW 1
- #define BENCH_REFRESH 0
- #define NUM_AVG	100
- #define SET_MOUSE 1
  
  static struct {char x[4];} Ztab[] = {
  #include "tab8.c"
  };
  
- #ifdef SH_MEM
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
- #include <X11/extensions/XShm.h>
- 
- XShmSegmentInfo shminfo;
- static shm_used;
- 
- #endif
- extern UL abase;
  int scr_width,scr_height,scr_planes;
- static char txt[256];
- extern int verbose;
- extern int priv_cmap;
- extern int chunky;
- static Cursor cursors[2];
- static int cursidx=0;
- static int warped=0;
- #if BENCH_REFRESH
- static int cref=0;
- static clock_t reftime;
- static int chunks_seen=0,chunks_drawn=0;
- #endif
- static Pixmap empty;
- #if GRABMODE
- static int grabbed=1;
- #endif
- static Window in_which=None;
- 
- SCRDEF scr_def[3];
- 
- /* some interesting events: */
- #define E_MASK (KeyPressMask|KeyReleaseMask|ButtonPressMask	\
- 				|ButtonReleaseMask|PointerMotionMask|ColormapChangeMask|\
- 				EnterWindowMask|LeaveWindowMask|ExposureMask)
- 
- char **ksyms;
- int kmin,kmax;
- int redraw_flag=0;
- 
  int depth;
! int shmflag = 1, shm_mono=1;
! Display *display;
! char win_name[64];
! Visual *visual = NULL;
! Status status;
! unsigned long wp, bp;		/* pixel values for black & white */
! int screen, nplanes, ncolors;
! int Max_x, Max_y;
! 
! XEvent event;
! XSetWindowAttributes attrib;
! 
! GC gc;
! XGCValues gc_val;
! XSizeHints sizehints;
! Window imagewin;		/* window ID for image */
! XImage *image = NULL;
! B *Image;
! Colormap cmap=0, hlcmap;
! char keybuf[64];
! extern int refresh,scanlines;
! int refcount=0;
! int lastmx=0,lastmy=0;
! static B *buf;
! int shm_ct;
! 
! #define BUF(a,b) buf[(viewy * (b)) + (a)]
! #undef SHM_WAIT
! 
! /*------------------------------------------------------------------*/
! /* This is our information about the current shifter mode/state: 	*/
! /* (from hw.c) 														*/
! extern int shiftmod;	/* shift mode 								*/
! extern UW *color;		/* palette, rasters not possible! :-( 		*/
! extern volatile UL vbase;		/* screen address (Physbase) 				*/
! /*------------------------------------------------------------------*/
! static int old_shiftmod=-1;	/* last known shift mode, used to detect changes */
! static UW old_color[16];	/* last known color palette */
! 
! /* Destroy the current emulator window
!  */
! void destroy_image (void)
! {
! 	if (image == NULL) return;
! 	XDestroyImage (image);
! #ifdef SH_MEM
!     if (shmflag && shm_used)
!     {
! 		XShmDetach (display, &shminfo);
! 		shmdt (shminfo.shmaddr);
! 		shmctl (shminfo.shmid, IPC_RMID, 0);
! 		shm_used = 0;
!     }
! #endif
! }
! 
! void 
! screen_clean_up (void)
! {
! 	XAutoRepeatOn(display);
! 	XFlush(display);
! 	destroy_image();
! }
! 
! void set_window_name (char *name)
! {
! 	XStoreName (display, imagewin, name);
! }
! 
! /* Create a new image for the emulation window, using shared memoy if possible
!  */
! void create_image (int w, int h, int format)
! {
! 	int planes = (format == XYBitmap ? 1 : 8);
! 	Max_x = w-1;
! 	Max_y = h-1;
! #ifdef SH_MEM
!     if (shmflag && (planes == 8 || shm_mono))
!     {
! 		image = XShmCreateImage (display, visual, planes, format,
! 				 				NULL, &shminfo, w, h);
! 		shminfo.shmid = shmget (IPC_PRIVATE, image->bytes_per_line
! 								* image->height, IPC_CREAT | 0777);
! 		buf = shminfo.shmaddr = image->data = shmat (shminfo.shmid, 0, 0);
! 		shminfo.readOnly = False;
! 		XShmAttach (display, &shminfo);
! 		XSync(display, False);
! 		shmctl(shminfo.shmid, IPC_RMID, 0);
! 		shm_used = 1;
! #if 0
! 		bzero (&shminfo, sizeof(shminfo));
! #endif
!     }
!     else
! #endif
! 	{
!     	buf = malloc (w * h * (format == XYBitmap ? 1 : 8));
!     	image = XCreateImage (display, visual, planes, format,
! 							0, (char *) buf, w, h, 8, 0);
! 	}
! #if 1
! 	image -> bitmap_bit_order = MSBFirst;
! 	image -> byte_order = MSBFirst;
! #else
! 	image -> bitmap_bit_order = LSBFirst;
! 	image -> byte_order = LSBFirst;
! #endif
!     Image = image->data;
! }
! 
! /* Change the window colormap according to the contents of old_color[].
!  * The colors are converted from ST/STe format (least-significant 9/12 bits
!  * of a 16 bit integer) to the 16 bit per RGB component format used in X11.
!  */
! #define COLS 16
! static int allocatedcols[COLS];
! char mapcol[COLS];
! void change_colors (void)
! {
! 	XColor colors[COLS];
! 	UW c;
! 	int i;
! 	int q=0;
! 	unsigned long pixels[COLS];
! 	int j,k;
! 	if (depth == 1) return;
! 
! 	if (shiftmod == 2)
! 	{
! 		for (i=0; i<COLS; i++)
! 		{
! 			colors[i].pixel = i;
! 			colors[i].flags = DoRed | DoGreen | DoBlue;
! 			colors[i].red = colors[i].green = colors[i].blue = 0;
! 		}
! 		if (old_color[0] == 0) {
! 			/* mono show_screen does just memcpy; XPutImage... */
! #if 0
! 			XSetForeground (display, gc, bp);
! 			XSetBackground (display, gc, wp);
! #endif
! 			colors[1].red = colors[1].green = colors[1].blue = 0xffff;
! 		} else {
! #if 0
! 			XSetForeground (display, gc, wp);
! 			XSetBackground (display, gc, bp);
! #endif
! 			colors[0].red = colors[0].green = colors[0].blue = 0xffff;
! 		}
! 	}
! 	else for (i=0; i<COLS; i++)
! 	{
! 		c = (i < (shiftmod == 0 ? 16 : 4) ? old_color[i] : 0);
! #if !STE
! 		c &= 0x777;
! #endif
! 		colors[i].pixel = i;
! 		colors[i].flags = DoRed | DoGreen | DoBlue;
! 		colors[i].red 	= (((c>>8)&7)<<13)|((c>>11)<<12);
! 		colors[i].green	= (((c>>4)&7)<<13)|(((c>>7)&1)<<12);
! 		colors[i].blue	= ((c&7)<<13)|(((c>>3)&1)<<12);
! 	}
! 
! if (!priv_cmap)
! {
! 	for (i=0; i<COLS; i++)
! 	{
! 		if (allocatedcols[i]>=0)
! 		{
! 			pixels[q++]=allocatedcols[i];
! 		}
! 	}
! 	if (q>0) XFreeColors(display, cmap, pixels, q, 0);
! 	for (i=0; i<COLS; i++)
! 	{
! 		XAllocColor (display, cmap, &colors[i]);
! 		mapcol[i]=colors[i].pixel;
! 	}
! }
! else
! {
! 	XStoreColors (display, cmap, colors, COLS);
! }
! #if 0
! 	XMapRaised (display, imagewin);
! 	XFlush(display);
! #endif
! #if 0
! 	XUnmapWindow (display, imagewin);
! 	XMapWindow (display, imagewin);
! #endif
! }
! 
! /* Do something appropriate when the 'shiftmod' hardware register has changed:
!  * 1. The window is resized
!  * 2. A new image is created
!  * 3. A new conversion function is used every VBL
!  */
! void change_mode (void)
! {
! 	scr_width = scr_def[shiftmod].w;
! 	scr_height = scr_def[shiftmod].h;
! 	scr_planes=4>>shiftmod;
! #if 1
! 	fprintf(stderr,"Screen is now %dx%d, shift mode %d\n",scr_width,scr_height,shiftmod);
! #endif
! 	switch (shiftmod)
! 	{
! 		case 0:
! 			XResizeWindow (display, imagewin, scr_width, scr_height);
! 			destroy_image();
! 			create_image (scr_width, scr_height, ZPixmap);
! 			change_colors();
! 			break;
! 
! 		case 1:
! 			XResizeWindow (display, imagewin, scr_width, scr_height*2);
! 			destroy_image();
! 			create_image (scr_width, scr_height*2, ZPixmap);
! 			change_colors();
! 			break;
! 
! 		case 2:
! 			XResizeWindow (display, imagewin, scr_width, scr_height);
! 			destroy_image();
! 			create_image (scr_width, scr_height, XYBitmap);
! 			change_colors();
! 			break;
! 	}
! }
! 
! /* Process all events that occured since we last came here...
!  */
! void process_events (void)
! {
! 	int tx,ty;
! 	XEvent e;
! 	XExposeEvent *x;
! 	while (XCheckMaskEvent (display, E_MASK, &e))
! 	{
! 		switch (e.type)
! 		{
! 		case EnterNotify:
! 			XAutoRepeatOff(display);
! 			if (vdi && xw != None) vdi_mode = (e.xcrossing.window != imagewin);
! 			in_which = e.xcrossing.window;
! 
! 			if (in_which == imagewin)
! 			{
! #if SET_MOUSE
! 				lastmx = LM_W(MEM(abase-GCURX));
! 				lastmy = LM_W(MEM(abase-GCURY));
! 				XWarpPointer (display, None, imagewin, 0, 0, 0, 0, 
! 								lastmx, lastmy);
! 				XDefineCursor (display, imagewin, cursors[cursidx]);
! 				warped=1;
! #else
! 				int mx,my,nx,ny;
! #if 0
! 				mx=LM_W(MEM(abase-GCURX));
! 				my=LM_W(MEM(abase-GCURY));
! #endif
! 				nx=(((XCrossingEvent *)&e)->x);
! 				ny=(((XCrossingEvent *)&e)->y);
! #if 0
! 				fprintf(stderr,"Repositioning mouse from %d,%d to %d,%d\n",
! 					mx,my,nx,ny);
! 				ikbd_adjust(nx-lastmx,ny-lastmy);
! 				lastmx=mx;
! 				lastmy=my;
! #endif
! 				ikbd_pointer(nx,ny,Max_x,Max_y);
! #endif
! 			}
! 			break;
! 		case LeaveNotify:
! 			XAutoRepeatOn(display); /* BUG: should restore previous value */
! 			if (e.xcrossing.window == imagewin) XUndefineCursor(display,imagewin);
! 			in_which = None;
! 			break;
! 		case KeyPress:
! 			/* fprintf (stderr, "Keypress: %d\n", ((XKeyEvent *)&e)->keycode);*/
! 			ikbd_key (((XKeyEvent *)&e)->keycode, 1);
! 			break;
! 		case KeyRelease:
! 		/*	fprintf (stderr, "Keyrelease: %d\n", ((XKeyEvent *)&e)->keycode);*/
! 			ikbd_key (((XKeyEvent *)&e)->keycode, 0);
! 			break;
! 		case ButtonPress:
! #if GRABMODE
! 			if (((XButtonEvent *)&e)->button == 3)
! 			{
! #if 0
! 				fprintf(stderr, "in window %lx\n",(long)in_which);
! #endif
! 				if (grabbed)
! 				{
! 					XUngrabKeyboard (display, CurrentTime);
! 					XUngrabPointer (display, CurrentTime);
! 					grabbed=0;
! 				}
! 				else if (in_which != xw)
! 				{
! 					XGrabPointer (display, imagewin, True, PointerMotionMask
! 					|ButtonPressMask|ButtonReleaseMask,
! 					GrabModeAsync, GrabModeAsync, None, hidden, CurrentTime);
! 					XGrabKeyboard (display, imagewin,True, GrabModeAsync,
! 						GrabModeAsync, CurrentTime);
! 					grabbed=1;
! 					fprintf (stderr, "grabbed\n");
! 				}
! 			}
! #if 0
! 			if (((XButtonEvent *)&e)->button == 3 &&
! 				((XButtonEvent *)&e)->window == xw)
! 					redraw_flag=1;
! 		fprintf (stderr, "Buttonpress: %d\n", ((XButtonEvent *)&e)->button);
! #endif
! #elif HIDEMODE
! 			if (((XButtonEvent *)&e)->button == 3)
! 			{
! 				cursidx = !cursidx;
! 				XDefineCursor (display, imagewin, cursors[cursidx]);
! 				break;
! 			}
! #endif
! 			ikbd_button (((XButtonEvent *)&e)->button, 1);
! 			break;
! 		case ButtonRelease:
! #if 0
! 		fprintf (stderr, "Buttonrelease: %d\n", ((XButtonEvent *)&e)->button);
! #endif
! 			ikbd_button (((XButtonEvent *)&e)->button, 0);
! 			break;
! 		case Expose:
! 			x = (XExposeEvent *)&e;
! #if XBUFFER
! 			if (xw == x->window)
! 				vdi_redraw(x->x,x->y,x->width,x->height);
! #endif
! 			break;
! 		case MotionNotify:
! 			if (e.xmotion.window == imagewin && warped)
! 			{
! 				warped=0;
! #if 0
! 				lastmx = ((XMotionEvent *)&e)->x;
! 				lastmy = ((XMotionEvent *)&e)->y;
! 				break;
! #endif
! 			}
! #if 0
! 
! #if 0	
! 			if (e.xmotion.window == imagewin)
! #endif
! /*	fprintf (stderr, "Pointer: %d,%d\n", ((XMotionEvent *)&e)->x,((XMotionEvent *)&e)->y); */
! #if 0
! 			SM_W(MEM(abase-GCURX),((XMotionEvent *)&e)->x);
! 			SM_W(MEM(abase-GCURY),((XMotionEvent *)&e)->y);
! 			SM_W(MEM(abase-0x158),((XMotionEvent *)&e)->x);
! 			SM_W(MEM(abase-0x156),((XMotionEvent *)&e)->y);
! 			SM_B(MEM(abase-0x154),0xff);
! #endif
! #if 0
! #if 1
! 			tx=LM_W(MEM(abase-0x158));
! 			ty=LM_W(MEM(abase-0x156));
! #if 1
! 			if (tx==lastmx && ty==lastmy) break;
! #endif
! 			lastmx=tx;
! 			lastmy=ty;
! #endif
! 			fprintf(stderr,"Adjusting: (%d,%d)->(%d,%d)\n",lastmx,lastmy,
! 			((XMotionEvent *)&e)->x,((XMotionEvent *)&e)->y);
! 			ikbd_adjust (((XMotionEvent *)&e)->x-lastmx,
! 						((XMotionEvent *)&e)->y-lastmy);
! #else
! 			ikbd_adjust (((XMotionEvent *)&e)->x-lastmx,
! 						((XMotionEvent *)&e)->y-lastmy);
! 			lastmx = ((XMotionEvent *)&e)->x;
! 			lastmy = ((XMotionEvent *)&e)->y;
! #endif
! 
! #else
! #if 0
! 			ikbd_pointer (((XMotionEvent *)&e)->x,((XMotionEvent *)&e)->y,Max_x,Max_y);
! #else
! 			ikbd_adjust (((XMotionEvent *)&e)->x-lastmx,
!                         ((XMotionEvent *)&e)->y-lastmy);
!             lastmx = ((XMotionEvent *)&e)->x;
!             lastmy = ((XMotionEvent *)&e)->y;
! #endif
! #endif
! 			break;
! 		}
! 	}
! }
! 
! void init_screen (void)
! {
!     int i, j;
!     int shm_major, shm_minor;
!     Bool shm_pixmaps;
!     XSizeHints h;
!     XFontStruct *font_info;
!     XImage *t;
! 	XColor ccols[2];
! 
! 	scr_width = scr_def[shiftmod].w;
! 	scr_height = scr_def[shiftmod].h;
! 
!     strcpy (win_name, "STonX Main Window");
! 
!     if ((display = XOpenDisplay (NULL)) == NULL)
!     {
! 		fprintf (stderr, "Could not open display.\n");
! 		exit (1);
!     }
! 
! #if 0
! 	XAutoRepeatOff(display);
! #endif
! 	verbose && fprintf (stderr, "Obtaining Keysym mappings for display...\n");
! 	XDisplayKeycodes (display, &kmin, &kmax);
! 	verbose && fprintf (stderr, "Keycode range = %d..%d\n", kmin, kmax);
! 	ksyms = (char **)malloc(sizeof(char *)*(kmax-kmin+1));
! 	for (i=kmin; i<=kmax; i++)
! 	{
! 		char *s = XKeysymToString(XKeycodeToKeysym(display,i,0));
! 		ksyms[i-kmin] = (s == NULL ? s : strdup(s));
! #if 0
! 		fprintf (stderr, "Keycode %d = %s\n", i,s);
! #endif
! 	}
! 
! #ifdef SH_MEM
!     if (shmflag)
!     {
! 		if (!XShmQueryVersion (display, &shm_major, &shm_minor, &shm_pixmaps))
! 		{
! 	    	verbose && fprintf(stderr,
! 					"MIT Shared Memory Extension not supported.\n");
! 	    	shmflag = 0;
! 		}
! 		else
! 		{
! 			int foo;
! 	  		verbose && fprintf (stderr,
! 				"Using MIT Shared Memory Extension %d.%d," \
! 		  	   " %s shared pixmaps.\n", shm_major, shm_minor,
! 		   	  (shm_pixmaps ? "with" : "without"));
! 			foo = XShmPixmapFormat (display);
! 			verbose && fprintf (stderr,
! 					"XShm Pixmap format: %s\n", ((foo == XYBitmap ? 
! 				"XYBitmap" : (foo == XYPixmap ? "XYPixmap" : "ZPixmap"))));
! 			verbose && fprintf (stderr, "If you get a BadAccess error, try the -noshm option!\n");
! 		}
!     }
! #endif
! 	
!     screen = XDefaultScreen (display);
!     depth = DefaultDepth (display, screen);
! 	if (depth == 1)
! 	{
! 		SM_B(MEM(0xff8260),2);
! 		old_shiftmod = 2;
! 	}
!     visual = XDefaultVisual (display, screen);
!     nplanes = XDisplayPlanes (display, screen);
! 
! 	/* See if we are on a local little-endian display - in that case,
! 	   XShmPutImage will refuse to swap bits most of the time! */
! 	if (shmflag)
! 	{
! 		char *c=malloc(64);
! 		t = XCreateImage (display, visual, 1, XYBitmap, 0, c, 32, 16, 8, 0);
! 		if (t->bitmap_bit_order == LSBFirst)
! 		{
! 			fprintf (stderr, "NOTE: Because XShmPutImage apparently can't swap bits, shared memory support\nwas turned off for monochrome mode!\n");
! 			shm_mono=0;
! 		}
! 		XDestroyImage (t);
! 	}
! 
!     h.width = scr_width;
!     h.height = scr_height;
!     h.x = 500;
!     h.y = 0;
! 
!     h.flags = PSize | PPosition;
!     bp = BlackPixel (display, screen);
!     wp = WhitePixel (display, screen);
!     imagewin = XCreateSimpleWindow (display, RootWindow (display, screen),
! 			h.x, h.y, h.width, h.height, 1, bp, wp);
!     XSelectInput (display, imagewin, StructureNotifyMask|E_MASK);
!     XSetStandardProperties (display, imagewin, win_name, win_name, None,
! 			    NULL, 0, &h);
!     XMapWindow (display, imagewin);
!     for (;;)
!     {
! 		XEvent e;
! 		XNextEvent (display, &e);
! 		if (e.type == MapNotify && e.xmap.event == imagewin) break;
!     }
!     gc_val.background = bp;
!     gc_val.foreground = wp;
!     gc = XCreateGC (display, imagewin, GCForeground | GCBackground, &gc_val);
! #ifdef SH_MEM
!     shm_ct = XShmGetEventBase (display) + ShmCompletion;
! #endif
!     XSetForeground (display, gc, 1);
!     XSetBackground (display, gc, 0);
! 	if (depth > 1)
! 	{
! 	if (!priv_cmap)
! 	{
! 		cmap = DefaultColormap (display, screen);
! 		for (i=0; i<COLS; i++) allocatedcols[i]=-1;
! 	}
! 	else
! 	{
! 		cmap = XCreateColormap (display, RootWindow(display, screen), visual,
! 								AllocAll);
! 	}
! 	XSetWindowColormap (display, imagewin, cmap);
! 	}
!     XClearWindow (display, imagewin);
! #if 0
! 	XWarpPointer (display, None, imagewin, 0, 0, 0, 0, 320, 200);
! #endif
!     XSelectInput (display, imagewin, E_MASK);
! #if !MONITOR && GRAB
! 	XGrabPointer (display, imagewin, False, ButtonPressMask|ButtonReleaseMask
! 					|PointerMotionMask, GrabModeAsync,
! 					GrabModeAsync, None, None, CurrentTime);
! #endif
! 	if (depth == 1) create_image (scr_width,scr_height,XYBitmap);
! 	empty = XCreatePixmapFromBitmapData (display, imagewin, calloc(32,1),
! 			16, 16,0,0,1);
! 	ccols[0].pixel = 0;
! 	ccols[1].pixel = 0;
! 	cursors[0] = XCreatePixmapCursor (display, empty, empty, &ccols[0], &ccols[1],
! 				0,0);
! 	cursors[1] = XCreateFontCursor (display, XC_tcross);
! #if GRABMODE
! 	XGrabPointer (display, imagewin, True, PointerMotionMask
! 	|ButtonPressMask|ButtonReleaseMask,
! 	GrabModeAsync, GrabModeAsync, None, hidden, CurrentTime);
! 	XGrabKeyboard (display, imagewin,True, GrabModeAsync,
! 		GrabModeAsync, CurrentTime);
! 	fprintf (stderr, "The X pointer and keyboard have been grabbed by STonX - press the 3rd mouse\nbutton to release/grab again.\n");
! #endif
! 	OnExit (screen_clean_up);
! }
  
  /* Convert an image in ST format (4 interleaved bitplanes) to ZPixmap format
   *
--- 4,22 ----
   * COPYING for details
   */
  #include "defs.h"
! #include "mem.h"
  #include "screen.h"
  #include <stdio.h>
  #include <string.h>
  
  static struct {char x[4];} Ztab[] = {
  #include "tab8.c"
  };
  
  int scr_width,scr_height,scr_planes;
  int depth;
! int shift_mod;
! extern char mapcol[16];
  
  /* Convert an image in ST format (4 interleaved bitplanes) to ZPixmap format
   *
***************
*** 647,657 ****
   *
   * This code assumes short = 16 bit and int = 32 bit and aligned data!
   */
- #define CHUNK_LINES 8
- #define MAX_CHUNKS 1000
- #define MAX_AGE	20
  
! static int chunk_age[MAX_CHUNKS];
  static unsigned long chunk_sum[MAX_CHUNKS];
  #if IS_BIG_ENDIAN
  #define LL(_x) *(_x)
--- 25,32 ----
   *
   * This code assumes short = 16 bit and int = 32 bit and aligned data!
   */
  
! int chunk_age[MAX_CHUNKS];
  static unsigned long chunk_sum[MAX_CHUNKS];
  #if IS_BIG_ENDIAN
  #define LL(_x) *(_x)
***************
*** 662,668 ****
  #define SL(_x,_v) *(_x)=_v
  /* #define SL(_x,_v) SM_L(_x,_v) */
  #endif
! static void st16c_to_z (char *st, char *data)
  {
  	int *y, lo, hi, i, idx, l, q, j,ch;
  	unsigned short w1,w2,w3,w4,*x;
--- 37,43 ----
  #define SL(_x,_v) *(_x)=_v
  /* #define SL(_x,_v) SM_L(_x,_v) */
  #endif
! void st16c_to_z (char *st, char *data)
  {
  	int *y, lo, hi, i, idx, l, q, j,ch;
  	unsigned short w1,w2,w3,w4,*x;
***************
*** 724,730 ****
  /* Convert an image in 2 interleaved bitplane format to ZPixmap with 400
   * lines. An optimizing compiler is a good idea ;-) (CSE)
   */
! static void st4c_to_z (char *st, char *data)
  {
  	int *r = (int *)st, r1, r2, ch;
  	int i, j, k;
--- 99,105 ----
  /* Convert an image in 2 interleaved bitplane format to ZPixmap with 400
   * lines. An optimizing compiler is a good idea ;-) (CSE)
   */
! void st4c_to_z (char *st, char *data)
  {
  	int *r = (int *)st, r1, r2, ch;
  	int i, j, k;
***************
*** 791,796 ****
--- 166,225 ----
  	}
  }
  
+ /* Convert an image in 2 interleaved bitplane format to ZPixmap with 200
+  * lines. An optimizing compiler is a good idea ;-) (CSE)
+  */
+ void st4c_to_z200 (char *st, char *data)
+ {
+ 	int *r = (int *)st, r1, r2, ch;
+ 	int i, j, k;
+ 	int chunk_bytes=(scr_width/4)*CHUNK_LINES;
+ 	for (ch=0; ch<scr_height/CHUNK_LINES; ch++)
+ 	{
+ 		if (chunky && ++chunk_age[ch] < MAX_AGE)
+ 		{
+ 			unsigned long sum=0;
+ 			int p;
+ 			unsigned long *chp = (unsigned long *)r;
+ 			for (p=0; p<chunk_bytes/sizeof(*chp); p++)
+ 				sum += chp[p];
+ 			if (sum == chunk_sum[ch])
+ 			{
+ 				data += scr_width*CHUNK_LINES;
+ 				r += chunk_bytes/4;
+ 				continue;
+ 			}
+ 			chunk_sum[ch]=sum;
+ 		}
+ 		chunk_age[ch]=1;
+ 
+ 		for (k=0; k<CHUNK_LINES; k++)
+ 		for (i=0; i<scr_width/16; i++,r++,data+=16)
+ 		{
+ 			r1 = LL(r);
+ 			r2 = ((r1>>16)&0x5555)|((r1<<1)&0xaaaa);
+ 			data[15] = r2 & 3; r2 >>= 2;
+ 			data[13] = r2 & 3; r2 >>= 2;
+ 			data[11] = r2 & 3; r2 >>= 2;
+ 			data[9] = r2 & 3; r2 >>= 2;
+ 			data[7] = r2 & 3; r2 >>= 2;
+ 			data[5] = r2 & 3; r2 >>= 2;
+ 			data[3] = r2 & 3; r2 >>= 2;
+ 			data[1] = r2 & 3; r2 >>= 2;
+ 			r2 >>= 2;
+ 			r2 = ((r1>>17)&0x5555)|(r1&0xaaaa);
+ 			data[14] = r2 & 3; r2 >>= 2;
+ 			data[12] = r2 & 3; r2 >>= 2;
+ 			data[10] = r2 & 3; r2 >>= 2;
+ 			data[8] = r2 & 3; r2 >>= 2;
+ 			data[6] = r2 & 3; r2 >>= 2;
+ 			data[4] = r2 & 3; r2 >>= 2;
+ 			data[2] = r2 & 3; r2 >>= 2;
+ 			data[0] = r2 & 3; r2 >>= 2;
+ 		}
+ 	}
+ }
+ 
  void stmono_to_xy (char *data, char *st)
  {
  	int i;
***************
*** 825,1003 ****
  		data += bytes_per_chunk;
  	}
  }
- 
- /* Update the X window using the shifter mode known when change_mode was last
-  * called...
-  */
- void show_screen (void)
- {
- 	int w, h;
- 	int xzoom,yzoom=1;
- 	w=scr_width;
- 	h=scr_height;
- 	switch (old_shiftmod)
- 	{
- 		case 0:
- 			st16c_to_z (MEM(vbase), buf);
- 			break;
- 		case 1:
- 			yzoom=2;
- 			st4c_to_z (MEM(vbase), buf);
- 			break;
- 								/* image->data = MEM(vbase)!!!! */
- 		case 2:
- 			stmono_to_xy(buf, MEM(vbase));
- 			break;
- 	}
- #ifdef SH_MEM
-     if (shmflag && (old_shiftmod != 2 || shm_mono))
-    	{
- 		XEvent xev;
- 		if (chunky)
- 		{
- 			int i;
- 			for (i=0; i<h/CHUNK_LINES; i++)
- 				if (chunk_age[i]==1)
- 				{
- 					XShmPutImage (display, imagewin, gc, image,
- 						0, yzoom*i*CHUNK_LINES,
- 						0, yzoom*i*CHUNK_LINES, w,
- 						yzoom*CHUNK_LINES,
- 						False);
- #if BENCH_REFRESH
- 					chunks_drawn++;
- #endif
- 				}
- #if BENCH_REFRESH
- 			chunks_seen+=h/CHUNK_LINES;
- #endif
- 		}
- 		else
- 		XShmPutImage (display, imagewin, gc, image, 0, 0, 0, 0, w, h*yzoom,
- 					False);
- 		XFlush (display);
- #ifdef SHM_WAIT
- 		do
- 		{
- 		    XNextEvent (display, &xev);
- 		}
- 		while (xev.type != shm_ct);
- #endif
-    	}
-     else
- #endif
- 	{
- 		if (chunky)
- 		{
- 			int i;
- 			for (i=0; i<h/CHUNK_LINES; i++)
- 				if (chunk_age[i]==1)
- 				{
- 					XPutImage (display, imagewin, gc, image,
- 						0, yzoom*i*CHUNK_LINES,
- 						0, yzoom*i*CHUNK_LINES, w,
- 						yzoom*CHUNK_LINES);
- #if BENCH_REFRESH
- 					chunks_drawn++;
- #endif
- 				}
- #if BENCH_REFRESH
- 			chunks_seen+=h/CHUNK_LINES;
- #endif
- 		}
- 		else
- 		XPutImage (display, imagewin, gc, image, 0, 0, 0, 0, w, h);
- 		XFlush (display);
- 	}
- #if 1
-     XSync (display, False);
- #endif
- }
- 
- void manage_window ()
- {
-     XKeyEvent *keypress;
-     KeySym keysym;
-     XComposeStatus cstat;
- 
-     keypress = (XKeyEvent *) & event;
- 
- 	if (XPending (display))
- 	{
- 	    XNextEvent (display, &event);
- 	    switch ((int) event.type)
- 	    {
- 		case KeyPress:
- 		    if (XLookupString (keypress, keybuf, sizeof (keybuf),
- 				&keysym, &cstat) != 0)
- 			{
- 		/*		update_IKBD_BUFFER (); */
- 			}
- 			break;
- 		default:
- 		    break;
- 	    }
- 	}
- }
- 
- /* This function is called periodically (from a signal handler) to check what's
-  * new with the shifter mode, colors, and update ("shift") the screen. It
-  * should probably rewritten to check whether it's necessary to update the
-  * screen, since for color modes this is a very costly operation...
-  *
-  * The Shifter status information is changed in hw.c, where the hardware regs
-  * are read.
-  */
- void shifter (void)
- {
- 	int i, w, pal = 0;
- 
- 	process_events();	/* misplaced */
- 	if (++refcount < refresh) return;
- 	refcount=0;
- 
- 	for (i=0; i<16; i++)
- 	{
- 		if ((w = LM_UW(&color[i])) != old_color[i])
- 		{
- 			pal = 1;	/* palette has changed */
- 			old_color[i] = w;
- 		}
- 	}
- 
- 	if (pal) change_colors();	/* update the window colormap */
- 
- 	if (depth > 1 && old_shiftmod != shiftmod)
- 	{
- 		old_shiftmod = shiftmod;
- 		change_mode();
- 	}
- 
- 	if (!vdi_mode || xw == None)
- 	{
- #if BENCH_REFRESH
- 		struct tms ta;
- 		clock_t rt;
- 		times(&ta);
- 		rt=ta.tms_utime+ta.tms_stime;
- 		show_screen();
- 		times(&ta);
- 		reftime += ta.tms_utime+ta.tms_stime-rt;
- 		cref++;
- 		if (cref==NUM_AVG)
- 		{
- 			fprintf(stderr, "Refresh time (%d samples): %lf ms\n", NUM_AVG,
- 				1000.0*(double)reftime/(NUM_AVG*CLK_TCK));
- 			if (chunky) fprintf(stderr,"Chunks drawn/seen = %d/%d\n",chunks_drawn,chunks_seen);
- 			reftime=0;
- 			cref=0;
- 		}
- #else
- 		show_screen();
- #endif
- 	}
- #if 0
- 	check_ui();
- #endif
- }
- 
--- 254,256 ----
diff -rcN STonX-0.6.4/screen.h STonX-0.6.5/screen.h
*** STonX-0.6.4/screen.h	Tue Jan 16 02:19:58 1996
--- STonX-0.6.5/screen.h	Fri Feb  9 19:02:02 1996
***************
*** 3,17 ****
   * STonX is free software and comes with NO WARRANTY - read the file
   * COPYING for details
   */
  #ifndef SCREEN_H
  #define SCREEN_H
  #include <X11/Xlib.h>
  
! extern void shifter(void);
! extern void init_screen(void);
! extern void screen_clean_up(void);
  
  extern Display *display;
  
  typedef struct
  {
--- 3,37 ----
   * STonX is free software and comes with NO WARRANTY - read the file
   * COPYING for details
   */
+ 
  #ifndef SCREEN_H
  #define SCREEN_H
  #include <X11/Xlib.h>
  
! typedef struct
! {       void (*screen_open)(void);
!         void (*screen_close)(void);
!         void (*screen_shifter)(void);
!         void (*init_keys)(void);
! } Machine_Specific;
! extern Machine_Specific machine;
! #define COLS 16
! #define CHUNK_LINES 8
! #define MAX_CHUNKS 1000
! #define MAX_AGE 20
! 
! extern void svga_screen_open(void);
! extern void svga_screen_close(void);
! extern void svga_screen_shifter(void);
! extern void svga_init_keys(void);
! extern void x_screen_open(void);
! extern void x_screen_close(void);
! extern void x_screen_shifter(void);
! extern void x_init_keys(void);
  
+ extern int chunk_age[MAX_CHUNKS];
  extern Display *display;
+ extern int *keycodes;
  
  typedef struct
  {
***************
*** 20,23 ****
  
  extern SCRDEF scr_def[];
  
! #endif /* SCREEN_H */
--- 40,57 ----
  
  extern SCRDEF scr_def[];
  
! /*------------------------------------------------------------------*/
! /* This is our information about the current shifter mode/state: 	*/
! /* (from hw.c) 														*/
! extern int shiftmod;	/* shift mode 								*/
! extern UW *color;		/* palette, rasters not possible! :-( 		*/
! extern volatile UL vbase;		/* screen address (Physbase) 				*/
! /*------------------------------------------------------------------*/
! extern UL abase;
! extern int scr_width,scr_height,scr_planes;
! extern int verbose;
! extern int priv_cmap;
! extern int chunky,depth;
! extern int scanlines;
! extern int shiftmod,refresh;
! #endif
diff -rcN STonX-0.6.4/svga.c STonX-0.6.5/svga.c
*** STonX-0.6.4/svga.c	Thu Jan  1 01:00:00 1970
--- STonX-0.6.5/svga.c	Fri Feb  9 19:01:49 1996
***************
*** 0 ****
--- 1,400 ----
+ /* This file is part of STonX, the Atari ST Emulator for Unix/X
+  * ============================================================
+  * STonX is free software and comes with NO WARRANTY - read the file
+  * COPYING for details
+  *
+  *	SVGALIB (Linux) Stuff,
+  *	Martin Griffiths, January 1996.
+  *	
+  *	
+  */
+ 
+ #include "config.h"
+ #include "options.h"
+ 
+ #ifdef USE_SVGALIB
+ 
+ #include "defs.h"
+ #include "mem.h"
+ #include "screen.h"
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <vga.h> 
+ #include <vgagl.h>
+ #include <vgamouse.h>
+ #include <vgakeyboard.h>
+ #include "ikbd.h"
+ 
+ #define COLS 16
+ 
+ static int oldvga_mode;
+ static int old_shiftmod=-1;	/* last known shift mode, used to detect changes */
+ static B *buf;
+ static int mx=320,my=200,mb=0;
+ static int refcount=0;
+ static UW old_color[16];	/* last known color palette */
+ extern int kmin,kmax;
+ 
+ /*
+  *	Here we have the stuff to convert between PC and ST scancodes 
+  */
+ 
+ #define SCANCODE_0 11
+ #define SCANCODE_1 2
+ #define SCANCODE_2 3
+ #define SCANCODE_3 4
+ #define SCANCODE_4 5 
+ #define SCANCODE_5 6
+ #define SCANCODE_6 7 
+ #define SCANCODE_7 8
+ #define SCANCODE_8 9
+ #define SCANCODE_9 10
+ #define SCANCODE_F11 87
+ #define SCANCODE_F12 88
+ #define SCANCODE_LEFTSHIFT 42
+ #define SCANCODE_RIGHTSHIFT 54
+ #define SCANCODE_BS 14
+ #define SCANCODE_TAB 15
+ #define SCANCODE_MINUS 12
+ #define SCANCODE_EQUAL 13
+ #define SCANCODE_SQ_OPEN 26
+ #define SCANCODE_SQ_CLOSE 27
+ #define SCANCODE_SEMIC 39
+ #define SCANCODE_COMMA 51
+ #define SCANCODE_DOT 52
+ #define SCANCODE_SLASH 53
+ #define SCANCODE_KEYPADMULT 55 
+ #define SCANCODE_KEYPADDOT 83 
+ #define SCANCODE_KEYPADDIV 98 
+ #define SCANCODE_CAPSLOCK 58
+ #define SCANCODE_APOST 40
+ #define SCANCODE_GRAVE 41
+ #define SCANCODE_BACKSL 43
+ #define SCANCODE_ISO 86 
+ #define SCANCODE_PAUSE 96 
+ #define SCANCODE_PRTSCR 99
+ #define SCANCODE_PGUP 104 
+ #define SCANCODE_PGDOWN 109 
+ #define SCANCODE_INS 110
+ #define SCANCODE_DEL 111
+ 
+ static int keyflag[256];
+ 
+ static int svga_keytab[][2] =
+ {
+ 	{ SCANCODE_F1,ST_F1 },
+ 	{ SCANCODE_F2,ST_F2 },
+ 	{ SCANCODE_F3,ST_F3 },
+ 	{ SCANCODE_F4,ST_F4 },
+ 	{ SCANCODE_F5,ST_F5 },
+ 	{ SCANCODE_F6,ST_F6 },
+ 	{ SCANCODE_F7,ST_F7 },
+ 	{ SCANCODE_F8,ST_F8 },
+ 	{ SCANCODE_F9,ST_F9 },
+ 	{ SCANCODE_F10,ST_F10 },
+ 
+ 	{ SCANCODE_ESCAPE,ST_ESC },
+ 	{ SCANCODE_1,ST_1 },
+ 	{ SCANCODE_2,ST_2 },
+ 	{ SCANCODE_3,ST_3 },
+ 	{ SCANCODE_4,ST_4 },
+ 	{ SCANCODE_5,ST_5 },
+ 	{ SCANCODE_6,ST_6 },
+ 	{ SCANCODE_7,ST_7 },
+ 	{ SCANCODE_8,ST_8 },
+ 	{ SCANCODE_9,ST_9 },
+ 	{ SCANCODE_0,ST_0 },
+ 	{ SCANCODE_MINUS,ST_MINUS },
+ 	{ SCANCODE_EQUAL,ST_EQUAL },
+ 
+ 	{ SCANCODE_BACKSL,ST_BACKSL },
+ 	{ SCANCODE_GRAVE,ST_GRAVE }, /* '_ */
+ 	{ SCANCODE_APOST,ST_APOST }, 
+ 
+ 	{ SCANCODE_ISO,ST_ISO },
+ 
+ 	{ SCANCODE_BS,ST_BS },
+ 	{ SCANCODE_TAB,ST_TAB },
+ 	{ SCANCODE_Q,ST_Q },
+ 	{ SCANCODE_W,ST_W },
+ 	{ SCANCODE_E,ST_E },
+ 	{ SCANCODE_R,ST_R },
+ 	{ SCANCODE_T,ST_T },
+ 	{ SCANCODE_Y,ST_Y },
+ 	{ SCANCODE_U,ST_U },
+ 	{ SCANCODE_I,ST_I },
+ 	{ SCANCODE_O,ST_O },
+ 	{ SCANCODE_P,ST_P },
+ 	{ SCANCODE_SQ_OPEN,ST_SQ_OPEN },	/* [ */
+ 	{ SCANCODE_SQ_CLOSE,ST_SQ_CLOSE },	/* ] */
+ 	{ SCANCODE_ENTER,ST_RETURN },
+ 
+ 	{ SCANCODE_LEFTCONTROL,ST_CONTROL },
+ 	{ SCANCODE_A,ST_A },
+ 	{ SCANCODE_S,ST_S },
+ 	{ SCANCODE_D,ST_D },
+ 	{ SCANCODE_F,ST_F },
+ 	{ SCANCODE_G,ST_G },
+ 	{ SCANCODE_H,ST_H },
+ 	{ SCANCODE_J,ST_J },
+ 	{ SCANCODE_K,ST_K },
+ 	{ SCANCODE_L,ST_L },
+ 	{ SCANCODE_SEMIC,ST_SEMIC },
+ 	{ SCANCODE_LEFTSHIFT,ST_LSH },
+ 	{ SCANCODE_Z,ST_Z },
+ 	{ SCANCODE_X,ST_X },
+ 	{ SCANCODE_C,ST_C },
+ 	{ SCANCODE_V,ST_V },
+ 	{ SCANCODE_B,ST_B },
+ 	{ SCANCODE_N,ST_N },
+ 	{ SCANCODE_M,ST_M },
+ 	{ SCANCODE_COMMA,ST_COMMA },
+ 	{ SCANCODE_DOT,ST_DOT },
+ 	{ SCANCODE_SLASH,ST_SLASH },
+ 	{ SCANCODE_RIGHTSHIFT,ST_RSH },
+ 	{ SCANCODE_LEFTALT,ST_ALT },
+ 	{ SCANCODE_SPACE,ST_SPACE },
+ 	{ SCANCODE_CAPSLOCK,ST_CAPSLOCK },
+ 	{ SCANCODE_KEYPAD0,ST_KP_0 },
+ 	{ SCANCODE_KEYPAD1,ST_KP_1 },
+ 	{ SCANCODE_KEYPAD2,ST_KP_2 },
+ 	{ SCANCODE_KEYPAD3,ST_KP_3 },
+ 	{ SCANCODE_KEYPAD4,ST_KP_4 },
+ 	{ SCANCODE_KEYPAD5,ST_KP_5 },
+ 	{ SCANCODE_KEYPAD6,ST_KP_6 },
+ 	{ SCANCODE_KEYPAD7,ST_KP_7 },
+ 	{ SCANCODE_KEYPAD8,ST_KP_8 },
+ 	{ SCANCODE_KEYPAD9,ST_KP_9 },
+ 	{ SCANCODE_CURSORBLOCKUP,ST_UP },
+ 	{ SCANCODE_CURSORBLOCKLEFT,ST_LEFT },
+ 	{ SCANCODE_CURSORBLOCKRIGHT,ST_RIGHT }, 
+ 	{ SCANCODE_CURSORBLOCKDOWN,ST_DOWN }, 
+ 	{ SCANCODE_INS,ST_INSERT },
+ 	{ SCANCODE_DEL,ST_DELETE },
+ 	{ SCANCODE_KEYPADENTER,ST_KP_ENTER },
+ 	{ SCANCODE_KEYPADPLUS,ST_KP_PLUS },
+ 	{ SCANCODE_KEYPADMINUS,ST_KP_MINUS },
+ 	{ SCANCODE_KEYPADMULT,ST_KP_MULT },
+ 	{ SCANCODE_KEYPADDOT,ST_KP_DOT },
+ 	{ SCANCODE_KEYPADDIV,ST_KP_DIV },
+ 	{ SCANCODE_PRTSCR,ST_HELP },
+ 	{ SCANCODE_PAUSE,ST_UNDO },
+ 	{ SCANCODE_PGUP,ST_KP_OPEN },
+ 	{ SCANCODE_PGDOWN,ST_KP_CLOSE },
+ 	{ SCANCODE_RIGHTALT,ST_CAPSLOCK },
+ 	{ SCANCODE_RIGHTCONTROL,ST_CONTROL }
+ };
+ 
+ void svga_init_keys()
+ {	extern int *keycodes;
+ 	int i;
+ #if 0 
+ 	fprintf(stderr,"SVGALIB Keycode convertor initialising...\n");
+ #endif
+ 	kmin = 0;
+ 	kmax = 255;
+ 	keycodes = malloc(256 * sizeof(int));
+ 	for (i=0 ; i < 256 ; i++)
+ 	{	keycodes[i] = ST_UNDEF;	
+ 		keyflag[i] = 0;
+ 	}
+ 	for (i=0 ; i < sizeof(svga_keytab)/(sizeof(int)*2) ; i++)
+ 		keycodes[svga_keytab[i][0]] = svga_keytab[i][1];
+ }
+ 
+ static void mymouse_handler(int button, int dx, int dy)
+ {	mx += dx;
+ 	my += dy;
+ 	mb = button;
+ }
+ 
+ static int lastcode;
+ 
+ static void mykey_handler(int scancode,int state)
+ {
+ 	if (keyflag[scancode] == state)
+  		return;			/*already in this state */
+     	else
+ 		keyflag[scancode] = state;
+ 	switch (scancode)
+ 	{	case SCANCODE_F11:
+ 			mc68000_reset();
+ 			break;	
+ 		case SCANCODE_F12:
+ 			(void) svga_screen_close();
+ 			/*fprintf(stderr,"Last code was:%d\n",lastcode);*/
+ 			exit(0);
+ 			break;
+ 		default:
+ 			break;	
+ 	}
+ 	lastcode=scancode;
+ 	ikbd_key(scancode,(state==KEY_EVENTPRESS));
+ }
+ 
+ static void process_events(void)
+ {	
+ 	if (mouse_update())
+ 	{	ikbd_pointer(mx,my,639,399);
+ 		ikbd_button(1, (mb & MOUSE_LEFTBUTTON) != 0);
+ 		ikbd_button(2, (mb & MOUSE_RIGHTBUTTON) != 0);
+ 	}
+ 	keyboard_update();
+ }
+ 
+ 
+ /* Change the window colormap according to the contents of old_color[].
+  * The colors are converted from ST/STe format (least-significant 9/12 bits
+  * of a 16 bit integer) to the 6 bit per RGB component format used in VGA.
+  */
+ 
+ static void change_colors (void)
+ {	int i;
+ 	unsigned long pixels[COLS];
+ 
+ 	if (shiftmod == 2)
+ 	{
+ 		gl_setpalettecolor(0,63,63,63);
+ 		gl_setpalettecolor(15,0,0,0); 
+ 	}
+ 	else for (i=0; i<COLS; i++)
+ 	{	int r,g,b,c;
+ 		c = (i < (shiftmod == 0 ? 16 : 4) ? old_color[i] : 0);
+ #if !STE
+ 		c &= 0x777;
+ #endif
+ 		r 	= (((c>>8)&7)<<3)|((c>>11)<<2);
+ 		g	= (((c>>4)&7)<<3)|(((c>>7)&1)<<2);
+ 		b	= ((c&7)<<3)|(((c>>3)&1)<<2);
+ 		gl_setpalettecolor(i,r,g,b);
+ 	}
+ 
+ }
+ 
+ /* Do something appropriate when the 'shiftmod' hardware register has changed:
+  */
+ 
+ static void change_mode (void)
+ {
+ 	scr_width = scr_def[shiftmod].w;
+         scr_height = scr_def[shiftmod].h;
+         scr_planes=4>>shiftmod;
+ 
+ 	switch (shiftmod)
+ 	{
+ 		case 0:
+ 			vga_setmode(G320x200x256);
+ 			gl_setcontextvga(G320x200x256);
+ 			change_colors();
+ 			break;
+ 
+ 		case 1:
+ 			vga_setmode(G640x200x16);
+ 			gl_setcontextvga(G640x200x16);
+ 			change_colors();
+ 			break;
+ 
+ 		case 2:
+ 			vga_setmode(G640x480x2);
+ 			gl_setcontextvga(G640x480x2);
+ 			change_colors();
+ 			break;
+ 	}
+ 	mouse_seteventhandler(mymouse_handler); 
+ }
+ 
+ /* Update the screen using the shifter mode known when change_mode was last
+  * called...
+  */
+ 
+ static void show_screen (void)
+ {
+ 	switch (old_shiftmod)
+ 	{
+ 		case 0:	
+ 			{	char *x=vga_getgraphmem();
+ 				st16c_to_z (MEM(vbase), x);
+ 			}
+ 			break;
+ 		case 1:
+ 			{	unsigned char *m=buf;
+ 				int i;		
+ 				st4c_to_z200 (MEM(vbase), m);
+ 				for (i=0 ; i<200 ;i++,m+=640) vga_drawscanline(i,m);
+ 			} 
+ 			break;
+ 		case 2: 
+ 			{	unsigned char *m=MEM(vbase);
+ 				int i;		
+ 				for (i= 0 ; i<400 ;i++,m+=80) vga_drawscanline(i,m);
+ 			} 
+ 			break;
+ 	
+ 	}
+ #if 0 
+ 	vga_waitretrace();
+ #endif
+ 
+ }
+ 
+ /* This function is called periodically (from a signal handler) to check what's
+  * new with the shifter mode, colors, and update ("shift") the screen. It
+  * should probably rewritten to check whether it's necessary to update the
+  * screen, since for color modes this is a very costly operation...
+  *
+  * The Shifter status information is changed in hw.c, where the hardware regs
+  * are read.
+  */
+ 
+ void svga_screen_shifter (void)
+ {
+ 	int i, w, pal = 0;
+ 
+ 	process_events();	
+ 	if (++refcount < refresh) return;
+ 	refcount=0;
+ 
+ 	for (i=0; i<16; i++)
+ 	{
+ 		if ((w = LM_UW(&color[i])) != old_color[i])
+ 		{
+ 			pal = 1;	/* palette has changed */
+ 			old_color[i] = w;
+ 		}
+ 	}
+ 
+ 	if (pal) change_colors();	/* update the window colormap */
+ 
+ 	if (old_shiftmod != shiftmod)
+ 	{
+ 		old_shiftmod = shiftmod;
+ 		change_mode();
+ 	}
+ 
+ 	show_screen();
+ }
+ 
+ void svga_screen_open(void)
+ {	vga_init();
+ 	vga_setmousesupport(1);
+ /*	vga_runinbackground(1);*/
+ 	oldvga_mode = vga_getcurrentmode();
+ 	mouse_init("/dev/mouse",vga_getmousetype(),16);
+ 	change_mode();
+ 	if (keyboard_init() != 0) exit(0);
+ 	keyboard_seteventhandler(mykey_handler);
+     	buf = malloc (640*400*4);
+ 	depth = 1;
+ 	priv_cmap = 1;
+ }
+ 
+ void svga_screen_close (void)
+ {	mouse_close();
+ 	keyboard_close();
+ 	free(buf);
+ 	vga_setmode(oldvga_mode);
+ }
+ 
+ 
+ #endif
diff -rcN STonX-0.6.4/x.c STonX-0.6.5/x.c
*** STonX-0.6.4/x.c	Thu Jan  1 01:00:00 1970
--- STonX-0.6.5/x.c	Fri Feb  9 19:01:55 1996
***************
*** 0 ****
--- 1,1052 ----
+ /* This file is part of STonX, the Atari ST Emulator for Unix/X
+  * ============================================================
+  * STonX is free software and comes with NO WARRANTY - read the file
+  * COPYING for details
+  */
+ #include "defs.h"
+ #include "tosdefs.h"
+ #include "debug.h"
+ #include "ikbd.h"
+ #include "main.h"
+ #include "missing.h"
+ #include "onexit.h"
+ #include "screen.h"
+ #include "xlib_vdi.h"
+ #include <stdio.h>
+ #include <string.h>
+ #include <sys/param.h>
+ #include <sys/times.h>
+ #include <time.h>
+ #include <X11/Xos.h>
+ #include <X11/Xatom.h>
+ #include <X11/Xlib.h>
+ #include <X11/Xutil.h>
+ #include <X11/cursorfont.h>
+ 
+ #ifndef CLK_TCK
+ #define CLK_TCK HZ
+ #endif
+ 
+ #define GCURX 0x25a
+ #define GCURY 0x258
+ 
+ #define GRABMODE 0
+ #define HIDEMODE 1
+ #define REDRAW 1
+ #define BENCH_REFRESH 0
+ #define NUM_AVG	100
+ #define SET_MOUSE 1
+ 
+ #ifdef SH_MEM
+ #include <sys/types.h>
+ #include <sys/ipc.h>
+ #include <sys/shm.h>
+ #include <X11/extensions/XShm.h>
+ 
+ static XShmSegmentInfo shminfo;
+ static shm_used;
+ 
+ #endif
+ static char txt[256];
+ static Cursor cursors[2];
+ static int cursidx=0;
+ static int warped=0;
+ #if BENCH_REFRESH
+ static int cref=0;
+ static clock_t reftime;
+ static int chunks_seen=0,chunks_drawn=0;
+ #endif
+ static Pixmap empty;
+ #if GRABMODE
+ static int grabbed=1;
+ #endif
+ static Window in_which=None;
+ 
+ SCRDEF scr_def[3];
+ 
+ /* some interesting events: */
+ #define E_MASK (KeyPressMask|KeyReleaseMask|ButtonPressMask	\
+ 				|ButtonReleaseMask|PointerMotionMask|ColormapChangeMask|\
+ 				EnterWindowMask|LeaveWindowMask|ExposureMask)
+ 
+ static int old_shiftmod=-1;	/* last known shift mode, used to detect changes */
+ static UW old_color[16];	/* last known color palette */
+ static int shm_mono=1;
+ static char **ksyms;
+ static int redraw_flag=0;
+ static char win_name[64];
+ static Visual *visual = NULL;
+ static Status status;
+ static unsigned long wp, bp;		/* pixel values for black & white */
+ static int screen, nplanes, ncolors;
+ static int Max_x, Max_y;
+ static XEvent event;
+ static XSetWindowAttributes attrib;
+ static GC gc;
+ static XGCValues gc_val;
+ static XSizeHints sizehints;
+ static Window imagewin;		/* window ID for image */
+ static XImage *image = NULL;
+ static B *Image;
+ static Colormap hlcmap;
+ static char keybuf[64];
+ static int refcount=0;
+ static int lastmx=0,lastmy=0;
+ static B *buf;
+ static int shm_ct;
+ 
+ Display *display;
+ int kmin,kmax;
+ int shmflag = 1;
+ Colormap cmap=0;
+ 
+ #define BUF(a,b) buf[(viewy * (b)) + (a)]
+ #undef SHM_WAIT
+ 
+ /* Destroy the current emulator window
+  */
+ static void destroy_image (void)
+ {
+ 	if (image == NULL) return;
+ 	XDestroyImage (image);
+ #ifdef SH_MEM
+     if (shmflag && shm_used)
+     {
+ 		XShmDetach (display, &shminfo);
+ 		shmdt (shminfo.shmaddr);
+ 		shmctl (shminfo.shmid, IPC_RMID, 0);
+ 		shm_used = 0;
+     }
+ #endif
+ }
+ 
+ void x_screen_close (void)
+ {
+ 	XAutoRepeatOn(display);
+ 	XFlush(display);
+ 	destroy_image();
+ }
+ 
+ static void set_window_name (char *name)
+ {
+ 	XStoreName (display, imagewin, name);
+ }
+ 
+ /* Create a new image for the emulation window, using shared memoy if possible
+  */
+ static void create_image (int w, int h, int format)
+ {
+ 	int planes = (format == XYBitmap ? 1 : 8);
+ 	Max_x = w-1;
+ 	Max_y = h-1;
+ #ifdef SH_MEM
+     if (shmflag && (planes == 8 || shm_mono))
+     {
+ 		image = XShmCreateImage (display, visual, planes, format,
+ 				 				NULL, &shminfo, w, h);
+ 		shminfo.shmid = shmget (IPC_PRIVATE, image->bytes_per_line
+ 								* image->height, IPC_CREAT | 0777);
+ 		buf = shminfo.shmaddr = image->data = shmat (shminfo.shmid, 0, 0);
+ 		shminfo.readOnly = False;
+ 		XShmAttach (display, &shminfo);
+ 		XSync(display, False);
+ 		shmctl(shminfo.shmid, IPC_RMID, 0);
+ 		shm_used = 1;
+ #if 0
+ 		bzero (&shminfo, sizeof(shminfo));
+ #endif
+     }
+     else
+ #endif
+ 	{
+     	buf = malloc (w * h * (format == XYBitmap ? 1 : 8));
+     	image = XCreateImage (display, visual, planes, format,
+ 							0, (char *) buf, w, h, 8, 0);
+ 	}
+ #if 1
+ 	image -> bitmap_bit_order = MSBFirst;
+ 	image -> byte_order = MSBFirst;
+ #else
+ 	image -> bitmap_bit_order = LSBFirst;
+ 	image -> byte_order = LSBFirst;
+ #endif
+     Image = image->data;
+ }
+ 
+ /* Change the window colormap according to the contents of old_color[].
+  * The colors are converted from ST/STe format (least-significant 9/12 bits
+  * of a 16 bit integer) to the 16 bit per RGB component format used in X11.
+  */
+ static int allocatedcols[COLS];
+ char mapcol[COLS];
+ static void change_colors (void)
+ {
+ 	XColor colors[COLS];
+ 	UW c;
+ 	int i;
+ 	int q=0;
+ 	unsigned long pixels[COLS];
+ 	int j,k;
+ 	if (depth == 1) return;
+ 
+ 	if (shiftmod == 2)
+ 	{
+ 		for (i=0; i<COLS; i++)
+ 		{
+ 			colors[i].pixel = i;
+ 			colors[i].flags = DoRed | DoGreen | DoBlue;
+ 			colors[i].red = colors[i].green = colors[i].blue = 0;
+ 		}
+ 		if (old_color[0] == 0) {
+ 			/* mono show_screen does just memcpy; XPutImage... */
+ #if 0
+ 			XSetForeground (display, gc, bp);
+ 			XSetBackground (display, gc, wp);
+ #endif
+ 			colors[1].red = colors[1].green = colors[1].blue = 0xffff;
+ 		} else {
+ #if 0
+ 			XSetForeground (display, gc, wp);
+ 			XSetBackground (display, gc, bp);
+ #endif
+ 			colors[0].red = colors[0].green = colors[0].blue = 0xffff;
+ 		}
+ 	}
+ 	else for (i=0; i<COLS; i++)
+ 	{
+ 		c = (i < (shiftmod == 0 ? 16 : 4) ? old_color[i] : 0);
+ #if !STE
+ 		c &= 0x777;
+ #endif
+ 		colors[i].pixel = i;
+ 		colors[i].flags = DoRed | DoGreen | DoBlue;
+ 		colors[i].red 	= (((c>>8)&7)<<13)|((c>>11)<<12);
+ 		colors[i].green	= (((c>>4)&7)<<13)|(((c>>7)&1)<<12);
+ 		colors[i].blue	= ((c&7)<<13)|(((c>>3)&1)<<12);
+ 	}
+ 
+ if (!priv_cmap)
+ {
+ 	for (i=0; i<COLS; i++)
+ 	{
+ 		if (allocatedcols[i]>=0)
+ 		{
+ 			pixels[q++]=allocatedcols[i];
+ 		}
+ 	}
+ 	if (q>0) XFreeColors(display, cmap, pixels, q, 0);
+ 	for (i=0; i<COLS; i++)
+ 	{
+ 		XAllocColor (display, cmap, &colors[i]);
+ 		mapcol[i]=colors[i].pixel;
+ 	}
+ }
+ else
+ {
+ 	XStoreColors (display, cmap, colors, COLS);
+ }
+ #if 0
+ 	XMapRaised (display, imagewin);
+ 	XFlush(display);
+ #endif
+ #if 0
+ 	XUnmapWindow (display, imagewin);
+ 	XMapWindow (display, imagewin);
+ #endif
+ }
+ 
+ /* Do something appropriate when the 'shiftmod' hardware register has changed:
+  * 1. The window is resized
+  * 2. A new image is created
+  * 3. A new conversion function is used every VBL
+  */
+ static void change_mode (void)
+ {
+ 	scr_width = scr_def[shiftmod].w;
+ 	scr_height = scr_def[shiftmod].h;
+ 	scr_planes=4>>shiftmod;
+ #if 0
+ 	fprintf(stderr,"Screen is now %dx%d, shift mode %d\n",scr_width,scr_height,shiftmod);
+ #endif
+ 	switch (shiftmod)
+ 	{
+ 		case 0:
+ 			XResizeWindow (display, imagewin, scr_width, scr_height);
+ 			destroy_image();
+ 			create_image (scr_width, scr_height, ZPixmap);
+ 			change_colors();
+ 			break;
+ 
+ 		case 1:
+ 			XResizeWindow (display, imagewin, scr_width, scr_height*2);
+ 			destroy_image();
+ 			create_image (scr_width, scr_height*2, ZPixmap);
+ 			change_colors();
+ 			break;
+ 
+ 		case 2:
+ 			XResizeWindow (display, imagewin, scr_width, scr_height);
+ 			destroy_image();
+ 			create_image (scr_width, scr_height, XYBitmap);
+ 			change_colors();
+ 			break;
+ 	}
+ }
+ 
+ /* Process all events that occured since we last came here...
+  */
+ static void process_events (void)
+ {
+ 	int tx,ty;
+ 	XEvent e;
+ 	XExposeEvent *x;
+ 	while (XCheckMaskEvent (display, E_MASK, &e))
+ 	{
+ 		switch (e.type)
+ 		{
+ 		case EnterNotify:
+ 			XAutoRepeatOff(display);
+ 			if (vdi && xw != None) vdi_mode = (e.xcrossing.window != imagewin);
+ 			in_which = e.xcrossing.window;
+ 
+ 			if (in_which == imagewin)
+ 			{
+ #if SET_MOUSE
+ 				lastmx = LM_W(MEM(abase-GCURX));
+ 				lastmy = LM_W(MEM(abase-GCURY));
+ 				XWarpPointer (display, None, imagewin, 0, 0, 0, 0, 
+ 								lastmx, lastmy);
+ 				XDefineCursor (display, imagewin, cursors[cursidx]);
+ 				warped=1;
+ #else
+ 				int mx,my,nx,ny;
+ #if 0
+ 				mx=LM_W(MEM(abase-GCURX));
+ 				my=LM_W(MEM(abase-GCURY));
+ #endif
+ 				nx=(((XCrossingEvent *)&e)->x);
+ 				ny=(((XCrossingEvent *)&e)->y);
+ #if 0
+ 				fprintf(stderr,"Repositioning mouse from %d,%d to %d,%d\n",
+ 					mx,my,nx,ny);
+ 				ikbd_adjust(nx-lastmx,ny-lastmy);
+ 				lastmx=mx;
+ 				lastmy=my;
+ #endif
+ 				ikbd_pointer(nx,ny,Max_x,Max_y);
+ #endif
+ 			}
+ 			break;
+ 		case LeaveNotify:
+ 			XAutoRepeatOn(display); /* BUG: should restore previous value */
+ 			if (e.xcrossing.window == imagewin) XUndefineCursor(display,imagewin);
+ 			in_which = None;
+ 			break;
+ 		case KeyPress:
+ 			/* fprintf (stderr, "Keypress: %d\n", ((XKeyEvent *)&e)->keycode);*/
+ 			ikbd_key (((XKeyEvent *)&e)->keycode, 1);
+ 			break;
+ 		case KeyRelease:
+ 		/*	fprintf (stderr, "Keyrelease: %d\n", ((XKeyEvent *)&e)->keycode);*/
+ 			ikbd_key (((XKeyEvent *)&e)->keycode, 0);
+ 			break;
+ 		case ButtonPress:
+ #if GRABMODE
+ 			if (((XButtonEvent *)&e)->button == 3)
+ 			{
+ #if 0
+ 				fprintf(stderr, "in window %lx\n",(long)in_which);
+ #endif
+ 				if (grabbed)
+ 				{
+ 					XUngrabKeyboard (display, CurrentTime);
+ 					XUngrabPointer (display, CurrentTime);
+ 					grabbed=0;
+ 				}
+ 				else if (in_which != xw)
+ 				{
+ 					XGrabPointer (display, imagewin, True, PointerMotionMask
+ 					|ButtonPressMask|ButtonReleaseMask,
+ 					GrabModeAsync, GrabModeAsync, None, hidden, CurrentTime);
+ 					XGrabKeyboard (display, imagewin,True, GrabModeAsync,
+ 						GrabModeAsync, CurrentTime);
+ 					grabbed=1;
+ 					fprintf (stderr, "grabbed\n");
+ 				}
+ 			}
+ #if 0
+ 			if (((XButtonEvent *)&e)->button == 3 &&
+ 				((XButtonEvent *)&e)->window == xw)
+ 					redraw_flag=1;
+ 		fprintf (stderr, "Buttonpress: %d\n", ((XButtonEvent *)&e)->button);
+ #endif
+ #elif HIDEMODE
+ 			if (((XButtonEvent *)&e)->button == 3)
+ 			{
+ 				cursidx = !cursidx;
+ 				XDefineCursor (display, imagewin, cursors[cursidx]);
+ 				break;
+ 			}
+ #endif
+ 			ikbd_button (((XButtonEvent *)&e)->button, 1);
+ 			break;
+ 		case ButtonRelease:
+ #if 0
+ 		fprintf (stderr, "Buttonrelease: %d\n", ((XButtonEvent *)&e)->button);
+ #endif
+ 			ikbd_button (((XButtonEvent *)&e)->button, 0);
+ 			break;
+ 		case Expose:
+ 			x = (XExposeEvent *)&e;
+ #if XBUFFER
+ 			if (xw == x->window)
+ 				vdi_redraw(x->x,x->y,x->width,x->height);
+ #endif
+ 			break;
+ 		case MotionNotify:
+ 			if (e.xmotion.window == imagewin && warped)
+ 			{
+ 				warped=0;
+ #if 0
+ 				lastmx = ((XMotionEvent *)&e)->x;
+ 				lastmy = ((XMotionEvent *)&e)->y;
+ 				break;
+ #endif
+ 			}
+ #if 0
+ 
+ #if 0	
+ 			if (e.xmotion.window == imagewin)
+ #endif
+ /*	fprintf (stderr, "Pointer: %d,%d\n", ((XMotionEvent *)&e)->x,((XMotionEvent *)&e)->y); */
+ #if 0
+ 			SM_W(MEM(abase-GCURX),((XMotionEvent *)&e)->x);
+ 			SM_W(MEM(abase-GCURY),((XMotionEvent *)&e)->y);
+ 			SM_W(MEM(abase-0x158),((XMotionEvent *)&e)->x);
+ 			SM_W(MEM(abase-0x156),((XMotionEvent *)&e)->y);
+ 			SM_B(MEM(abase-0x154),0xff);
+ #endif
+ #if 0
+ #if 1
+ 			tx=LM_W(MEM(abase-0x158));
+ 			ty=LM_W(MEM(abase-0x156));
+ #if 1
+ 			if (tx==lastmx && ty==lastmy) break;
+ #endif
+ 			lastmx=tx;
+ 			lastmy=ty;
+ #endif
+ 			fprintf(stderr,"Adjusting: (%d,%d)->(%d,%d)\n",lastmx,lastmy,
+ 			((XMotionEvent *)&e)->x,((XMotionEvent *)&e)->y);
+ 			ikbd_adjust (((XMotionEvent *)&e)->x-lastmx,
+ 						((XMotionEvent *)&e)->y-lastmy);
+ #else
+ 			ikbd_adjust (((XMotionEvent *)&e)->x-lastmx,
+ 						((XMotionEvent *)&e)->y-lastmy);
+ 			lastmx = ((XMotionEvent *)&e)->x;
+ 			lastmy = ((XMotionEvent *)&e)->y;
+ #endif
+ 
+ #else
+ #if 0
+ 			ikbd_pointer (((XMotionEvent *)&e)->x,((XMotionEvent *)&e)->y,Max_x,Max_y);
+ #else
+ 			ikbd_adjust (((XMotionEvent *)&e)->x-lastmx,
+                         ((XMotionEvent *)&e)->y-lastmy);
+             lastmx = ((XMotionEvent *)&e)->x;
+             lastmy = ((XMotionEvent *)&e)->y;
+ #endif
+ #endif
+ 			break;
+ 		}
+ 	}
+ }
+ 
+ void x_screen_open (void)
+ {
+     int i, j;
+     int shm_major, shm_minor;
+     Bool shm_pixmaps;
+     XSizeHints h;
+     XFontStruct *font_info;
+     XImage *t;
+ 	XColor ccols[2];
+ 
+ 	scr_width = scr_def[shiftmod].w;
+ 	scr_height = scr_def[shiftmod].h;
+ 
+     strcpy (win_name, "STonX Main Window");
+ 
+     if ((display = XOpenDisplay (NULL)) == NULL)
+     {
+ 		fprintf (stderr, "Could not open display.\n");
+ 		exit (1);
+     }
+ 
+ #if 0
+ 	XAutoRepeatOff(display);
+ #endif
+ 	verbose && fprintf (stderr, "Obtaining Keysym mappings for display...\n");
+ 	XDisplayKeycodes (display, &kmin, &kmax);
+ 	verbose && fprintf (stderr, "Keycode range = %d..%d\n", kmin, kmax);
+ 	ksyms = (char **)malloc(sizeof(char *)*(kmax-kmin+1));
+ 	for (i=kmin; i<=kmax; i++)
+ 	{
+ 		char *s = XKeysymToString(XKeycodeToKeysym(display,i,0));
+ 		ksyms[i-kmin] = (s == NULL ? s : strdup(s));
+ #if 0
+ 		fprintf (stderr, "Keycode %d = %s\n", i,s);
+ #endif
+ 	}
+ 
+ #ifdef SH_MEM
+     if (shmflag)
+     {
+ 		if (!XShmQueryVersion (display, &shm_major, &shm_minor, &shm_pixmaps))
+ 		{
+ 	    	verbose && fprintf(stderr,
+ 					"MIT Shared Memory Extension not supported.\n");
+ 	    	shmflag = 0;
+ 		}
+ 		else
+ 		{
+ 			int foo;
+ 	  		verbose && fprintf (stderr,
+ 				"Using MIT Shared Memory Extension %d.%d," \
+ 		  	   " %s shared pixmaps.\n", shm_major, shm_minor,
+ 		   	  (shm_pixmaps ? "with" : "without"));
+ 			foo = XShmPixmapFormat (display);
+ 			verbose && fprintf (stderr,
+ 					"XShm Pixmap format: %s\n", ((foo == XYBitmap ? 
+ 				"XYBitmap" : (foo == XYPixmap ? "XYPixmap" : "ZPixmap"))));
+ 			verbose && fprintf (stderr, "If you get a BadAccess error, try the -noshm option!\n");
+ 		}
+     }
+ #endif
+ 	
+     screen = XDefaultScreen (display);
+     depth = DefaultDepth (display, screen);
+ 	if (depth == 1)
+ 	{
+ 		SM_B(MEM(0xff8260),2);
+ 		old_shiftmod = 2;
+ 	}
+     visual = XDefaultVisual (display, screen);
+     nplanes = XDisplayPlanes (display, screen);
+ 
+ 	/* See if we are on a local little-endian display - in that case,
+ 	   XShmPutImage will refuse to swap bits most of the time! */
+ 	if (shmflag)
+ 	{
+ 		char *c=malloc(64);
+ 		t = XCreateImage (display, visual, 1, XYBitmap, 0, c, 32, 16, 8, 0);
+ 		if (t->bitmap_bit_order == LSBFirst)
+ 		{
+ 			fprintf (stderr, "NOTE: Because XShmPutImage apparently can't swap bits, shared memory support\nwas turned off for monochrome mode!\n");
+ 			shm_mono=0;
+ 		}
+ 		XDestroyImage (t);
+ 	}
+ 
+     h.width = scr_width;
+     h.height = scr_height;
+     h.x = 500;
+     h.y = 0;
+ 
+     h.flags = PSize | PPosition;
+     bp = BlackPixel (display, screen);
+     wp = WhitePixel (display, screen);
+     imagewin = XCreateSimpleWindow (display, RootWindow (display, screen),
+ 			h.x, h.y, h.width, h.height, 1, bp, wp);
+     XSelectInput (display, imagewin, StructureNotifyMask|E_MASK);
+     XSetStandardProperties (display, imagewin, win_name, win_name, None,
+ 			    NULL, 0, &h);
+     XMapWindow (display, imagewin);
+     for (;;)
+     {
+ 		XEvent e;
+ 		XNextEvent (display, &e);
+ 		if (e.type == MapNotify && e.xmap.event == imagewin) break;
+     }
+     gc_val.background = bp;
+     gc_val.foreground = wp;
+     gc = XCreateGC (display, imagewin, GCForeground | GCBackground, &gc_val);
+ #ifdef SH_MEM
+     shm_ct = XShmGetEventBase (display) + ShmCompletion;
+ #endif
+     XSetForeground (display, gc, 1);
+     XSetBackground (display, gc, 0);
+ 	if (depth > 1)
+ 	{
+ 	if (!priv_cmap)
+ 	{
+ 		cmap = DefaultColormap (display, screen);
+ 		for (i=0; i<COLS; i++) allocatedcols[i]=-1;
+ 	}
+ 	else
+ 	{
+ 		cmap = XCreateColormap (display, RootWindow(display, screen), visual,
+ 								AllocAll);
+ 	}
+ 	XSetWindowColormap (display, imagewin, cmap);
+ 	}
+     XClearWindow (display, imagewin);
+ #if 0
+ 	XWarpPointer (display, None, imagewin, 0, 0, 0, 0, 320, 200);
+ #endif
+     XSelectInput (display, imagewin, E_MASK);
+ #if !MONITOR && GRAB
+ 	XGrabPointer (display, imagewin, False, ButtonPressMask|ButtonReleaseMask
+ 					|PointerMotionMask, GrabModeAsync,
+ 					GrabModeAsync, None, None, CurrentTime);
+ #endif
+ 	if (depth == 1) create_image (scr_width,scr_height,XYBitmap);
+ 	empty = XCreatePixmapFromBitmapData (display, imagewin, calloc(32,1),
+ 			16, 16,0,0,1);
+ 	ccols[0].pixel = 0;
+ 	ccols[1].pixel = 0;
+ 	cursors[0] = XCreatePixmapCursor (display, empty, empty, &ccols[0], &ccols[1],
+ 				0,0);
+ 	cursors[1] = XCreateFontCursor (display, XC_tcross);
+ #if GRABMODE
+ 	XGrabPointer (display, imagewin, True, PointerMotionMask
+ 	|ButtonPressMask|ButtonReleaseMask,
+ 	GrabModeAsync, GrabModeAsync, None, hidden, CurrentTime);
+ 	XGrabKeyboard (display, imagewin,True, GrabModeAsync,
+ 		GrabModeAsync, CurrentTime);
+ 	fprintf (stderr, "The X pointer and keyboard have been grabbed by STonX - press the 3rd mouse\nbutton to release/grab again.\n");
+ #endif
+ 	OnExit (x_screen_close);
+ }
+ 
+ /* Update the X window using the shifter mode known when change_mode was last
+  * called...
+  */
+ static void show_screen (void)
+ {
+ 	int w, h;
+ 	int xzoom,yzoom=1;
+ 	w=scr_width;
+ 	h=scr_height;
+ 	switch (old_shiftmod)
+ 	{
+ 		case 0:
+ 			st16c_to_z (MEM(vbase), buf);
+ 			break;
+ 		case 1:
+ 			yzoom=2;
+ 			st4c_to_z (MEM(vbase), buf);
+ 			break;
+ 								/* image->data = MEM(vbase)!!!! */
+ 		case 2:
+ 			stmono_to_xy(buf, MEM(vbase));
+ 			break;
+ 	}
+ #ifdef SH_MEM
+     if (shmflag && (old_shiftmod != 2 || shm_mono))
+    	{
+ 		XEvent xev;
+ 		if (chunky)
+ 		{
+ 			int i;
+ 			for (i=0; i<h/CHUNK_LINES; i++)
+ 				if (chunk_age[i]==1)
+ 				{
+ 					XShmPutImage (display, imagewin, gc, image,
+ 						0, yzoom*i*CHUNK_LINES,
+ 						0, yzoom*i*CHUNK_LINES, w,
+ 						yzoom*CHUNK_LINES,
+ 						False);
+ #if BENCH_REFRESH
+ 					chunks_drawn++;
+ #endif
+ 				}
+ #if BENCH_REFRESH
+ 			chunks_seen+=h/CHUNK_LINES;
+ #endif
+ 		}
+ 		else
+ 		XShmPutImage (display, imagewin, gc, image, 0, 0, 0, 0, w, h*yzoom,
+ 					False);
+ 		XFlush (display);
+ #ifdef SHM_WAIT
+ 		do
+ 		{
+ 		    XNextEvent (display, &xev);
+ 		}
+ 		while (xev.type != shm_ct);
+ #endif
+    	}
+     else
+ #endif
+ 	{
+ 		if (chunky)
+ 		{
+ 			int i;
+ 			for (i=0; i<h/CHUNK_LINES; i++)
+ 				if (chunk_age[i]==1)
+ 				{
+ 					XPutImage (display, imagewin, gc, image,
+ 						0, yzoom*i*CHUNK_LINES,
+ 						0, yzoom*i*CHUNK_LINES, w,
+ 						yzoom*CHUNK_LINES);
+ #if BENCH_REFRESH
+ 					chunks_drawn++;
+ #endif
+ 				}
+ #if BENCH_REFRESH
+ 			chunks_seen+=h/CHUNK_LINES;
+ #endif
+ 		}
+ 		else
+ 		XPutImage (display, imagewin, gc, image, 0, 0, 0, 0, w, h);
+ 		XFlush (display);
+ 	}
+ #if 1
+     XSync (display, False);
+ #endif
+ }
+ 
+ static void manage_window ()
+ {
+     XKeyEvent *keypress;
+     KeySym keysym;
+     XComposeStatus cstat;
+ 
+     keypress = (XKeyEvent *) & event;
+ 
+ 	if (XPending (display))
+ 	{
+ 	    XNextEvent (display, &event);
+ 	    switch ((int) event.type)
+ 	    {
+ 		case KeyPress:
+ 		    if (XLookupString (keypress, keybuf, sizeof (keybuf),
+ 				&keysym, &cstat) != 0)
+ 			{
+ 		/*		update_IKBD_BUFFER (); */
+ 			}
+ 			break;
+ 		default:
+ 		    break;
+ 	    }
+ 	}
+ }
+ 
+ /* This function is called periodically (from a signal handler) to check what's
+  * new with the shifter mode, colors, and update ("shift") the screen. It
+  * should probably rewritten to check whether it's necessary to update the
+  * screen, since for color modes this is a very costly operation...
+  *
+  * The Shifter status information is changed in hw.c, where the hardware regs
+  * are read.
+  */
+ void x_screen_shifter (void)
+ {
+ 	int i, w, pal = 0;
+ 
+ 	process_events();	/* misplaced */
+ 	if (++refcount < refresh) return;
+ 	refcount=0;
+ 
+ 	for (i=0; i<16; i++)
+ 	{
+ 		if ((w = LM_UW(&color[i])) != old_color[i])
+ 		{
+ 			pal = 1;	/* palette has changed */
+ 			old_color[i] = w;
+ 		}
+ 	}
+ 
+ 	if (pal) change_colors();	/* update the window colormap */
+ 
+ 	if (depth > 1 && old_shiftmod != shiftmod)
+ 	{
+ 		old_shiftmod = shiftmod;
+ 		change_mode();
+ 	}
+ 
+ 	if (!vdi_mode || xw == None)
+ 	{
+ #if BENCH_REFRESH
+ 		struct tms ta;
+ 		clock_t rt;
+ 		times(&ta);
+ 		rt=ta.tms_utime+ta.tms_stime;
+ 		show_screen();
+ 		times(&ta);
+ 		reftime += ta.tms_utime+ta.tms_stime-rt;
+ 		cref++;
+ 		if (cref==NUM_AVG)
+ 		{
+ 			fprintf(stderr, "Refresh time (%d samples): %lf ms\n", NUM_AVG,
+ 				1000.0*(double)reftime/(NUM_AVG*CLK_TCK));
+ 			if (chunky) fprintf(stderr,"Chunks drawn/seen = %d/%d\n",chunks_drawn,chunks_seen);
+ 			reftime=0;
+ 			cref=0;
+ 		}
+ #else
+ 		show_screen();
+ #endif
+ 	}
+ #if 0
+ 	check_ui();
+ #endif
+ }
+ 
+ #define KB_DEBUG 0
+ #define KEYMAP_HARDCODED 0
+ 
+ struct
+ {
+ 	int c;
+ 	char *s;
+ } st_keysyms[] =
+ {
+ 	{ST_1, "ST_1"},
+ 	{ST_2, "ST_2"},
+ 	{ST_3, "ST_3"},
+ 	{ST_4, "ST_4"},
+ 	{ST_5, "ST_5"},
+ 	{ST_6, "ST_6"},
+ 	{ST_7, "ST_7"},
+ 	{ST_8, "ST_8"},
+ 	{ST_9, "ST_9"},
+ 	{ST_0, "ST_0"},
+ 	{ST_F1, "ST_F1"},
+ 	{ST_F2, "ST_F2"},
+ 	{ST_F3, "ST_F3"},
+ 	{ST_F4, "ST_F4"},
+ 	{ST_F5, "ST_F5"},
+ 	{ST_F6, "ST_F6"},
+ 	{ST_F7, "ST_F7"},
+ 	{ST_F8, "ST_F8"},
+ 	{ST_F9, "ST_F9"},
+ 	{ST_F10, "ST_F10"},
+ 	{ST_A, "ST_A"},
+ 	{ST_B, "ST_B"},
+ 	{ST_C, "ST_C"},
+ 	{ST_D, "ST_D"},
+ 	{ST_E, "ST_E"},
+ 	{ST_F, "ST_F"},
+ 	{ST_G, "ST_G"},
+ 	{ST_H, "ST_H"},
+ 	{ST_I, "ST_I"},
+ 	{ST_J, "ST_J"},
+ 	{ST_K, "ST_K"},
+ 	{ST_L, "ST_L"},
+ 	{ST_M, "ST_M"},
+ 	{ST_N, "ST_N"},
+ 	{ST_O, "ST_O"},
+ 	{ST_P, "ST_P"},
+ 	{ST_Q, "ST_Q"},
+ 	{ST_R, "ST_R"},
+ 	{ST_S, "ST_S"},
+ 	{ST_T, "ST_T"},
+ 	{ST_U, "ST_U"},
+ 	{ST_V, "ST_V"},
+ 	{ST_W, "ST_W"},
+ 	{ST_X, "ST_X"},
+ 	{ST_Y, "ST_Y"},
+ 	{ST_Z, "ST_Z"},
+ 	{ST_SPACE, "ST_SPACE"},
+ 	{ST_ALT, "ST_ALT"},
+ 	{ST_ESC, "ST_ESC"},
+ 	{ST_MINUS, "ST_MINUS"},
+ 	{ST_EQUAL, "ST_EQUAL"},
+ 	{ST_GRAVE, "ST_GRAVE"},
+ 	{ST_BS, "ST_BS"},
+ 	{ST_DELETE, "ST_DELETE"},
+ 	{ST_ISO, "ST_ISO"},
+ 	{ST_INSERT, "ST_INSERT"},
+ 	{ST_TAB, "ST_TAB"},
+ 	{ST_SQ_OPEN, "ST_SQ_OPEN"},
+ 	{ST_SQ_CLOSE, "ST_SQ_CLOSE"},
+ 	{ST_UP, "ST_UP"},
+ 	{ST_LEFT, "ST_LEFT"},
+ 	{ST_RIGHT, "ST_RIGHT"},
+ 	{ST_DOWN, "ST_DOWN"},
+ 	{ST_CONTROL, "ST_CONTROL"},
+ 	{ST_LSH, "ST_LSH"},
+ 	{ST_RSH, "ST_RSH"},
+ 	{ST_CAPSLOCK, "ST_CAPSLOCK"},
+ 	{ST_SEMIC, "ST_SEMIC"},
+ 	{ST_APOST, "ST_APOST"},
+ 	{ST_BACKSL, "ST_BACKSL"},
+ 	{ST_COMMA, "ST_COMMA"},
+ 	{ST_DOT, "ST_DOT"},
+ 	{ST_SLASH, "ST_SLASH"},
+ 	{ST_RETURN, "ST_RETURN"},
+ 	{ST_KP_ENTER, "ST_KP_ENTER"},
+ 	{ST_KP_MINUS, "ST_KP_MINUS"},
+ 	{ST_KP_PLUS, "ST_KP_PLUS"},
+ 	{ST_HELP, "ST_HELP"},
+ 	{ST_UNDO, "ST_UNDO"},
+ 	{ST_KP_OPEN, "ST_KP_OPEN"},
+ 	{ST_KP_CLOSE, "ST_KP_CLOSE"},
+ 	{ST_KP_DIV, "ST_KP_DIV"},
+ 	{ST_KP_MULT, "ST_KP_MULT"},
+ 	{ST_KP_DOT, "ST_KP_DOT"},
+ 	{ST_KP_0, "ST_KP_0"},
+ 	{ST_KP_1, "ST_KP_1"},
+ 	{ST_KP_2, "ST_KP_2"},
+ 	{ST_KP_3, "ST_KP_3"},
+ 	{ST_KP_4, "ST_KP_4"},
+ 	{ST_KP_5, "ST_KP_5"},
+ 	{ST_KP_6, "ST_KP_6"},
+ 	{ST_KP_7, "ST_KP_7"},
+ 	{ST_KP_8, "ST_KP_8"},
+ 	{ST_KP_9, "ST_KP_9"},
+ 	{ST_HOME, "ST_HOME"},
+ };
+ 
+ #define NUM_STK (sizeof(st_keysyms)/sizeof(st_keysyms[0]))
+ static char mapped[NUM_STK];
+ 
+ extern char **ksyms;
+ 
+ /* This is the keycode translation table. It is dependent on your kind of X
+  * terminal, and on the mapping you want to use for the ST keys.
+  * To make your own table, you'll need to examine the `xmodmap -pke' output
+  * on your system, and write the corresponding ST keycode as the item with
+  * the index of the keycode you want it on in the array below.
+  *
+  * Maybe, sometime in the future, a translation table based on Keysyms would
+  * be a better idea...
+  */
+ #if 0
+ int keycodes[] =
+ {
+ #if KEYMAP_HARDCODED
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_F1, ST_F2, ST_F10, ST_F3, ST_UNDEF, ST_F4, ST_UNDEF, ST_F5, ST_UNDEF,
+ 	ST_F6, ST_UNDEF, ST_F7, ST_F8, ST_F9, ST_ALT,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDO,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_ESC,
+ 	ST_1, ST_2, ST_3, ST_4, ST_5, ST_6, ST_7, ST_8, ST_9, ST_0, ST_MINUS,
+ 	ST_EQUAL, ST_GRAVE, ST_BS,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_DELETE,
+ 	ST_UNDEF,
+ 	ST_UNDEF,
+ 	ST_TAB, ST_Q, ST_W, ST_E, ST_R, ST_T, ST_Y, ST_U, ST_I, ST_O, ST_P,
+ 	ST_SQ_OPEN, ST_SQ_CLOSE, ST_DELETE, ST_UNDEF, ST_UNDEF, ST_UP,
+ 	ST_UNDEF, ST_KP_MINUS,
+ 	ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_CONTROL, ST_A, ST_S, ST_D, ST_F,
+ 	ST_G, ST_H, ST_J, ST_K, ST_L, ST_SEMIC, ST_APOST, ST_BACKSL, ST_RETURN,
+ 	ST_KP_ENTER, ST_LEFT, ST_UNDEF, ST_RIGHT, ST_INSERT, ST_UNDEF, ST_UNDEF,
+ 	ST_UNDEF, ST_UNDEF, ST_LSH, ST_Z, ST_X, ST_C, ST_V, ST_B, ST_N, ST_M,
+ 	ST_COMMA, ST_DOT, ST_SLASH, ST_RSH, ST_UNDEF, ST_UNDEF, ST_DOWN, ST_UNDEF,
+ 	ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_HELP, ST_CAPSLOCK, ST_UNDEF, ST_SPACE,
+ 	ST_UNDEF, ST_UNDEF, ST_UNDEF, ST_KP_PLUS
+ #else
+ #include "keytab.c"
+ #endif
+ };
+ #endif
+ 
+ char *kdefsfile = "Keysyms";
+ void x_init_keys(void)
+ {
+ 	int i, l=0, j;
+ 	FILE *f;
+ 	char b[1000], x[1000], y[1000];
+ 	keycodes = (int *)malloc(sizeof(int)*(kmax+1));
+ 	for (i=0; i<=kmax; i++)
+ 		keycodes[i] = ST_UNDEF;
+ 	verbose && 
+ 	fprintf (stderr, "Reading keycode mappings from `%s'...\n", kdefsfile);
+ 	f = fopen(kdefsfile, "r");
+ 	if (f == NULL)
+ 	{
+ 		fprintf(stderr,"FATAL error: File `%s' not found - exiting...\n",
+ 			kdefsfile);
+ 		exit(1);
+ 	}
+ 	while (fgets(b, 1000, f) != NULL)
+ 	{
+ 		l++;
+ 		if (b[0] == '#') continue;
+ 		if (sscanf(b, "%s %s", x, y) < 2)
+ 		{
+ 			verbose && 
+ 				fprintf (stderr, "Malformed line %d in file %s, ignoring it\n",
+ 						l, kdefsfile);
+ 		}
+ 		else 
+ 		{
+ 			int q;
+ 			int ok=0, u;
+ 			for (j=kmin; j<=kmax; j++)
+ 			{
+ #if KB_DEBUG
+ 				if (*x == 'F')
+ 				{
+ 					fprintf (stderr, "x=<%s>, ksyms[%d]=<%s>, cmp=%d\n",
+ 						x,j-kmin,ksyms[j-kmin],(ksyms[j-kmin]==NULL?999:strcasecmp(x,ksyms[j-kmin])));
+ 				}
+ #endif
+ 				if (ksyms[j-kmin] != NULL && strcasecmp (x, ksyms[j-kmin]) == 0)
+ 				{
+ 					q = /*XKeysymToKeycode(display,
+ 						XStringToKeysym(ksyms[*/ j /* -kmin ]))*/; 
+ 					for (u=0; u<sizeof(st_keysyms)/sizeof(st_keysyms[0]); u++)
+ 					{
+ 						if (strcasecmp (y, st_keysyms[u].s) == 0)
+ 						{
+ 							keycodes[q] = st_keysyms[u].c;
+ 							mapped[u] = 1;
+ 							break;
+ 						}
+ 					}
+ 					if (u == sizeof(st_keysyms)/sizeof(st_keysyms[0]))
+ 					{
+ 						fprintf (stderr,
+ 							"Error: Illegal ST-Keysym in %s, line %d `%s'\n",
+ 							kdefsfile, l, y);
+ 						exit(1);
+ 					}
+ 					ok=1;
+ 				}
+ 			}
+ 			if (!ok)
+ 			{
+ 				verbose &&
+ 				fprintf (stderr,"Warning: unknown KeySym in %s, line %d `%s'\n",
+ 								kdefsfile, l, x);
+ 				continue;
+ 			}
+ 		}
+ 	}
+ 	for (i=0; i<NUM_STK; i++)
+ 	{
+ 		if (!mapped[i] && verbose)
+ 			fprintf (stderr, "Warning: %s not mapped!\n", st_keysyms[i].s);
+ 	}
+ 	SM_UB(MEM(0xfffc00),0x0e);
+ }
+ 
diff -rcN STonX-0.6.4/xlib_vdi.c STonX-0.6.5/xlib_vdi.c
*** STonX-0.6.4/xlib_vdi.c	Mon Jan 22 01:45:03 1996
--- STonX-0.6.5/xlib_vdi.c	Fri Jan 19 00:00:28 1996
***************
*** 112,118 ****
  sysfontinfo sfinfo[3]=
  {
  	{5,6,4,4,3,1,1,4,6,0},
! 	{6,8,6,6,4,1,1,7,8,9},
  #if 0
  	{15,16,13,11,8,2,2,6,8,10},
  #else
--- 112,118 ----
  sysfontinfo sfinfo[3]=
  {
  	{5,6,4,4,3,1,1,4,6,0},
! 	{8,8,6,6,4,1,1,6,8,9},
  #if 0
  	{15,16,13,11,8,2,2,6,8,10},
  #else
***************
*** 128,149 ****
  
  #define IGNORE(_x) static void _x(void){T(unimpl_ ## _x);}
  
- #if 0
  extern int scr_width,scr_height,scr_planes;
  #define vdi_w scr_width
  #define vdi_h scr_height
- #else
- extern int scr_width,scr_height,scr_planes;
- static int vdi_w, vdi_h;
- extern int vdi_planes;
- extern SCRDEF scr_def[];
- extern int shiftmod;
- #endif
  int vdi_done = 0;
  Window xw=None;
  static Window root;
  extern volatile UL vbase;
- #define CHAR_HEIGHT() (vdi && (vdi_h >= 400 || vdi_planes==1) ? 16 : 8)
  
  #include "fill.xbm"
  Pixmap *fillpat[5];
--- 128,140 ----
***************
*** 300,308 ****
  	xw = XCreateWindow (display, root, 0, 0, vdi_w, vdi_h, 0, depth, 
  						InputOutput, visual, 0, &at);
  #else	
- #if 0
- 	fprintf(stderr,"Creating %dx%d VDI window\n",vdi_w,vdi_h);
- #endif
  	xw = XCreateSimpleWindow (display, root, 0, 0, vdi_w, vdi_h, 0, 0, 0);
  #endif
  	XSelectInput (display, xw, KeyPressMask|KeyReleaseMask|ButtonPressMask \
--- 291,296 ----
***************
*** 649,655 ****
  
  static void init_vwk (int i)
  {
- 	int fi;
  	XGCValues gv;
  	if (vwk[i]==NULL) vwk[i]=malloc (sizeof(VWK));
  	gv.function = GXcopy;
--- 637,642 ----
***************
*** 658,666 ****
  	gv.background = FIX_COLOR(0);
  	gv.plane_mask = AllPlanes; /* 1 */
  	gv.graphics_exposures = False;
! 	fi = CHAR_HEIGHT() == 16 ? 2:1;
! 	gv.font = sysfont[fi];
! 	vwk[i]->font_index = fi;
  	vwk[i]->font_yoff = 0;
  	vwk[i]->font_ver = 0;
  	vwk[i]->font_hor = 0;
--- 645,652 ----
  	gv.background = FIX_COLOR(0);
  	gv.plane_mask = AllPlanes; /* 1 */
  	gv.graphics_exposures = False;
! 	gv.font = sysfont[2];
! 	vwk[i]->font_index = 2;
  	vwk[i]->font_yoff = 0;
  	vwk[i]->font_ver = 0;
  	vwk[i]->font_hor = 0;
***************
*** 690,710 ****
  {
  	XGCValues gv;
  	char *sid;
! 	int i,r;
! 	r = LM_W(INTIN(0));
! 	fprintf(stderr,"v_opnwk(%d)\n",r);
! 	if (r >= 1 && r <= 4)
! 	{
! 		if (r==1) r=shiftmod;
! 		else r-=2;
! 		if (shiftmod != 2 && r == 2) r=0;
! 		vdi_w = scr_def[r].w;
! 		vdi_h = scr_def[r].h;
! 		vdi_planes=4>>r;
! 	}
  	init_window();
  #if VDEBUG
! 	fprintf(stderr,"opnwk input:\n%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
  	LM_W(INTIN(0)),
  	LM_W(INTIN(1)),
  	LM_W(INTIN(2)),
--- 676,685 ----
  {
  	XGCValues gv;
  	char *sid;
! 	int i;
  	init_window();
  #if VDEBUG
! 	fprintf(stderr,"openvwk input:\n%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
  	LM_W(INTIN(0)),
  	LM_W(INTIN(1)),
  	LM_W(INTIN(2)),
***************
*** 948,954 ****
  	for(i=0; i<16; i++)
  	  {
  	    p[2*i]   = LM_B(INTIN(i));
! 	    p[2*i+1] = LM_B(INTIN(i+1));
  	  }
  
  	XFreePixmap(display, vwk[h]->fill_pattern);
--- 923,929 ----
  	for(i=0; i<16; i++)
  	  {
  	    p[2*i]   = LM_B(INTIN(i));
! 	    p[2*i+1] = LM_B(INTIN(i)+1);
  	  }
  
  	XFreePixmap(display, vwk[h]->fill_pattern);
***************
*** 1290,1297 ****
  		int words=LM_W(MEM(d+8));
  		int height=LM_W(MEM(d+6));
  		int bpp=words*2*height;
! 		UB *dp = (UB *)MEM(da)+words*2*dy+((dx+15)&-16)/8;/*FIXME */
! 		UB *sp = (UB *)&(subimage->data[dx+dy*vdi_w]);
  		int planes=LM_W(MEM(d+12));
  		int i,j,k,l;
  
--- 1265,1272 ----
  		int words=LM_W(MEM(d+8));
  		int height=LM_W(MEM(d+6));
  		int bpp=words*2*height;
! 		UB *dp = MEM(da)+words*2*dy+((dx+15)&-16)/8;/*FIXME */
! 		UB *sp = &(subimage->data[dx+dy*vdi_w]);
  		int planes=LM_W(MEM(d+12));
  		int i,j,k,l;
  
***************
*** 1341,1348 ****
  	}
  	else
  	{
! 		UB *sp = (UB *)MEM(sa)+LM_W(MEM(s+8))*2*y+((x+15)&-16)/8;/* FIXME */
! 		UB *dp = (UB *)&(subimage->data[dx+dy*vdi_w]);
  		int planes=LM_W(MEM(s+12));
  		int words=LM_W(MEM(s+8));
  		int height=LM_W(MEM(s+6));
--- 1316,1323 ----
  	}
  	else
  	{
! 		UB *sp = MEM(sa)+LM_W(MEM(s+8))*2*y+((x+15)&-16)/8;/* FIXME */
! 		UB *dp = &(subimage->data[dx+dy*vdi_w]);
  		int planes=LM_W(MEM(s+12));
  		int words=LM_W(MEM(s+8));
  		int height=LM_W(MEM(s+6));
***************
*** 1769,1778 ****
  	SM_W(PTSOUT(1),sfinfo[vwk[h]->font_index].height);
  	SM_W(PTSOUT(2),sfinfo[vwk[h]->font_index].cellwidth);
  	SM_W(PTSOUT(3),sfinfo[vwk[h]->font_index].cellheight);
! #if VDEBUG 
  	fprintf(stderr,"vqt_attributes output: (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\n",LM_W(INTOUT(0)),LM_W(INTOUT(1)),LM_W(INTOUT(2)),LM_W(INTOUT(3)),LM_W(INTOUT(4)),LM_W(INTOUT(5)),LM_W(PTSOUT(0)),LM_W(PTSOUT(1)),LM_W(PTSOUT(2)),LM_W(PTSOUT(3)));
  #endif
! 	vdi_done=1; /* XXX */
  }
  
  static void vq_extnd (void)
--- 1744,1753 ----
  	SM_W(PTSOUT(1),sfinfo[vwk[h]->font_index].height);
  	SM_W(PTSOUT(2),sfinfo[vwk[h]->font_index].cellwidth);
  	SM_W(PTSOUT(3),sfinfo[vwk[h]->font_index].cellheight);
! #if VDEBUG
  	fprintf(stderr,"vqt_attributes output: (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\n",LM_W(INTOUT(0)),LM_W(INTOUT(1)),LM_W(INTOUT(2)),LM_W(INTOUT(3)),LM_W(INTOUT(4)),LM_W(INTOUT(5)),LM_W(PTSOUT(0)),LM_W(PTSOUT(1)),LM_W(PTSOUT(2)),LM_W(PTSOUT(3)));
  #endif
! 	vdi_done=1;
  }
  
  static void vq_extnd (void)
***************
*** 1957,1986 ****
  	vdi_ok=1;
  }
  
  
  void fix_vars (void)
  {
  	UW *a;
  	a=MEM(abase);
! 	if (vdi_w == 0) /* VDI not yet initialized */
! 	{
! 		vdi_w = scr_width;
! 		vdi_h = scr_height;
! 		vdi_planes=scr_planes;
! 	}
! 	SM_W(a+1,(vdi_w*vdi_planes)/8);
! 	SM_W(a-1,(vdi_w*vdi_planes)/8);
  	SM_W(a-23,CHAR_HEIGHT());
! 	SM_W(a-22,vdi_w/8-1);
! 	SM_W(a-21,vdi_h/CHAR_HEIGHT()-1);
! 	SM_W(a-20,((vdi_w*vdi_planes)/8)*CHAR_HEIGHT());
! 	SM_W(a-6,vdi_w);
! 	SM_W(a-2,vdi_h);
! #if 0
! 	fprintf(stderr,"Screen=%lx (%ld), %dx%dx%d (%ld)\n",
! 		LM_UL(MEM(0x44e)), 0x400000-LM_UL(MEM(0x44e)),
! 		vdi_w,vdi_h,vdi_planes,(vdi_w*vdi_h*vdi_planes)/8);
! #endif
  #if 0
  	fprintf(stderr,"FBASE=%08x, CUR_FONT=%08x, DEF_FONT=%08x, [%d,%d,%d,%d]\n",
  		LM_UL(a+0x54/2),LM_UL(a-0x38a/2),LM_UL(a-0x1cc/2),
--- 1932,1951 ----
  	vdi_ok=1;
  }
  
+ #define CHAR_HEIGHT() (vdi && scr_height >= 400 || scr_planes==1 ? 16 : 8)
  
  void fix_vars (void)
  {
  	UW *a;
  	a=MEM(abase);
! 	SM_W(a+1,(scr_width*scr_planes)/8);
! 	SM_W(a-1,(scr_width*scr_planes)/8);
  	SM_W(a-23,CHAR_HEIGHT());
! 	SM_W(a-22,scr_width/8-1);
! 	SM_W(a-21,scr_height/CHAR_HEIGHT()-1);
! 	SM_W(a-20,((scr_width*scr_planes)/8)*CHAR_HEIGHT());
! 	SM_W(a-6,scr_width);
! 	SM_W(a-2,scr_height);
  #if 0
  	fprintf(stderr,"FBASE=%08x, CUR_FONT=%08x, DEF_FONT=%08x, [%d,%d,%d,%d]\n",
  		LM_UL(a+0x54/2),LM_UL(a-0x38a/2),LM_UL(a-0x1cc/2),
***************
*** 2004,2013 ****
  	ptsin 	= LM_UL(MEM(pblock+8));
  	intout 	= LM_UL(MEM(pblock+12));
  	ptsout 	= LM_UL(MEM(pblock+16));
- #if 0
- 	if (LM_W(CONTRL(0)) == 38)
- 	fprintf(stderr,"vqt_attributes output: (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\n",LM_W(INTOUT(0)),LM_W(INTOUT(1)),LM_W(INTOUT(2)),LM_W(INTOUT(3)),LM_W(INTOUT(4)),LM_W(INTOUT(5)),LM_W(PTSOUT(0)),LM_W(PTSOUT(1)),LM_W(PTSOUT(2)),LM_W(PTSOUT(3)));
- #endif
  	if (LM_UW(CONTRL(0)) != 1 && LM_UW(CONTRL(0)) != 100)
  	{
  		return;
--- 1969,1974 ----
