# Unofficial but *REQUIRED* patch for Linux svgalib code in xz80 v0.1d
# --------------------------------------------------------------------
#
# NB: You don't need this unless you want to use the svgalib version.
# If you don't use Linux, or always use X, don't bother with this
# patch.
#
# This is an unofficial patch, but since I wrote the Linux-specific
# code for xz80 I think it makes sense for me to make this patch
# available so it works ok until IMC gets around to 0.1e. :-)
#
# The patch does the following:
#
# - fixes a few nasty bugs in the keyboard emulation.
#
# - fixes weird bug where the border colour is `delayed'.
#
# - fixes bug which meant you got an error when compiling without
#    -DDEV_AUDIO_IN. Not related to svgalib, but I figured I'd take
#    the opportunity anyway.
#
# - I also fixed the indentation in linuxcon.c, but that's not
#    terribly exciting. :-)
#
# A new `README.linuxcon' is created, which tells you how to
# compile and install the svgalib version. This info was somewhat
# lacking in IMC's README, though that was hardly his fault.
#
# Patch with `patch <this_file' from the dir you unpacked xz80 in.
# Patch will display this text, but don't worry about that, it's
# perfectly normal.
#
# - Russell Marks.
#
# (No email addr; see ZCN in ftp.nvg.unit.no:/pub/cpc/nc100 for snail
# address. It's at the end of doc/zcn.txt in the zip.)
#
diff -c --new-file orig/README.linuxcon ./README.linuxcon
*** orig/README.linuxcon	Thu Jan  1 01:00:00 1970
--- ./README.linuxcon	Mon Dec 16 01:31:52 1996
***************
*** 0 ****
--- 1,37 ----
+ Installing Linux svgalib version
+ --------------------------------
+ 
+ Be sure to read the main README before doing this.
+ 
+ After reading that, do the following:
+ 
+ 1. Set all the options in the Makefile as you would for a normal X
+ version.
+ 
+ 2. Uncomment the LINUX_SVGALIB option in the Makefile, and alter the
+ `SCALE=2' line to read `SCALE=1'.
+ 
+ 3. If you previously compiled an X version, do `rm -f *.o'.
+ (Similarly, you should do the same if you want to compile an X version
+ after compiling the svgalib version.)
+ 
+ 4. Do `make svga', and make a cup of coffee, take a nap, work out the
+ question to the ultimate answer, etc. :-)
+ 
+ 5. Install as for the X version. Except, the binary is called `lz80',
+ and must be installed setuid root. To install it like that, do (as
+ root) something like `install -o root -m 4511 lz80 /usr/local/bin'.
+ 
+ That's it. Now you should be able to run `lz80' and do the same things
+ as you can in the usual `xz80'. Alt-Fn can be used to switch VCs as
+ usual.
+ 
+ Known bugs (specific to `lz80', of course):
+ 
+ - `-border full' doesn't work.
+ - Joystick emulation isn't supported.
+ - Screen update is not optimal, unlike the X version.
+ - The aspect ratio is wrong. (But, the 320x200 mode is much faster
+    than 320x240, as no page swapping is required.)
+ 
+ -Rus.
diff -c --new-file orig/linuxcon.c ./linuxcon.c
*** orig/linuxcon.c	Wed Aug  2 15:58:47 1995
--- ./linuxcon.c	Mon Dec 16 01:03:10 1996
***************
*** 1,4 ****
! /* Linux console support for xz80, copyright (C) 1994/5 Russell Marks.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
--- 1,4 ----
! /* Linux console support for xz80, copyright (C) 1994-6 Russell Marks.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
***************
*** 17,39 ****
  
  #ifdef LINUX_SVGALIB
  
! /* an explanation of the way graphics works:
!  * we bang the border up around the speccy screen when it's changed,
!  * but otherwise just draw the whole 256x192 on each reqd. refresh.
!  *
!  * I tried my original idea (below) first, but 'twas WWAAAAYYYY too slow.
!  *
!  * We use image to store a malloc'ed 256x192 XImage-like image of
!  * the speccy screen. Whenever a screen refresh is done, we blank out the
!  * a virtual screen svgalib GC in the border colour, then put the speccy
!  * screen image into that, *then* copy that virtual screen to the real one.
!  * It has to be done this way, as the functions available for planar
!  * 256-colour modes are very limited.
!  *
!  * Er, but it's done that way again now, except it's unbuffered.
   */
   
  
  
  #include <stdio.h>
  #include <signal.h>
--- 17,34 ----
  
  #ifdef LINUX_SVGALIB
  
! /* NB: There are some seemingly `unnecessary' brackets in here which
!  * aren't. Be careful, and if it ain't broke...
!  * -Rus.
   */
   
  
