summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/inputdev.h
blob: f6f0027b325b3ae01751eedd97bf12c965916f52 (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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    inputdev.h

    Input devices, items and device classes.

***************************************************************************/

#ifndef MAME_EMU_INPUTDEV_H
#define MAME_EMU_INPUTDEV_H

#pragma once


//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************

// callback for getting the value of an item on a device
typedef s32 (*item_get_state_func)(void *device_internal, void *item_internal);

// ======================> joystick_map

// a 9x9 joystick map
class joystick_map
{
public:
	// construction/destruction
	joystick_map();
	joystick_map(const joystick_map &src) { copy(src); }

	// operators
	joystick_map &operator=(const joystick_map &src) { if (this != &src) copy(src); return *this; }

	// parse from a string
	bool parse(const char *mapstring);

	// create a friendly string
	std::string to_string() const;

	// update the state of a live map
	u8 update(s32 xaxisval, s32 yaxisval);

	// joystick mapping codes
	static constexpr u8 JOYSTICK_MAP_NEUTRAL = 0x00;
	static constexpr u8 JOYSTICK_MAP_LEFT    = 0x01;
	static constexpr u8 JOYSTICK_MAP_RIGHT   = 0x02;
	static constexpr u8 JOYSTICK_MAP_UP      = 0x04;
	static constexpr u8 JOYSTICK_MAP_DOWN    = 0x08;
	static constexpr u8 JOYSTICK_MAP_STICKY  = 0x0f;

private:
	// internal helpers
	void copy(const joystick_map &src)
	{
		memcpy(m_map, src.m_map, sizeof(m_map));
		m_lastmap = JOYSTICK_MAP_NEUTRAL;
		m_origstring = src.m_origstring;
	}

	// internal state
	u8                      m_map[9][9];            // 9x9 grid
	u8                      m_lastmap;              // last value returned (for sticky tracking)
	std::string             m_origstring;           // originally parsed string
};


// ======================> input_device_item

// a single item on an input device
class input_device_item
{
protected:
	// construction/destruction
	input_device_item(input_device &device, const char *name, void *internal, input_item_id itemid, item_get_state_func getstate, input_item_class itemclass);

public:
	virtual ~input_device_item();

	// getters
	input_device &device() const { return m_device; }
	input_manager &manager() const;
	running_machine &machine() const;
	const char *name() const { return m_name.c_str(); }
	void *internal() const { return m_internal; }
	input_item_id itemid() const { return m_itemid; }
	input_item_class itemclass() const { return m_itemclass; }
	input_code code() const;
	const char *token() const { return m_token.c_str(); }
	s32 current() const { return m_current; }
	s32 memory() const { return m_memory; }

	// helpers
	s32 update_value();
	void set_memory(s32 value) { m_memory = value; }

	// readers
	virtual s32 read_as_switch(input_item_modifier modifier) = 0;
	virtual s32 read_as_relative(input_item_modifier modifier) = 0;
	virtual s32 read_as_absolute(input_item_modifier modifier) = 0;

protected:
	// internal state
	input_device &          m_device;               // reference to our owning device
	std::string             m_name;                 // string name of item
	void *                  m_internal;             // internal callback pointer
	input_item_id           m_itemid;               // originally specified item id
	input_item_class        m_itemclass;            // class of the item
	item_get_state_func     m_getstate;             // get state callback
	std::string             m_token;                // tokenized name for non-standard items

	// live state
	s32                     m_current;              // current raw value
	s32                     m_memory;               // "memory" value, to remember where we started during polling
};


// ======================> input_device

// a logical device of a given class that can provide input
class input_device
{
	friend class input_class;

public:
	// construction/destruction
	input_device(input_manager &manager, const char *_name, const char *_id, void *_internal);
	virtual ~input_device();

	// getters
	input_manager &manager() const { return m_manager; }
	running_machine &machine() const { return m_manager.machine(); }
	input_device_class devclass() const { return device_class(); }
	const char *name() const { return m_name.c_str(); }
	const char *id() const { return m_id.c_str(); }
	int devindex() const { return m_devindex; }
	input_device_item *item(input_item_id index) const { return m_item[index].get(); }
	input_item_id maxitem() const { return m_maxitem; }
	void *internal() const { return m_internal; }
	bool steadykey_enabled() const { return m_steadykey_enabled; }
	bool lightgun_reload_button() const { return m_lightgun_reload_button; }

	// setters
	void set_devindex(int devindex) { m_devindex = devindex; }

	// item management
	input_item_id add_item(const char *name, input_item_id itemid, item_get_state_func getstate, void *internal = nullptr);

	// helpers
	s32 adjust_absolute(s32 value) const { return adjust_absolute_value(value); }
	bool match_device_id(const char *deviceid);

protected:
	// specific overrides
	virtual input_device_class device_class() const = 0;
	virtual s32 adjust_absolute_value(s32 value) const { return value; }

private:
	// internal state
	input_manager &         m_manager;              // reference to input manager
	std::string             m_name;                 // string name of device
	std::string             m_id;                   // id of device
	int                     m_devindex;             // device index of this device
	std::unique_ptr<input_device_item> m_item[ITEM_ID_ABSOLUTE_MAXIMUM+1]; // array of pointers to items
	input_item_id           m_maxitem;              // maximum item index
	void *                  m_internal;             // internal callback pointer

	bool                    m_steadykey_enabled;    // steadykey enabled for keyboards
	bool                    m_lightgun_reload_button; // lightgun reload hack
};


// ======================> input_device_keyboard

class input_device_keyboard : public input_device
{
public:
	// construction/destruction
	input_device_keyboard(input_manager &manager, const char *_name, const char *_id, void *_internal);

	// helpers
	void apply_steadykey() const;

protected:
	// specific overrides
	virtual input_device_class device_class() const override { return DEVICE_CLASS_KEYBOARD; }
};


// ======================> input_device_mouse

class input_device_mouse : public input_device
{
public:
	// construction/destruction
	input_device_mouse(input_manager &manager, const char *_name, const char *_id, void *_internal);

protected:
	// specific overrides
	virtual input_device_class device_class() const override { return DEVICE_CLASS_MOUSE; }
};


// ======================> input_device_lightgun

class input_device_lightgun : public input_device
{
public:
	// construction/destruction
	input_device_lightgun(input_manager &manager, const char *_name, const char *_id, void *_internal);

protected:
	// specific overrides
	virtual input_device_class device_class() const override { return DEVICE_CLASS_LIGHTGUN; }
};


// ======================> input_device_joystick

// a logical device of a given class that can provide input
class input_device_joystick : public input_device
{
public:
	// construction/destruction
	input_device_joystick(input_manager &manager, const char *_name, const char *_id, void *_internal);

	// getters
	joystick_map &joymap() { return m_joymap; }

	// item management
	void set_joystick_map(const joystick_map &map) { m_joymap = map; }

protected:
	// specific overrides
	virtual input_device_class device_class() const override { return DEVICE_CLASS_JOYSTICK; }
	virtual s32 adjust_absolute_value(s32 value) const override;

private:
	// joystick information
	joystick_map            m_joymap;               // joystick map for this device
	s32                     m_joystick_deadzone;    // deadzone for joystick
	s32                     m_joystick_saturation;  // saturation position for joystick
};


// ======================> input_class

// a class of device that provides input
class input_class
{
public:
	// construction/destruction
	input_class(input_manager &manager, input_device_class devclass, const char *name, bool enabled = false, bool multi = false);
	virtual ~input_class();

	// getters
	input_manager &manager() const { return m_manager; }
	running_machine &machine() const  { return m_manager.machine(); }
	input_device *device(int index) const { return (index <= m_maxindex) ? m_device[index].get() : nullptr; }
	input_device_class devclass() const { return m_devclass; }
	const char *name() const { return m_name; }
	int maxindex() const { return m_maxindex; }
	bool enabled() const { return m_enabled; }
	bool multi() const { return m_multi; }

	// setters
	void enable(bool state = true) { m_enabled = state; }
	void set_multi(bool multi = true) { m_multi = multi; }

	// device management
	input_device *add_device(const char *name, const char *id, void *internal = nullptr);
	input_device *add_device(std::unique_ptr<input_device> &&new_device);

	// misc helpers
	input_item_class standard_item_class(input_item_id itemid) const;
	void remap_device_index(int oldindex, int newindex);

protected:
	// specific overrides
	virtual std::unique_ptr<input_device> make_device(const char *name, const char *id, void *internal) = 0;

private:
	// indexing helpers
	int newindex(input_device &device);

	// internal state
	input_manager &         m_manager;              // reference to our manager
	std::unique_ptr<input_device> m_device[DEVICE_INDEX_MAXIMUM]; // array of devices in this class
	input_device_class      m_devclass;             // our device class
	const char *            m_name;                 // name of class (used for option settings)
	int                     m_maxindex;             // maximum populated index
	bool                    m_enabled;              // is this class enabled?
	bool                    m_multi;                // are multiple instances of this class allowed?
};


// ======================> input_class_keyboard

// class of device that provides keyboard input
class input_class_keyboard : public input_class
{
public:
	// construction/destruction
	input_class_keyboard(input_manager &manager);

protected:
	// specific overrides
	virtual std::unique_ptr<input_device> make_device(const char *name, const char *id, void *internal) override
	{
		return std::make_unique<input_device_keyboard>(manager(), name, id, internal);
	}

private:
	// internal helpers
	void frame_callback();
};


// ======================> input_class_mouse

// class of device that provides mouse input
class input_class_mouse : public input_class
{
public:
	// construction/destruction
	input_class_mouse(input_manager &manager);

protected:
	// specific overrides
	virtual std::unique_ptr<input_device> make_device(const char *name, const char *id, void *internal) override
	{
		return std::make_unique<input_device_mouse>(manager(), name, id, internal);
	}
};


// ======================> input_class_lightgun

// class of device that provides lightgun input
class input_class_lightgun : public input_class
{
public:
	// construction/destruction
	input_class_lightgun(input_manager &manager);

protected:
	// specific overrides
	virtual std::unique_ptr<input_device> make_device(const char *name, const char *id, void *internal) override
	{
		return std::make_unique<input_device_lightgun>(manager(), name, id, internal);
	}
};


// ======================> input_class_joystick

// class of device that provides joystick input
class input_class_joystick : public input_class
{
public:
	// construction/destruction
	input_class_joystick(input_manager &manager);

	// misc
	bool set_global_joystick_map(const char *mapstring);

	// standard joystick maps
	static const char map_8way[];
	static const char map_4way_diagonal[];

protected:
	// specific overrides
	virtual std::unique_ptr<input_device> make_device(const char *name, const char *id, void *internal) override
	{
		return std::make_unique<input_device_joystick>(manager(), name, id, internal);
	}
};


//**************************************************************************
//  INLINE FUNCTIONS
//**************************************************************************

// input_device_item helpers
inline input_manager &input_device_item::manager() const { return m_device.manager(); }
inline running_machine &input_device_item::machine() const { return m_device.machine(); }
inline input_code input_device_item::code() const { return input_code(m_device.devclass(), m_device.devindex(), m_itemclass, ITEM_MODIFIER_NONE, m_itemid); }
inline s32 input_device_item::update_value() { return m_current = (*m_getstate)(m_device.internal(), m_internal); }

#endif  // MAME_EMU_INPUTDEV_H