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