+ /* an explanation of the way the graphics works:
+  * We use image to store a malloc'ed 256x192 XImage-like image of
+  * the speccy screen. Whenever a screen/border refresh is done, we redraw
+  * the appropriate part (screen or border).
+  */
+ 
  
  #include <stdio.h>
  #include <signal.h>
***************
*** 58,64 ****
  static int asciimap[256];	/* ASCII -> scancode translation */
  static int tty_fd=-1;
  
- static int old_border = -1;
  static int shift_pressed = 0,ctrl_pressed = 0,alt_pressed=0;
  static int colour_index_kludge = 0;
  static int palette_sav[16*3];
--- 53,58 ----
***************
*** 94,156 ****
  	
  if(c!=-1)
    {
!   xev->type = (c&128)?KeyRelease:KeyPress;
! 		c &= 127;
! 		xev->key = c;
! 		
! 		if (c == LEFT_SHIFT || c == RIGHT_SHIFT)
! 			/* this isn't quite right, but it's good enough */
! 			shift_pressed = (xev->type == KeyPress)?1:0;
! 
! 		if (c == LEFT_CTRL)
! 			ctrl_pressed  = (xev->type == KeyPress)?1:0;
! 		
! 		if (c == LEFT_ALT)
! 			alt_pressed  = (xev->type == KeyPress)?1:0;
! 		
! 		/* these are for a UK keyboard. It's possible to do this
! 		 * better :), but it's pretty awkward.
! 		 */
! 		if (shift_pressed) {
! 			/* with shift */
! 			if (c == scancode_trans('-')) xev->key = XK_underscore;
! 			if (c == scancode_trans(';')) xev->key = XK_colon;
! 			if (c == scancode_trans(',')) xev->key = XK_less;
! 			if (c == scancode_trans('.')) xev->key = XK_greater;
! 			if (c == scancode_trans('/')) xev->key = XK_question;
! 			if (c == scancode_trans('\\')) xev->key = XK_bar;
! 		} else {
! 			/* without shift */
! 			if (c == scancode_trans('=')) xev->key = XK_equal;
! 			if (c == scancode_trans(';')) xev->key = XK_semicolon;
! 			if (c == scancode_trans('\'')) xev->key = XK_apostrophe;
! 			if (c == scancode_trans(',')) xev->key = XK_comma;
! 			if (c == scancode_trans('.')) xev->key = XK_period;
! 			if (c == scancode_trans('/')) xev->key = XK_slash;
! 			if (c == scancode_trans('\\')) xev->key = XK_backslash;
! 		}
  #ifdef CONTROL_Z_SUSPENDS
! 		if (ctrl_pressed && c == scancode_trans('z'))
! 			xev->key = CTRL_Z;
  #endif
! 		if (alt_pressed && c>=XK_F1 && c<=XK_F9+1) {
! 			struct vt_stat vts;
! 			int newvt;
! 			
! 			ioctl(tty_fd,VT_GETSTATE,&vts);
! 			newvt=c-XK_F1+1;
! 			if(vts.v_active!=newvt) {
! 				ioctl(tty_fd,VT_ACTIVATE,newvt);
! 				restart_emu=0;
! 				while(restart_emu==0) usleep(50000);
! 			}
! 			xev->type=KeyRelease;
! 			xev->key=NoKeyPressed;
! 		}
! 	} else {
! 		xev->type = KeyRelease;
! 		xev->key  = NoKeyPressed;
! 	}
  }
  
  
