fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 380 lines 7.5 kB view raw
1/***************************************************************************** 2 * pce * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/drivers/char/char-mouse.c * 7 * Created: 2011-10-15 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2011-2019 Hampa Hug <hampa@hampa.ch> * 9 *****************************************************************************/ 10 11/***************************************************************************** 12 * This program is free software. You can redistribute it and / or modify it * 13 * under the terms of the GNU General Public License version 2 as published * 14 * by the Free Software Foundation. * 15 * * 16 * This program is distributed in the hope that it will be useful, but * 17 * WITHOUT ANY WARRANTY, without even the implied warranty of * 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 19 * Public License for more details. * 20 *****************************************************************************/ 21 22 23#include <stdlib.h> 24#include <stdio.h> 25#include <string.h> 26 27#include <drivers/options.h> 28#include <drivers/char/char.h> 29#include <drivers/char/char-mouse.h> 30 31 32#define MOUSE_MAX 8 33 34#define MOUSE_MS 0 35#define MOUSE_MSYS 1 36 37 38static unsigned mouse_cnt = 0; 39static char_mouse_t *mouse[MOUSE_MAX]; 40 41 42static 43void chr_mouse_close (char_drv_t *cdrv) 44{ 45 unsigned i, n; 46 char_mouse_t *drv; 47 48 drv = cdrv->ext; 49 50 n = 0; 51 52 for (i = 0; i < mouse_cnt; i++) { 53 if (mouse[i] != drv) { 54 mouse[n++] = mouse[i]; 55 } 56 } 57 58 mouse_cnt = n; 59 60 free (drv); 61} 62 63static 64unsigned chr_mouse_get_buf_cnt (const char_mouse_t *drv) 65{ 66 unsigned cnt; 67 68 cnt = (CHAR_MOUSE_BUF + drv->buf_hd - drv->buf_tl) % CHAR_MOUSE_BUF; 69 70 return (CHAR_MOUSE_BUF - cnt); 71} 72 73static 74void chr_mouse_add_val (char_mouse_t *drv, unsigned char val) 75{ 76 drv->buf[drv->buf_hd] = val; 77 drv->buf_hd = (drv->buf_hd + 1) % CHAR_MOUSE_BUF; 78} 79 80static 81unsigned chr_mouse_get_val (int *val, int min, int max) 82{ 83 unsigned ret; 84 int tmp; 85 86 tmp = *val; 87 88 if (tmp < min) { 89 tmp = min; 90 } 91 else if (tmp > max) { 92 tmp = max; 93 } 94 95 *val -= tmp; 96 97 if (tmp < 0) { 98 ret = -tmp; 99 ret = ~ret + 1; 100 } 101 else { 102 ret = tmp; 103 } 104 105 return (ret); 106} 107 108static 109void chr_mouse_add_packet_ms (char_mouse_t *drv) 110{ 111 unsigned x, y, v; 112 113 if (chr_mouse_get_buf_cnt (drv) < 3) { 114 return; 115 } 116 117 x = chr_mouse_get_val (&drv->dx, -127, 127); 118 y = chr_mouse_get_val (&drv->dy, -127, 127); 119 120 v = 0x40; 121 v |= (drv->button & 0x01) ? 0x20 : 0x00; 122 v |= (drv->button & 0x02) ? 0x10 : 0x00; 123 v |= (y >> 4) & 0x0c; 124 v |= (x >> 6) & 0x03; 125 126 chr_mouse_add_val (drv, v); 127 chr_mouse_add_val (drv, x & 0x3f); 128 chr_mouse_add_val (drv, y & 0x3f); 129} 130 131static 132void chr_mouse_add_packet_msys (char_mouse_t *drv) 133{ 134 unsigned i, v; 135 136 if (chr_mouse_get_buf_cnt (drv) < 5) { 137 return; 138 } 139 140 v = 0x80; 141 v |= (drv->button & 0x01) ? 0x00 : 0x04; 142 v |= (drv->button & 0x02) ? 0x00 : 0x01; 143 v |= (drv->button & 0x04) ? 0x00 : 0x02; 144 145 chr_mouse_add_val (drv, v); 146 147 for (i = 0; i < 2; i++) { 148 v = chr_mouse_get_val (&drv->dx, -127, 127); 149 chr_mouse_add_val (drv, v); 150 151 v = chr_mouse_get_val (&drv->dy, -127, 127); 152 chr_mouse_add_val (drv, ~v + 1); 153 } 154} 155 156static 157void chr_mouse_add_packet (char_mouse_t *drv) 158{ 159 switch (drv->protocol) { 160 case MOUSE_MS: 161 chr_mouse_add_packet_ms (drv); 162 break; 163 164 case MOUSE_MSYS: 165 chr_mouse_add_packet_msys (drv); 166 break; 167 } 168} 169 170static 171void chr_mouse_set_drv (char_mouse_t *drv, int dx, int dy, unsigned button) 172{ 173 int tx, ty; 174 unsigned tb; 175 176 tb = drv->button; 177 178 dx = drv->scale_x[0] * dx + drv->scale_x[2]; 179 tx = dx; 180 dx = dx / drv->scale_x[1]; 181 drv->scale_x[2] = tx - drv->scale_x[1] * dx; 182 183 dy = drv->scale_y[0] * dy + drv->scale_y[2]; 184 ty = dy; 185 dy = dy / drv->scale_y[1]; 186 drv->scale_y[2] = ty - drv->scale_y[1] * dy; 187 188 drv->dx += dx; 189 drv->dy += dy; 190 drv->button = button; 191 192 if ((tb ^ button) & 3) { 193 chr_mouse_add_packet (drv); 194 } 195} 196 197static 198unsigned chr_mouse_read (char_drv_t *cdrv, void *buf, unsigned cnt) 199{ 200 unsigned i, n; 201 unsigned char *tmp; 202 char_mouse_t *drv; 203 204 drv = cdrv->ext; 205 tmp = buf; 206 207 if (drv->protocol == MOUSE_MS) { 208 if ((drv->dtr == 0) || (drv->rts == 0)) { 209 return (0); 210 } 211 } 212 213 if (drv->buf_hd == drv->buf_tl) { 214 if ((drv->dx != 0) || (drv->dy != 0)) { 215 chr_mouse_add_packet (drv); 216 } 217 } 218 219 if (drv->buf_hd == drv->buf_tl) { 220 return (0); 221 } 222 223 n = (drv->buf_hd - drv->buf_tl + CHAR_MOUSE_BUF) % CHAR_MOUSE_BUF; 224 225 if (n > cnt) { 226 n = cnt; 227 } 228 229 for (i = 0; i < n; i++) { 230 tmp[i] = drv->buf[drv->buf_tl]; 231 drv->buf_tl = (drv->buf_tl + 1) % CHAR_MOUSE_BUF; 232 } 233 234 return (n); 235} 236 237static 238unsigned chr_mouse_write (char_drv_t *cdrv, const void *buf, unsigned cnt) 239{ 240 return (cnt); 241} 242 243static 244int chr_mouse_get_ctl (char_drv_t *cdrv, unsigned *ctl) 245{ 246 *ctl = PCE_CHAR_DSR | PCE_CHAR_CTS | PCE_CHAR_CD; 247 248 return (0); 249} 250 251static 252int chr_mouse_set_ctl (char_drv_t *cdrv, unsigned ctl) 253{ 254 int dtr, rts; 255 char_mouse_t *drv; 256 257 drv = cdrv->ext; 258 259 dtr = (ctl & PCE_CHAR_DTR) != 0; 260 rts = (ctl & PCE_CHAR_RTS) != 0; 261 262 if (drv->protocol == MOUSE_MS) { 263 if (rts && dtr) { 264 if ((drv->dtr == 0) || (drv->rts == 0)) { 265 drv->dx = 0; 266 drv->dy = 0; 267 drv->scale_x[2] = 0; 268 drv->scale_y[2] = 0; 269 270 drv->buf_hd = 1; 271 drv->buf_tl = 0; 272 drv->buf[0] = 'M'; 273 } 274 } 275 } 276 277 drv->dtr = dtr; 278 drv->rts = rts; 279 280 return (0); 281} 282 283static 284int chr_mouse_set_params (char_drv_t *cdrv, unsigned long bps, unsigned bpc, unsigned parity, unsigned stop) 285{ 286 return (0); 287} 288 289static 290int chr_mouse_init (char_mouse_t *drv, const char *name) 291{ 292 char *proto; 293 294 chr_init (&drv->cdrv, drv); 295 296 drv->cdrv.close = chr_mouse_close; 297 drv->cdrv.read = chr_mouse_read; 298 drv->cdrv.write = chr_mouse_write; 299 drv->cdrv.get_ctl = chr_mouse_get_ctl; 300 drv->cdrv.set_ctl = chr_mouse_set_ctl; 301 drv->cdrv.set_params = chr_mouse_set_params; 302 303 drv->protocol = MOUSE_MS; 304 305 drv->buf_hd = 0; 306 drv->buf_tl = 0; 307 308 drv->dtr = 0; 309 drv->rts = 0; 310 311 drv->dx = 0; 312 drv->dy = 0; 313 drv->button = 0; 314 315 proto = drv_get_option (name, "protocol"); 316 317 if (proto != NULL) { 318 if (strcmp (proto, "microsoft") == 0) { 319 drv->protocol = MOUSE_MS; 320 } 321 else if (strcmp (proto, "msys") == 0) { 322 drv->protocol = MOUSE_MSYS; 323 } 324 else { 325 free (proto); 326 return (1); 327 } 328 329 free (proto); 330 } 331 332 drv->scale_x[0] = drv_get_option_sint (name, "xmul", 1); 333 drv->scale_x[1] = drv_get_option_sint (name, "xdiv", 1); 334 drv->scale_x[2] = 0; 335 336 if (drv->scale_x[1] == 0) { 337 drv->scale_x[1] = 1; 338 } 339 340 drv->scale_y[0] = drv_get_option_sint (name, "ymul", 1); 341 drv->scale_y[1] = drv_get_option_sint (name, "ydiv", 1); 342 drv->scale_y[2] = 0; 343 344 if (drv->scale_y[1] == 0) { 345 drv->scale_y[1] = 1; 346 } 347 348 if ((mouse_cnt + 1) < MOUSE_MAX) { 349 mouse[mouse_cnt++] = drv; 350 } 351 352 return (0); 353} 354 355void chr_mouse_set (int dx, int dy, unsigned button) 356{ 357 unsigned i; 358 359 for (i = 0; i < mouse_cnt; i++) { 360 chr_mouse_set_drv (mouse[i], dx, dy, button); 361 } 362} 363 364char_drv_t *chr_mouse_open (const char *name) 365{ 366 char_mouse_t *drv; 367 368 drv = malloc (sizeof (char_mouse_t)); 369 370 if (drv == NULL) { 371 return (NULL); 372 } 373 374 if (chr_mouse_init (drv, name)) { 375 free (drv); 376 return (NULL); 377 } 378 379 return (&drv->cdrv); 380}