1 /*****************************************************************************
2 ** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/Input/MsxMouse.c,v $
3 **
4 ** $Revision: 1.3 $
5 **
6 ** $Date: 2008-03-30 18:38:40 $
7 **
8 ** More info: http://www.bluemsx.com
9 **
10 ** Copyright (C) 2003-2006 Daniel Vik
11 **
12 ** This program is free software; you can redistribute it and/or modify
13 ** it under the terms of the GNU General Public License as published by
14 ** the Free Software Foundation; either version 2 of the License, or
15 ** (at your option) any later version.
16 **
17 ** This program is distributed in the hope that it will be useful,
18 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ** GNU General Public License for more details.
21 **
22 ** You should have received a copy of the GNU General Public License
23 ** along with this program; if not, write to the Free Software
24 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 **
26 ******************************************************************************
27 */
28 #include "MsxMouse.h"
29 #include "InputEvent.h"
30 #include "ArchInput.h"
31 #include "Board.h"
32 #include "SaveState.h"
33 
34 #include <stdlib.h>
35 
36 struct MsxMouse {
37     MsxJoystickDevice joyDevice;
38     int dx;
39     int dy;
40     int count;
41     int mouseAsJoystick;
42     UInt8 oldValue;
43     UInt32 clock;
44 };
45 
saveState(MsxMouse * mouse)46 static void saveState(MsxMouse* mouse)
47 {
48     SaveState* state = saveStateOpenForWrite("msxMouse");
49 
50     saveStateSet(state, "dx",               mouse->dx);
51     saveStateSet(state, "dy",               mouse->dy);
52     saveStateSet(state, "count",            mouse->count);
53     saveStateSet(state, "mouseAsJoystick",  mouse->mouseAsJoystick);
54     saveStateSet(state, "oldValue",         mouse->oldValue);
55     saveStateSet(state, "clock",            mouse->clock);
56 
57     saveStateClose(state);
58 }
59 
loadState(MsxMouse * mouse)60 static void loadState(MsxMouse* mouse)
61 {
62     SaveState* state = saveStateOpenForRead("msxMouse");
63 
64     mouse->dx              =        saveStateGet(state, "dx",              0);
65     mouse->dy              =        saveStateGet(state, "dy",              0);
66     mouse->count           =        saveStateGet(state, "count",           0);
67     mouse->mouseAsJoystick =        saveStateGet(state, "mouseAsJoystick", 0);
68     mouse->oldValue        = (UInt8)saveStateGet(state, "oldValue",        0);
69     mouse->clock           =        saveStateGet(state, "clock",           0);
70 
71     saveStateClose(state);
72 }
73 
read(MsxMouse * mouse)74 static UInt8 read(MsxMouse* mouse)
75 {
76     UInt8 state = 0x3f;
77     UInt32 systemTime = boardSystemTime();
78 
79     if (mouse->mouseAsJoystick) {
80         if (systemTime - mouse->clock > boardFrequency() / 120) {
81             int dx;
82             int dy;
83 
84             archMouseGetState(&dx, &dy);
85             mouse->clock = systemTime;
86 
87             mouse->dx = (dx > 127 ? 127 : (dx < -127 ? -127 : dx));
88             mouse->dy = (dy > 127 ? 127 : (dy < -127 ? -127 : dy));
89         }
90 
91         if ((mouse->oldValue & 0x04) == 0) {
92             state = ((mouse->dx / 3) ? ((mouse->dx > 0) ? 0x08 : 0x04) : 0x0c) |
93                     ((mouse->dy / 3) ? ((mouse->dy > 0) ? 0x02 : 0x01) : 0x03);
94         }
95     }
96     else {
97         switch (mouse->count) {
98         case 0:
99             state = (mouse->dx >> 4) & 0x0f;
100             break;
101         case 1:
102             state = mouse->dx & 0x0f;
103             break;
104         case 2:
105             state =(mouse->dy >> 4) & 0x0f;
106             break;
107         case 3:
108             state = mouse->dy & 0x0f;
109             break;
110         }
111     }
112 
113     state |= (~archMouseGetButtonState(0) << 4) & 0x30;
114 
115     return state;
116 }
117 
write(MsxMouse * mouse,UInt8 value)118 static void write(MsxMouse* mouse, UInt8 value)
119 {
120     UInt32 systemTime = boardSystemTime();
121 
122     if (mouse->mouseAsJoystick) {
123         return;
124     }
125 
126     if ((value ^ mouse->oldValue) & 0x04) {
127         if (systemTime - mouse->clock > boardFrequency() / 2500) {
128             mouse->count = 0;
129         }
130         else {
131             mouse->count = (mouse->count + 1) & 3;
132         }
133 
134         mouse->clock = systemTime;
135 
136         if (mouse->count == 0) {
137             int dx;
138             int dy;
139             archMouseGetState(&dx, &dy);
140             mouse->clock = systemTime;
141             mouse->dx = (dx > 127 ? 127 : (dx < -127 ? -127 : dx));
142             mouse->dy = (dy > 127 ? 127 : (dy < -127 ? -127 : dy));
143         }
144     }
145     mouse->oldValue = value;
146 }
147 
reset(MsxMouse * mouse)148 static void reset(MsxMouse* mouse) {
149     mouse->dx       = 0;
150     mouse->dy       = 0;
151     mouse->count    = 0;
152     mouse->clock    = 0;
153     mouse->oldValue = 0;
154 }
155 
msxMouseCreate()156 MsxJoystickDevice* msxMouseCreate()
157 {
158     MsxMouse* mouse = (MsxMouse*)calloc(1, sizeof(MsxMouse));
159     mouse->joyDevice.read       = read;
160     mouse->joyDevice.write      = write;
161     mouse->joyDevice.reset      = reset;
162     mouse->joyDevice.loadState  = loadState;
163     mouse->joyDevice.saveState  = saveState;
164 
165     reset(mouse);
166 
167     return (MsxJoystickDevice*)mouse;
168 }