1 /**************************************************************************************\
2 *                                                                                      *
3 *              The Lisa Emulator Project  V1.2.6      DEV 2007.12.04                   *
4 *                             http://lisaem.sunder.net                                 *
5 *                                                                                      *
6 *                  Copyright (C) 1998, 2007 Ray A. Arachelian                          *
7 *                                All Rights Reserved                                   *
8 *                                                                                      *
9 *           This program is free software; you can redistribute it and/or              *
10 *           modify it under the terms of the GNU General Public License                *
11 *           as published by the Free Software Foundation; either version 2             *
12 *           of the License, or (at your option) any later version.                     *
13 *                                                                                      *
14 *           This program is distributed in the hope that it will be useful,            *
15 *           but WITHOUT ANY WARRANTY; without even the implied warranty of             *
16 *           MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
17 *           GNU General Public License for more details.                               *
18 *                                                                                      *
19 *           You should have received a copy of the GNU General Public License          *
20 *           along with this program;  if not, write to the Free Software               *
21 *           Foundation, Inc., 59 Temple Place #330, Boston, MA 02111-1307, USA.        *
22 *                                                                                      *
23 *                   or visit: http://www.gnu.org/licenses/gpl.html                     *
24 *                                                                                      *
25 *                                                                                      *
26 *                                                                                      *
27 *                              COPS.C Routines                                         *
28 *                                                                                      *
29 \**************************************************************************************/
30 
31  /*  Yes, we are including a .c file in here, that's because this file is actually the
32  * keyboard table array, so it's nicer to have it in a separate file and since it doesn't
33  * actually contain any code, it doesn't make sense to have a .h file for it with just a
34  * single extern refrence to the array which would be lame.
35  *
36  */
37 
38 #define IN_COPS_C
39 #include "vars.h"
40 #include "keyscan.h"
41 #include "keytable.c"
42 
43 // Older COPS behavior is to send keyboard unplugged signal before keyboard id,
44 // and mouse unplugged signal before mouse plugged signal on a reset.
45 // // #define OLD_COPS_BEHAVIOR 1
46 
47 #define LISA_REBOOTED(x)   { save_pram(); profile_unmount(); lisa_rebooted();     return;}
48 
49 // this one is a bit more convoluted because we need to force reg68k.c to quit without doing anything else, or crashing the emulator.
50 #define LISA_POWEREDOFF(x) { save_pram(); profile_unmount(); lisa_powered_off(); pc24=0xffffffff; cpu68k_clocks_stop=cpu68k_clocks; abort_opcode=1; memset(lisaram,0xff,65536); return;}
51 
52 
53 static int32 cops_key_id=0;
54 static int   keyboard_keytronix=1;      // need to recode this as user editable
55 
56 
57 // used to debug LisaTest (mouse seeking doesn't work for this OS, likely because it's
58 // either freezing after displaying the menu, or it stores mouse X,Y somewhere else in memory.
59 //
60 // So I cheat by using control+shift+comma to enable it, then control-shift-arrow and . to work the mouse
61 // while debugging is enabled, so I can see where mouse x,y is stored.
62 //
63 int mouse_keys_enabled=0, mouse_keys_x=0, mouse_keys_y=0;
64 
65 // duplicated from VIA:
66 #define  VIA_CLEAR_IRQ_PORT_A(x) { if (((via[x].via[PCR]>>1) & 7)!=1 &&                                      \
67                                        ((via[x].via[PCR]>>1) & 7)!=3   )                                     \
68                                             via[x].via[IFR] &=(0xff-VIA_IRQ_BIT_CA2-VIA_IRQ_BIT_CA1);        \
69                                    via[x].ca1=0; via[x].ca2=0; if ( via[x].via[IFR]==128) via[x].via[IFR]=0;}
70 // clear Cb1/Cb2 on ORb/IRb access
71 #define  VIA_CLEAR_IRQ_PORT_B(x) { if (((via[x].via[PCR]>>5) & 7)!=1 &&                                      \
72                                              ((via[x].via[PCR]>>5) & 7)!=3   )                               \
73                                                   via[x].via[IFR] &=(0xff-VIA_IRQ_BIT_CB2-VIA_IRQ_BIT_CB1);  \
74                                     via[x].cb1=0; via[x].cb2=0; if ( via[x].via[IFR]==128) via[x].via[IFR]=0;}
75 // clear SR irq on SR access
76 #define  VIA_CLEAR_IRQ_SR(x)     { via[x].via[IFR] &=!VIA_IRQ_BIT_SR; if (via[x].via[IFR]==128) via[x].via[IFR]=0; DEBUG_LOG(0,"SR IRQ on via %d cleared",x);}
77 
78 ///////////////////////////////////
79 
80 
81 void init_clock(void);
82 
83 void bigm_delta(int16 x, int16 y);
84 //void recalibratemouse_inside(int x,int y,int wx,int wy,int ww,int wh);
85 
86 
87 
88 #define MAXQUEUEFULL 32
89 //static  int16 diff_mouse_x=0,    diff_mouse_y=0,    diff_mouse_button=0;
90 static  uint16 copsqueuefull=0;
91 
92 
93 
94 #define COPS_RES_KBFAILURE        0xff    /* Keyboard COPS failure detected  */
95 #define COPS_RES_IOFAILURE        0xfe    /* I/O Board COPS failure detected */
96 #define COPS_RES_KBUNPLUGD        0xfd    /* Keyboard unplugged              */
97 #define COPS_RES_CLOCKTIRQ        0xfc    /* clock timer interrupt           */
98 #define COPS_RES_POWERKEY         0xfb    /* Soft Power Switch hit           */
99 
100 #define COPS_CLOCK_0              0xe0    /* COPS year  followed by 5 bytes */
101 #define COPS_CLOCK_1              0xe1    /* COPS year  followed by 5 bytes */
102 #define COPS_CLOCK_2              0xe2    /* COPS year  followed by 5 bytes */
103 #define COPS_CLOCK_3              0xe3    /* COPS year  followed by 5 bytes */
104 #define COPS_CLOCK_4              0xe4    /* COPS year  followed by 5 bytes */
105 #define COPS_CLOCK_5              0xe5    /* COPS year  followed by 5 bytes */
106 #define COPS_CLOCK_6              0xe6    /* COPS year  followed by 5 bytes */
107 #define COPS_CLOCK_7              0xe7    /* COPS year  followed by 5 bytes */
108 #define COPS_CLOCK_8              0xe8    /* COPS year  followed by 5 bytes */
109 #define COPS_CLOCK_9              0xe9    /* COPS year  followed by 5 bytes */
110 #define COPS_CLOCK_a              0xea    /* COPS year  followed by 5 bytes */
111 #define COPS_CLOCK_b              0xeb    /* COPS year  followed by 5 bytes */
112 #define COPS_CLOCK_c              0xec    /* COPS year  followed by 5 bytes */
113 #define COPS_CLOCK_d              0xed    /* COPS year  followed by 5 bytes */
114 #define COPS_CLOCK_e              0xee    /* COPS year  followed by 5 bytes */
115 #define COPS_CLOCK_f              0xef    /* COPS year  followed by 5 bytes */
116 
117 /* dd dh hm ms st - ddd day, hh-hour, mm min ss=second t=tenths of second   */
118 
119 /* Keyboard ID # produced whenever the keyboard cops is reset.  valid codes
120    are  keytronix id,   apd  */
121 
122 #define COPS_KEYID_FRENCH         0xAD2d
123 #define COPS_KEYID_GERMAN         0xAE2e
124 #define COPS_KEYID_UK             0xAF2f
125 #define COPS_KEYID_US             0xBF2f
126 
127 
128 #define GET_RAT_XY(z)                                                                                         \
129         {                                                                                                     \
130          DEBUG_LOG(0,"Reading Mouse XY (mouse_keys is:%d)",mouse_keys_enabled);                               \
131          if (mouse_keys_enabled) {ratx=mouse_keys_x;     raty=mouse_keys_y;}                                  \
132          else                    {ratx=lisa_ram_safe_getword(1,lisa_os_mouse_x_ptr);                          \
133                                   raty=lisa_ram_safe_getword(1,lisa_os_mouse_y_ptr); }                        \
134         }
135 
136 
137 
138 
139 
140 // Is Lisa listening to the mouse?
is_lisa_mouse_on(void)141 uint8 is_lisa_mouse_on(void)
142        {
143         uint8 r;
144 
145         r=lisa_ram_safe_getlong(1,0x490)!=0xffffffff;
146 
147         DEBUG_LOG(0,"Checking is Mouse On? - %s",r ? "yes":"no");
148         return r;
149 
150         //     (! (fetchbyte(0x49a)|(!fetchbyte(0x49b))) );
151        }
152 
153 
154 //ifdef DEBUG
155 
my_dump_cops(FILE * buglog)156 void my_dump_cops(FILE *buglog)
157 {
158  int i;
159 
160  fflush(buglog);
161 
162  if ( copsqueuelen<=0)
163  {
164     switch ( copsqueuelen) {
165         case 0  : DEBUG_LOG(0,"COPS queue is empty, and no mouse motion is pending.");
166         case -1 : DEBUG_LOG(0,"Mouse: pending the send of 00");
167         case -2 : DEBUG_LOG(0,"Mouse: pending the send of mouse_x_delta %d",mouse_pending_x);
168         case -3 : DEBUG_LOG(0,"Mouse: pending the send of mouse_y_delta %d",mouse_pending_y);
169         default:  DEBUG_LOG(0,"ERROR! copsqueuelen is negative but out of range! %d",copsqueuelen);
170     }
171    return;
172  }
173 
174  fprintf(buglog,"SRC: COPS: QUEUE contains: %d items:\nSRC: COPS:",copsqueuelen);
175  for ( i=0; i<copsqueuelen; i++) {fprintf(buglog,"%02x ",copsqueue[i]);}
176  fprintf(buglog,"\n");
177  fflush(buglog);
178 }
179 //#else
180 ///
dump_cops(FILE * buglog)181 void dump_cops(FILE *buglog) {my_dump_cops(buglog);}
182 
183 //#endif
184 
185 //     dump_cops(buglog); was at the end of these
186 #define SEND_COPS_CODE(x)          {set_kb_data_ready();DEBUG_LOG(0,"COPS queue len: %d adding 0x%02x",copsqueuelen,(unsigned)(x)); \
187                                      if (copsqueuelen>=0 && (copsqueuelen+1<MAXCOPSQUEUE)) copsqueue[copsqueuelen]=(x); copsqueuelen++; \
188                                    }
189 
190 #define cops_reset_status(x)       {set_kb_data_ready();DEBUG_LOG(0,"COPS queue len: %d adding reset (0x80)",copsqueuelen); \
191                                      if (copsqueuelen>=0 && (copsqueuelen+1<MAXCOPSQUEUE)) copsqueue[copsqueuelen]=0x80; copsqueuelen++;\
192                                    }
193 #define SEND_RESETCOPS_AND_CODE(x) {set_kb_data_ready();DEBUG_LOG(0,"COPS queue len: %d adding reset and code (0x80+0x%02x)",copsqueuelen,x);\
194                                      if (copsqueuelen>=0 && (copsqueuelen+2<MAXCOPSQUEUE)) {copsqueue[copsqueuelen]=0x80; copsqueuelen++; \
195                                          copsqueue[copsqueuelen]=(x); copsqueuelen++;}}
196 
197 #ifndef abs
198   #define abs(x) (x<0 ? -x:x)
199 #endif
200 
201 #ifndef sgn
202  #define sgn(x) (x<0 ? -1: (x>0 ? 1:0))
203 #endif
204 
bigm_delta(int16 x,int16 y)205 void bigm_delta(int16 x, int16 y)       // x,y are delta-x, delta-y, but there are limits (max=+/-127) this normalizes it.
206 {
207     int16 dx=0, dy=0, max=32;//max=127;
208 
209     DEBUG_LOG(0,"x,y inputs before dx,dy:%d,%d",x,y);
210 
211     if (lisa_os_mouse_x_ptr!=0x486)
212     {
213          max=127;  // hack to limit Lisa Test Mouse Jitter.
214          while(x || y)
215          {
216             dx=0; dy=0;
217 
218             if      ( x>-(max+1) && x<1) { dx=x;    x=0;    }
219             else if ( x<-max )       { dx=-max; x+=max; }
220             else if ( x>0 && x<(max+1))  { dx=x;    x=0;    }
221             else if ( x>max )        { dx=+max; x-=max; }
222 
223             if      ( y>-(max+1) && y<1) { dy=y;    y=0;    }
224             else if ( y<-max       ) { dy=-max; y+=max; }
225             else if ( y>0  && y<(max+1)) { dy=y;    y=0;    }
226             else if ( y>max        ) { dy=+max; y-=max; }
227          }
228 
229          // reduce jitter caused by acceleration a bit further when getting close to the mouse pointer
230 
231 
232 
233          if (abs(dx)>mouse_x_halfing_tolerance) dx >>=1;
234          if (abs(dy)>mouse_y_halfing_tolerance) dy >>=1;
235 
236          mouse_pending=-1;
237          mouse_pending_x=dx;
238          mouse_pending_y=dy;
239 
240          //DEBUG_LOG(0,"Returing dx,dy:%d,%d",dx,dy);
241 
242          return;
243     }
244 
245 
246 
247     while(abs(x)>mouse_x_tolerance || abs(y)>mouse_y_tolerance)         // jitter reduction
248     {
249         dx=0; dy=0;
250 
251         if      ( x>-(max+1) && x<1) { dx=x;    x=0;    }
252         else if ( x<-max )       { dx=-max; x+=max; }
253         else if ( x>0 && x<(max+1))  { dx=x;    x=0;    }
254         else if ( x>max )        { dx=+max; x-=max; }
255 
256         if      ( y>-(max+1) && y<1) { dy=y;    y=0;    }
257         else if ( y<-max       ) { dy=-max; y+=max; }
258         else if ( y>0  && y<(max+1)) { dy=y;    y=0;    }
259         else if ( y>max        ) { dy=+max; y-=max; }
260 
261       // reduce jitter caused by acceleration a bit further when getting close to the mouse pointer
262         mouse_pending=-1;
263         mouse_pending_x=dx;
264         mouse_pending_y=dy;
265      //      copsqueuelen=-1;                  // -1=send 00, -2=sendx, -3=sendy, 0=copsqueuelen=0;
266     }
267 
268 }
269 
270 
271 
272 // mirrored inside reg68k as inline for speed.
273 
get_cops_pending_irq(void)274 int get_cops_pending_irq(void )
275 {
276      // bit 7 of IFR indicates whether any VIA1 IRQ's have been fired, so check to see if any of them have, then set bit 7
277      if (via[1].via[IER] & via[1].via[IFR] & 0x7f)
278      {
279        via[1].via[IFR] |=0x80;
280        return 0x80;
281      }
282 
283      via[1].via[IFR] &=0x7f;
284      return 0;
285 }
286 
287 
keystroke_cops(unsigned char c)288 void keystroke_cops(unsigned char c)
289 {
290     uint8 k;
291     int8 j,len;
292 
293 //    DEBUG_LOG(0,"SRC: COPS Keystroke %02x %c",c,c>31 && c<127 ? c:'*');
294 
295     for (len=0,j=0; j<9; j++)
296             if (keydecodetable[c][j]) len=j;
297 
298     DEBUG_LOG(0,"key length is:%d",len);
299 
300     // should this be <=0????
301     if ( !len || copsqueuelen<0 || copsqueuelen>MAXCOPSQUEUE-len-1)
302             {
303                 DEBUG_LOG(0,"Could not add keystroke %02x because:qlen=%d len=%d",c,copsqueuelen,len);
304                 return;
305             }
306 
307 
308     for (j=0; j<=len; j++)
309     {
310         k=keydecodetable[c][j];
311         if (k) {SEND_COPS_CODE(k);}
312         else    {
313                  if (k==NMIKEY && NMIKEY) {fprintf(buglog,"COPS NMI KEY:%04x hit, firing.\n",NMIKEY); lisa_nmi_vector(CHK_MMU_TRANS(pc24));}
314         }
315     }
316     SET_COPS_NEXT_EVENT(0);
317 }
318 
319 
send_nmi_key(void)320 void send_nmi_key(void)
321 {
322     if ((NMIKEY & 0x7f)==0)
323        {
324           if (yesnomessagebox("The Lisa isn't ready to accept an NMI, are you sure?",
325                 "Lisa Not ready for NMI")==0) return;
326        }
327 
328 //    DEBUG_LOG(0,"SRC: COPS User NMI key");
329     if ( copsqueuelen<0 || copsqueuelen>MAXCOPSQUEUE-8)
330             {
331                 messagebox("Could not add NMI keystroke because cops queue is full", "COPS queue full");
332                 DEBUG_LOG(0,"Could not add NMI keystroke because:qlen=%d",NMIKEY,copsqueuelen);
333                 return;
334             }
335 
336         if (NMIKEY & 0x80)  SEND_COPS_CODE(KEYCODE_COMMAND|KEY_DOWN); // apple key down
337       //if (NMIKEY & 0x40)  SEND_COPS_CODE(KEYCODE_LOPTION|KEY_DOWN); // option key down
338         SEND_COPS_CODE( (NMIKEY & 0x7f)                   |KEY_DOWN); // NMI key down          //3f if option enabled
339         SEND_COPS_CODE( (NMIKEY & 0x7f)                            ); // NMI key up            //3f if option enabled
340       //if (NMIKEY & 0x40)  SEND_COPS_CODE(KEYCODE_LOPTION         ); // option key down
341         if (NMIKEY & 0x80)  SEND_COPS_CODE(KEYCODE_COMMAND         ); // apple key up
342 
343         lisa_nmi_vector(CHK_MMU_TRANS(pc24));
344 
345     SET_COPS_NEXT_EVENT(0);
346 }
347 
348 
349 
send_cops_keycode(int k)350 void send_cops_keycode(int k)
351      {
352         SEND_COPS_CODE(k);
353         SET_COPS_NEXT_EVENT(0);
354      }
355 
cops_timer_alarm(void)356 void cops_timer_alarm(void)
357 {   DEBUG_LOG(0,"Sending Alarm code.");
358     //SEND_COPS_CODE(COPS_RES_CLOCKTIRQ);}
359     SEND_RESETCOPS_AND_CODE(COPS_RES_CLOCKTIRQ);}
360 
361 //static uint8 releasekey=0;
362 //static uint8 release_shift=0;
363 //static uint8 release_cmd=0;
364 //char *release_key_s;
365 
apple_combo_key(uint8 key,uint8 shift,uint8 cmdkey,uint8 option,char * s)366 void apple_combo_key(uint8 key, uint8 shift, uint8 cmdkey, uint8 option, char *s)
367 {
368   int size=1;
369 
370   ALERT_LOG(0,"Sending %s",s);
371 
372   if (shift)  size+=2;
373   if (cmdkey) size+=2;
374   if (option) size+=2;
375 
376   if (copsqueuelen>MAXCOPSQUEUE-size ||copsqueuelen<0)  { ALERT_LOG(0,"cannot send key - copsqlen");   return; }
377 
378 
379   if (option) SEND_COPS_CODE(KEYCODE_OPTION |KEY_DOWN);
380   if (cmdkey) SEND_COPS_CODE(KEYCODE_COMMAND|KEY_DOWN);
381   if (shift)  SEND_COPS_CODE(KEYCODE_SHIFT  |KEY_DOWN);
382 
383   /*      */  SEND_COPS_CODE(key            |KEY_DOWN);
384 
385   /*      */  SEND_COPS_CODE(key            |KEY_UP);
386 
387   if (shift)  SEND_COPS_CODE(KEYCODE_SHIFT  |KEY_UP);
388   if (cmdkey) SEND_COPS_CODE(KEYCODE_COMMAND|KEY_UP);
389   if (option) SEND_COPS_CODE(KEYCODE_OPTION |KEY_UP);
390 
391   if ((NMIKEY & 0x7f)==key) {ALERT_LOG(0,"Also sending NMI"); lisa_external_nmi_vector(pc24);}
392 
393   ALERT_LOG(0,"done.")
394 }
395 
396 //                                            KEYCODE_,   shift,apple,option, text for logging
apple_1(void)397 void apple_1(void)           {apple_combo_key(KEYCODE_1,       0,1,0, "Apple-1");                                          }
apple_2(void)398 void apple_2(void)           {apple_combo_key(KEYCODE_2,       0,1,0, "Apple-2");                                          }
apple_3(void)399 void apple_3(void)           {apple_combo_key(KEYCODE_3,       0,1,0, "Apple-3");                                          }
apple_enternum(void)400 void apple_enternum(void)    {apple_combo_key(KEYCODE_ENTERNUM,0,1,0, "Apple-ENTERNUM");                                   }
apple_enter(void)401 void apple_enter(void)       {apple_combo_key(KEYCODE_ENTERNUM,0,1,0, "Apple-ENTERNUM");                                   }
apple_renter(void)402 void apple_renter(void)      {apple_combo_key(KEYCODE_LENTER,  0,1,0, "Apple-LENTER");                                     }
apple_S(void)403 void apple_S(void)           {apple_combo_key(KEYCODE_S,       0,1,0, "Apple-S");                      }
apple_dot(void)404 void apple_dot(void)         {apple_combo_key(KEYCODE_DOT,     0,1,0, "Apple-DOT");                                        }
shift_option_0(void)405 void shift_option_0(void)    {apple_combo_key(KEYCODE_0,       1,0,1, "Shift-Option-0");                                   }
shift_option_4(void)406 void shift_option_4(void)    {apple_combo_key(KEYCODE_4,       1,0,1, "Shift-Option-4");                                   }
shift_option_7(void)407 void shift_option_7(void)    {apple_combo_key(KEYCODE_7,       1,0,1, "Shift-Option-7");                                   }
408 
409 
apple_dot_down(void)410 void apple_dot_down(void)
411 {
412   if ((NMIKEY & 0x7f)==KEYCODE_DOT) {lisa_external_nmi_vector(pc24); return;}
413   if (copsqueuelen>MAXCOPSQUEUE-3 ||copsqueuelen<0) return;
414   DEBUG_LOG(0,"apple-. down");
415   SEND_COPS_CODE(KEYCODE_LEFTCMD|KEY_DOWN);
416   SEND_COPS_CODE(KEYCODE_DOT    |KEY_DOWN);
417 }
418 
apple_dot_up(void)419 void apple_dot_up(void)
420 {
421   if (copsqueuelen>MAXCOPSQUEUE-3 ||copsqueuelen<0) return;
422   DEBUG_LOG(0,"apple-. up");
423   SEND_COPS_CODE(KEYCODE_DOT    |KEY_UP);
424   SEND_COPS_CODE(KEYCODE_LEFTCMD|KEY_UP);
425 }
426 
427 
428 
presspowerswitch(void)429 void presspowerswitch(void)
430 {
431     DEBUG_LOG(0,"SRC: COPS: Pressing Power Switch");
432     SEND_RESETCOPS_AND_CODE(0xFB);      // 0x80 0xFB - Soft Power Switch Sequence
433 }
434 
cops_fire_clock_timer_irq(void)435 void cops_fire_clock_timer_irq(void)
436 {
437     DEBUG_LOG(0,"SRC: COPS: Timer IRQ");
438     SEND_RESETCOPS_AND_CODE(0xFB);      // 0x80 0xFC - Clock Timer IRQ
439 }
440 
set_keyboard_id(int32 id)441 void set_keyboard_id(int32 id)
442 {
443 
444   DEBUG_LOG(0,"SRC: COPS: Setting keyboard type to %08x",id);
445 
446   // incase it's out of range default to the US keyboard - is that super-pro-american patriotic or what? (humming yankee doodle...) :)
447   if ( id>0xffff || id<-5) {cops_key_id=COPS_KEYID_US; return;}
448   switch (id)
449         {
450           case -1: cops_key_id=COPS_KEYID_US;     DEBUG_LOG(0,"US"); break;
451           case -2: cops_key_id=COPS_KEYID_UK;     DEBUG_LOG(0,"UK"); ;break;
452           case -3: cops_key_id=COPS_KEYID_GERMAN; DEBUG_LOG(0,"DE"); break;
453           case -4: cops_key_id=COPS_KEYID_FRENCH; DEBUG_LOG(0,"FR"); break;
454           default: cops_key_id=(id & 0xffff);     DEBUG_LOG(0,"Other");
455         }
456 }
457 
458 
459 
460 // a keyboard ID is sent when the keyboard is plugged in, or power is turned on
cops_keyboard_id(void)461 void cops_keyboard_id(void)
462 {
463     uint8 x;
464     DEBUG_LOG(0,"SRC: COPS: reporting keyboard ID:%04x len:%d",cops_key_id,copsqueuelen);
465     if    (keyboard_keytronix) x=(cops_key_id>>8) & 0xff;        // keyboard id (allow user to change keyboards later)
466     else  x=(uint8)(cops_key_id & 0xff);                                // keyboard id (allow user to change keyboards later)
467 
468     SEND_RESETCOPS_AND_CODE(x);
469     DEBUG_LOG(0,"len:%d",copsqueuelen);
470 }
471 
472 
cops_unplug_keyboard(void)473 void cops_unplug_keyboard(void)
474 {
475     DEBUG_LOG(0,"SRC: COPS: Unplug");
476     SEND_RESETCOPS_AND_CODE(0xFD);      // send 0x80 0xFD
477 }
478 
479 
unplugmouse(void)480 void unplugmouse(void)                  // Used by initialization sequence - checked by Lisa POST
481 {
482  /*  If the mouse is plugged in, 1000 0111 is returned, if unplugged,
483      0000 0111 is returned. */
484     DEBUG_LOG(0,"SRC: COPS: Unplug");
485     //cops_mouse=0;
486     SEND_COPS_CODE(0x07);
487 }
488 
489 
plugmouse(void)490 void plugmouse(void)                    // Used by initialization sequence - checked by Lisa POST
491 {
492  /*  If the mouse is plugged in, 1000 0111 is returned, if unplugged,
493      0000 0111 is returned. */
494     if (!cops_mouse) cops_mouse=400;
495     SEND_COPS_CODE(0x87);
496     DEBUG_LOG(0,"SRC: COPS: plugmouse. copsqueue=%d after pushing 80,87",copsqueuelen);
497 }
498 
499 
500 
set_mouse_button(int i)501 void set_mouse_button(int i)  {  DEBUG_LOG(0,"mouse button event:%d",i); SEND_COPS_CODE( ( i?0x86:0x06) ); }
502 
503 //#define OLD_COPS_BEHAVIOR
504 
cops_reset(void)505 void cops_reset(void)                   // write 0 to port b bit 0
506 {
507     // Older COPS behavior is to send keyboard unplugged signal before keyboard id,
508     // and mouse unplugged signal before mouse plugged signal on a reset.
509     copsqueuelen=0;
510 
511     //DEBUG_LOG(0,"COPS Reset");
512     //if ((pc24 & 0x00ff0000)!=0x00fe0000) {debug_on("cops_reset"); debug_log_enabled=1;}
513     //else {DEBUG_LOG(0,"Did not turn on logging for COPS_RESET because pc24:%08x",pc24);}
514 
515     #ifdef OLD_COPS_BEHAVIOR
516           cops_unplug_keyboard();
517           cops_keyboard_id();
518           unplugmouse();
519           plugmouse();
520     #else
521           cops_keyboard_id();
522           //plugmouse();
523     #endif
524 
525     #ifdef DEBUG
526     if (0==copsqueuelen) {DEBUG_LOG(0,"ERROR COPSQUEUELEN IS ZERO AFTER COPSRESET");}
527     else {DEBUG_LOG(0,"After COPS Reset copsqueuelen=%d",copsqueuelen);}
528     #endif
529 
530     if ((lisa_clock.year & 0x0f)<3) init_clock(); // prevent warning about clock by going to 1983.
531 }
532 
533 
normalize_lisa_clock(void)534 void normalize_lisa_clock(void)
535 {
536      int years, days, hours, minutes, seconds, tenths;
537 
538      years=lisa_clock.year & 0x0f;
539      days   =(((lisa_clock.days_h & 0xf0)>>4)*100+(lisa_clock.days_h & 0x0f)*10+lisa_clock.days_l);
540      hours  =lisa_clock.hours_h*10 + lisa_clock.hours_l;
541      minutes=lisa_clock.mins_h *10 + lisa_clock.mins_l;
542      seconds=lisa_clock.secs_h *10 + lisa_clock.secs_l;
543      tenths =lisa_clock.tenths;
544 
545   //   fflush(buglog);
546 
547      if (tenths > 9)  tenths  =  9;
548      if (seconds>59)  seconds = 59;
549      if (minutes>59)  minutes = 59;
550      if (hours  >23)  hours   = 23;
551      if (days  >365)  days    =365;
552 
553 
554      lisa_clock.year= (0x0f & years) | 0xe0;
555      if ((lisa_clock.year & 0x0f)<3) init_clock(); // prevent warning about clock by going to 1983.
556 
557      lisa_clock.days_l=                                days%10;  days /=10;
558      lisa_clock.days_h=                                days%10;  days /=10;
559      lisa_clock.days_h=((lisa_clock.days_h & 0x0f) |  (days<<4));
560 
561 
562      lisa_clock.hours_h=hours   /10; lisa_clock.hours_l=hours   %10;
563 
564      lisa_clock.mins_h =minutes /10; lisa_clock.mins_l =minutes %10;
565 
566      lisa_clock.secs_h =seconds /10; lisa_clock.secs_l =seconds %10;
567 
568      lisa_clock.tenths=tenths;
569 
570 
571     //   fflush(buglog);
572 
573 }
574 
normalize_lisa_set_clock(void)575 void normalize_lisa_set_clock(void)
576 {
577      int years, days, hours, minutes, seconds, tenths;
578 
579      years=lisa_clock.year & 0x0f;
580      days   =(((lisa_clock.days_h & 0xf0)>>4)*100+(lisa_clock.days_h & 0x0f)*10+lisa_clock.days_l);
581      hours  =lisa_clock.hours_h*10 + lisa_clock.hours_l;
582      minutes=lisa_clock.mins_h *10 + lisa_clock.mins_l;
583      seconds=lisa_clock.secs_h *10 + lisa_clock.secs_l;
584      tenths =lisa_clock.tenths;
585 
586      //fprintf(buglog,"normalizing_set clock\n"); fflush(buglog);
587 
588      // might just have to do a wrap around here instead?
589      if (years==0 && days==366 && hours==23 && minutes==59 && seconds==59 && tenths==9)
590      {
591          years=1; days=0; hours=23; minutes=59; seconds=59; tenths=9;
592          //fprintf(buglog,"hak done normalizing_set clock:: %d,%d %d:%d:%d.%d :: ",years,days,hours,minutes,seconds,tenths);
593      }
594      else
595      {
596          if (tenths > 9)  tenths  =  9;
597          if (seconds>59)  seconds = 59;
598          if (minutes>59)  minutes = 59;
599          if (hours  >23)  hours   = 23;
600          if (days  >365)  days    =365;
601          //fprintf(buglog,"done normalizing_set clock:: %d,%d %d:%d:%d.%d :: ",years,days,hours,minutes,seconds,tenths);
602      }
603 
604      //fprintf(buglog,"\n");
605 
606      lisa_clock.year= (0x0f & years) | 0xe0;
607      if ((lisa_clock.year & 0x0f)<3) init_clock(); // prevent warning about clock by going to 1983.
608 
609      lisa_clock.days_l=                                days%10;  days /=10;
610      lisa_clock.days_h=                                days%10;  days /=10;
611      lisa_clock.days_h=((lisa_clock.days_h & 0x0f) |  (days<<4));
612 
613      lisa_clock.hours_h=hours   /10; lisa_clock.hours_l=hours   %10;
614 
615      lisa_clock.mins_h =minutes /10; lisa_clock.mins_l =minutes %10;
616 
617      lisa_clock.secs_h =seconds /10; lisa_clock.secs_l =seconds %10;
618 
619      lisa_clock.tenths=tenths;
620 
621      //fprintf(buglog,"hex:: %02x %02x%x  %x%x:%x%x:%x%x.%x \n",lisa_clock.year, lisa_clock.days_h, lisa_clock.days_l,
622      //                                                          lisa_clock.hours_h,lisa_clock.hours_l,
623      //                                                          lisa_clock.mins_h,lisa_clock.mins_l,
624      //                                                          lisa_clock.secs_h,lisa_clock.secs_l,
625      //                                                          lisa_clock.tenths);
626      //
627      //  fflush(buglog);
628 }
629 
630 
631 /*-----------------4/29/98 11:14AM------------------
632  * These routines interface with the Lisa's VIA and
633  * are called by the Lisa emulated code.
634  * --------------------------------------------------*/
635 
init_clock(void)636 void init_clock(void)
637 {
638 	struct tm *timev;
639 	time_t clktime;
640 	uint8 dd_hun, dd_ten, dd_one;
641 	uint16 yday;
642 
643 		clktime=time(&clktime);
644 		timev=(struct tm *)localtime(&clktime);
645 
646 		yday=timev->tm_yday;
647      dd_hun=(uint8) (yday/100);
648      dd_ten=(uint8)((yday/10)%10);
649      dd_one=(uint8) (yday%10);
650 
651     // It hasn't yet been initialized, so do that.
652     if ((lisa_clock.year & 0xf0)!=0xe0)
653      {
654 //       ALERT_LOG(0,"date not set, setting now from system time.\n");
655        //tenth_sec_cycles =cpu68k_clocks+500000;
656        lisa_clock.year=   0xe7; //;|(timev->tm_year & 0x0f);
657        if (lisa_clock.year<0xe3) lisa_clock.year=0xe0|0x07;
658        lisa_clock.days_h= (dd_hun<<4) | dd_ten;
659 
660        lisa_clock.days_l= (dd_one);
661        lisa_clock.hours_h=(timev->tm_hour/10);
662 
663        lisa_clock.hours_l=(timev->tm_hour%10);
664        lisa_clock.mins_h= (timev->tm_min/10);
665 
666        lisa_clock.mins_l= (timev->tm_min%10);
667 
668        if (timev->tm_sec>59) timev->tm_sec=0;
669 
670        lisa_clock.secs_h= (timev->tm_sec/10);
671 
672        lisa_clock.secs_l= (timev->tm_sec % 10);
673        lisa_clock.tenths= 0;
674 
675        // hacks to do a test:
676        //lisa_clock.days_l=2;
677        //lisa_clock.days_h=0;
678        //lisa_clock.hours_l=11;
679        //lisa_clock.hours_h=0;
680      }
681 
682 }
683 
init_cops(void)684 void init_cops(void)
685 {
686     copsqueuelen = 0;
687     memset(copsqueue,0,MAXCOPSQUEUE);
688     lisa_clock.year = 0;         // flag to get real time from host OS on first Lisa timer request.
689     init_clock();
690 }
691 
692 /* send commands to the cops, or to other stuff on VIA1 - not simple shit */
via1_ora(uint8 data,uint8 regnum)693 void via1_ora(uint8 data,uint8 regnum)
694 {
695 
696 
697     VIA_CLEAR_IRQ_PORT_A(1); // clear CA1/CA2 on ORA/IRA access
698 
699     if (via[1].via[DDRA]==0) return;    // output is disabled, can't write.
700 
701     DEBUG_LOG(0,"SRC: SRC: COPS: command is is %02x regnum: %d CRDY line is %d",data,regnum,is_crdy_line());
702     set_crdy_line();
703     if ( data & 0x80) return;               // handle NOP's
704 
705     // added hack to fix issue when cops is in middle of mouse but lisa just sent a command
706     //20060607//copsqueuelen=0;
707     ///
708 
709 
710 	switch ( data) {
711         case 0x00 : cops_reset(); DEBUG_LOG(0,"cops reset 0 - PORT ON\n");
712                     return;   // turn off port - just ignore it (reset signal received)
713 
714         case 0x01 : cops_reset(); DEBUG_LOG(0,"cops reset 1 - PORT OFF cops turned off???\n");
715                     return;   // not sure if this is correct;
716 
717         case 0x02 :                               // read clock data
718 
719             if ( copsqueuelen+8>MAXCOPSQUEUE) {fprintf(buglog,"\n\n\n\n     COPS OVERFLOW! CAN'T SET DATE!\n\n\n"); }
720             if ( copsqueuelen+7<MAXCOPSQUEUE)  // if the queue isn't full that is...
721 			{
722               DEBUG_LOG(0,"getting clock.\n");
723 
724 
725 
726 
727               #ifdef DEBUG
728                 DEBUG_LOG(0,"cops.c - sent cops clock time-date to lisa:\n");
729                 DEBUG_LOG(0,"before normalize hex:: %02x %02x%x  %x%x:%x%x:%x%x.%x \n",lisa_clock.year, lisa_clock.days_h, lisa_clock.days_l,
730                                                                lisa_clock.hours_h,lisa_clock.hours_l,
731                                                                lisa_clock.mins_h,lisa_clock.mins_l,
732                                                                lisa_clock.secs_h,lisa_clock.secs_l,
733                                                                lisa_clock.tenths);
734 
735                 if (debug_log_enabled)
736                     printlisatime(buglog);  // this calls normalize_lisa_clock, if you comment this, add normalize_lisa_clock(); here
737 
738               #else
739                 normalize_lisa_clock();
740               #endif
741 
742                 SEND_COPS_CODE(0x80                                                 );   // COPS Reset Code
743                 SEND_COPS_CODE(((lisa_clock.year & 0x0f)|0xe0)                      );   // 0xeY  Y=0-15
744                 SEND_COPS_CODE(( lisa_clock.days_h  )                               );   // 0xdd  days
745                 SEND_COPS_CODE(( lisa_clock.days_l<<4) | (lisa_clock.hours_h)       );   // 0xdh  h=tens of hours
746                 SEND_COPS_CODE((uint8)((lisa_clock.hours_l<<4) | lisa_clock.mins_h) );   // 0xhm
747                 SEND_COPS_CODE((uint8)((lisa_clock.mins_l<<4)  | lisa_clock.secs_h) );   // 0xms
748                 SEND_COPS_CODE((uint8)((lisa_clock.secs_l<<4)  | lisa_clock.tenths) );   // 0xst t=tenths of sec, leave
749                                                                                          // empty unless OS can get
750                                                                                          // this for ya...
751                 DEBUG_LOG(0,"cops.c - done sending clock time-date normalizing_set::");
752                 DEBUG_LOG(0,"hex:: %02x %02x%x  %x%x:%x%x:%x%x.%x \n",lisa_clock.year, lisa_clock.days_h, lisa_clock.days_l,
753                                                                lisa_clock.hours_h,lisa_clock.hours_l,
754                                                                lisa_clock.mins_h,lisa_clock.mins_l,
755                                                                lisa_clock.secs_h,lisa_clock.secs_l,
756                                                                lisa_clock.tenths);
757 
758 
759                 return;
760 			}
761 
762            case 0x10:
763            case 0x11:
764            case 0x12:
765            case 0x13:
766            case 0x14:
767            case 0x15:
768            case 0x16:
769            case 0x17:
770            case 0x18:
771            case 0x19:
772            case 0x1a:
773            case 0x1b:
774            case 0x1c:
775            case 0x1d:
776            case 0x1e:
777            case 0x1f:             // 0001 xxxx  0001 nnnn - 0x1? write nnnn to clock
778                {                  // 8421 8421
779                 ALERT_LOG(0,"Writing %02x at position %d of LisaClockSet",data & 0x0f, lisa_clock_set_idx);
780 
781                 if (lisa_clock_set_idx<16)lisa_clock_set[lisa_clock_set_idx++]=data & 0x0f;
782                 #ifdef DEBUG
783                 else DEBUG_LOG(0,"attempt to write %02x to clock set failed because index is %d",data,lisa_clock_set_idx);
784                 #endif
785                 return;
786                }
787 
788 
789            case 0x20:
790            case 0x21:
791            case 0x22:
792            case 0x23:
793            case 0x24:
794            case 0x25:
795            case 0x26:
796            case 0x27:
797            case 0x28:
798            case 0x29:
799            case 0x2a:
800            case 0x2b:
801            case 0x2c:
802            case 0x2d:
803            case 0x2e:
804            case 0x2f:                          // 0010 spmm - 0x2? set clock modes
805             {//      8421                      // 8421 8421
806              /* 0010 spmm - 2x set clock modes: 00 -disable clock/timer, 01 - timer disable,
807               *              10=timer underflow generates irq, 11=timer underflow turns system on if off, else generates irq */
808               if ((data & 3) ==0) {lisa_clock_on=0; lisa_alarm=0;}  // disable clock/timer both stop alarm timer.
809               if ((data & 3) ==1) lisa_alarm=0;                     // disable timer only
810               lisa_alarm_power=(data & 7);
811               DEBUG_LOG(0,"copsclk:  %d ALARM:%d Alarm Power:%d",lisa_clock_on, lisa_alarm, lisa_alarm_power);
812               if (data & 8) {lisa_clock_set_idx=0; }         // entering setmode
813               //            spmm
814               //
815               //0x21 - 0010 0001 - 21==power off now and stay off. (timer off, clock on, power off)
816               //0x23 - 0010 0011 - 23==power cycle from Lisa ROM - have to enable this properly.
817 
818               // Check for poweroff command
819               if (((data & 8)==0) && lisa_alarm_power==1)           // timer is disabled, power=0, poweroff now
820                   LISA_POWEREDOFF(0);
821 
822               // timer based power cycle - should turn back on based on alarm
823               if (((data & 8)==0) && lisa_alarm_power==3)           LISA_POWEREDOFF(0);
824 
825               if (( (data & 8)==0) && lisa_alarm_power==3)          LISA_REBOOTED(0);
826 
827               //ALERT_LOG(0,"Data:%02x alarm:%02x\n",data,lisa_alarm_power);
828 
829 
830               if (((data & 8)==0) && lisa_clock_set_idx)            // exitting setmode ////////////////////////////////////////
831               {
832                char temp[1024]; //, temp2[1024];
833                lisa_alarm=0;
834                lisa_clock_on=1;
835 
836                //fprintf(buglog,"copsclk:");
837                switch(lisa_clock_set_idx-1)                         // don't want breaks here, we want it to fall through!!
838                   {   case  0xf: lisa_clock.tenths   = lisa_clock_set[0xf];  //fall through
839                       case  0xe: lisa_clock.secs_l   = lisa_clock_set[0xe];  //fall through
840                       case  0xd: lisa_clock.secs_h   = lisa_clock_set[0xd];  //fall through
841                       case  0xc: lisa_clock.mins_l   = lisa_clock_set[0xc];  //fall through
842                       case  0xb: lisa_clock.mins_h   = lisa_clock_set[0xb];  //fall through
843                       case  0xa: lisa_clock.hours_l  = lisa_clock_set[0xa];  //fall through
844                       case  0x9: lisa_clock.hours_h  = lisa_clock_set[0x9];  //fall through
845 
846                       case  0x8: lisa_clock.days_l   = lisa_clock_set[0x8];
847   //                               fprintf(buglog,"days_l=%02x ",lisa_clock.days_l);         //fall through
848 
849                       case  0x7: lisa_clock.days_h   =((lisa_clock_set[0x7]&0x0f)  | (lisa_clock.days_h & 0xf0));
850   //                               fprintf(buglog,"days_h=%02x ",lisa_clock.days_h);         //fall through
851 
852                       case  0x6: lisa_clock.days_h   =((lisa_clock_set[0x6]&0x0f)<<4) | (lisa_clock.days_h & 0x0f);
853   //                               fprintf(buglog,"days_h=%02x ",lisa_clock.days_h);         //fall through
854 
855                       case  0x5: lisa_clock.year     = (lisa_clock_set[0x5] & 0x0f)|0xe0;
856   //                               fprintf(buglog,"year=%02x ",lisa_clock.year);             //fall through
857                       case  0x4:                                                           //fall through
858                       case  0x3:                                                           //fall through
859                       case  0x2:                                                           //fall through
860                       case  0x1:                                                           //fall through
861                       case  0x0: lisa_alarm=0;
862                                  lisa_alarm=((lisa_clock_set[0x4]&0x0f)    )
863                                            |((lisa_clock_set[0x3]&0x0f)<< 4)
864                                            |((lisa_clock_set[0x2]&0x0f)<< 8)
865                                            |((lisa_clock_set[0x1]&0x0f)<<12)
866                                            |((lisa_clock_set[0x0]&0x0f)<<16);
867 
868 //                                  fprintf(buglog,"alarm=%02x \n",lisa_alarm);
869                   }
870 
871 
872 
873 //               fprintf(buglog,"copsclk: Clock set: buffer:%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x idx:%d",
874 //                                                  lisa_clock_set[ 0],
875 //                                                  lisa_clock_set[ 1],
876 //                                                  lisa_clock_set[ 2],
877 //                                                  lisa_clock_set[ 3],
878 //                                                  lisa_clock_set[ 4],     ////////////////
879 //                                                  lisa_clock_set[ 5],
880 //                                                  lisa_clock_set[ 6],
881 //                                                  lisa_clock_set[ 7],
882 //                                                  lisa_clock_set[ 8],
883 //                                                  lisa_clock_set[ 9],
884 //                                                  lisa_clock_set[10],
885 //                                                  lisa_clock_set[11],
886 //                                                  lisa_clock_set[12],
887 //                                                  lisa_clock_set[13],
888 //                                                  lisa_clock_set[14],
889 //                                                  lisa_clock_set[15],lisa_clock_set_idx);
890 
891                lisa_clock_set_idx=0;
892 
893                snprintf(temp,1024,"copsclk: Clock set:cpuclk:%llx year:%d days:%d, hours:%x%x,mins:%x%x, secs:%x%x, tenths:%x alarm:%1x%1x%1x%1x%1x",
894                     cpu68k_clocks,
895                     1980+(lisa_clock.year & 0x0f),
896 
897                     (lisa_clock.days_h & 0x0f)*10+(lisa_clock.days_h>>4)*100+lisa_clock.days_l,
898 
899                     lisa_clock.hours_h,lisa_clock.hours_l,
900                     lisa_clock.mins_h,lisa_clock.mins_l,
901                     lisa_clock.secs_h, lisa_clock.secs_l,
902                     lisa_clock.tenths,
903                     lisa_clock_set[0x0],lisa_clock_set[0x1],lisa_clock_set[0x2],lisa_clock_set[0x3],lisa_clock_set[0x4]);
904                //fprintf(buglog,temp);
905                DEBUG_LOG(0,temp);
906                DEBUG_LOG(0,temp);
907                //debug_on("clock set");
908 
909               //#ifdef DEBUG
910               //  fprintf(buglog,"cops.c - sent cops clock time-date to lisa:\n");
911               //  printlisatime(buglog);
912               //#endif
913 
914               normalize_lisa_set_clock();
915               }                                                     ////////////////////////////////////////////////////////////
916               return;
917             }
918 
919 
920         case 0x30:
921         case 0x31:
922         case 0x32:
923         case 0x33:
924         case 0x34:
925         case 0x35:
926         case 0x36:
927         case 0x37:
928         case 0x38:
929         case 0x39:
930         case 0x3a:
931         case 0x3b:
932         case 0x3c:
933         case 0x3d:
934         case 0x3e:
935         case 0x3f:  DEBUG_LOG(0,"SRC: 0x%2x Weird COPS command: set high keyboard LED's:%d%d%d%d",data, data & 8, data & 4, data & 2, data & 1);
936                     return;
937 
938         case 0x40:
939         case 0x41:
940         case 0x42:
941         case 0x43:
942         case 0x44:
943         case 0x45:
944         case 0x46:
945         case 0x47:
946         case 0x48:
947         case 0x49:
948         case 0x4a:
949         case 0x4b:
950         case 0x4c:
951         case 0x4d:
952         case 0x4e:
953         case 0x4f:  DEBUG_LOG(0,"SRC: 0x%2x Weird COPS command: set low keyboard LED's:%d%d%d%d",data, data & 8, data & 4, data & 2, data & 1);
954                     return;
955 
956 
957         case 0x50: // set high nibble of NMI key  // or disable NMI to nothing
958         case 0x51:
959         case 0x52:
960         case 0x53:
961         case 0x54:
962         case 0x55:
963         case 0x56:
964         case 0x57:
965         case 0x58:
966         case 0x59:
967         case 0x5a:
968         case 0x5b:
969         case 0x5c:
970         case 0x5d:
971         case 0x5e:
972         case 0x5f:   NMIKEY=(NMIKEY & 0x0f) | (data & 0x0f)<<4;
973                         DEBUG_LOG(0,"cops command - set nmi key high:%02x NMI key is now:%02x",data,NMIKEY);
974                         return;
975 
976 
977         case 0x60:                            // set low nibble of NMI key
978         case 0x61:
979         case 0x62:
980         case 0x63:
981         case 0x64:
982         case 0x65:
983         case 0x66:
984         case 0x67:
985         case 0x68:
986         case 0x69:
987         case 0x6a:
988         case 0x6b:
989         case 0x6c:
990         case 0x6d:
991         case 0x6e:
992         case 0x6f:  NMIKEY=(NMIKEY & 0xf0) | (data & 0x0f);
993                        DEBUG_LOG(0,"cops command - set nmi key low:%02x NMI key is now:%02x\n",data,NMIKEY);
994         return;
995 
996 
997                 // cops irq timing in miliseconds * 4.  i.e. 7c=4*4
998         case 0x70 :
999         case 0x71 :
1000         case 0x72 :
1001         case 0x73 :
1002         case 0x74 :
1003         case 0x75 :
1004         case 0x76 :
1005         case 0x77 :  DEBUG_LOG(0,"SRC: Mouse turned off %02x copsqueuelen:%d",data,copsqueuelen);
1006                      //fprintf(buglog,"COPS Timer: mouse turned off :%02x\n",data);
1007                      cops_mouse=0;
1008                      SET_COPS_NEXT_EVENT(0);
1009                      return; // turn mouse off
1010 
1011         case 0x78 :
1012         case 0x79 :
1013         case 0x7a :
1014         case 0x7b :
1015         case 0x7c :
1016         case 0x7d :
1017         case 0x7e :
1018         case 0x7f :  DEBUG_LOG(0,"SRC: Mouse turned on %02x",data);
1019                      //fprintf(buglog,"COPS Timer: mouse set to:%02x\n",data);
1020                      cops_mouse=(data & 7) * COPS_IRQ_TIMER_FACTOR;
1021                      SET_COPS_NEXT_EVENT(0);
1022                      return; // turn mouse on
1023 
1024         case 0x80:   // COPS NOP - just ignore'em
1025         case 0x81:
1026         case 0x82:
1027         case 0x83:
1028         case 0x84:
1029         case 0x85:
1030         case 0x86:
1031         case 0x87:
1032         case 0x88:
1033         case 0x89:
1034         case 0x8a:
1035         case 0x8b:
1036         case 0x8c:
1037         case 0x8d:
1038         case 0x8e:
1039         case 0x8f:  return;
1040 
1041 
1042         default:
1043            DEBUG_LOG(0,"COPS: unimplemented cops command %02x",data);
1044 
1045 	}
1046 
1047 
1048     // does the lisa actually use this? - maybe we can ignore it... maybe...
1049     DEBUG_LOG(0,"SRC: COPS::0x%x Set Timer mode... uncompleted emulator code.",data);
1050     return;
1051 }
1052 
1053 /* read data from cops queue  */
1054 
1055 
via1_ira(uint8 regnum)1056 uint8 via1_ira(uint8 regnum)
1057 {
1058 	uint8 data;
1059 	register int16 i;
1060     copsqueuefull=0;  // since the Lisa is reading the queue, assume it's alive,
1061                       // clear the copsqueuefull watchdog.
1062     DEBUG_LOG(0,"IRA1 copsqueuelen:%d, mousequeuelen:%d cops_mouse:%d",copsqueuelen,mousequeuelen,cops_mouse);
1063 
1064     #ifdef DEBUG
1065 
1066       if (debug_log_enabled)
1067       {  fprintf(buglog,"IRA1 COPS Queue:");
1068          for(i=0; i<MAXCOPSQUEUE; i++) fprintf(buglog,"%02x ",copsqueue[i]);
1069          fprintf(buglog,"\n");
1070       }
1071     #endif
1072 
1073     VIA_CLEAR_IRQ_PORT_A(1); // clear CA1/CA2 on ORA/IRA access
1074 
1075     // if there are no keystrokes pending, send mouse events.
1076     if ( copsqueuelen<=0)
1077     {
1078         DEBUG_LOG(0,"copsqueuelen=%d so sending mouse events.",copsqueuelen);
1079         copsqueuelen=0;
1080 
1081 
1082         DEBUG_LOG(0,"IRA1: since COPS queue<=0 (%d), will send mouse delta X,Y:[0x00],%d,%d",copsqueuelen,mouse_pending_x,mouse_pending_y);
1083 
1084         i=(uint8)(mouse_pending_x);   /* if (!i) {flipflopdx^=0xff;  i=flipflopdx;} */
1085         SEND_COPS_CODE(i);
1086 
1087         i=(uint8)(mouse_pending_y);
1088         SEND_COPS_CODE(i);
1089         DEBUG_LOG(0,"IRA1: added mouse dx,dy above %02x, %02x",mouse_pending_x,mouse_pending_y);
1090 
1091         mouse_pending_x=0;
1092         mouse_pending_y=0;
1093 
1094         DEBUG_LOG(0,"Sending mouse 00, x,y to follow.")
1095         return 0x00; // this one is 1st, then dx, then dy to indicate mouse motion data. ie: 00,dx,dy
1096 
1097     }
1098 
1099     data=copsqueue[0];
1100     DEBUG_LOG(0,"SRC: IRA1: COPS: read from regnum: %d returning %08x, %d bytes in cops queue left",regnum,data,copsqueuelen);
1101 
1102     for ( i=0; i<copsqueuelen; i++)  copsqueue[i]=copsqueue[i+1];
1103     copsqueuelen--; copsqueue[i]=0x00;
1104 //    ALERT_LOG(0,"returning %02x, %d bytes left.  %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,",data,copsqueuelen,
1105 //                copsqueue[0],copsqueue[1],copsqueue[2],copsqueue[3],
1106 //				copsqueue[4],copsqueue[5],copsqueue[6],copsqueue[7]);
1107 //    ALERT_LOG(0,".");
1108     return data;
1109 }
1110 
1111 
1112 
add_mouse_event(int16 x,int16 y,int8 button)1113 void add_mouse_event(int16 x, int16 y, int8 button)
1114 {
1115 
1116     if ( mousequeuelen+1>MAXMOUSEQUEUE) mousequeuelen=0;  // we overflowed, just dump the old ones 20060609 17:15
1117 
1118     if (!cops_mouse||contrast==0xff) return;
1119 
1120     if  (x<0||x>lisa_vid_size_x||y<0||y>lisa_vid_size_y) return;
1121 
1122 
1123     // if it's not a click, update the current one in the queue - if there is one.
1124     if ( !button && mousequeuelen && !mousequeue[mousequeuelen].button)
1125        {mousequeue[mousequeuelen].x=x; mousequeue[mousequeuelen].y=y; return;}
1126 
1127     // Otherwise add the event to the current one.
1128 
1129     mousequeuelen++; mousequeue[mousequeuelen].x=x; mousequeue[mousequeuelen].y=y; mousequeue[mousequeuelen].button=button;
1130 }
1131 
1132 
1133 static int mouse_seek_count=0;
1134 static int last_mouse_button_state=0;   // this is used to prevent repeated mouse up, mouse down events being sent.
1135                                         // sort of like a switch debounce
1136 
seek_mouse_event(void)1137 void seek_mouse_event(void)
1138 {
1139   uint16 ratx, raty; int16 dx, dy, i;
1140   int xabort_opcode=abort_opcode;
1141 
1142   if (floppy_6504_wait>0 && floppy_6504_wait<128) floppy_6504_wait--;
1143 
1144 
1145   if (mouse_seek_count) {mouse_seek_count--; return;}
1146 
1147   mouse_pending=0;
1148 
1149   if (!cops_mouse||contrast==0xff || !mousequeuelen)
1150         { DEBUG_LOG(0,"skipping seek_mouse_event because:%d,%d,%d\n",cops_mouse,contrast,mousequeuelen);
1151           return;}
1152 
1153 
1154 
1155   if (!is_lisa_mouse_on())
1156         {   DEBUG_LOG(0,"skipping because lisa isn't listening to the mouse");
1157             return;
1158         }
1159 
1160 
1161 
1162   abort_opcode=2;
1163   GET_RAT_XY(0);
1164 
1165   if ( abort_opcode==1)
1166   {
1167     DEBUG_LOG(0,"Got abort opcode while reading the mouse - this should never happen");
1168     debug_on("abort_opcode_reading_mouse");
1169     DEBUG_LOG(0,"Got abort opcode while reading the mouse");
1170     DEBUG_LOG(0,"Got abort opcode while reading the mouse");
1171     DEBUG_LOG(0,"abort_opcode while reading mouse");
1172     //exit(36);
1173   }
1174 
1175   dx=mousequeue[1].x-(int16)(ratx);
1176   dy=mousequeue[1].y-(int16)(raty);
1177   DEBUG_LOG(0,"ratx,y: %d,%d mousequeue:%d,%d dx,dy",ratx,raty,mousequeue[1].x,mousequeue[1].y,dx,dy);
1178 
1179 
1180   abort_opcode=xabort_opcode;
1181   if  (ratx>lisa_vid_size_x||raty>lisa_vid_size_y) {DEBUG_LOG(0,"ratx,raty out of range:%d,%d",ratx,raty); return;}
1182 
1183 
1184   // might want to paremetrise these.
1185   // anti-acceleration jitter
1186   //if      ((abs(dx)+abs(dy))<64 && !mouse_seek_count) mouse_seek_count=1;
1187   //else if ((abs(dx)+abs(dy))<32 && !mouse_seek_count) mouse_seek_count=2;
1188   //else if ((abs(dx)+abs(dy))<16 && !mouse_seek_count) mouse_seek_count=4;
1189   //else if ((abs(dx)+abs(dy))<8  && !mouse_seek_count) mouse_seek_count=16;
1190   //else if ((abs(dx)+abs(dy))<4  && !mouse_seek_count) mouse_seek_count=32;
1191   //else if ((abs(dx)+abs(dy))<2  && !mouse_seek_count) mouse_seek_count=64;
1192 
1193 
1194   for (i=0;  anti_jitter_sample_dec1[i] &&  ((abs(dx)+abs(dy))<anti_jitter_sample_dec1[i] && !mouse_seek_count);   i++ )
1195        mouse_seek_count=anti_jitter_sample_dec2[i];
1196 
1197 
1198   // do we need to move some more?  If so move, otherwise see if there has been a click, and send that.
1199   if ( (dx|dy) )
1200      {
1201 
1202       for (i=0; anti_jitter_decellerate_xt[i]; i++)
1203           if (abs(dx)<anti_jitter_decellerate_xt[i]) {dx=dx>>anti_jitter_decellerate_xn[i]; break;}
1204 
1205       for (i=0; anti_jitter_decellerate_yt[i]; i++)
1206           if (abs(dy)<anti_jitter_decellerate_yt[i]) {dy=dy>>anti_jitter_decellerate_yn[i]; break;}
1207 
1208 
1209       /*
1210             if (abs(dx)<8 ) dx=dx>>1;
1211        else if (abs(dx)<32) dx=dx>>2;
1212        else if (abs(dx)<64) dx=dx>>4;
1213 
1214 
1215             if (abs(dy)<8 ) dy=dy>>1;
1216        else if (abs(dy)<32) dy=dy>>2;
1217        else if (abs(dy)<64) dy=dy>>3;
1218 
1219       */
1220 
1221 
1222         bigm_delta(dx,dy);
1223         DEBUG_LOG(0,"mouse dx,dy is (%d,%d) non zero, won't send it yet - still moving.",dx,dy);
1224 
1225         // if the delta is small and we're in LisaTest mouseland, fall through and click, so it's off by
1226         // upto 8x8 pixels in any dir, so what!  Hack to LisaTest  - probably need a better test for this
1227 
1228         // mouse jitter here!  mousejitter
1229         //if (!(   abs(dx)<8 && abs(dy)<8 && lisa_os_mouse_x_ptr!=0x486 && lisa_os_mouse_x_ptr!=0xcc00f0 ))return;
1230         //if (!(   abs(dx)<8 && abs(dy)<8 && mousequeue[1].button && lisa_os_boot_mouse_x_ptr!=0x486  ))return;
1231 
1232         /*
1233         if ( (   abs(dx)>2 || abs(dy)>2) && mousequeue[1].button && !last_mouse_button_state)
1234                {
1235                 DEBUG_LOG(0,"Mouse is too far away for button press. (%d,%d)",dx,dy);
1236                 return;
1237                }
1238         */
1239      }
1240   //DEBUG_LOG(0,"mouse dx,dy is (%d,%d) button is %d so we might send it.",dx,dy,mousequeue[1].button);
1241 
1242 
1243 
1244   switch ( mousequeue[1].button)
1245   { case -1 : if (last_mouse_button_state!=0)
1246               {
1247                set_mouse_button(0); //DEBUG_LOG(0,"mouse button set to 0 (up)");   // mouse is now up
1248                last_mouse_button_state=0;
1249               }
1250               break;
1251     case +1 : if (last_mouse_button_state!=1)
1252               {
1253                 set_mouse_button(1); //DEBUG_LOG(0,"mouse button set 1 (down)");   // mouse is now down
1254                 last_mouse_button_state=1;
1255               }
1256 
1257     case  0 : break;
1258     default: EXIT(352,0,"Bug in mousequeue 1 button is %d",mousequeue[1].button);
1259   }
1260 
1261   // shift the mouse queue over
1262   if (mousequeuelen>1)
1263      {
1264         for ( i=0;i<mousequeuelen;i++)
1265          {  mousequeue[i].x      = mousequeue[i+1].x;
1266             mousequeue[i].y      = mousequeue[i+1].y;
1267             mousequeue[i].button = mousequeue[i+1].button;}
1268 
1269      mousequeuelen--; }  //2006.07.12 moved this inside of the if statement.
1270 
1271      //** the above worked, however, need to stop the jitter when it's close **
1272 }
1273 
1274 
1275 
1276 
set_loram_clk(void)1277 void set_loram_clk(void)
1278 {
1279 // $1BA-1BF : Clock setting (Ey,dd,dh,hm,ms,st)
1280    lisa_ram_safe_setbyte(1,0x1ba, (   0xe0)                        | (lisa_clock.year    &0x0f));
1281    lisa_ram_safe_setbyte(1,0x1bb, (((lisa_clock.days_h)&0xf0)    ) | (lisa_clock.days_h  &0x0f));
1282    lisa_ram_safe_setbyte(1,0x1bc, (((lisa_clock.days_l)&0x0f)<<4 ) | (lisa_clock.hours_h &0x0f));
1283    lisa_ram_safe_setbyte(1,0x1bd, (((lisa_clock.hours_l)&0x0f)<<4) | (lisa_clock.mins_h  &0x0f));
1284    lisa_ram_safe_setbyte(1,0x1be, (((lisa_clock.mins_l)&0x0f)<<4 ) | (lisa_clock.secs_h  &0x0f));
1285    lisa_ram_safe_setbyte(1,0x1bf, (((lisa_clock.secs_l)&0x0f)<<4 ) | (lisa_clock.tenths  &0x0f));
1286 
1287 
1288 
1289 
1290 }
1291 
1292 
1293 
1294 // "Devastation is on the way" - In memory of Dimebag Darrell 2004.12.08
1295