--- 88,157 ----
  	
  if(c!=-1)
    {
!   xev->type = ((c&128)?KeyRelease:KeyPress);
!   c &= 127;
!   xev->key = c;
!   
!   if (c == LEFT_SHIFT || c == RIGHT_SHIFT)
!     /* this isn't quite right, but it's good enough */
!     shift_pressed = ((xev->type == KeyPress)?1:0);
! 
!   if (c == LEFT_CTRL)
!     ctrl_pressed  = ((xev->type == KeyPress)?1:0);
!   
!   if (c == LEFT_ALT)
!     alt_pressed  = ((xev->type == KeyPress)?1:0);
!   
!   /* these are for a UK keyboard. It's possible to do this
!    * better :-), but it's pretty awkward.
!    */
!   if (shift_pressed)
!     {
!     /* with shift */
!     if (c == scancode_trans('-')) xev->key = XK_underscore;
!     if (c == scancode_trans(';')) xev->key = XK_colon;
!     if (c == scancode_trans(',')) xev->key = XK_less;
!     if (c == scancode_trans('.')) xev->key = XK_greater;
!     if (c == scancode_trans('/')) xev->key = XK_question;
!     if (c == scancode_trans('\\')) xev->key = XK_bar;
!     }
!   else
!     {
!     /* without shift */
!     if (c == scancode_trans('=')) xev->key = XK_equal;
!     if (c == scancode_trans(';')) xev->key = XK_semicolon;
!     if (c == scancode_trans('\'')) xev->key = XK_apostrophe;
!     if (c == scancode_trans(',')) xev->key = XK_comma;
!     if (c == scancode_trans('.')) xev->key = XK_period;
!     if (c == scancode_trans('/')) xev->key = XK_slash;
!     if (c == scancode_trans('\\')) xev->key = XK_backslash;
!     }
  #ifdef CONTROL_Z_SUSPENDS
!   if (ctrl_pressed && c == scancode_trans('z'))
!     xev->key = CTRL_Z;
  #endif
!   if (alt_pressed && c>=XK_F1 && c<=XK_F9+1)
!     {
!     struct vt_stat vts;
!     int newvt;
!   
!     ioctl(tty_fd,VT_GETSTATE,&vts);
!     newvt=c-XK_F1+1;
!     if(vts.v_active!=newvt)
!       {
!       ioctl(tty_fd,VT_ACTIVATE,newvt);
!       restart_emu=0;
!       while(restart_emu==0) usleep(50000);
!       }
!     xev->type=KeyRelease;
!     xev->key=NoKeyPressed;
!     }
!   }
! else
!   {
!   xev->type = KeyRelease;
!   xev->key  = NoKeyPressed;
!   }
  }
  
  
***************
*** 166,190 ****
  void
  linux_graphics_on(void)
  {
! 	vga_disabledriverreport();
! 	vga_init();
! 	vga_setmode(MODE_TO_USE);
! 	signal(SIGSEGV,(void (*)(int))linux_panic_now);
! 	gl_setcontextvga(MODE_TO_USE);
! 
! 	rawmode_init();
! 
! 	/* fix termio stuff so ^C-style interrupts are ignored */
! 	ioctl(tty_fd,TCGETS,&old_termio);
! 	new_termio=old_termio;
! 	new_termio.c_lflag&=~(ISIG|ICANON);
! 	ioctl(tty_fd,TCSETSW,&new_termio);
! 	
! 	if ((image = malloc(256*192)) == NULL) {
! 		linux_graphics_off();
! 		fprintf(stderr,"xz80: not enough memory for image!\n");
! 		exit(1);
! 	}
  }
  
  
--- 167,193 ----
  void
  linux_graphics_on(void)
  {
! vga_disabledriverreport();
! vga_init();
! vga_setmode(MODE_TO_USE);
! signal(SIGSEGV,(void (*)(int))linux_panic_now);
! gl_setcontextvga(MODE_TO_USE);
! 
! rawmode_init();
! 
! /* fix termio stuff so ^C-style interrupts are ignored */
! ioctl(tty_fd,TCGETS,&old_termio);
! new_termio=old_termio;
! new_termio.c_lflag&=~(ISIG|ICANON);
! new_termio.c_iflag&=~(INLCR|ICRNL);
! ioctl(tty_fd,TCSETSW,&new_termio);
! 
! if ((image = malloc(256*192)) == NULL)
!   {
!   linux_graphics_off();
!   fprintf(stderr,"xz80: not enough memory for image!\n");
!   exit(1);
!   }
  }
  
  
