ikbd.cpp
  1  /*
  2  * Castaway
  3  *  (C) 1994 - 2002 Martin Doering, Joachim Hoenig
  4  *
  5  * ikbd.c - ST keyboard processor emulator (german keymap)
  6  *
  7  * This file is distributed under the GPL, version 2 or at your
  8  * option any later version.  See doc/license.txt for details.
  9  *
 10  * revision history
 11  *  23.05.2002  0.02.00 JH  FAST1.0.1 code import: KR -> ANSI, restructuring
 12  *  09.06.2002  0.02.00 JH  Renamed io.c to st.c again (io.h conflicts with system headers)
 13  *  16.06.2002  0.02.00 JH  New function: IkbdQueryBuffer(). X11 keysym conversion removed.
 14  */
 15  static char     sccsid[] = "$Id: ikbd.c,v 1.3 2002/06/16 23:16:09 jhoenig Exp $";
 16  //#include "winbase.h"
 17  #include <stdio.h>
 18  #include <string.h>
 19  #include <Arduino.h>
 20  #include "dcastaway.h"
 21  #include "st.h"
 22  #define IBS 10                  /* Ikbd input buffer size */
 23  #define OBS 20                  /* Ikbd output buffer size */
 24  
 25  
 26  //extern char Msg[400];
 27  extern FILE* logfile;
 28  extern int exmousex,exmousey;
 29  int             pause = 0;
 30  struct _mouse mouse;
 31  struct _joystick joystick;
 32  
 33  extern unsigned char joynum;
 34  unsigned char   inbuff[IBS];
 35  unsigned char   outbuff[OBS];
 36  int             inbuffi = 0;
 37  int             outbuffi = 0;
 38  int				oldjoystate =0;
 39  int				joytick=0;
 40  unsigned char Buttons;
 41  //SYSTEMTIME SystemTime;
 42  unsigned char TempButtons=0x0a;
 43  unsigned char PrevButtons;
 44  
 45  unsigned char Misc_ConvertToBCD(unsigned short int Value)
 46  {
 47  	return( ((Value&0xf0)>>4)*10 + (Value&0x0f) );
 48  }
 49  
 50  PROGMEM void IkbdRecv(unsigned char inchar)
 51  {
 52      if (inbuffi == IBS) {
 53          inbuffi = 0;
 54      }
 55      inbuff[inbuffi++] = inchar;
 56       //Serial.print("d ");
 57       //Serial.println(inbuff[0]);
 58      switch (inbuff[0]) {
 59      case 0x07:                  /* set mouse button action */
 60          if (inbuffi == 2) {
 61              inbuffi = 0;
 62              mouse.button_action = inbuff[1];
 63          }
 64          break;
 65      case 0x08:                  /* set relative mouse position reporting */
 66          inbuffi = 0;
 67          mouse.mode = 1;
 68          break;
 69      case 0x09:                  /* set absolute mouse positioning */
 70          if (inbuffi == 5) {
 71              mouse.mode = 2;
 72              mouse.xmax = (inbuff[1] << 8) | inbuff[2];
 73              mouse.ymax = (inbuff[3] << 8) | inbuff[4];
 74  			mouse.x=mouse.xmax/2;
 75  			mouse.y=mouse.ymax/2;
 76              inbuffi = 0;
 77          }
 78          break;
 79      case 0x0a:                  /* set mouse keycode mode */
 80          if (inbuffi == 3) {
 81              mouse.mode = 3;
 82              mouse.xkcm = inbuff[1];
 83              mouse.ykcm = inbuff[2];
 84              inbuffi = 0;
 85          }
 86          break;
 87      case 0x0b:                  /* set mouse threshold */
 88          if (inbuffi == 3) {
 89              mouse.xth = inbuff[1];
 90              mouse.yth = inbuff[2];
 91              inbuffi = 0;
 92          }
 93          break;
 94      case 0x0c:                  /* set mouse scale */
 95          if (inbuffi == 3) {
 96              mouse.xscale = inbuff[1];
 97              mouse.yscale = inbuff[2];
 98              inbuffi = 0;
 99          }
100          break;
101      case 0x0d:                  /* interrogate mouse position */
102          
103  		if (outbuffi < (OBS -6)){
104  			inbuffi = 0;
105  			/* Test buttons */
106  			Buttons = 0;
107  			/* Set buttons to show if up/down */
108  			if (mouse.stbuttons&1) Buttons |= 0x01; else Buttons |= 0x02;
109  			if (mouse.stbuttons&2) Buttons |= 0x04; else Buttons |= 0x08;       
110  			
111  			/* Mask off it didn't send last time */
112  			PrevButtons = TempButtons;
113  			TempButtons = Buttons;
114  			Buttons &= ~PrevButtons;
115  			
116  			IkbdSend (0xf7);
117  			IkbdSend (Buttons);
118  			IkbdSend (mouse.stx >> 8);
119  			IkbdSend (mouse.stx);
120  			IkbdSend (mouse.sty >> 8);
121  			IkbdSend (mouse.sty);
122  		}
123          break;
124  		
125      case 0x0e:                  /* load mouse position */
126          if (inbuffi == 6) {
127              inbuffi = 0;
128              mouse.x = exmousex = mouse.stx = (inbuff[2] << 8) | inbuff[3];
129              mouse.y = exmousey = mouse.sty = (inbuff[4] << 8) | inbuff[5];
130          }
131          break;
132      case 0x0f:                  /* set Y=0 at bottom */
133          inbuffi = 0;
134          mouse.yinv = 1;
135          break;
136      case 0x10:                  /* set Y=0 at top */
137          inbuffi = 0;
138          mouse.yinv = 0;
139          break;
140      case 0x11:                  /* resume */
141          inbuffi = 0;
142          pause = 0;
143          break;
144      case 0x12:                  /* disable mouse */
145          inbuffi = 0;
146          //mouse.mode = 0;
147          break;
148      case 0x13:                  /* pause output */
149          inbuffi = 0;
150          //pause = 1;
151          break;
152      case 0x14:                  /* set joystick event reporting */
153          inbuffi = 0;
154          joystick.mode = 1;
155          break;
156      case 0x15:                  /* set joystick interrogation mode */
157          inbuffi = 0;
158          joystick.mode = 2;
159          break;
160      case 0x16:                  /* joystick interrogation */
161          inbuffi = 0;
162          IkbdSend (0xfd);
163          IkbdSend (0);
164          IkbdSend (oldjoystate);
165          break;
166      case 0x17:                  /* set joystick monitoring */
167          if (inbuffi == 2) {
168              inbuffi = 0;
169              joystick.rate = inbuff[1];
170              joystick.mode = 4;
171          }
172          break;
173      case 0x18:                  /* set fire button monitoring */
174          inbuffi = 0;
175          joystick.mode = 5;
176          break;
177      case 0x19:                  /* set joystick keycode mode */
178          if (inbuffi == 7) {
179              inbuffi = 0;
180              joystick.mode = 3;
181          }
182          break;
183      case 0x1a:                  /* disable joysticks */
184          inbuffi = 0;
185  		// joystick.mode = 0;
186          break;
187      case 0x1b:                  /* time-of-day clock set */
188          if (inbuffi == 7) {
189              inbuffi = 0;
190          }
191          break;
192      case 0x1c:                  /* interrogate time-of-day clock */
193  		inbuffi = 0;
194          IkbdSend (0xfc);
195          IkbdSend (0x0);
196          IkbdSend (0x0);
197          IkbdSend (0x0);
198          IkbdSend (0x0);
199          IkbdSend (0x0);
200          IkbdSend (0x0);
201          break;
202      case 0x20:                  /* memory load */
203      case 0x21:                  /* memory read */
204      case 0x22:                  /* controller execute */
205          inbuffi = 0;
206          break;
207      case 0x80:                  /* reset */
208          if (inbuffi == 2) {
209              IkbdSend (0xf0);
210              inbuffi = 0;
211              mouse.buttons = mouse.stbuttons = 0;
212              switch (vid_shiftmode) {
213              case 0:
214                  mouse.x = exmousex = mouse.stx = 160;
215                  mouse.y = exmousey = mouse.sty = 100;
216                  break;
217              case 1:
218                  mouse.x = exmousex = mouse.stx = 320;
219                  mouse.y = exmousey = mouse.sty = 100;
220                  break;
221              case 2:
222                  mouse.x = exmousex = mouse.stx = 320;
223                  mouse.y = exmousey = mouse.sty = 200;
224                  break;
225              }
226          }
227          break;
228      case 0x87:                  /* request button action */
229          IkbdSend (0x07);
230          IkbdSend (mouse.button_action);
231          IkbdSend (0);
232          IkbdSend (0);
233          IkbdSend (0);
234          IkbdSend (0);
235          IkbdSend (0);
236          break;
237      case 0x88:                  /* request mouse mode */
238      case 0x89:
239      case 0x8a:
240          switch (mouse.mode) {
241          case 1:
242              IkbdSend (0x08);
243              IkbdSend (0);
244              IkbdSend (0);
245              IkbdSend (0);
246              IkbdSend (0);
247              IkbdSend (0);
248              IkbdSend (0);
249              break;
250          case 2:
251              IkbdSend (0x09);
252              IkbdSend (mouse.xmax >> 8);
253              IkbdSend (mouse.xmax);
254              IkbdSend (mouse.ymax >> 8);
255              IkbdSend (mouse.ymax);
256              IkbdSend (0);
257              IkbdSend (0);
258              break;
259          case 3:
260              IkbdSend (0x09);
261              IkbdSend (mouse.xkcm);
262              IkbdSend (mouse.ykcm);
263              IkbdSend (0);
264              IkbdSend (0);
265              IkbdSend (0);
266              IkbdSend (0);
267              break;
268          }
269          inbuffi = 0;
270          mouse.mode = 1;
271          break;
272  		case 0x8b:                  /* request mouse threshold */
273  			IkbdSend (0x0b);
274  			IkbdSend (mouse.xth);
275  			IkbdSend (mouse.yth);
276  			IkbdSend (0);
277  			IkbdSend (0);
278  			IkbdSend (0);
279  			IkbdSend (0);
280  			inbuffi = 0;
281  			break;
282  		case 0x8c:                  /* request mouse scale */
283  			IkbdSend (0x0b);
284  			IkbdSend (mouse.xscale);
285  			IkbdSend (mouse.yscale);
286  			IkbdSend (0);
287  			IkbdSend (0);
288  			IkbdSend (0);
289  			IkbdSend (0);
290  			inbuffi = 0;
291  			break;
292  		case 0x8f:                  /* request mouse vertical coordinates */
293  		case 0x90:
294  			if (mouse.yinv)
295  				IkbdSend (0x0f);
296  			else
297  				IkbdSend (0x10);
298  			IkbdSend (0);
299  			IkbdSend (0);
300  			IkbdSend (0);
301  			IkbdSend (0);
302  			IkbdSend (0);
303  			IkbdSend (0);
304  			inbuffi = 0;
305  			break;
306  		case 0x92:                  /* disable mouse */
307  			if (mouse.mode)
308  				IkbdSend (0);
309  			else
310  				IkbdSend (0x12);
311  			IkbdSend (0);
312  			IkbdSend (0);
313  			IkbdSend (0);
314  			IkbdSend (0);
315  			IkbdSend (0);
316  			IkbdSend (0);
317  			inbuffi = 0;
318  			break;
319  		case 0x94:                  /* request joystick mode */
320  		case 0x95:
321  		case 0x99:                  /* set joystick keycode mode */
322  			inbuffi = 0;
323  			switch (joystick.mode) {
324  			case 1:
325  				IkbdSend (0x14);
326  				IkbdSend (0);
327  				IkbdSend (0);
328  				IkbdSend (0);
329  				IkbdSend (0);
330  				IkbdSend (0);
331  				IkbdSend (0);
332  				break;
333  			case 2:
334  				IkbdSend (0x15);
335  				IkbdSend (0);
336  				IkbdSend (0);
337  				IkbdSend (0);
338  				IkbdSend (0);
339  				IkbdSend (0);
340  				IkbdSend (0);
341  				break;
342  			case 3:
343  				IkbdSend (0x19);
344  				IkbdSend (joystick.rx);
345  				IkbdSend (joystick.ry);
346  				IkbdSend (joystick.tx);
347  				IkbdSend (joystick.ty);
348  				IkbdSend (joystick.vx);
349  				IkbdSend (joystick.vy);
350  				break;
351  			}
352  			inbuffi = 0;
353  			break;
354  			case 0x9a:                  /* request joystick availability */
355  				if (joystick.mode)
356  					IkbdSend (0);
357  				else
358  					IkbdSend (0x1a);
359  				IkbdSend (joystick.rx);
360  				IkbdSend (joystick.ry);
361  				IkbdSend (joystick.tx);
362  				IkbdSend (joystick.ty);
363  				IkbdSend (joystick.vx);
364  				IkbdSend (joystick.vy);
365  				inbuffi = 0;
366  				break;
367      }
368  }
369  
370  void IkbdSend (unsigned char outchar)
371  {
372      if (outbuffi < (OBS - 1)) {
373          //Serial.print("q ");
374          //Serial.println(outchar);
375          outbuff[outbuffi++] = outchar;
376      }
377  }
378  
379  PROGMEM void IkbdWriteBuffer(void)
380  {
381  /*
382  if (mouse.flag && (outbuffi < (OBS / 2))) {
383  IkbdMouse ();
384  }
385  if (joystick.mode==4) IkbdJoystick();
386  	*/
387      if (outbuffi>0)
388      {     
389        if ((acia1_sr & 0x1) == 0) 
390        {
391            //Serial.println("KW");
392            acia1_sr |= 1;
393            if (acia1_cr & 0x80) {  /* receiver interrupt enabled? */
394                acia1_sr |= 0x80;
395                mfp_gpip &= (~0x10);
396            }
397      	    acia1_dr = outbuff[0];
398            memcpy (&outbuff[0], &outbuff[1], (OBS - 1));  
399            outbuffi--;
400        }
401      } 
402  }
403  
404  PROGMEM void IkbdKeyPress (unsigned short keysym) {
405      IkbdSend (keysym);
406  }
407  
408  PROGMEM void IkbdKeyRelease (unsigned short keysym) {
409      IkbdSend (0x80 | keysym);
410  }
411  
412  PROGMEM void IkbdMouseMotion (int x, int y)
413  {
414  	if (vid_shiftmode==1) {x+=x;}
415  	if (vid_shiftmode==2) {x+=x; y+=y;}
416      mouse.x=x; mouse.y=y;
417  }
418  
419  PROGMEM void IkbdMousePress (int code) {
420      mouse.buttons |= code;
421  }
422  
423  PROGMEM void IkbdMouseRelease (int code) {
424      mouse.buttons &= ~code;
425  }
426  
427  PROGMEM void joystickevent (int joystate)
428  {
429  	//Has joystick moved?
430  	if (joystate==oldjoystate) return;
431  	oldjoystate=joystate;
432  	//send fire button to mouse as well
433  	if (mouse.mode==1 || mouse.mode==0) {
434  		if (joystate&0x80) {
435  			IkbdSend (0xf9);
436              IkbdSend (0);
437              IkbdSend (0);
438  		}
439  		else {
440  			IkbdSend (0xf8);
441              IkbdSend (0);
442              IkbdSend (0);
443  		}
444  	}
445  	//In event mode send the joystick event immediately
446  	if (joystick.mode==1) {
447  		IkbdSend (0xff);
448  		IkbdSend (joystate);
449  	}
450  }
451  
452  PROGMEM void IkbdLoop()
453  {
454      int dx, dy;
455  	if (mouse.mode==1) {
456  		dx=mouse.x-mouse.stx; if (dx>127) dx=127;  else if (dx<-127) dx=-127;
457  		dy=mouse.y-mouse.sty; if (dy>127) dy=127; else if (dy<-127) dy=-127;
458  		if (mouse.stbuttons!=mouse.buttons || dx>mouse.xth || dy>mouse.yth || -dx>mouse.xth || -dy>mouse.yth) {
459  			if (outbuffi<OBS/2) {
460  				mouse.stbuttons = mouse.buttons;
461  				mouse.stx = mouse.stx + dx;
462  				mouse.sty = mouse.sty + dy;
463  				if (mouse.stx <= 0) {mouse.stx = 0; dx = -127;}
464  				if (mouse.sty <= 0) {mouse.sty = 0; dy = -127;}
465  				switch (vid_shiftmode) {
466  				case 0:
467  					if (mouse.stx >= 319) {mouse.stx = 319; dx = 127;}
468  					if (mouse.sty >= 199) {mouse.sty = 199; dy = 127;}
469  					break;
470  				case 1:
471  					if (mouse.stx >= 639) {mouse.stx = 639; dx = 127;}
472  					if (mouse.sty >= 199) {mouse.sty = 199; dy = 127;}
473  					break;
474  				case 2:
475  					if (mouse.stx >= 639) {mouse.stx = 639; dx = 127;}
476  					if (mouse.sty >= 399) {mouse.sty = 399; dy = 127;}
477  					break;
478  				}
479  				IkbdSend (0xf8 | (mouse.stbuttons&3));
480  				IkbdSend (dx);
481  				IkbdSend (dy);
482  			}
483  		}
484  	}
485  	else {
486  		if (mouse.x>mouse.xmax) mouse.x=mouse.xmax;
487  		if (mouse.y>mouse.ymax) mouse.y=mouse.ymax;
488  		mouse.stx=mouse.x;
489  		mouse.sty=mouse.y;
490  		mouse.stbuttons=mouse.buttons;
491  		
492  	}
493  	if (joystick.mode==4) {
494  		//Called at 200hz when joystick is in mode 4
495  		joytick+=2;
496  		if (joytick<joystick.rate) return;
497  		joytick=0;
498  		IkbdSend (oldjoystate>>7);
499  		IkbdSend (oldjoystate&15);
500  	}
501  }
502  
503  PROGMEM void IkbdReset (void) 
504  {
505  	joystick.mode=1;
506  	mouse.mode=1;
507    IkbdSend(0x80);
508    IkbdSend(0xff);
509    IkbdSend(0x80);
510    acia1_cr=150;
511    acia1_sr=0;
512    acia1_dr=240;
513    acia2_cr=149;
514    acia2_sr=0;
515    acia2_dr=0;
516    inbuffi = 0;
517    outbuffi = 0;
518  }
519  
520  
521  PROGMEM void IkbdJoystickChange(int number, uint8 state)
522  {
523      joystickevent(state);
524  }