1  /*
2   * UAE - The Un*x Amiga Emulator
3   *
4   * DOS handlers.
5   *
6   * (c) 1997 Gustavo Goedert
7   *
8   * Led routines by Michael Sontheimer
9   */
10 
11 #include "sysconfig.h"
12 #include "sysdeps.h"
13 
14 #include <dos.h>
15 #include <go32.h>
16 #include <dpmi.h>
17 #include <sys/farptr.h>
18 
19 #include "config.h"
20 #include "options.h"
21 #include "threaddep/thread.h"
22 #include "memory.h"
23 #include "custom.h"
24 #include "readcpu.h"
25 #include "newcpu.h"
26 #include "keyboard.h"
27 #include "xwin.h"
28 #include "keybuf.h"
29 #include "disk.h"
30 #include "gui.h"
31 #include "tui.h"
32 #include "uae.h"
33 #include "picasso96.h"
34 #include "misc/handlers.h"
35 #include "misc/misc.h"
36 
37 /* dummie Amiga Keys */
38 #define AK_Options	0x1fc
39 #define AK_SaveScreen1  0x1fd
40 #define AK_SaveScreen2  0x1fe
41 #define AK_TougleScreen 0x1ff
42 
43 /* Event Flags */
44 #define EF_ResetCPU       0x01
45 #define EF_ChangeOptions  0x02
46 #define EF_EnterDebug     0x04
47 #define EF_SaveScreen     0x08
48 #define EF_TougleScreen   0x10
49 #define EF_TougleSound    0x20
50 #define EF_TougleCapsLock 0x40
51 #define EF_QuitProgram    0x80
52 
53 extern int kpb_first, kpb_last;
54 extern int keybuf[256];
55 
56 int Original_produce_sound;
57 int KeyBoardInstalled = 0, MouseInstalled = 0;
58 int EventFlags = 0;
59 int KeyState[512];
60 int buttonstate[3] = {0, 0, 0};
61 int lastmx, lastmy;
62 int newmousecounters = 0;
63 _go32_dpmi_seginfo OldKeyboardHandler, NewKeyboardHandler, NewMouseHandler;
64 _go32_dpmi_registers MouseCallbackRegs;
65 volatile int NumLockState = -1, CapsLockState = -1, ScrollLockState = -1;
66 UBYTE SavedLEDa;
67 
68 int AmigaKeys[128] = {
69     -1,             AK_ESC,        AK_1,           AK_2,           AK_3,      AK_4,     AK_5,            AK_6,
70     AK_7,           AK_8,          AK_9,           AK_0,           AK_MINUS,  AK_EQUAL, AK_BS,           AK_TAB,
71     AK_Q,           AK_W,          AK_E,           AK_R,           AK_T,      AK_Y,     AK_U,            AK_I,
72     AK_O,           AK_P,          AK_LBRACKET,    AK_RBRACKET,    AK_RET,    AK_CTRL,  AK_A,            AK_S,
73     AK_D,           AK_F,          AK_G,           AK_H,           AK_J,      AK_K,     AK_L,            AK_SEMICOLON,
74     AK_QUOTE,       AK_NUMBERSIGN, AK_LSH,         AK_LTGT,        AK_Z,      AK_X,     AK_C,            AK_V,
75     AK_B,           AK_N,          AK_M,           AK_COMMA,       AK_PERIOD, AK_SLASH, AK_RSH,          -1,
76     AK_LALT,        AK_SPC,        AK_CAPSLOCK,    AK_F1,          AK_F2,     AK_F3,    AK_F4,           AK_F5,
77     AK_F6,          AK_F7,         AK_F8,          AK_F9,          AK_F10,    -1,       AK_TougleScreen, AK_NP7,
78     AK_NP8,         AK_NP9,        -1,             AK_NP4,         AK_NP5,    AK_NP6,   -1,              AK_NP1,
79     AK_NP2,         AK_NP3,        AK_NP0,         -1,             -1,        -1,       -1,              AK_BACKSLASH,
80     -1, 	    -1,            -1,             -1,             -1,        -1,       -1,              -1,
81     -1,             AK_RCTRL,      AK_SaveScreen1, AK_SaveScreen2, AK_RALT,   -1,       AK_Options,	 AK_UP,
82     AK_RAMI,        AK_LF,         AK_RT,          -1,   	   AK_DN,     AK_LAMI,  AK_HELP,         AK_DEL,
83     -1,             -1,            -1,             -1,             -1,        -1,       -1,              -1,
84     -1,             -1,            -1,             -1,             -1,        AK_LAMI,  AK_RAMI,         -1
85 };
86 
87 unsigned char EscapeKeys[128] = {
88     0,   0,   0,   0,   0,   0,   0,   0,
89     0,   0,   0,   0,   0,   0,   0,   0,
90     0,   0,   0,   0,   0,   0,   0,   0,
91     0,   0,   0,   0,   96,  97,  0,   0,
92     0,   0,   0,   0,   0,   0,   0,   0,
93     0,   0,   98,  0,   0,   0,   0,   0,
94     0,   0,   0,   0,   0,   0,   0,   99,
95     100, 0,   0,   0,   0,   0,   0,   0,
96     0,   0,   0,   0,   0,   0,   0,   102,
97     103, 104, 0,   105, 0,   106, 0,   107,
98     108, 109, 110, 111, 0,   0,   0,   0,
99     0,   0,   0,   125, 126, 127, 0,   0,
100     0,   0,   0,   0,   0,   0,   0,   0,
101     0,   0,   0,   0,   0,   0,   0,   0,
102     0,   0,   0,   0,   0,   0,   0,   0,
103     0,   0,   0,   0,   0,   0,   0,   0,
104 };
105 
InstallHandlers(void)106 int InstallHandlers(void) {
107     if (!KeyBoardInstalled)
108 	if (!InstallKeyboardHandler())
109 	    return(0);
110     if (!MouseInstalled)
111 	if (!InstallMouseHandler())
112 	    return(0);
113     SavedLEDa = InitLED();
114     return(1);
115 }
116 
UninstallHandlers(void)117 void UninstallHandlers(void) {
118     if (KeyBoardInstalled)
119 	UninstallKeyboardHandler();
120     if (MouseInstalled)
121 	UninstallMouseHandler();
122     RestoreLEDStatus(SavedLEDa);
123 }
124 
handle_events(void)125 void handle_events(void) {
126     if (EventFlags) {
127 	if (EventFlags & EF_ResetCPU) {
128 	    m68k_reset();
129 	    EventFlags &= ~EF_ResetCPU;
130 	}
131 	if (EventFlags & EF_ChangeOptions) {
132 	    HandleOptions();
133 	    KeyState[AK_Options] = 0;
134 	    KeyState[AK_F1] = 0;
135 	    record_key ((AK_F1 << 1) | 1);
136 	    EventFlags &= ~EF_ChangeOptions;
137 	}
138 	if (EventFlags & EF_EnterDebug) {
139 	    EnterDebug();
140 	    EventFlags &= ~EF_EnterDebug;
141 	}
142 	if (EventFlags & EF_SaveScreen) {
143 	    SaveScreen();
144 	    EventFlags &= ~EF_SaveScreen;
145 	}
146 	if (EventFlags & EF_TougleScreen) {
147 	    inhibit_frame ^= 1;
148 	    EventFlags &= ~EF_TougleScreen;
149 	}
150 	if (EventFlags & EF_TougleSound) {
151 	    if (currprefs.produce_sound == 0)
152 		currprefs.produce_sound = Original_produce_sound;
153 	    else
154 		currprefs.produce_sound = 0;
155 	    EventFlags &= ~EF_TougleSound;
156 	}
157 	if (EventFlags & EF_TougleCapsLock) {
158 	    CapsLockLED(!CapsLockState);
159 	    EventFlags &= ~EF_TougleCapsLock;
160 	}
161 	if (EventFlags & EF_QuitProgram) {
162 	    regs.spcflags |= SPCFLAG_BRK;
163 	    quit_program = 1;
164 	    EventFlags &= ~EF_QuitProgram;
165 	}
166     }
167 #ifdef PICASSO96
168     PicassoRefresh();
169 #endif
170 }
171 
KeyboardHandler(void)172 static void KeyboardHandler(void) {
173     static int IsEscape = 0, CapsLockCanChange = 1;
174     int ScanCode, NewState, AmigaKey;
175 
176     ScanCode = inportb(0x60);
177 
178     if (ScanCode == 0xe0) {
179 	IsEscape = 1;
180 	outportb(0x20, 0x20);
181 	return;
182     }
183 
184     /* PAUSE Key */
185     if (IsEscape > 1) {
186 	IsEscape++;
187 	if (IsEscape == 7) {
188 	    EventFlags |= EF_TougleSound;
189 	    IsEscape = 0;
190 	}
191 	outportb(0x20, 0x20);
192 	return;
193     }
194     if (ScanCode == 0xe1) {
195 	IsEscape = 2;
196 	outportb(0x20, 0x20);
197 	return;
198     }
199 
200     NewState = !(ScanCode & 0x80);
201     ScanCode = ScanCode & 0x7f;
202     if (IsEscape) {
203 	ScanCode = EscapeKeys[ScanCode];
204 	IsEscape = 0;
205     }
206     outportb(0x20, 0x20);
207 
208     AmigaKey = AmigaKeys[ScanCode];
209 
210     if (AmigaKey == -1)
211 	return;
212 
213     if (AmigaKey == AK_CAPSLOCK) {
214 	if (NewState) {
215 	    if (CapsLockCanChange) {
216 		NewState = !KeyState[AmigaKey];
217 		CapsLockCanChange = 0;
218 	    } else
219 	       return;
220 	} else {
221 	    CapsLockCanChange = 1;
222 	    return;
223 	}
224 	EventFlags |= EF_TougleCapsLock;
225     }
226 
227     if (KeyState[AmigaKey] == NewState)
228 	return;
229     KeyState[AmigaKey] = NewState;
230 
231     if (AmigaKey < AK_Options) {
232 	if (NewState)
233 	    record_key (AmigaKey << 1);
234 	else
235 	    record_key ((AmigaKey << 1) | 1);
236     }
237 
238     if ((KeyState[AK_CTRL] && KeyState[AK_LAMI] && KeyState[AK_RAMI]) ||
239 	(KeyState[AK_RCTRL] && KeyState[AK_LAMI] && KeyState[AK_RAMI]))
240 	EventFlags |= EF_ResetCPU;
241     if (KeyState[AK_Options]) {
242 	if (KeyState[AK_ESC])
243 	    EventFlags |= EF_QuitProgram;
244 	if (KeyState[AK_F1])
245 	    EventFlags |= EF_ChangeOptions;
246 	if (KeyState[AK_F2])
247 	    EventFlags |= EF_EnterDebug;
248     }
249     if (KeyState[AK_TougleScreen])
250 	EventFlags |= EF_TougleScreen;
251     if (KeyState[AK_SaveScreen1] && KeyState[AK_SaveScreen2])
252 	EventFlags |= EF_SaveScreen;
253 }
254 
InstallKeyboardHandler(void)255 int InstallKeyboardHandler(void) {
256     int i;
257 
258     if (KeyBoardInstalled)
259 	return(1);
260     _go32_dpmi_get_protected_mode_interrupt_vector(9, &OldKeyboardHandler);
261     NewKeyboardHandler.pm_offset = (int)KeyboardHandler;
262     if (_go32_dpmi_allocate_iret_wrapper(&NewKeyboardHandler) != 0) {
263 	printf ("Can't allocate keyboard iret_wrapper.\n");
264 	return(0);
265     }
266     if (_go32_dpmi_set_protected_mode_interrupt_vector(9, &NewKeyboardHandler) != 0) {
267 	printf ("Can't set protected mode interrupt vector.\n");
268 	return(0);
269     }
270     for(i = 0; i < 256; i++)
271 	KeyState[i] = 0;
272     _go32_dpmi_lock_code(KeyboardHandler, (unsigned int)InstallKeyboardHandler-(unsigned int)KeyboardHandler);
273     _go32_dpmi_lock_data(AmigaKeys, sizeof(AmigaKeys));
274     _go32_dpmi_lock_data(EscapeKeys, sizeof(EscapeKeys));
275     _go32_dpmi_lock_data(KeyState, sizeof(KeyState));
276     _go32_dpmi_lock_data(&EventFlags, sizeof(EventFlags));
277     _go32_dpmi_lock_data(&OldKeyboardHandler, sizeof(OldKeyboardHandler));
278     _go32_dpmi_lock_data(&NewKeyboardHandler, sizeof(NewKeyboardHandler));
279     _go32_dpmi_lock_code(record_key, (unsigned int)keybuf_init-(unsigned int)record_key);
280     _go32_dpmi_lock_data(&kpb_first, sizeof(kpb_first));
281     _go32_dpmi_lock_data(&kpb_last, sizeof(kpb_last));
282     _go32_dpmi_lock_data(keybuf, sizeof(keybuf));
283     KeyBoardInstalled = 1;
284     return(1);
285 }
286 
UninstallKeyboardHandler(void)287 void UninstallKeyboardHandler(void) {
288     if (!KeyBoardInstalled)
289 	return;
290     _go32_dpmi_set_protected_mode_interrupt_vector(9, &OldKeyboardHandler);
291     _go32_dpmi_free_iret_wrapper(&NewKeyboardHandler);
292     KeyBoardInstalled = 0;
293 }
294 
MouseHandler(_go32_dpmi_registers * MouseRegs)295 static void MouseHandler(_go32_dpmi_registers *MouseRegs) {
296     lastmx = (short)MouseRegs->x.si;
297     lastmy = (short)MouseRegs->x.di;
298     buttonstate[0] = MouseRegs->x.bx & 1;
299     buttonstate[1] = MouseRegs->x.bx & 4;
300     buttonstate[2] = MouseRegs->x.bx & 2;
301 }
302 
InstallMouseHandler(void)303 int InstallMouseHandler(void) {
304     _go32_dpmi_registers IntRegs;
305 
306     if (MouseInstalled)
307 	return(1);
308     IntRegs.x.ax = 0;
309     IntRegs.x.ss = IntRegs.x.sp = IntRegs.x.flags = 0;
310     _go32_dpmi_simulate_int(0x33, &IntRegs);
311     if (IntRegs.x.ax==0) {
312 	printf ("Mouse driver not present.\n");
313 	return(0);
314     }
315     NewMouseHandler.pm_offset = (int)MouseHandler;
316     if (_go32_dpmi_allocate_real_mode_callback_retf(&NewMouseHandler, &MouseCallbackRegs) != 0) {
317 	printf ("Can't allocate mouse callback_retf.\n");
318 	return(0);
319     }
320     IntRegs.x.ax = 0xc;
321     IntRegs.x.cx = 0x7f;
322     IntRegs.x.es = NewMouseHandler.rm_segment;
323     IntRegs.x.dx = NewMouseHandler.rm_offset;
324     IntRegs.x.ss = IntRegs.x.sp = IntRegs.x.flags = 0;
325     buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
326     lastmx = lastmy = 0;
327     newmousecounters = 0;
328     _go32_dpmi_simulate_int(0x33, &IntRegs);
329     _go32_dpmi_lock_code(MouseHandler, (unsigned int)InstallMouseHandler-(unsigned int)MouseHandler);
330     _go32_dpmi_lock_data(&lastmx, sizeof(lastmx));
331     _go32_dpmi_lock_data(&lastmy, sizeof(lastmy));
332     _go32_dpmi_lock_data(buttonstate, sizeof(buttonstate));
333     _go32_dpmi_lock_data(&NewMouseHandler, sizeof(NewMouseHandler));
334     _go32_dpmi_lock_data(&MouseCallbackRegs, sizeof(MouseCallbackRegs));
335     MouseInstalled = 1;
336     return(1);
337 }
338 
UninstallMouseHandler(void)339 void UninstallMouseHandler(void) {
340     _go32_dpmi_registers IntRegs;
341 
342     if (!MouseInstalled)
343 	return;
344     IntRegs.x.ax = 0xc;
345     IntRegs.x.cx = 0x0;
346     IntRegs.x.ss = IntRegs.x.sp = IntRegs.x.flags = 0;
347     _go32_dpmi_simulate_int(0x33, &IntRegs);
348     _go32_dpmi_free_real_mode_callback(&NewMouseHandler);
349     MouseInstalled = 0;
350 }
351 
352 
LED(int on)353 void LED(int on) {
354 
355     ScrollLockLED(!on);
356 
357 }
358 
NumLockLED(int on)359 void NumLockLED(int on) {
360 
361     _go32_dpmi_registers regs;
362 
363     if( NumLockState != on )     // Avoid more int's than necessary
364     {
365 	if( on )
366 	    _farnspokeb( (0x40<<4)+0x17, _farnspeekb( (0x40<<4)+0x17 ) | 32 );
367 	else
368 	    _farnspokeb( (0x40<<4)+0x17, _farnspeekb( (0x40<<4)+0x17 ) & ~32 );
369 
370 	regs.x.ax = 0x0100;
371 	regs.x.ss=regs.x.sp=regs.x.flags=0;
372 	_go32_dpmi_simulate_int(0x16, &regs);
373 
374 	NumLockState = on;
375     }
376 
377 }
378 
CapsLockLED(int on)379 void CapsLockLED(int on) {
380 
381     _go32_dpmi_registers regs;
382 
383     if( CapsLockState != on )     // Avoid more int's than necessary
384     {
385 	if( on )
386 	    _farnspokeb( (0x40<<4)+0x17, _farnspeekb( (0x40<<4)+0x17 ) | 64 );
387 	else
388 	    _farnspokeb( (0x40<<4)+0x17, _farnspeekb( (0x40<<4)+0x17 ) & ~64 );
389 
390 	regs.x.ax = 0x0100;
391 	regs.x.ss=regs.x.sp=regs.x.flags=0;
392 	_go32_dpmi_simulate_int(0x16, &regs);
393 
394 	CapsLockState = on;
395     }
396 
397 }
398 
ScrollLockLED(int on)399 void ScrollLockLED(int on) {
400 
401     _go32_dpmi_registers regs;
402 
403     if( ScrollLockState != on )     // Avoid more int's than necessary
404     {
405 	if( on )
406 	    _farnspokeb( (0x40<<4)+0x17, _farnspeekb( (0x40<<4)+0x17 ) | 16 );
407 	else
408 	    _farnspokeb( (0x40<<4)+0x17, _farnspeekb( (0x40<<4)+0x17 ) & ~16 );
409 
410 	regs.x.ax = 0x0100;
411 	regs.x.ss=regs.x.sp=regs.x.flags=0;
412 	_go32_dpmi_simulate_int(0x16, &regs);
413 
414 	ScrollLockState = on;
415     }
416 
417 }
418 
InitLED(void)419 UBYTE InitLED(void) {
420 
421     UBYTE ubSavedLED;
422 
423     ubSavedLED = _farnspeekb( (0x40<<4)+0x17 );    // Save LED-status
424 
425     NumLockLED(0);
426     CapsLockLED(0);
427     ScrollLockLED(0);
428 
429     return(ubSavedLED);
430 
431 }
432 
RestoreLEDStatus(UBYTE ubSavedLED)433 void RestoreLEDStatus(UBYTE ubSavedLED) {
434 
435     _go32_dpmi_registers regs;
436 
437     _farnspokeb( (0x40<<4)+0x17, ubSavedLED );
438 
439     regs.x.ax = 0x0100;
440     regs.x.ss=regs.x.sp=regs.x.flags=0;
441     _go32_dpmi_simulate_int(0x16, &regs);
442 
443 }
444