***************
*** 255,274 ****
  linux_text_end(void)
  {
  #if 0
! 	usleep(500000);		/* let them read any message */
  #endif
! 	vga_setmode(MODE_TO_USE);
! 	vga_setpalvec(0,16,palette_sav);
! 	old_border=-1;
!         
!         refresh_screen=1;
! 	
! 	shift_pressed=ctrl_pressed=alt_pressed=0;
! 	keyports[0] |= 0x01;
! 	keyports[7] |= 0x02;
  
! 	rawmode_init();
! 	ioctl(tty_fd,TCSETSW,&new_termio);
  }
  
  
--- 258,277 ----
  linux_text_end(void)
  {
  #if 0
! usleep(500000);		/* let them read any message */
  #endif
! vga_setmode(MODE_TO_USE);
! vga_setpalvec(0,16,palette_sav);
! 
! refresh_screen=1;
! linux_draw_border();
! 
! shift_pressed=ctrl_pressed=alt_pressed=0;
! keyports[0] |= 0x01;
! keyports[7] |= 0x02;
  
! rawmode_init();
! ioctl(tty_fd,TCSETSW,&new_termio);
  }
  
  
diff -c --new-file orig/xspectrum.c ./xspectrum.c
*** orig/xspectrum.c	Thu Aug 10 12:05:55 1995
--- ./xspectrum.c	Mon Dec 16 01:29:19 1996
***************
*** 789,797 ****
     XMapRaised(display,borderwin);
     XMapRaised(display,mainwin);
     XSetWindowBackground(display,borderwin,pixels[bordercr]);
     XClearWindow(display,borderwin);
     XFlush(display);
- #endif
     refresh_screen=1;
  }
  
--- 789,797 ----
     XMapRaised(display,borderwin);
     XMapRaised(display,mainwin);
     XSetWindowBackground(display,borderwin,pixels[bordercr]);
+ #endif
     XClearWindow(display,borderwin);
     XFlush(display);
     refresh_screen=1;
  }
  
***************
*** 1014,1021 ****
--- 1014,1029 ----
  #undef symshift
  #undef capshift
  #define dosym (symbolshift || (keyports[7]|=2))
+ #ifndef LINUX_SVGALIB
  #define symshift (--symbolshift || (keyports[7]|=2))
  #define capshift (--capsshift || (keyports[0]|=1))
+ #else
+ /* The console generates multiple `presses' if a key is held, but only
+  * one `release'. This is an imperfect (but tolerable) kludge. -Rus
+  */
+ #define symshift ((symbolshift=0) || (keyports[7]|=2))
+ #define capshift ((capsshift=0) || (keyports[0]|=1))
+ #endif
  
  static void process_keyrelease(kev)
  XKeyEvent *kev;
***************
*** 1672,1680 ****
           cent+=(audioinbuf[i]=walu[(unsigned char)audioinbuf[i]]);
        }
        centre=cent/(framebytes*10);
- #endif
     }
  #endif
  }
  
  /* Output "val" to the I/O port whose high address byte is "hi" and
--- 1680,1688 ----
           cent+=(audioinbuf[i]=walu[(unsigned char)audioinbuf[i]]);
        }
        centre=cent/(framebytes*10);
     }
  #endif
+ #endif
  }
  
  /* Output "val" to the I/O port whose high address byte is "hi" and
***************
*** 1696,1701 ****
--- 1704,1715 ----
  #endif
           if(config.border){
              XSetWindowBackground(display,borderwin,pixels[newbord]);
+ #ifdef LINUX_SVGALIB
+             /* linuxcon.c bases XClearWindow() colour on bordercr,
+              * so we must update it now rather than later.
+              */
+             bordercr=newbord;
+ #endif
              /* clear takes a long time, so only do once per refresh */
              if(!borderchange++)XClearWindow(display,borderwin);
           }
