Common Source Code Project for Qt (a.k.a for FM-7).
Revision | e14c3feeab0ca62e8db0699950846f1185c0c6ff (tree) |
---|---|
Zeit | 2020-03-25 20:14:47 |
Autor | K.Ohta <whatisthis.sowhat@gmai...> |
Commiter | K.Ohta |
[VM][JOYSTICK][MOUSE] Implement *true* Joystick and MOUSE.
@@ -11,45 +11,39 @@ | ||
11 | 11 | #include "./joystick.h" |
12 | 12 | |
13 | 13 | namespace FMTOWNS { |
14 | - | |
14 | +#define EVENT_MOUSE_TIMEOUT 1 | |
15 | + | |
15 | 16 | void JOYSTICK::reset() |
16 | 17 | { |
17 | 18 | joydata[0] = joydata[1] = 0x00; |
18 | 19 | dx = dy = 0; |
19 | 20 | lx = ly = 0; |
21 | + mouse_state = emu->get_mouse_buffer(); | |
22 | + mask = 0xff; | |
23 | + mouse_type = -1; // Force update data. | |
20 | 24 | mouse_phase = 0; |
21 | 25 | mouse_strobe = false; |
22 | - mouse_type = config.mouse_type; | |
23 | - switch(mouse_type & 0x03){ | |
24 | - case 1: | |
25 | - emulate_mouse[0] = true; | |
26 | - emulate_mouse[1] = false; | |
27 | - break; | |
28 | - case 2: | |
29 | - emulate_mouse[0] = false; | |
30 | - emulate_mouse[1] = true; | |
31 | - break; | |
32 | - default: | |
33 | - emulate_mouse[0] = false; | |
34 | - emulate_mouse[1] = false; | |
35 | - break; | |
26 | + mouse_data = 0x00; | |
27 | + if(mouse_timeout_event >= 0) { | |
28 | + cancel_event(this, mouse_timeout_event); | |
36 | 29 | } |
37 | - mouse_state = emu->get_mouse_buffer(); | |
38 | - mask = 0xff; | |
30 | + mouse_timeout_event = -1; | |
31 | + update_config(); // Update MOUSE PORT. | |
39 | 32 | } |
40 | 33 | |
41 | 34 | void JOYSTICK::initialize() |
42 | 35 | { |
43 | 36 | rawdata = emu->get_joy_buffer(); |
44 | 37 | mouse_state = emu->get_mouse_buffer(); |
45 | - emulate_mouse[0] = emulate_mouse[1] = false; | |
46 | 38 | joydata[0] = joydata[1] = 0x00; |
47 | 39 | dx = dy = 0; |
48 | 40 | lx = ly = -1; |
49 | 41 | mouse_button = 0x00; |
50 | 42 | mouse_timeout_event = -1; |
51 | - | |
43 | + set_emulate_mouse(); | |
44 | + mouse_type = config.mouse_type; | |
52 | 45 | register_frame_event(this); |
46 | + | |
53 | 47 | } |
54 | 48 | |
55 | 49 | void JOYSTICK::release() |
@@ -66,15 +60,15 @@ void JOYSTICK::event_frame() | ||
66 | 60 | if(mouse_state != NULL) { |
67 | 61 | dx += mouse_state[0]; |
68 | 62 | dy += mouse_state[1]; |
69 | - if(dx < -127) { | |
70 | - dx = -127; | |
71 | - } else if(dx > 127) { | |
72 | - dx = 127; | |
63 | + if(dx < -255) { | |
64 | + dx = -255; | |
65 | + } else if(dx > 255) { | |
66 | + dx = 255; | |
73 | 67 | } |
74 | - if(dy < -127) { | |
75 | - dy = -127; | |
76 | - } else if(dy > 127) { | |
77 | - dy = 127; | |
68 | + if(dy < -255) { | |
69 | + dy = -255; | |
70 | + } else if(dy > 255) { | |
71 | + dy = 255; | |
78 | 72 | } |
79 | 73 | } |
80 | 74 | if(mouse_state != NULL) { |
@@ -96,19 +90,23 @@ void JOYSTICK::event_frame() | ||
96 | 90 | if(val & 0x08) retval |= 0x08; |
97 | 91 | if(val & 0x10) retval |= 0x10; |
98 | 92 | if(val & 0x20) retval |= 0x20; |
99 | - if(val & 0x40) retval |= 0x10; // Button A' | |
100 | - if(val & 0x80) retval |= 0x20; // Button B' | |
101 | 93 | if(val & 0x40) retval |= 0x40; // RUN |
102 | 94 | if(val & 0x80) retval |= 0x80; // SELECT |
95 | +// out_debug_log(_T("JOY DATA[%d]=%02X"), ch, retval); | |
103 | 96 | joydata[ch] = retval; |
104 | - } else { // MOUSE | |
105 | 97 | } |
98 | + // Note: MOUSE don't update at vsync. | |
106 | 99 | } |
107 | 100 | } |
108 | 101 | void JOYSTICK::write_io8(uint32_t address, uint32_t data) |
109 | 102 | { |
110 | 103 | // ToDo: Mouse |
111 | 104 | if(address == 0x04d6) { |
105 | + if(emulate_mouse[0]) { | |
106 | + update_strobe(((data & 0x20) != 0)); | |
107 | + } else if(emulate_mouse[1]) { | |
108 | + update_strobe(((data & 0x20) != 0)); | |
109 | + } | |
112 | 110 | mask = data; |
113 | 111 | } |
114 | 112 | } |
@@ -118,25 +116,52 @@ uint32_t JOYSTICK::read_io8(uint32_t address) | ||
118 | 116 | // ToDo: Implement 6 buttons pad. & mouse |
119 | 117 | uint8_t retval = 0; |
120 | 118 | uint8_t port_num = (address & 0x02) >> 1; |
119 | + uint8_t trig = (mask >> (address & 0x02)) & 0x03; | |
121 | 120 | switch(address) { |
122 | 121 | case 0x04d0: |
123 | 122 | case 0x04d2: |
124 | - if((mask & (0x10 << port_num)) != 0) { | |
125 | - retval = (joydata[port_num] & 0x3f) | 0x40; | |
123 | + if(emulate_mouse[port_num]) { | |
124 | + uint8_t rval = 0xb0; | |
125 | + rval |= update_mouse() & 0x0f; | |
126 | + if((mouse_button & 0x10) != 0) { | |
127 | + rval &= ~0x10; // Button LEFT | |
128 | + } | |
129 | + if((mouse_button & 0x20) != 0) { | |
130 | + rval &= ~0x20; // Button RIGHT | |
131 | + } | |
132 | + retval = rval; | |
126 | 133 | } else { |
127 | - retval = (joydata[port_num] & 0x0f) | 0x30; | |
128 | - } | |
129 | - if((joydata[port_num] & 0x40) != 0) { // RUN = L+R | |
130 | - retval = retval & ~0x0c; | |
131 | - } | |
132 | - if((joydata[port_num] & 0x80) != 0) { // RUN = UP+DOWN | |
133 | - retval = retval & ~0x03; | |
134 | - } | |
135 | - if(((joydata[port_num] & 0x40) != 0) && (mask & (0x01 << (port_num * 2)) != 0)) { | |
136 | - retval = retval & ~0x10; | |
137 | - } | |
138 | - if(((joydata[port_num] & 0x40) != 0) && (mask & (0x02 << (port_num * 2)) != 0)) { | |
139 | - retval = retval & ~0x20; | |
134 | + if((mask & (0x10 << port_num)) != 0) { | |
135 | + retval = 0xff; // COM ON | |
136 | + } else { | |
137 | + retval = 0xbf; // COM OFF | |
138 | + } | |
139 | + if((mask & (0x10 << port_num)) == 0) { | |
140 | + if((joydata[port_num] & 0x40) != 0) { // RUN = L+R | |
141 | + retval = retval & ~0x0c; // LEFT + RIGHT | |
142 | + } else { | |
143 | + if((joydata[port_num] & 0x04) != 0) { // LEFT | |
144 | + retval = retval & ~0x04; // LEFT | |
145 | + } else if((joydata[port_num] & 0x08) != 0) { // RIGHT | |
146 | + retval = retval & ~0x08; // RIGHT | |
147 | + } | |
148 | + } | |
149 | + if((joydata[port_num] & 0x80) != 0) { // RUN = UP+DOWN | |
150 | + retval = retval & ~0x03; // FWD + BACK | |
151 | + } else { | |
152 | + if((joydata[port_num] & 0x01) != 0) { // UP | |
153 | + retval = retval & ~0x01; // FWD | |
154 | + } else if((joydata[port_num] & 0x02) != 0) { // DOWN | |
155 | + retval = retval & ~0x02; // BACK | |
156 | + } | |
157 | + } | |
158 | + } | |
159 | + if(((trig & 0x01) != 0) && ((joydata[port_num] & 0x10) != 0)) { // TRIGGER1 | |
160 | + retval = retval & ~0x10; | |
161 | + } | |
162 | + if(((trig & 0x02) != 0) && ((joydata[port_num] & 0x20) != 0)) { // TRIGGER2 | |
163 | + retval = retval & ~0x20; | |
164 | + } | |
140 | 165 | } |
141 | 166 | return retval; |
142 | 167 | break; |
@@ -148,6 +173,15 @@ uint32_t JOYSTICK::read_io8(uint32_t address) | ||
148 | 173 | |
149 | 174 | void JOYSTICK::event_callback(int event_id, int err) |
150 | 175 | { |
176 | + switch(event_id) { | |
177 | + case EVENT_MOUSE_TIMEOUT: | |
178 | + mouse_phase = 0; | |
179 | + mouse_strobe = false; | |
180 | + mouse_timeout_event = -1; | |
181 | + dx = dy = lx = ly = 0; | |
182 | + mouse_data = ly & 0x0f; | |
183 | + break; | |
184 | + } | |
151 | 185 | } |
152 | 186 | |
153 | 187 | void JOYSTICK::write_signal(int id, uint32_t data, uint32_t mask) |
@@ -156,9 +190,74 @@ void JOYSTICK::write_signal(int id, uint32_t data, uint32_t mask) | ||
156 | 190 | |
157 | 191 | void JOYSTICK::update_config(void) |
158 | 192 | { |
193 | + set_emulate_mouse(); | |
194 | + mouse_type = config.mouse_type; | |
159 | 195 | } |
160 | 196 | |
161 | -#define STATE_VERSION 1 | |
197 | +void JOYSTICK::set_emulate_mouse() | |
198 | +{ | |
199 | + switch(config.mouse_type & 0x03){ | |
200 | + case 1: | |
201 | + emulate_mouse[0] = true; | |
202 | + emulate_mouse[1] = false; | |
203 | + break; | |
204 | + case 2: | |
205 | + emulate_mouse[0] = false; | |
206 | + emulate_mouse[1] = true; | |
207 | + break; | |
208 | + default: | |
209 | + emulate_mouse[0] = false; | |
210 | + emulate_mouse[1] = false; | |
211 | + break; | |
212 | + } | |
213 | +} | |
214 | + | |
215 | +void JOYSTICK::update_strobe(bool flag) | |
216 | +{ | |
217 | + if(mouse_strobe != flag) { | |
218 | + mouse_strobe = flag; | |
219 | + if((mouse_phase == 0)) { | |
220 | + // Sample data from MOUSE to registers. | |
221 | + lx = -dx; | |
222 | + ly = -dy; | |
223 | + dx = 0; | |
224 | + dy = 0; | |
225 | + if(mouse_timeout_event >= 0) { | |
226 | + cancel_event(this, mouse_timeout_event); | |
227 | + } | |
228 | + register_event(this, EVENT_MOUSE_TIMEOUT, 2000.0, false, &mouse_timeout_event); | |
229 | + } | |
230 | + mouse_phase++; | |
231 | + if(mouse_phase >= 4) { | |
232 | + mouse_phase = 0; | |
233 | +// if(mouse_timeout_event >= 0) { | |
234 | +// cancel_event(this, mouse_timeout_event); | |
235 | +// mouse_timeout_event = -1; | |
236 | +// } | |
237 | + } | |
238 | + } | |
239 | +} | |
240 | + | |
241 | +uint32_t JOYSTICK::update_mouse() | |
242 | +{ | |
243 | + switch(mouse_phase) { | |
244 | + case 1: | |
245 | + mouse_data = (lx >> 1) & 0x0f; | |
246 | + break; | |
247 | + case 2: | |
248 | + mouse_data = (lx >> 5) & 0x0f; | |
249 | + break; | |
250 | + case 3: | |
251 | + mouse_data = (ly >> 1) & 0x0f; | |
252 | + break; | |
253 | + case 0: | |
254 | + mouse_data = (ly >> 5) & 0x0f; | |
255 | + break; | |
256 | + } | |
257 | + return mouse_data; | |
258 | +} | |
259 | + | |
260 | +#define STATE_VERSION 2 | |
162 | 261 | |
163 | 262 | bool JOYSTICK::process_state(FILEIO *state_fio, bool loading) |
164 | 263 | { |
@@ -176,12 +275,12 @@ bool JOYSTICK::process_state(FILEIO *state_fio, bool loading) | ||
176 | 275 | state_fio->StateValue(lx); |
177 | 276 | state_fio->StateValue(ly); |
178 | 277 | state_fio->StateValue(mouse_button); |
278 | + state_fio->StateValue(mouse_type); | |
179 | 279 | state_fio->StateValue(mouse_strobe); |
180 | 280 | state_fio->StateValue(mouse_phase); |
181 | 281 | state_fio->StateValue(mouse_data); |
182 | - //state_fio->StateValue(mouse_timeout_event); | |
282 | + state_fio->StateValue(mouse_timeout_event); | |
183 | 283 | |
184 | - | |
185 | 284 | return true; |
186 | 285 | } |
187 | 286 |
@@ -25,12 +25,18 @@ private: | ||
25 | 25 | int dx, dy; |
26 | 26 | int lx, ly; |
27 | 27 | uint32_t mouse_button; |
28 | - bool mouse_strobe; | |
29 | - uint32_t mouse_data; | |
30 | 28 | int mouse_phase; |
29 | + bool mouse_strobe; | |
30 | + uint8_t mouse_data; | |
31 | + | |
31 | 32 | int mouse_timeout_event; |
32 | 33 | int mouse_type; |
33 | 34 | uint8_t mask; |
35 | + | |
36 | + void set_emulate_mouse(); | |
37 | + virtual void update_strobe(bool flag); | |
38 | + uint32_t update_mouse(); | |
39 | + | |
34 | 40 | public: |
35 | 41 | JOYSTICK(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) |
36 | 42 | { |