Xemu [doxygen]  hyppo 0a42be3a057156924bc1b626a687bd6e27349c45 @ Sat 19 Mar 02:15:11 CET 2022
input_devices.c
Go to the documentation of this file.
1 /* Minimalistic Enterprise-128 emulator with focus on "exotic" hardware
2  Part of the Xemu project, please visit: https://github.com/lgblgblgb/xemu
3  Copyright (C)2015-2016,2020 LGB (Gábor Lénárt) <lgblgblgb@gmail.com>
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18 
19 #include "xemu/emutools.h"
20 #include "xemu/emutools_hid.h"
21 #include "enterprise128.h"
22 #include "dave.h"
23 #include "ui.h"
24 
25 #include "input_devices.h"
26 
27 static int move_dx, move_dy, nibble_counter;
28 int mouse_grab = 0;
29 static int wheel_dx, wheel_dy;
30 static Uint8 nibble;
31 static int mouse_button1, mouse_button2;
32 static int rts_old_level = -1;
33 static int mouse_pulse = 0;
34 //static int _mouse_wait_warn = 1;
35 extern Uint32 raster_time; // we use Nick's raster_time "timing source" because it's kinda free without introducing another timer source
36 static Uint32 watchdog_mouse; // watchdog value (raster_time related) used by the mouse nibble-reset protocol
37 static Uint32 watchdog_xep128; // watchdog value (raster_time related) used by Xep128 to decide between joy-1 and j-column mouse
38 
39 int show_keys = 0;
40 static int control_port_emu_mode = -1;
41 
42 const struct KeyMappingDefault ep128_key_map[] = {
43  { SDL_SCANCODE_1, 0x31, "1" },
44  { SDL_SCANCODE_2, 0x36, "2" },
45  { SDL_SCANCODE_3, 0x35, "3" },
46  { SDL_SCANCODE_4, 0x33, "4" },
47  { SDL_SCANCODE_5, 0x34, "5" },
48  { SDL_SCANCODE_6, 0x32, "6" },
49  { SDL_SCANCODE_7, 0x30, "7" },
50  { SDL_SCANCODE_8, 0x50, "8" },
51  { SDL_SCANCODE_9, 0x52, "9" },
52  { SDL_SCANCODE_0, 0x54, "0" },
53  { SDL_SCANCODE_Q, 0x21, "Q" },
54  { SDL_SCANCODE_W, 0x26, "W" },
55  { SDL_SCANCODE_E, 0x25, "E" },
56  { SDL_SCANCODE_R, 0x23, "R" },
57  { SDL_SCANCODE_T, 0x24, "T" },
58  { SDL_SCANCODE_Y, 0x22, "Y" },
59  { SDL_SCANCODE_U, 0x20, "U" },
60  { SDL_SCANCODE_I, 0x90, "I" },
61  { SDL_SCANCODE_O, 0x92, "O" },
62  { SDL_SCANCODE_P, 0x94, "P" },
63  { SDL_SCANCODE_A, 0x16, "A" },
64  { SDL_SCANCODE_S, 0x15, "S" },
65  { SDL_SCANCODE_D, 0x13, "D" },
66  { SDL_SCANCODE_F, 0x14, "F" },
67  { SDL_SCANCODE_G, 0x12, "G" },
68  { SDL_SCANCODE_H, 0x10, "H" },
69  { SDL_SCANCODE_J, 0x60, "J" },
70  { SDL_SCANCODE_K, 0x62, "K" },
71  { SDL_SCANCODE_L, 0x64, "L" },
72  { SDL_SCANCODE_RETURN, 0x76, "ENTER" },
73  { SDL_SCANCODE_LSHIFT, 0x07, "L-SHIFT" },
74  { SDL_SCANCODE_RSHIFT, 0x85, "R-SHIFT" },
75  { SDL_SCANCODE_CAPSLOCK, 0x11, "CAPS" },
76  { SDL_SCANCODE_Z, 0x06, "Z" },
77  { SDL_SCANCODE_X, 0x05, "X" },
78  { SDL_SCANCODE_C, 0x03, "C" },
79  { SDL_SCANCODE_V, 0x04, "V" },
80  { SDL_SCANCODE_B, 0x02, "B" },
81  { SDL_SCANCODE_N, 0x00, "N" },
82  { SDL_SCANCODE_M, 0x80, "M" },
83  { SDL_SCANCODE_LCTRL, 0x17, "CTRL" },
84  { SDL_SCANCODE_SPACE, 0x86, "SPACE" },
85  { SDL_SCANCODE_SEMICOLON, 0x63, ";" },
86  { SDL_SCANCODE_LEFTBRACKET, 0x95, "[" },
87  { SDL_SCANCODE_RIGHTBRACKET, 0x66, "]" },
88  { SDL_SCANCODE_APOSTROPHE, 0x65, ":" }, // for EP : we map PC '
89  { SDL_SCANCODE_MINUS, 0x53, "-" },
90  { SDL_SCANCODE_BACKSLASH, 0x01, "\\" },
91  { SDL_SCANCODE_TAB, 0x27, "TAB" },
92  { SDL_SCANCODE_ESCAPE, 0x37, "ESC" },
93  { SDL_SCANCODE_INSERT, 0x87, "INS" },
94  { SDL_SCANCODE_BACKSPACE, 0x56, "ERASE" },
95  { SDL_SCANCODE_DELETE, 0x81, "DEL" },
96  { SDL_SCANCODE_LEFT, 0x75, "LEFT" },
97  { SDL_SCANCODE_RIGHT, 0x72, "RIGHT" },
98  { SDL_SCANCODE_UP, 0x73, "UP" },
99  { SDL_SCANCODE_DOWN, 0x71, "DOWN" },
100  { SDL_SCANCODE_SLASH, 0x83, "/" },
101  { SDL_SCANCODE_PERIOD, 0x84, "." },
102  { SDL_SCANCODE_COMMA, 0x82, "," },
103  { SDL_SCANCODE_EQUALS, 0x93, "@" }, // for EP @ we map PC =
104  { SDL_SCANCODE_F1, 0x47, "F1" },
105  { SDL_SCANCODE_F2, 0x46, "F2" },
106  { SDL_SCANCODE_F3, 0x42, "F3" },
107  { SDL_SCANCODE_F4, 0x40, "F4" },
108  { SDL_SCANCODE_F5, 0x44, "F5" },
109  { SDL_SCANCODE_F6, 0x43, "F6" },
110  { SDL_SCANCODE_F7, 0x45, "F7" },
111  { SDL_SCANCODE_F8, 0x41, "F8" },
112 // { SDL_SCANCODE_F9, 0x77, "F9" },
113  { SDL_SCANCODE_HOME, 0x74, "HOLD" }, // for EP HOLD we map PC HOME
114  { SDL_SCANCODE_END, 0x70, "STOP" }, // for EP STOP we map PC END
115  /* ---- Not real EP kbd matrix, used for extjoy emulation with numeric keypad ---- */
116  { SDL_SCANCODE_KP_5, 0xA0, "ExtJoy FIRE" }, // for EP external joy FIRE we map PC num keypad 5
117  { SDL_SCANCODE_KP_8, 0xA1, "ExtJoy UP" }, // for EP external joy UP we map PC num keypad 8
118  { SDL_SCANCODE_KP_2, 0xA2, "ExtJoy DOWN" }, // for EP external joy DOWN we map PC num keypad 2
119  { SDL_SCANCODE_KP_4, 0xA3, "ExtJoy LEFT" }, // for EP external joy LEFT we map PC num keypad 4
120  { SDL_SCANCODE_KP_6, 0xA4, "ExtJoy RIGHT" }, // for EP external joy RIGHT we map PC num keypad 6
121  /* ---- emu related "SYS" keys (like screenshot, exit, fullscreen ...) position codes are the identifier for the caller! Must be values, not used otherwise by the emulated computer! */
122 // { SDL_SCANCODE_F11, 0xFF, "EMU fullscreen" }, // ... on EP the lower nibble is the mask shift, so values X8-XF are not used!
123 // { SDL_SCANCODE_F9, 0xFE, "EMU exit" },
124 // { SDL_SCANCODE_F10, 0xFD, "EMU screenshot" },
125 // { SDL_SCANCODE_PAUSE, 0xFC, "EMU reset" },
126 // { SDL_SCANCODE_PAGEDOWN, 0xFB, "EMU slower-cpu" },
127 // { SDL_SCANCODE_PAGEUP, 0xFA, "EMU faster-cpu" },
128 // { SDL_SCANCODE_GRAVE, 0xF9, "EMU osd-replay" },
129 // { SDL_SCANCODE_KP_MINUS, 0xF8, "EMU console" },
130  /* ---- */
132  /* ---- end of table marker, must be the last entry ---- */
133  { 0, -1, NULL }
134 };
135 
136 /* The mouse buffer. nibble_counter shows which nibble is to read (thus "nibble_counter >> 1" is the byte pointer actually.
137  mouse_protocol_nibbles limits the max nibbles to read, ie it's 4 (= 2 bytes) for boxsoft protocol for the default setting */
138 static Uint8 mouse_buffer[] = {
139  0x00, // BOXSOFT: delta X as signed, positive-left, updated from mouse_dx
140  0x00, // BOXSOFT: delta Y as signed, positive-up, updates from mouse_dy
141  0x10, // EXTENDED MSX: proto ID + extra buttons on lower nibble (I update those - lower nibble - on mouse SDL events)
142  0x00, // EXTENDED MSX: horizontal wheel (it's splitted for horizontal/Z, but according to entermice it's handled as a 8 bit singed now for a single wheel, so I do this as well)
143  0x44, // ENTERMICE: extra bytes to read (incl this: 4 now) + PS/2 Mouse ID [it's 4 now ...]
144  0x14, // ENTERMICE: hardware version major.minor
145  0x19, // ENTERMICE: firmware version major.minor
146  0x5D // ENTERMICE: Device ID, should be 5D for Entermice
147 };
148 
149 #define WATCHDOG_USEC(n) (n / 64)
150 
151 /* Values can be used in mouse modes, buttons[] array to map PC mouse buttons to EP related mouse buttons
152  The first two are mapped then according to the button*_mask of the mode struct.
153  The EX buttons instructs setting the button status in mouse buffer directly at byte 3, lower nibble
154 */
155 #define BUTTON_MAIN 1
156 #define BUTTON_OTHER 2
157 #define BUTTON_EX3 3
158 #define BUTTON_EX4 4
159 #define BUTTON_EX5 5
160 
161 /* Values can be used in *_mask options in mouse modes struct */
162 #define J_COLUMN 1
163 #define K_COLUMN 2
164 
166  const char *name; // some name for the given mouse protocol/mode ...
167  int buttons[5]; // button map: indexed by emulator given PC left/middle/right/x1/x2 (in this order), with values of the BUTTON_* macros above to map to protcol values
168  int nibbles; // nibbles in the protocol (before the constant zero answer or warping around if warp is non-zero)
169  int wrap; // wraps around nibble counter automatically or not (not = constant zero nibble answer, watchdog can only reset the counter)
170  int watchdog; // watchdog time-out, or -1, for not using watchdog, times are Xep128 specific use the WATCHDOG_USEC macro to convert from usec!
171  int data_mask; // bit mask for mouse data read (J/K/L = 1 / 2 / 4), you can use *_COLUMN macros
172 };
173 
174 /* Definition of mouse modes follows :) */
175 static const struct mouse_modes_st mouse_modes[] = {
176  { // MODE - 0: NOT USED POSITION
177  }, { // MODE - 1:
178  .name = "BoxSoft J-col",
179  .buttons = { BUTTON_MAIN, BUTTON_EX3, BUTTON_OTHER, BUTTON_EX4, BUTTON_EX5 }, // mapping for SDL left/middle/right/X1/X2 events to EP
180  .nibbles = 4,
181  .wrap = 0,
182  .watchdog = WATCHDOG_USEC(1500),
183  .data_mask = J_COLUMN
184  }, { // MODE - 2:
185  .name = "ExtMSX J-col",
186  .buttons = { BUTTON_MAIN, BUTTON_EX3, BUTTON_OTHER, BUTTON_EX4, BUTTON_EX5 }, // mapping for SDL left/middle/right/X1/X2 events to EP
187  .nibbles = 8,
188  .wrap = 0,
189  .watchdog = WATCHDOG_USEC(1500),
190  .data_mask = J_COLUMN
191  }, { // MODE - 3:
192  .name = "EnterMice J-col",
193  .buttons = { BUTTON_MAIN, BUTTON_EX3, BUTTON_OTHER, BUTTON_EX4, BUTTON_EX5 }, // mapping for SDL left/middle/right/X1/X2 events to EP
194  .nibbles = 16,
195  .wrap = 0,
196  .watchdog = WATCHDOG_USEC(1500),
197  .data_mask = J_COLUMN
198  }, { // MODE - 4:
199  .name = "BoxSoft K-col",
200  .buttons = { BUTTON_MAIN, BUTTON_EX3, BUTTON_OTHER, BUTTON_EX4, BUTTON_EX5 }, // mapping for SDL left/middle/right/X1/X2 events to EP
201  .nibbles = 4,
202  .wrap = 0,
203  .watchdog = WATCHDOG_USEC(1500),
204  .data_mask = K_COLUMN
205  }, { // MODE - 5:
206  .name = "ExtMSX K-col",
207  .buttons = { BUTTON_MAIN, BUTTON_EX3, BUTTON_OTHER, BUTTON_EX4, BUTTON_EX5 }, // mapping for SDL left/middle/right/X1/X2 events to EP
208  .nibbles = 8,
209  .wrap = 0,
210  .watchdog = WATCHDOG_USEC(1500),
211  .data_mask = K_COLUMN
212  }, { // MODE - 6:
213  .name = "EnterMice K-col",
214  .buttons = { BUTTON_MAIN, BUTTON_EX3, BUTTON_OTHER, BUTTON_EX4, BUTTON_EX5 }, // mapping for SDL left/middle/right/X1/X2 events to EP
215  .nibbles = 16,
216  .wrap = 0,
217  .watchdog = WATCHDOG_USEC(1500),
218  .data_mask = K_COLUMN
219  }
220 };
221 
222 #define LAST_MOUSE_MODE ((sizeof(mouse_modes) / sizeof(const struct mouse_modes_st)) - 1)
223 
224 static const struct mouse_modes_st *mode; // current mode mode, pointer to the selected mouse_modes
225 int mouse_mode; // current mode, with an integer
226 
227 #define JOYSTICK_SCAN(num, dir) joystick_scan(num, dir)
228 
229 
230 
231 int mouse_mode_description ( int cfg, char *buffer )
232 {
233  if (cfg == 0)
234  cfg = mouse_mode;
235  if (cfg < 1 || cfg > LAST_MOUSE_MODE) {
236  sprintf(buffer, "#%d *** Invalid mouse mode ***", cfg);
237  return 1;
238  } else {
239  sprintf(
240  buffer,
241  "#%d (%s) nibbles=%d wrap=%d watchdog=%d mask=%d",
242  cfg,
243  mouse_modes[cfg].name,
244  mouse_modes[cfg].nibbles,
245  mouse_modes[cfg].wrap,
246  mouse_modes[cfg].watchdog,
247  mouse_modes[cfg].data_mask
248  );
249  return 0;
250  }
251 }
252 
253 
254 
255 void mouse_reset_button ( void )
256 {
257  mouse_button1 = 0;
258  mouse_button2 = 0;
259  mouse_buffer[2] &= 0xF0; // extra buttons for MSX extended protocol should be cleared as well
260 }
261 
262 
263 
264 static inline void set_button ( Uint8 *storage, int mask, int pressed )
265 {
266  if (pressed)
267  *storage |= mask;
268  else
269  *storage &= 255 - mask;
270 }
271 
272 
273 
274 void emu_mouse_button ( Uint8 sdl_button, int press )
275 {
276  const char *name;
277  int id;
278  switch (sdl_button) {
279  case SDL_BUTTON_LEFT:
280  name = "left";
281  id = 0;
282  break;
283  case SDL_BUTTON_MIDDLE:
284  name = "middle";
285  id = 1;
286  break;
287  case SDL_BUTTON_RIGHT:
288  name = "right";
289  id = 2;
290  break;
291  case SDL_BUTTON_X1:
292  name = "x1";
293  id = 3;
294  break;
295  case SDL_BUTTON_X2:
296  name = "x2";
297  id = 4;
298  break;
299  default:
300  name = "UNKNOWN";
301  id = -1;
302  break;
303  }
304  DEBUG("MOUSE: BUTTON: event: SDL#%d XEP#%d (%s) %s" NL, sdl_button, id, name, press ? "pressed" : "released");
305  if (id == -1) {
306  DEBUG("MOUSE: BUTTON: unknown button on SDL level (see previous MOUSE: line)!!" NL);
307  return; // unknown mouse button??
308  }
309  if (sdl_button == SDL_BUTTON_LEFT && press && mouse_grab == 0) {
310  //emu_osd_msg("Mouse grab. Press ESC to exit.");
311  set_mouse_grab(SDL_TRUE, 0);
312  mouse_grab = 1;
314  }
315  if (!mouse_grab) {
316  DEBUG("MOUSE: BUTTON: not in grab mode, do not forward event" NL);
317  return; // not in mouse grab mode
318  }
319  switch (mode->buttons[id]) {
320  case BUTTON_MAIN:
321  mouse_button1 = press;
322  break;
323  case BUTTON_OTHER:
324  mouse_button2 = press;
325  break;
326  case BUTTON_EX3:
327  set_button(&mouse_buffer[2], 1, press);
328  break;
329  case BUTTON_EX4:
330  set_button(&mouse_buffer[2], 2, press);
331  break;
332  case BUTTON_EX5:
333  set_button(&mouse_buffer[2], 4, press);
334  break;
335  default:
336  DEBUG("MOUSE: used mouse button cannot be mapped for the given mouse mode (map=%d), ignored" NL, mode->buttons[id]);
337  break;
338  }
339 }
340 
341 
342 
343 void emu_mouse_motion ( int dx, int dy )
344 {
345  DEBUG("MOUSE: MOTION: event: dx = %d, dy = %d" NL, dx, dy);
346  if (!mouse_grab) {
347  DEBUG("MOUSE: MOTION: not in grab mode, do not forward event" NL);
348  return; // not in mouse grab mode
349  }
350  move_dx -= dx;
351  if (move_dx > 127) move_dx = 127;
352  else if (move_dx < -128) move_dx = -128;
353  move_dy -= dy;
354  if (move_dy > 127) move_dy = 127;
355  else if (move_dy < -128) move_dy = -128;
356 }
357 
358 
359 
360 void emu_mouse_wheel ( int x, int y, int flipped )
361 {
362  DEBUG("MOUSE: WHEEL: event: x = %d, y = %d, flipped = %d" NL, x, y, flipped);
363  if (!mouse_grab) {
364  DEBUG("MOUSE: WHEEL: not in grab mode, do not forward event" NL);
365  return; // not in mouse grab mode
366  }
367  flipped = flipped ? -1 : 1;
368  wheel_dx -= x * flipped;
369  if (wheel_dx > 127) wheel_dx = 127;
370  else if (wheel_dx < -128) wheel_dx = -128;
371  wheel_dy -= y * flipped;
372  if (wheel_dy > 127) wheel_dy = 127;
373  else if (wheel_dy < -128) wheel_dy = -128;
374 }
375 
376 
377 
378 void mouse_reset ( void )
379 {
380  // mouse_grab = 0; // commented out to fix the issue: emu reset hotkey is pressed with grabbed mouse ...
381  nibble_counter = 0;
382  //if (rts_old_level == -1)
383  rts_old_level = 0;
384  nibble = 0;
385  move_dx = 0;
386  move_dy = 0;
387  wheel_dx = 0;
388  wheel_dy = 0;
389  watchdog_mouse = raster_time;
390  watchdog_xep128 = raster_time;
392  mouse_buffer[0] = mouse_buffer[1] = mouse_buffer[3] = 0;
393 }
394 
395 
396 
397 static inline void check_mouse_watchdog ( void )
398 {
399  int time = raster_time - watchdog_mouse;
400  watchdog_mouse = raster_time;
401  if (mode->watchdog >= 0 && (time > mode->watchdog || time < 0)) // negative case in case of raster_time counter warp-around (integer overflow)
402  nibble_counter = 0; // in case of timeout, nibble counter resets to zero
403 }
404 
405 // FIXME: port the old one here, it's for only able to compile :-/
406 int joystick_scan ( int num, int dir )
407 {
408  if (num != 0 && num != 1)
409  return 0;
410  return !(kbd_matrix[10] & (1 << dir));
411 }
412 
413 
414 // Called from cpu.c in case of read port 0xB6, this function MUST only give back bits 0-2, ie control ports ones, higher bits
415 // bits should be zero as they are used for other purposes (ie: tape, printer ...) and OR'ed by cpu.c at port reading func ...
417 {
418  int mouse_ok, joy1_ok;
419  int time = raster_time - watchdog_xep128;
420  // Note: unlike watchdog_mouse, watchdog_xep128 is set in check data shift only but queried here
421  if (time < 0)
422  watchdog_xep128 = raster_time; // integer overflow
423  if (mode->data_mask == K_COLUMN) { // mouse on K-column, joy-1 is always enabled
424  mouse_ok = 2;
425  joy1_ok = 1;
426  } else if (mouse_pulse && (time < WATCHDOG_USEC(100000) || time < 0)) { // mouse on J-column, joy-1 is disabled on mouse usage
427  mouse_ok = 2;
428  joy1_ok = 0;
429  } else { // mouse on J-column, joy-1 is enabled because no mouse usage
430  mouse_ok = 0;
431  joy1_ok = 1;
432  mouse_pulse = 0;
433  }
434  if (control_port_emu_mode != mouse_ok + joy1_ok) {
435  static const char *m[] = { "joystick", "Mouse", "dual (K-col)" };
436  control_port_emu_mode = mouse_ok + joy1_ok;
437  OSD(-1, -1, "Control port: %s mode", m[control_port_emu_mode - 1 ]);
438  }
439  switch (kbd_selector) {
440  /* joystick-1 or mouse related */
441  case 0: // The Entermice wiki mentioned priority of mouse buttons are not so much implemented ... TODO
442  return
443  (mouse_ok ? ((mouse_button1 ? 0 : mode->data_mask) | (7 - mode->data_mask - 4) | (mouse_button2 ? 0 : 4)) : 7) &
444  (joy1_ok ? ((JOYSTICK_SCAN(0, JOY_SCAN_FIRE1) ? 0 : 1) | (JOYSTICK_SCAN(0, JOY_SCAN_FIRE2) ? 0 : 2) | (JOYSTICK_SCAN(0, JOY_SCAN_FIRE3) ? 0 : 4)) : 7);
445  case 1: return (mouse_ok ? (((nibble & 1) ? mode->data_mask : 0) | (7 - mode->data_mask)) : 7) & ((joy1_ok && JOYSTICK_SCAN(0, JOY_SCAN_UP )) ? 6 : 7);
446  case 2: return (mouse_ok ? (((nibble & 2) ? mode->data_mask : 0) | (7 - mode->data_mask)) : 7) & ((joy1_ok && JOYSTICK_SCAN(0, JOY_SCAN_DOWN )) ? 6 : 7);
447  case 3: return (mouse_ok ? (((nibble & 4) ? mode->data_mask : 0) | (7 - mode->data_mask)) : 7) & ((joy1_ok && JOYSTICK_SCAN(0, JOY_SCAN_LEFT )) ? 6 : 7);
448  case 4: return (mouse_ok ? (((nibble & 8) ? mode->data_mask : 0) | (7 - mode->data_mask)) : 7) & ((joy1_ok && JOYSTICK_SCAN(0, JOY_SCAN_RIGHT)) ? 6 : 7);
449  /* always joystick#2 on J-column (bit 0), other bits are spare */
450  case 5: return (JOYSTICK_SCAN(1, JOY_SCAN_FIRE1) ? 0 : 1) | (JOYSTICK_SCAN(1, JOY_SCAN_FIRE2) ? 0 : 2) | (JOYSTICK_SCAN(1, JOY_SCAN_FIRE3) ? 0 : 4);
451  case 6: return JOYSTICK_SCAN(1, JOY_SCAN_UP ) ? 6 : 7;
452  case 7: return JOYSTICK_SCAN(1, JOY_SCAN_DOWN ) ? 6 : 7;
453  case 8: return JOYSTICK_SCAN(1, JOY_SCAN_LEFT ) ? 6 : 7;
454  case 9: return JOYSTICK_SCAN(1, JOY_SCAN_RIGHT) ? 6 : 7;
455  /* and if not ... */
456  default: return 7; // it shouldn't happen too much (only if no valid scan row is selected?)
457  }
458 }
459 
460 
461 
462 // Called from cpu.c in case of write of port 0xB7
464 {
465  if ((val & 2) == rts_old_level) // check of change on the RTS signal change
466  return; // if no change, we're not interested in at all, mouse "nibble shifting" in RTS _edge_ triggered (both of the edges!) not level
467  rts_old_level = val & 2;
468  mouse_pulse = 1; // this variable is only for the emulator to keep track of mouse reading tries and display OSD, etc
469  watchdog_xep128 = raster_time; // this watchdog is used to control auto-switch of Xep128 between J-column mouse and joy-1 emulation
470  check_mouse_watchdog(); // this is the mouse watchdog to reset nibble counter in a given timeout
471  if (nibble_counter >= mode->nibbles && mode->wrap) // support nibble counter wrap-around mode, if the current mouse mode directs that
472  nibble_counter = 0;
473  // note: information larger than one nibble shouldn't updated by the mouse SDL events directly in mouse_buffer, because it's possible
474  // that between the reading of two nibbles that is modified. To avoid this, these things are updated here at a well defined counter state only:
475  if (nibble_counter == 0) {
476  // update mouse buffer byte 0 with delta X
477  //mouse_buffer[0] = ((unsigned int)move_dx) & 0xFF; // signed will be converted to unsigned
478  mouse_buffer[0] = move_dx;
479  move_dx = 0;
480  } else if (nibble_counter == 2) {
481  // update mouse buffer byte 1 with delta Y
482  //mouse_buffer[1] = ((unsigned int)move_dy) & 0xFF; // signed will be converted to unsigned
483  mouse_buffer[1] = move_dy;
484  move_dy = 0;
485  } else if (nibble_counter == 6) { // this may not be used at all, if mouse_protocol_nibbles limits the available nibbles to read, boxsoft will not read this ever!
486  mouse_buffer[3] = wheel_dy;
487  wheel_dy = 0;
488  }
489  if (nibble_counter < mode->nibbles) {
490  // if nibble counter is below the constraint of the used mouse protocol, provide the upper or lower nibble of the buffer
491  // based on the counter's lowest bit (ie, odd or even)
492  nibble = ((nibble_counter & 1) ? (mouse_buffer[nibble_counter >> 1] & 15) : (mouse_buffer[nibble_counter >> 1] >> 4));
493  nibble_counter++;
494  } else
495  nibble = 0; // if we hit the max number of nibbles, we constantly provide zero as the nibble, until watchdog resets
496 }
497 
498 
499 
500 int mouse_setup ( int cfg )
501 {
502  char buffer[128];
503  if (cfg < 0)
504  return mouse_mode;
505  if (cfg < 1 || cfg > LAST_MOUSE_MODE)
506  cfg = 1;
507  mouse_mode = cfg;
508  mode = &mouse_modes[cfg];
509  mouse_mode_description(cfg, buffer);
510  DEBUG("MOUSE: SETUP: %s" NL, buffer);
511  mouse_reset();
512  return cfg;
513 }
514 
515 
516 /* ------------------- KEYBOARD ----------------------- */
517 
518 // HID needs this to be defined, it's up to the emulator if it uses or not ...
519 int emu_callback_key ( int pos, SDL_Scancode key, int pressed, int handled )
520 {
521  if (!pressed && pos == -2 && key == 0 && handled == SDL_BUTTON_RIGHT)
522  ui_enter();
523  return 0;
524 }
mouse_modes_st::wrap
int wrap
Definition: input_devices.c:169
read_control_port_bits
Uint8 read_control_port_bits(void)
Definition: input_devices.c:416
kbd_selector
int kbd_selector
Definition: dave.c:35
raster_time
Uint32 raster_time
Definition: nick.c:56
ep128_key_map
const struct KeyMappingDefault ep128_key_map[]
Definition: input_devices.c:42
ui.h
joystick_scan
int joystick_scan(int num, int dir)
Definition: input_devices.c:406
K_COLUMN
#define K_COLUMN
Definition: input_devices.c:163
mouse_grab
int mouse_grab
Definition: input_devices.c:28
emutools.h
BUTTON_EX5
#define BUTTON_EX5
Definition: input_devices.c:159
JOY_SCAN_RIGHT
#define JOY_SCAN_RIGHT
Definition: input_devices.h:28
mouse_mode_description
int mouse_mode_description(int cfg, char *buffer)
Definition: input_devices.c:231
set_mouse_grab
int set_mouse_grab(SDL_bool state, int force_allow)
Definition: emutools.c:131
JOY_SCAN_UP
#define JOY_SCAN_UP
Definition: input_devices.h:25
BUTTON_EX4
#define BUTTON_EX4
Definition: input_devices.c:158
id
int id
Definition: joystick.c:52
Uint32
uint32_t Uint32
Definition: fat32.c:49
LAST_MOUSE_MODE
#define LAST_MOUSE_MODE
Definition: input_devices.c:222
Uint8
uint8_t Uint8
Definition: fat32.c:51
mouse_mode
int mouse_mode
Definition: input_devices.c:225
JOY_SCAN_FIRE2
#define JOY_SCAN_FIRE2
Definition: input_devices.h:29
JOY_SCAN_LEFT
#define JOY_SCAN_LEFT
Definition: input_devices.h:27
mouse_modes_st::nibbles
int nibbles
Definition: input_devices.c:168
emu_callback_key
int emu_callback_key(int pos, SDL_Scancode key, int pressed, int handled)
Definition: input_devices.c:138
x
int x
Definition: console.c:27
STD_XEMU_SPECIAL_KEYS
#define STD_XEMU_SPECIAL_KEYS
Definition: emutools_hid.h:108
mouse_modes_st
Definition: input_devices.c:165
mouse_modes_st::name
const char * name
Definition: input_devices.c:166
mouse_reset_button
void mouse_reset_button(void)
Definition: input_devices.c:255
dir
DIR * dir
Definition: cpmfs.c:46
JOYSTICK_SCAN
#define JOYSTICK_SCAN(num, dir)
Definition: input_devices.c:227
BUTTON_EX3
#define BUTTON_EX3
Definition: input_devices.c:157
mode
int mode
Definition: vera.c:61
NL
#define NL
Definition: fat32.c:37
BUTTON_MAIN
#define BUTTON_MAIN
Definition: input_devices.c:155
KeyMappingDefault
Definition: emutools_hid.h:24
mouse_modes_st::data_mask
int data_mask
Definition: input_devices.c:171
dave.h
WATCHDOG_USEC
#define WATCHDOG_USEC(n)
Definition: input_devices.c:149
mouse_check_data_shift
void mouse_check_data_shift(Uint8 val)
Definition: input_devices.c:463
input_devices.h
JOY_SCAN_FIRE3
#define JOY_SCAN_FIRE3
Definition: input_devices.h:30
JOY_SCAN_DOWN
#define JOY_SCAN_DOWN
Definition: input_devices.h:26
kbd_matrix
Uint8 kbd_matrix[16]
Definition: dave.c:30
emu_mouse_button
void emu_mouse_button(Uint8 sdl_button, int press)
Definition: input_devices.c:274
mouse_modes_st::buttons
int buttons[5]
Definition: input_devices.c:167
show_keys
int show_keys
Definition: input_devices.c:39
OSD
#define OSD(...)
Definition: xep128.h:100
JOY_SCAN_FIRE1
#define JOY_SCAN_FIRE1
Definition: input_devices.h:24
y
int y
Definition: console.c:27
mask
int mask
Definition: dma65.c:83
mouse_reset
void mouse_reset(void)
Definition: input_devices.c:378
J_COLUMN
#define J_COLUMN
Definition: input_devices.c:162
mouse_modes_st::watchdog
int watchdog
Definition: input_devices.c:170
emutools_hid.h
emu_mouse_motion
void emu_mouse_motion(int dx, int dy)
Definition: input_devices.c:343
name
const char * name
Definition: joystick.c:46
enterprise128.h
DEBUG
#define DEBUG(...)
Definition: emutools_basicdefs.h:167
ui_enter
void ui_enter(void)
Definition: ui.c:326
BUTTON_OTHER
#define BUTTON_OTHER
Definition: input_devices.c:156
emu_mouse_wheel
void emu_mouse_wheel(int x, int y, int flipped)
Definition: input_devices.c:360
mouse_setup
int mouse_setup(int cfg)
Definition: input_devices.c:500