aboutsummaryrefslogtreecommitdiff
path: root/src/fake86/sermouse.c
blob: 98e25ab000547be35fd5895bf783cc7a87120553 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
  Fake86: A portable, open-source 8086 PC emulator.
  Copyright (C)2010-2013 Mike Chambers

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

/* sermouse.c: functions to emulate a standard Microsoft-compatible serial mouse. */

#include "config.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "sermouse.h"

extern void set_port_write_redirector (uint16_t startport, uint16_t endport, void *callback);
extern void set_port_read_redirector (uint16_t startport, uint16_t endport, void *callback);
extern void doirq (uint8_t irqnum);

struct sermouse_s sermouse;

void bufsermousedata (uint8_t value) {
	if (sermouse.bufptr == 16) return;
	if (sermouse.bufptr == 0 ) doirq (4);
	sermouse.buf[sermouse.bufptr++] = value;
}

void outsermouse (uint16_t portnum, uint8_t value) {
	uint8_t oldreg;
	//printf("[DEBUG] Serial mouse, port %X out: %02X\n", portnum, value);
	portnum &= 7;
	oldreg = sermouse.reg[portnum];
	sermouse.reg[portnum] = value;
	switch (portnum) {
			case 4: //modem control register
				if ( (value & 1) != (oldreg & 1) ) { //software toggling of this register
						sermouse.bufptr = 0; //causes the mouse to reset and fill the buffer
						bufsermousedata ('M'); //with a bunch of ASCII 'M' characters.
						bufsermousedata ('M'); //this is intended to be a way for
						bufsermousedata ('M'); //drivers to verify that there is
						bufsermousedata ('M'); //actually a mouse connected to the port.
						bufsermousedata ('M');
						bufsermousedata ('M');
					}
				break;
		}
}

uint8_t insermouse (uint16_t portnum) {
	uint8_t temp;
	//printf("[DEBUG] Serial mouse, port %X in\n", portnum);
	portnum &= 7;
	switch (portnum) {
			case 0: //data receive
				temp = sermouse.buf[0];
				memmove (sermouse.buf, &sermouse.buf[1], 15);
				sermouse.bufptr--;
				if (sermouse.bufptr < 0) sermouse.bufptr = 0;
				if (sermouse.bufptr > 0) doirq (4);
				sermouse.reg[4] = ~sermouse.reg[4] & 1;
				return (temp);
			case 5: //line status register (read-only)
				if (sermouse.bufptr > 0) temp = 1;
				else temp = 0;
				return (0x1);
				return (0x60 | temp);
		}
	return (sermouse.reg[portnum & 7]);
}

void initsermouse (uint16_t baseport, uint8_t irq) {
	sermouse.bufptr = 0;
	set_port_write_redirector (baseport, baseport + 7, &outsermouse);
	set_port_read_redirector (baseport, baseport + 7, &insermouse);
}

void sermouseevent (uint8_t buttons, int8_t xrel, int8_t yrel) {
	uint8_t highbits = 0;
	if (xrel < 0) highbits = 3;
	else highbits = 0;
	if (yrel < 0) highbits |= 12;
	bufsermousedata (0x40 | (buttons << 4) | highbits);
	bufsermousedata (xrel & 63);
	bufsermousedata (yrel & 63);
}