103
131
#include <ctype.h>
104
132
#include <time.h>
106
/* temporary: set this to 1 to enable the originally defined behavior that
107
a field specified via PORT_MODIFY which intersects a previously-defined
108
field completely wipes out the previous definition */
134
// temporary: set this to 1 to enable the originally defined behavior that
135
// a field specified via PORT_MODIFY which intersects a previously-defined
136
// field completely wipes out the previous definition
109
137
#define INPUT_PORT_OVERRIDE_FULLY_NUKES_PREVIOUS 1
112
/***************************************************************************
114
***************************************************************************/
116
#define DIGITAL_JOYSTICKS_PER_PLAYER 3
118
/* these constants must match the order of the joystick directions in the IPT definition */
120
#define JOYDIR_DOWN 1
121
#define JOYDIR_LEFT 2
122
#define JOYDIR_RIGHT 3
124
#define JOYDIR_UP_BIT (1 << JOYDIR_UP)
125
#define JOYDIR_DOWN_BIT (1 << JOYDIR_DOWN)
126
#define JOYDIR_LEFT_BIT (1 << JOYDIR_LEFT)
127
#define JOYDIR_RIGHT_BIT (1 << JOYDIR_RIGHT)
129
#define NUM_SIMUL_KEYS (UCHAR_SHIFT_END - UCHAR_SHIFT_BEGIN + 1)
131
#define SPACE_COUNT 3
132
#define INVALID_CHAR '?'
133
#define IP_NAME_DEFAULT NULL
136
/***************************************************************************
138
***************************************************************************/
140
/* live analog field information */
141
typedef struct _analog_field_state analog_field_state;
142
struct _analog_field_state
144
analog_field_state * next; /* link to the next analog state for this port */
145
const input_field_config * field; /* pointer to the input field referenced */
147
/* adjusted values (right-justified and tweaked) */
148
UINT8 shift; /* shift to align final value in the port */
149
INT32 adjdefvalue; /* adjusted default value from the config */
150
INT32 adjmin; /* adjusted minimum value from the config */
151
INT32 adjmax; /* adjusted maximum value from the config */
153
/* live values of configurable parameters */
154
INT32 sensitivity; /* current live sensitivity (100=normal) */
155
UINT8 reverse; /* current live reverse flag */
156
INT32 delta; /* current live delta to apply each frame a digital inc/dec key is pressed */
157
INT32 centerdelta; /* current live delta to apply each frame no digital inputs are pressed */
159
/* live analog value tracking */
160
INT32 accum; /* accumulated value (including relative adjustments) */
161
INT32 previous; /* previous adjusted value */
162
INT32 previousanalog; /* previous analog value */
164
/* parameters for modifying live values */
165
INT32 minimum; /* minimum adjusted value */
166
INT32 maximum; /* maximum adjusted value */
167
INT32 center; /* center adjusted value for autocentering */
168
INT32 reverse_val; /* value where we subtract from to reverse directions */
170
/* scaling factors */
171
INT64 scalepos; /* scale factor to apply to positive adjusted values */
172
INT64 scaleneg; /* scale factor to apply to negative adjusted values */
173
INT64 keyscalepos; /* scale factor to apply to the key delta field when pos */
174
INT64 keyscaleneg; /* scale factor to apply to the key delta field when neg */
175
INT64 positionalscale; /* scale factor to divide a joystick into positions */
178
UINT8 absolute; /* is this an absolute or relative input? */
179
UINT8 wraps; /* does the control wrap around? */
180
UINT8 autocenter; /* autocenter this input? */
181
UINT8 single_scale; /* scale joystick differently if default is between min/max */
182
UINT8 interpolate; /* should we do linear interpolation for mid-frame reads? */
183
UINT8 lastdigital; /* was the last modification caused by a digital form? */
187
/* shared digital joystick state */
188
typedef struct _digital_joystick_state digital_joystick_state;
189
struct _digital_joystick_state
191
const input_field_config * field[4]; /* input field for up, down, left, right respectively */
192
UINT8 inuse; /* is this joystick used? */
193
UINT8 current; /* current value */
194
UINT8 current4way; /* current 4-way value */
195
UINT8 previous; /* previous value */
199
/* live device field information */
200
typedef struct _device_field_info device_field_info;
201
struct _device_field_info
203
device_field_info * next; /* linked list of info for this port */
204
const input_field_config * field; /* pointer to the input field referenced */
205
device_t * device; /* device */
206
UINT8 shift; /* shift to apply to the final result */
207
input_port_value oldval; /* last value */
211
/* internal live state of an input field */
212
struct _input_field_state
214
analog_field_state * analog; /* pointer to live analog data if this is an analog field */
215
digital_joystick_state * joystick; /* pointer to digital joystick information */
216
input_seq seq[SEQ_TYPE_TOTAL];/* currently configured input sequences */
217
input_port_value value; /* current value of this port */
218
UINT8 impulse; /* counter for impulse controls */
219
UINT8 last; /* were we pressed last time? */
220
UINT8 joydir; /* digital joystick direction index */
221
char * name; /* overridden name */
225
/* internal live state of an input port */
226
struct _input_port_state
228
analog_field_state * analoglist; /* pointer to list of analog port info */
229
device_field_info * readdevicelist; /* pointer to list of input device info */
230
device_field_info * writedevicelist; /* pointer to list of output device info */
231
input_port_value defvalue; /* combined default value across the port */
232
input_port_value digital; /* current value from all digital inputs */
233
input_port_value vblank; /* value of all IPT_VBLANK bits */
234
input_port_value outputvalue; /* current value for outputs */
238
typedef struct _inputx_code inputx_code;
242
const input_field_config * field[NUM_SIMUL_KEYS];
245
typedef struct _key_buffer key_buffer;
250
unsigned int status_keydown : 1;
251
unicode_char buffer[4096];
254
typedef struct _char_info char_info;
140
//**************************************************************************
142
//**************************************************************************
144
#define LOG_NATURAL_KEYBOARD 0
148
//**************************************************************************
150
//**************************************************************************
152
const int SPACE_COUNT = 3;
153
const int KEY_BUFFER_SIZE = 4096;
154
const unicode_char INVALID_CHAR = '?';
158
//**************************************************************************
160
//**************************************************************************
162
// live analog field information
165
friend class simple_list<analog_field>;
166
friend class ioport_manager;
167
friend void ioport_field::set_user_settings(const ioport_field::user_settings &settings);
170
// construction/destruction
171
analog_field(ioport_field &field);
174
analog_field *next() const { return m_next; }
175
ioport_manager &manager() const { return m_field.manager(); }
176
ioport_field &field() const { return m_field; }
177
INT32 sensitivity() const { return m_sensitivity; }
178
bool reverse() const { return m_reverse; }
179
INT32 delta() const { return m_delta; }
180
INT32 centerdelta() const { return m_centerdelta; }
183
void read(ioport_value &value);
184
float crosshair_read();
185
void frame_update(running_machine &machine);
189
INT32 apply_min_max(INT32 value) const;
190
INT32 apply_settings(INT32 value) const;
191
INT32 apply_sensitivity(INT32 value) const;
192
INT32 apply_inverse_sensitivity(INT32 value) const;
195
analog_field * m_next; // link to the next analog state for this port
196
ioport_field & m_field; // pointer to the input field referenced
198
// adjusted values (right-justified and tweaked)
199
UINT8 m_shift; // shift to align final value in the port
200
INT32 m_adjdefvalue; // adjusted default value from the config
201
INT32 m_adjmin; // adjusted minimum value from the config
202
INT32 m_adjmax; // adjusted maximum value from the config
204
// live values of configurable parameters
205
INT32 m_sensitivity; // current live sensitivity (100=normal)
206
bool m_reverse; // current live reverse flag
207
INT32 m_delta; // current live delta to apply each frame a digital inc/dec key is pressed
208
INT32 m_centerdelta; // current live delta to apply each frame no digital inputs are pressed
210
// live analog value tracking
211
INT32 m_accum; // accumulated value (including relative adjustments)
212
INT32 m_previous; // previous adjusted value
213
INT32 m_previousanalog; // previous analog value
215
// parameters for modifying live values
216
INT32 m_minimum; // minimum adjusted value
217
INT32 m_maximum; // maximum adjusted value
218
INT32 m_center; // center adjusted value for autocentering
219
INT32 m_reverse_val; // value where we subtract from to reverse directions
222
INT64 m_scalepos; // scale factor to apply to positive adjusted values
223
INT64 m_scaleneg; // scale factor to apply to negative adjusted values
224
INT64 m_keyscalepos; // scale factor to apply to the key delta field when pos
225
INT64 m_keyscaleneg; // scale factor to apply to the key delta field when neg
226
INT64 m_positionalscale; // scale factor to divide a joystick into positions
229
bool m_absolute; // is this an absolute or relative input?
230
bool m_wraps; // does the control wrap around?
231
bool m_autocenter; // autocenter this input?
232
bool m_single_scale; // scale joystick differently if default is between min/max
233
bool m_interpolate; // should we do linear interpolation for mid-frame reads?
234
bool m_lastdigital; // was the last modification caused by a digital form?
238
// live device field information
241
friend class simple_list<dynamic_field>;
244
// construction/destruction
245
dynamic_field(ioport_field &field);
248
dynamic_field *next() const { return m_next; }
249
ioport_field &field() const { return m_field; }
252
void read(ioport_value &result);
253
void write(ioport_value newval);
257
dynamic_field * m_next; // linked list of info for this port
258
ioport_field & m_field; // reference to the input field
259
UINT8 m_shift; // shift to apply to the final result
260
ioport_value m_oldval; // last value
264
// internal live state of an input field
265
struct ioport_field_live
267
// construction/destruction
268
ioport_field_live(ioport_field &field, analog_field *analog);
271
analog_field * analog; // pointer to live analog data if this is an analog field
272
digital_joystick * joystick; // pointer to digital joystick information
273
input_seq seq[SEQ_TYPE_TOTAL];// currently configured input sequences
274
ioport_value value; // current value of this port
275
UINT8 impulse; // counter for impulse controls
276
bool last; // were we pressed last time?
277
digital_joystick::direction_t joydir; // digital joystick direction index
278
astring name; // overridden name
282
// internal live state of an input port
283
struct ioport_port_live
285
// construction/destruction
286
ioport_port_live(ioport_port &port);
289
simple_list<analog_field> analoglist; // list of analog port info
290
simple_list<dynamic_field> readlist; // list of dynamic read fields
291
simple_list<dynamic_field> writelist; // list of dynamic write fields
292
ioport_value defvalue; // combined default value across the port
293
ioport_value digital; // current value from all digital inputs
294
ioport_value outputvalue; // current value for outputs
298
// character information
258
302
const char *name;
259
const char *alternate; /* alternative string, in UTF-8 */
263
/* private input port state */
264
struct _input_port_private
267
UINT8 safe_to_read; /* clear at start; set after state is loaded */
270
simple_list<input_type_entry> typelist; /* list of live type states */
271
input_type_entry * type_to_entry[__ipt_max][MAX_PLAYERS]; /* map from type/player to type state */
273
/* specific special global input states */
274
digital_joystick_state joystick_info[MAX_PLAYERS][DIGITAL_JOYSTICKS_PER_PLAYER]; /* joystick states */
276
/* frame time tracking */
277
attotime last_frame_time; /* time of the last frame callback */
278
attoseconds_t last_delta_nsec; /* nanoseconds that passed since the previous callback */
280
/* playback/record information */
281
emu_file * record_file; /* recording file (NULL if not recording) */
282
emu_file * playback_file; /* playback file (NULL if not recording) */
283
UINT64 playback_accumulated_speed;/* accumulated speed during playback */
284
UINT32 playback_accumulated_frames;/* accumulated frames during playback */
288
key_buffer *keybuffer;
289
emu_timer *inputx_timer;
290
int (*queue_chars)(running_machine &machine, const unicode_char *text, size_t text_len);
291
int (*accept_char)(running_machine &machine, unicode_char ch);
292
int (*charqueue_empty)(running_machine &machine);
293
attotime current_rate;
297
/***************************************************************************
299
***************************************************************************/
301
#define APPLY_SENSITIVITY(x,s) (((INT64)(x) * (s)) / 100.0 + 0.5)
302
#define APPLY_INVERSE_SENSITIVITY(x,s) (((INT64)(x) * 100) / (s))
304
#define COMPUTE_SCALE(num,den) (((INT64)(num) << 24) / (den))
305
#define RECIP_SCALE(s) (((INT64)1 << 48) / (s))
306
#define APPLY_SCALE(x,s) (((INT64)(x) * (s)) >> 24)
310
/***************************************************************************
312
***************************************************************************/
314
/* XML attributes for the different types */
303
const char *alternate; // alternative string, in UTF-8
305
static const char_info *find(unicode_char target);
310
//**************************************************************************
312
//**************************************************************************
314
//-------------------------------------------------
315
// compute_scale -- compute an 8.24 scale value
316
// from a numerator and a denominator
317
//-------------------------------------------------
319
inline INT64 compute_scale(INT32 num, INT32 den)
321
return (INT64(num) << 24) / den;
325
//-------------------------------------------------
326
// recip_scale -- compute an 8.24 reciprocal of
327
// an 8.24 scale value
328
//-------------------------------------------------
330
inline INT64 recip_scale(INT64 scale)
332
return (INT64(1) << 48) / scale;
336
//-------------------------------------------------
337
// apply_scale -- apply an 8.24 scale value to
339
//-------------------------------------------------
341
inline INT32 apply_scale(INT32 value, INT64 scale)
343
return (INT64(value) * scale) >> 24;
348
//**************************************************************************
350
//**************************************************************************
352
// XML attributes for the different types
315
353
static const char *const seqtypestrings[] = { "standard", "increment", "decrement" };
355
// master character info table
318
356
static const char_info charinfo[] =
320
{ 0x0008, "Backspace", NULL }, /* Backspace */
321
{ 0x0009, "Tab", " " }, /* Tab */
322
{ 0x000c, "Clear", NULL }, /* Clear */
323
{ 0x000d, "Enter", NULL }, /* Enter */
324
{ 0x001a, "Esc", NULL }, /* Esc */
325
{ 0x0020, "Space", " " }, /* Space */
326
{ 0x0061, NULL, "A" }, /* a */
327
{ 0x0062, NULL, "B" }, /* b */
328
{ 0x0063, NULL, "C" }, /* c */
329
{ 0x0064, NULL, "D" }, /* d */
330
{ 0x0065, NULL, "E" }, /* e */
331
{ 0x0066, NULL, "F" }, /* f */
332
{ 0x0067, NULL, "G" }, /* g */
333
{ 0x0068, NULL, "H" }, /* h */
334
{ 0x0069, NULL, "I" }, /* i */
335
{ 0x006a, NULL, "J" }, /* j */
336
{ 0x006b, NULL, "K" }, /* k */
337
{ 0x006c, NULL, "L" }, /* l */
338
{ 0x006d, NULL, "M" }, /* m */
339
{ 0x006e, NULL, "N" }, /* n */
340
{ 0x006f, NULL, "O" }, /* o */
341
{ 0x0070, NULL, "P" }, /* p */
342
{ 0x0071, NULL, "Q" }, /* q */
343
{ 0x0072, NULL, "R" }, /* r */
344
{ 0x0073, NULL, "S" }, /* s */
345
{ 0x0074, NULL, "T" }, /* t */
346
{ 0x0075, NULL, "U" }, /* u */
347
{ 0x0076, NULL, "V" }, /* v */
348
{ 0x0077, NULL, "W" }, /* w */
349
{ 0x0078, NULL, "X" }, /* x */
350
{ 0x0079, NULL, "Y" }, /* y */
351
{ 0x007a, NULL, "Z" }, /* z */
352
{ 0x00a0, NULL, " " }, /* non breaking space */
353
{ 0x00a1, NULL, "!" }, /* inverted exclaimation mark */
354
{ 0x00a6, NULL, "|" }, /* broken bar */
355
{ 0x00a9, NULL, "(c)" }, /* copyright sign */
356
{ 0x00ab, NULL, "<<" }, /* left pointing double angle */
357
{ 0x00ae, NULL, "(r)" }, /* registered sign */
358
{ 0x00bb, NULL, ">>" }, /* right pointing double angle */
359
{ 0x00bc, NULL, "1/4" }, /* vulgar fraction one quarter */
360
{ 0x00bd, NULL, "1/2" }, /* vulgar fraction one half */
361
{ 0x00be, NULL, "3/4" }, /* vulgar fraction three quarters */
362
{ 0x00bf, NULL, "?" }, /* inverted question mark */
363
{ 0x00c0, NULL, "A" }, /* 'A' grave */
364
{ 0x00c1, NULL, "A" }, /* 'A' acute */
365
{ 0x00c2, NULL, "A" }, /* 'A' circumflex */
366
{ 0x00c3, NULL, "A" }, /* 'A' tilde */
367
{ 0x00c4, NULL, "A" }, /* 'A' diaeresis */
368
{ 0x00c5, NULL, "A" }, /* 'A' ring above */
369
{ 0x00c6, NULL, "AE" }, /* 'AE' ligature */
370
{ 0x00c7, NULL, "C" }, /* 'C' cedilla */
371
{ 0x00c8, NULL, "E" }, /* 'E' grave */
372
{ 0x00c9, NULL, "E" }, /* 'E' acute */
373
{ 0x00ca, NULL, "E" }, /* 'E' circumflex */
374
{ 0x00cb, NULL, "E" }, /* 'E' diaeresis */
375
{ 0x00cc, NULL, "I" }, /* 'I' grave */
376
{ 0x00cd, NULL, "I" }, /* 'I' acute */
377
{ 0x00ce, NULL, "I" }, /* 'I' circumflex */
378
{ 0x00cf, NULL, "I" }, /* 'I' diaeresis */
379
{ 0x00d0, NULL, "D" }, /* 'ETH' */
380
{ 0x00d1, NULL, "N" }, /* 'N' tilde */
381
{ 0x00d2, NULL, "O" }, /* 'O' grave */
382
{ 0x00d3, NULL, "O" }, /* 'O' acute */
383
{ 0x00d4, NULL, "O" }, /* 'O' circumflex */
384
{ 0x00d5, NULL, "O" }, /* 'O' tilde */
385
{ 0x00d6, NULL, "O" }, /* 'O' diaeresis */
386
{ 0x00d7, NULL, "X" }, /* multiplication sign */
387
{ 0x00d8, NULL, "O" }, /* 'O' stroke */
388
{ 0x00d9, NULL, "U" }, /* 'U' grave */
389
{ 0x00da, NULL, "U" }, /* 'U' acute */
390
{ 0x00db, NULL, "U" }, /* 'U' circumflex */
391
{ 0x00dc, NULL, "U" }, /* 'U' diaeresis */
392
{ 0x00dd, NULL, "Y" }, /* 'Y' acute */
393
{ 0x00df, NULL, "SS" }, /* sharp S */
394
{ 0x00e0, NULL, "a" }, /* 'a' grave */
395
{ 0x00e1, NULL, "a" }, /* 'a' acute */
396
{ 0x00e2, NULL, "a" }, /* 'a' circumflex */
397
{ 0x00e3, NULL, "a" }, /* 'a' tilde */
398
{ 0x00e4, NULL, "a" }, /* 'a' diaeresis */
399
{ 0x00e5, NULL, "a" }, /* 'a' ring above */
400
{ 0x00e6, NULL, "ae" }, /* 'ae' ligature */
401
{ 0x00e7, NULL, "c" }, /* 'c' cedilla */
402
{ 0x00e8, NULL, "e" }, /* 'e' grave */
403
{ 0x00e9, NULL, "e" }, /* 'e' acute */
404
{ 0x00ea, NULL, "e" }, /* 'e' circumflex */
405
{ 0x00eb, NULL, "e" }, /* 'e' diaeresis */
406
{ 0x00ec, NULL, "i" }, /* 'i' grave */
407
{ 0x00ed, NULL, "i" }, /* 'i' acute */
408
{ 0x00ee, NULL, "i" }, /* 'i' circumflex */
409
{ 0x00ef, NULL, "i" }, /* 'i' diaeresis */
410
{ 0x00f0, NULL, "d" }, /* 'eth' */
411
{ 0x00f1, NULL, "n" }, /* 'n' tilde */
412
{ 0x00f2, NULL, "o" }, /* 'o' grave */
413
{ 0x00f3, NULL, "o" }, /* 'o' acute */
414
{ 0x00f4, NULL, "o" }, /* 'o' circumflex */
415
{ 0x00f5, NULL, "o" }, /* 'o' tilde */
416
{ 0x00f6, NULL, "o" }, /* 'o' diaeresis */
417
{ 0x00f8, NULL, "o" }, /* 'o' stroke */
418
{ 0x00f9, NULL, "u" }, /* 'u' grave */
419
{ 0x00fa, NULL, "u" }, /* 'u' acute */
420
{ 0x00fb, NULL, "u" }, /* 'u' circumflex */
421
{ 0x00fc, NULL, "u" }, /* 'u' diaeresis */
422
{ 0x00fd, NULL, "y" }, /* 'y' acute */
423
{ 0x00ff, NULL, "y" }, /* 'y' diaeresis */
424
{ 0x2010, NULL, "-" }, /* hyphen */
425
{ 0x2011, NULL, "-" }, /* non-breaking hyphen */
426
{ 0x2012, NULL, "-" }, /* figure dash */
427
{ 0x2013, NULL, "-" }, /* en dash */
428
{ 0x2014, NULL, "-" }, /* em dash */
429
{ 0x2015, NULL, "-" }, /* horizontal dash */
430
{ 0x2018, NULL, "\'" }, /* left single quotation mark */
431
{ 0x2019, NULL, "\'" }, /* right single quotation mark */
432
{ 0x201a, NULL, "\'" }, /* single low quotation mark */
433
{ 0x201b, NULL, "\'" }, /* single high reversed quotation mark */
434
{ 0x201c, NULL, "\"" }, /* left double quotation mark */
435
{ 0x201d, NULL, "\"" }, /* right double quotation mark */
436
{ 0x201e, NULL, "\"" }, /* double low quotation mark */
437
{ 0x201f, NULL, "\"" }, /* double high reversed quotation mark */
438
{ 0x2024, NULL, "." }, /* one dot leader */
439
{ 0x2025, NULL, ".." }, /* two dot leader */
440
{ 0x2026, NULL, "..." }, /* horizontal ellipsis */
441
{ 0x2047, NULL, "??" }, /* double question mark */
442
{ 0x2048, NULL, "?!" }, /* question exclamation mark */
443
{ 0x2049, NULL, "!?" }, /* exclamation question mark */
444
{ 0xff01, NULL, "!" }, /* fullwidth exclamation point */
445
{ 0xff02, NULL, "\"" }, /* fullwidth quotation mark */
446
{ 0xff03, NULL, "#" }, /* fullwidth number sign */
447
{ 0xff04, NULL, "$" }, /* fullwidth dollar sign */
448
{ 0xff05, NULL, "%" }, /* fullwidth percent sign */
449
{ 0xff06, NULL, "&" }, /* fullwidth ampersand */
450
{ 0xff07, NULL, "\'" }, /* fullwidth apostrophe */
451
{ 0xff08, NULL, "(" }, /* fullwidth left parenthesis */
452
{ 0xff09, NULL, ")" }, /* fullwidth right parenthesis */
453
{ 0xff0a, NULL, "*" }, /* fullwidth asterisk */
454
{ 0xff0b, NULL, "+" }, /* fullwidth plus */
455
{ 0xff0c, NULL, "," }, /* fullwidth comma */
456
{ 0xff0d, NULL, "-" }, /* fullwidth minus */
457
{ 0xff0e, NULL, "." }, /* fullwidth period */
458
{ 0xff0f, NULL, "/" }, /* fullwidth slash */
459
{ 0xff10, NULL, "0" }, /* fullwidth zero */
460
{ 0xff11, NULL, "1" }, /* fullwidth one */
461
{ 0xff12, NULL, "2" }, /* fullwidth two */
462
{ 0xff13, NULL, "3" }, /* fullwidth three */
463
{ 0xff14, NULL, "4" }, /* fullwidth four */
464
{ 0xff15, NULL, "5" }, /* fullwidth five */
465
{ 0xff16, NULL, "6" }, /* fullwidth six */
466
{ 0xff17, NULL, "7" }, /* fullwidth seven */
467
{ 0xff18, NULL, "8" }, /* fullwidth eight */
468
{ 0xff19, NULL, "9" }, /* fullwidth nine */
469
{ 0xff1a, NULL, ":" }, /* fullwidth colon */
470
{ 0xff1b, NULL, ";" }, /* fullwidth semicolon */
471
{ 0xff1c, NULL, "<" }, /* fullwidth less than sign */
472
{ 0xff1d, NULL, "=" }, /* fullwidth equals sign */
473
{ 0xff1e, NULL, ">" }, /* fullwidth greater than sign */
474
{ 0xff1f, NULL, "?" }, /* fullwidth question mark */
475
{ 0xff20, NULL, "@" }, /* fullwidth at sign */
476
{ 0xff21, NULL, "A" }, /* fullwidth 'A' */
477
{ 0xff22, NULL, "B" }, /* fullwidth 'B' */
478
{ 0xff23, NULL, "C" }, /* fullwidth 'C' */
479
{ 0xff24, NULL, "D" }, /* fullwidth 'D' */
480
{ 0xff25, NULL, "E" }, /* fullwidth 'E' */
481
{ 0xff26, NULL, "F" }, /* fullwidth 'F' */
482
{ 0xff27, NULL, "G" }, /* fullwidth 'G' */
483
{ 0xff28, NULL, "H" }, /* fullwidth 'H' */
484
{ 0xff29, NULL, "I" }, /* fullwidth 'I' */
485
{ 0xff2a, NULL, "J" }, /* fullwidth 'J' */
486
{ 0xff2b, NULL, "K" }, /* fullwidth 'K' */
487
{ 0xff2c, NULL, "L" }, /* fullwidth 'L' */
488
{ 0xff2d, NULL, "M" }, /* fullwidth 'M' */
489
{ 0xff2e, NULL, "N" }, /* fullwidth 'N' */
490
{ 0xff2f, NULL, "O" }, /* fullwidth 'O' */
491
{ 0xff30, NULL, "P" }, /* fullwidth 'P' */
492
{ 0xff31, NULL, "Q" }, /* fullwidth 'Q' */
493
{ 0xff32, NULL, "R" }, /* fullwidth 'R' */
494
{ 0xff33, NULL, "S" }, /* fullwidth 'S' */
495
{ 0xff34, NULL, "T" }, /* fullwidth 'T' */
496
{ 0xff35, NULL, "U" }, /* fullwidth 'U' */
497
{ 0xff36, NULL, "V" }, /* fullwidth 'V' */
498
{ 0xff37, NULL, "W" }, /* fullwidth 'W' */
499
{ 0xff38, NULL, "X" }, /* fullwidth 'X' */
500
{ 0xff39, NULL, "Y" }, /* fullwidth 'Y' */
501
{ 0xff3a, NULL, "Z" }, /* fullwidth 'Z' */
502
{ 0xff3b, NULL, "[" }, /* fullwidth left bracket */
503
{ 0xff3c, NULL, "\\" }, /* fullwidth backslash */
504
{ 0xff3d, NULL, "]" }, /* fullwidth right bracket */
505
{ 0xff3e, NULL, "^" }, /* fullwidth caret */
506
{ 0xff3f, NULL, "_" }, /* fullwidth underscore */
507
{ 0xff40, NULL, "`" }, /* fullwidth backquote */
508
{ 0xff41, NULL, "a" }, /* fullwidth 'a' */
509
{ 0xff42, NULL, "b" }, /* fullwidth 'b' */
510
{ 0xff43, NULL, "c" }, /* fullwidth 'c' */
511
{ 0xff44, NULL, "d" }, /* fullwidth 'd' */
512
{ 0xff45, NULL, "e" }, /* fullwidth 'e' */
513
{ 0xff46, NULL, "f" }, /* fullwidth 'f' */
514
{ 0xff47, NULL, "g" }, /* fullwidth 'g' */
515
{ 0xff48, NULL, "h" }, /* fullwidth 'h' */
516
{ 0xff49, NULL, "i" }, /* fullwidth 'i' */
517
{ 0xff4a, NULL, "j" }, /* fullwidth 'j' */
518
{ 0xff4b, NULL, "k" }, /* fullwidth 'k' */
519
{ 0xff4c, NULL, "l" }, /* fullwidth 'l' */
520
{ 0xff4d, NULL, "m" }, /* fullwidth 'm' */
521
{ 0xff4e, NULL, "n" }, /* fullwidth 'n' */
522
{ 0xff4f, NULL, "o" }, /* fullwidth 'o' */
523
{ 0xff50, NULL, "p" }, /* fullwidth 'p' */
524
{ 0xff51, NULL, "q" }, /* fullwidth 'q' */
525
{ 0xff52, NULL, "r" }, /* fullwidth 'r' */
526
{ 0xff53, NULL, "s" }, /* fullwidth 's' */
527
{ 0xff54, NULL, "t" }, /* fullwidth 't' */
528
{ 0xff55, NULL, "u" }, /* fullwidth 'u' */
529
{ 0xff56, NULL, "v" }, /* fullwidth 'v' */
530
{ 0xff57, NULL, "w" }, /* fullwidth 'w' */
531
{ 0xff58, NULL, "x" }, /* fullwidth 'x' */
532
{ 0xff59, NULL, "y" }, /* fullwidth 'y' */
533
{ 0xff5a, NULL, "z" }, /* fullwidth 'z' */
534
{ 0xff5b, NULL, "{" }, /* fullwidth left brace */
535
{ 0xff5c, NULL, "|" }, /* fullwidth vertical bar */
536
{ 0xff5d, NULL, "}" }, /* fullwidth right brace */
537
{ 0xff5e, NULL, "~" }, /* fullwidth tilde */
538
{ 0xff5f, NULL, "((" }, /* fullwidth double left parenthesis */
539
{ 0xff60, NULL, "))" }, /* fullwidth double right parenthesis */
540
{ 0xffe0, NULL, "\xC2\xA2" }, /* fullwidth cent sign */
541
{ 0xffe1, NULL, "\xC2\xA3" }, /* fullwidth pound sign */
542
{ 0xffe4, NULL, "\xC2\xA4" }, /* fullwidth broken bar */
543
{ 0xffe5, NULL, "\xC2\xA5" }, /* fullwidth yen sign */
544
{ 0xffe6, NULL, "\xE2\x82\xA9" }, /* fullwidth won sign */
545
{ 0xffe9, NULL, "\xE2\x86\x90" }, /* fullwidth left arrow */
546
{ 0xffea, NULL, "\xE2\x86\x91" }, /* fullwidth up arrow */
547
{ 0xffeb, NULL, "\xE2\x86\x92" }, /* fullwidth right arrow */
548
{ 0xffec, NULL, "\xE2\x86\x93" }, /* fullwidth down arrow */
549
{ 0xffed, NULL, "\xE2\x96\xAA" }, /* fullwidth solid box */
550
{ 0xffee, NULL, "\xE2\x97\xA6" }, /* fullwidth open circle */
551
{ UCHAR_SHIFT_1, "Shift", NULL }, /* Shift key */
552
{ UCHAR_SHIFT_2, "Ctrl", NULL }, /* Ctrl key */
553
{ UCHAR_MAMEKEY(F1), "F1", NULL }, /* F1 function key */
554
{ UCHAR_MAMEKEY(F2), "F2", NULL }, /* F2 function key */
555
{ UCHAR_MAMEKEY(F3), "F3", NULL }, /* F3 function key */
556
{ UCHAR_MAMEKEY(F4), "F4", NULL }, /* F4 function key */
557
{ UCHAR_MAMEKEY(F5), "F5", NULL }, /* F5 function key */
558
{ UCHAR_MAMEKEY(F6), "F6", NULL }, /* F6 function key */
559
{ UCHAR_MAMEKEY(F7), "F7", NULL }, /* F7 function key */
560
{ UCHAR_MAMEKEY(F8), "F8", NULL }, /* F8 function key */
561
{ UCHAR_MAMEKEY(F9), "F9", NULL }, /* F9 function key */
562
{ UCHAR_MAMEKEY(F10), "F10", NULL }, /* F10 function key */
563
{ UCHAR_MAMEKEY(F11), "F11", NULL }, /* F11 function key */
564
{ UCHAR_MAMEKEY(F12), "F12", NULL }, /* F12 function key */
565
{ UCHAR_MAMEKEY(F13), "F13", NULL }, /* F13 function key */
566
{ UCHAR_MAMEKEY(F14), "F14", NULL }, /* F14 function key */
567
{ UCHAR_MAMEKEY(F15), "F15", NULL }, /* F15 function key */
568
{ UCHAR_MAMEKEY(ESC), "Esc", "\033" }, /* Esc key */
569
{ UCHAR_MAMEKEY(INSERT), "Insert", NULL }, /* Insert key */
570
{ UCHAR_MAMEKEY(DEL), "Delete", "\010" }, /* Delete key */
571
{ UCHAR_MAMEKEY(HOME), "Home", "\014" }, /* Home key */
572
{ UCHAR_MAMEKEY(END), "End", NULL }, /* End key */
573
{ UCHAR_MAMEKEY(PGUP), "Page Up", NULL }, /* Page Up key */
574
{ UCHAR_MAMEKEY(PGDN), "Page Down", NULL }, /* Page Down key */
575
{ UCHAR_MAMEKEY(LEFT), "Cursor Left", NULL }, /* Cursor Left */
576
{ UCHAR_MAMEKEY(RIGHT), "Cursor Right", NULL }, /* Cursor Right */
577
{ UCHAR_MAMEKEY(UP), "Cursor Up", NULL }, /* Cursor Up */
578
{ UCHAR_MAMEKEY(DOWN), "Cursor Down", NULL }, /* Cursor Down */
579
{ UCHAR_MAMEKEY(0_PAD), "Keypad 0", NULL }, /* 0 on the numeric keypad */
580
{ UCHAR_MAMEKEY(1_PAD), "Keypad 1", NULL }, /* 1 on the numeric keypad */
581
{ UCHAR_MAMEKEY(2_PAD), "Keypad 2", NULL }, /* 2 on the numeric keypad */
582
{ UCHAR_MAMEKEY(3_PAD), "Keypad 3", NULL }, /* 3 on the numeric keypad */
583
{ UCHAR_MAMEKEY(4_PAD), "Keypad 4", NULL }, /* 4 on the numeric keypad */
584
{ UCHAR_MAMEKEY(5_PAD), "Keypad 5", NULL }, /* 5 on the numeric keypad */
585
{ UCHAR_MAMEKEY(6_PAD), "Keypad 6", NULL }, /* 6 on the numeric keypad */
586
{ UCHAR_MAMEKEY(7_PAD), "Keypad 7", NULL }, /* 7 on the numeric keypad */
587
{ UCHAR_MAMEKEY(8_PAD), "Keypad 8", NULL }, /* 8 on the numeric keypad */
588
{ UCHAR_MAMEKEY(9_PAD), "Keypad 9", NULL }, /* 9 on the numeric keypad */
589
{ UCHAR_MAMEKEY(SLASH_PAD), "Keypad /", NULL }, /* / on the numeric keypad */
590
{ UCHAR_MAMEKEY(ASTERISK), "Keypad *", NULL }, /* * on the numeric keypad */
591
{ UCHAR_MAMEKEY(MINUS_PAD), "Keypad -", NULL }, /* - on the numeric Keypad */
592
{ UCHAR_MAMEKEY(PLUS_PAD), "Keypad +", NULL }, /* + on the numeric Keypad */
593
{ UCHAR_MAMEKEY(DEL_PAD), "Keypad .", NULL }, /* . on the numeric keypad */
594
{ UCHAR_MAMEKEY(ENTER_PAD), "Keypad Enter", NULL }, /* Enter on the numeric keypad */
595
{ UCHAR_MAMEKEY(PRTSCR), "Print Screen", NULL }, /* Print Screen key */
596
{ UCHAR_MAMEKEY(PAUSE), "Pause", NULL }, /* Pause key */
597
{ UCHAR_MAMEKEY(LSHIFT), "Left Shift", NULL }, /* Left Shift key */
598
{ UCHAR_MAMEKEY(RSHIFT), "Right Shift", NULL }, /* Right Shift key */
599
{ UCHAR_MAMEKEY(LCONTROL), "Left Ctrl", NULL }, /* Left Control key */
600
{ UCHAR_MAMEKEY(RCONTROL), "Right Ctrl", NULL }, /* Right Control key */
601
{ UCHAR_MAMEKEY(LALT), "Left Alt", NULL }, /* Left Alt key */
602
{ UCHAR_MAMEKEY(RALT), "Right Alt", NULL }, /* Right Alt key */
603
{ UCHAR_MAMEKEY(SCRLOCK), "Scroll Lock", NULL }, /* Scroll Lock key */
604
{ UCHAR_MAMEKEY(NUMLOCK), "Num Lock", NULL }, /* Num Lock key */
605
{ UCHAR_MAMEKEY(CAPSLOCK), "Caps Lock", NULL }, /* Caps Lock key */
606
{ UCHAR_MAMEKEY(LWIN), "Left Win", NULL }, /* Left Win key */
607
{ UCHAR_MAMEKEY(RWIN), "Right Win", NULL }, /* Right Win key */
608
{ UCHAR_MAMEKEY(MENU), "Menu", NULL }, /* Menu key */
609
{ UCHAR_MAMEKEY(CANCEL), "Break", NULL } /* Break/Pause key */
358
{ 0x0008, "Backspace", NULL }, // Backspace
359
{ 0x0009, "Tab", " " }, // Tab
360
{ 0x000c, "Clear", NULL }, // Clear
361
{ 0x000d, "Enter", NULL }, // Enter
362
{ 0x001a, "Esc", NULL }, // Esc
363
{ 0x0020, "Space", " " }, // Space
364
{ 0x0061, NULL, "A" }, // a
365
{ 0x0062, NULL, "B" }, // b
366
{ 0x0063, NULL, "C" }, // c
367
{ 0x0064, NULL, "D" }, // d
368
{ 0x0065, NULL, "E" }, // e
369
{ 0x0066, NULL, "F" }, // f
370
{ 0x0067, NULL, "G" }, // g
371
{ 0x0068, NULL, "H" }, // h
372
{ 0x0069, NULL, "I" }, // i
373
{ 0x006a, NULL, "J" }, // j
374
{ 0x006b, NULL, "K" }, // k
375
{ 0x006c, NULL, "L" }, // l
376
{ 0x006d, NULL, "M" }, // m
377
{ 0x006e, NULL, "N" }, // n
378
{ 0x006f, NULL, "O" }, // o
379
{ 0x0070, NULL, "P" }, // p
380
{ 0x0071, NULL, "Q" }, // q
381
{ 0x0072, NULL, "R" }, // r
382
{ 0x0073, NULL, "S" }, // s
383
{ 0x0074, NULL, "T" }, // t
384
{ 0x0075, NULL, "U" }, // u
385
{ 0x0076, NULL, "V" }, // v
386
{ 0x0077, NULL, "W" }, // w
387
{ 0x0078, NULL, "X" }, // x
388
{ 0x0079, NULL, "Y" }, // y
389
{ 0x007a, NULL, "Z" }, // z
390
{ 0x00a0, NULL, " " }, // non breaking space
391
{ 0x00a1, NULL, "!" }, // inverted exclaimation mark
392
{ 0x00a6, NULL, "|" }, // broken bar
393
{ 0x00a9, NULL, "(c)" }, // copyright sign
394
{ 0x00ab, NULL, "<<" }, // left pointing double angle
395
{ 0x00ae, NULL, "(r)" }, // registered sign
396
{ 0x00bb, NULL, ">>" }, // right pointing double angle
397
{ 0x00bc, NULL, "1/4" }, // vulgar fraction one quarter
398
{ 0x00bd, NULL, "1/2" }, // vulgar fraction one half
399
{ 0x00be, NULL, "3/4" }, // vulgar fraction three quarters
400
{ 0x00bf, NULL, "?" }, // inverted question mark
401
{ 0x00c0, NULL, "A" }, // 'A' grave
402
{ 0x00c1, NULL, "A" }, // 'A' acute
403
{ 0x00c2, NULL, "A" }, // 'A' circumflex
404
{ 0x00c3, NULL, "A" }, // 'A' tilde
405
{ 0x00c4, NULL, "A" }, // 'A' diaeresis
406
{ 0x00c5, NULL, "A" }, // 'A' ring above
407
{ 0x00c6, NULL, "AE" }, // 'AE' ligature
408
{ 0x00c7, NULL, "C" }, // 'C' cedilla
409
{ 0x00c8, NULL, "E" }, // 'E' grave
410
{ 0x00c9, NULL, "E" }, // 'E' acute
411
{ 0x00ca, NULL, "E" }, // 'E' circumflex
412
{ 0x00cb, NULL, "E" }, // 'E' diaeresis
413
{ 0x00cc, NULL, "I" }, // 'I' grave
414
{ 0x00cd, NULL, "I" }, // 'I' acute
415
{ 0x00ce, NULL, "I" }, // 'I' circumflex
416
{ 0x00cf, NULL, "I" }, // 'I' diaeresis
417
{ 0x00d0, NULL, "D" }, // 'ETH'
418
{ 0x00d1, NULL, "N" }, // 'N' tilde
419
{ 0x00d2, NULL, "O" }, // 'O' grave
420
{ 0x00d3, NULL, "O" }, // 'O' acute
421
{ 0x00d4, NULL, "O" }, // 'O' circumflex
422
{ 0x00d5, NULL, "O" }, // 'O' tilde
423
{ 0x00d6, NULL, "O" }, // 'O' diaeresis
424
{ 0x00d7, NULL, "X" }, // multiplication sign
425
{ 0x00d8, NULL, "O" }, // 'O' stroke
426
{ 0x00d9, NULL, "U" }, // 'U' grave
427
{ 0x00da, NULL, "U" }, // 'U' acute
428
{ 0x00db, NULL, "U" }, // 'U' circumflex
429
{ 0x00dc, NULL, "U" }, // 'U' diaeresis
430
{ 0x00dd, NULL, "Y" }, // 'Y' acute
431
{ 0x00df, NULL, "SS" }, // sharp S
432
{ 0x00e0, NULL, "a" }, // 'a' grave
433
{ 0x00e1, NULL, "a" }, // 'a' acute
434
{ 0x00e2, NULL, "a" }, // 'a' circumflex
435
{ 0x00e3, NULL, "a" }, // 'a' tilde
436
{ 0x00e4, NULL, "a" }, // 'a' diaeresis
437
{ 0x00e5, NULL, "a" }, // 'a' ring above
438
{ 0x00e6, NULL, "ae" }, // 'ae' ligature
439
{ 0x00e7, NULL, "c" }, // 'c' cedilla
440
{ 0x00e8, NULL, "e" }, // 'e' grave
441
{ 0x00e9, NULL, "e" }, // 'e' acute
442
{ 0x00ea, NULL, "e" }, // 'e' circumflex
443
{ 0x00eb, NULL, "e" }, // 'e' diaeresis
444
{ 0x00ec, NULL, "i" }, // 'i' grave
445
{ 0x00ed, NULL, "i" }, // 'i' acute
446
{ 0x00ee, NULL, "i" }, // 'i' circumflex
447
{ 0x00ef, NULL, "i" }, // 'i' diaeresis
448
{ 0x00f0, NULL, "d" }, // 'eth'
449
{ 0x00f1, NULL, "n" }, // 'n' tilde
450
{ 0x00f2, NULL, "o" }, // 'o' grave
451
{ 0x00f3, NULL, "o" }, // 'o' acute
452
{ 0x00f4, NULL, "o" }, // 'o' circumflex
453
{ 0x00f5, NULL, "o" }, // 'o' tilde
454
{ 0x00f6, NULL, "o" }, // 'o' diaeresis
455
{ 0x00f8, NULL, "o" }, // 'o' stroke
456
{ 0x00f9, NULL, "u" }, // 'u' grave
457
{ 0x00fa, NULL, "u" }, // 'u' acute
458
{ 0x00fb, NULL, "u" }, // 'u' circumflex
459
{ 0x00fc, NULL, "u" }, // 'u' diaeresis
460
{ 0x00fd, NULL, "y" }, // 'y' acute
461
{ 0x00ff, NULL, "y" }, // 'y' diaeresis
462
{ 0x2010, NULL, "-" }, // hyphen
463
{ 0x2011, NULL, "-" }, // non-breaking hyphen
464
{ 0x2012, NULL, "-" }, // figure dash
465
{ 0x2013, NULL, "-" }, // en dash
466
{ 0x2014, NULL, "-" }, // em dash
467
{ 0x2015, NULL, "-" }, // horizontal dash
468
{ 0x2018, NULL, "\'" }, // left single quotation mark
469
{ 0x2019, NULL, "\'" }, // right single quotation mark
470
{ 0x201a, NULL, "\'" }, // single low quotation mark
471
{ 0x201b, NULL, "\'" }, // single high reversed quotation mark
472
{ 0x201c, NULL, "\"" }, // left double quotation mark
473
{ 0x201d, NULL, "\"" }, // right double quotation mark
474
{ 0x201e, NULL, "\"" }, // double low quotation mark
475
{ 0x201f, NULL, "\"" }, // double high reversed quotation mark
476
{ 0x2024, NULL, "." }, // one dot leader
477
{ 0x2025, NULL, ".." }, // two dot leader
478
{ 0x2026, NULL, "..." }, // horizontal ellipsis
479
{ 0x2047, NULL, "??" }, // double question mark
480
{ 0x2048, NULL, "?!" }, // question exclamation mark
481
{ 0x2049, NULL, "!?" }, // exclamation question mark
482
{ 0xff01, NULL, "!" }, // fullwidth exclamation point
483
{ 0xff02, NULL, "\"" }, // fullwidth quotation mark
484
{ 0xff03, NULL, "#" }, // fullwidth number sign
485
{ 0xff04, NULL, "$" }, // fullwidth dollar sign
486
{ 0xff05, NULL, "%" }, // fullwidth percent sign
487
{ 0xff06, NULL, "&" }, // fullwidth ampersand
488
{ 0xff07, NULL, "\'" }, // fullwidth apostrophe
489
{ 0xff08, NULL, "(" }, // fullwidth left parenthesis
490
{ 0xff09, NULL, ")" }, // fullwidth right parenthesis
491
{ 0xff0a, NULL, "*" }, // fullwidth asterisk
492
{ 0xff0b, NULL, "+" }, // fullwidth plus
493
{ 0xff0c, NULL, "," }, // fullwidth comma
494
{ 0xff0d, NULL, "-" }, // fullwidth minus
495
{ 0xff0e, NULL, "." }, // fullwidth period
496
{ 0xff0f, NULL, "/" }, // fullwidth slash
497
{ 0xff10, NULL, "0" }, // fullwidth zero
498
{ 0xff11, NULL, "1" }, // fullwidth one
499
{ 0xff12, NULL, "2" }, // fullwidth two
500
{ 0xff13, NULL, "3" }, // fullwidth three
501
{ 0xff14, NULL, "4" }, // fullwidth four
502
{ 0xff15, NULL, "5" }, // fullwidth five
503
{ 0xff16, NULL, "6" }, // fullwidth six
504
{ 0xff17, NULL, "7" }, // fullwidth seven
505
{ 0xff18, NULL, "8" }, // fullwidth eight
506
{ 0xff19, NULL, "9" }, // fullwidth nine
507
{ 0xff1a, NULL, ":" }, // fullwidth colon
508
{ 0xff1b, NULL, ";" }, // fullwidth semicolon
509
{ 0xff1c, NULL, "<" }, // fullwidth less than sign
510
{ 0xff1d, NULL, "=" }, // fullwidth equals sign
511
{ 0xff1e, NULL, ">" }, // fullwidth greater than sign
512
{ 0xff1f, NULL, "?" }, // fullwidth question mark
513
{ 0xff20, NULL, "@" }, // fullwidth at sign
514
{ 0xff21, NULL, "A" }, // fullwidth 'A'
515
{ 0xff22, NULL, "B" }, // fullwidth 'B'
516
{ 0xff23, NULL, "C" }, // fullwidth 'C'
517
{ 0xff24, NULL, "D" }, // fullwidth 'D'
518
{ 0xff25, NULL, "E" }, // fullwidth 'E'
519
{ 0xff26, NULL, "F" }, // fullwidth 'F'
520
{ 0xff27, NULL, "G" }, // fullwidth 'G'
521
{ 0xff28, NULL, "H" }, // fullwidth 'H'
522
{ 0xff29, NULL, "I" }, // fullwidth 'I'
523
{ 0xff2a, NULL, "J" }, // fullwidth 'J'
524
{ 0xff2b, NULL, "K" }, // fullwidth 'K'
525
{ 0xff2c, NULL, "L" }, // fullwidth 'L'
526
{ 0xff2d, NULL, "M" }, // fullwidth 'M'
527
{ 0xff2e, NULL, "N" }, // fullwidth 'N'
528
{ 0xff2f, NULL, "O" }, // fullwidth 'O'
529
{ 0xff30, NULL, "P" }, // fullwidth 'P'
530
{ 0xff31, NULL, "Q" }, // fullwidth 'Q'
531
{ 0xff32, NULL, "R" }, // fullwidth 'R'
532
{ 0xff33, NULL, "S" }, // fullwidth 'S'
533
{ 0xff34, NULL, "T" }, // fullwidth 'T'
534
{ 0xff35, NULL, "U" }, // fullwidth 'U'
535
{ 0xff36, NULL, "V" }, // fullwidth 'V'
536
{ 0xff37, NULL, "W" }, // fullwidth 'W'
537
{ 0xff38, NULL, "X" }, // fullwidth 'X'
538
{ 0xff39, NULL, "Y" }, // fullwidth 'Y'
539
{ 0xff3a, NULL, "Z" }, // fullwidth 'Z'
540
{ 0xff3b, NULL, "[" }, // fullwidth left bracket
541
{ 0xff3c, NULL, "\\" }, // fullwidth backslash
542
{ 0xff3d, NULL, "]" }, // fullwidth right bracket
543
{ 0xff3e, NULL, "^" }, // fullwidth caret
544
{ 0xff3f, NULL, "_" }, // fullwidth underscore
545
{ 0xff40, NULL, "`" }, // fullwidth backquote
546
{ 0xff41, NULL, "a" }, // fullwidth 'a'
547
{ 0xff42, NULL, "b" }, // fullwidth 'b'
548
{ 0xff43, NULL, "c" }, // fullwidth 'c'
549
{ 0xff44, NULL, "d" }, // fullwidth 'd'
550
{ 0xff45, NULL, "e" }, // fullwidth 'e'
551
{ 0xff46, NULL, "f" }, // fullwidth 'f'
552
{ 0xff47, NULL, "g" }, // fullwidth 'g'
553
{ 0xff48, NULL, "h" }, // fullwidth 'h'
554
{ 0xff49, NULL, "i" }, // fullwidth 'i'
555
{ 0xff4a, NULL, "j" }, // fullwidth 'j'
556
{ 0xff4b, NULL, "k" }, // fullwidth 'k'
557
{ 0xff4c, NULL, "l" }, // fullwidth 'l'
558
{ 0xff4d, NULL, "m" }, // fullwidth 'm'
559
{ 0xff4e, NULL, "n" }, // fullwidth 'n'
560
{ 0xff4f, NULL, "o" }, // fullwidth 'o'
561
{ 0xff50, NULL, "p" }, // fullwidth 'p'
562
{ 0xff51, NULL, "q" }, // fullwidth 'q'
563
{ 0xff52, NULL, "r" }, // fullwidth 'r'
564
{ 0xff53, NULL, "s" }, // fullwidth 's'
565
{ 0xff54, NULL, "t" }, // fullwidth 't'
566
{ 0xff55, NULL, "u" }, // fullwidth 'u'
567
{ 0xff56, NULL, "v" }, // fullwidth 'v'
568
{ 0xff57, NULL, "w" }, // fullwidth 'w'
569
{ 0xff58, NULL, "x" }, // fullwidth 'x'
570
{ 0xff59, NULL, "y" }, // fullwidth 'y'
571
{ 0xff5a, NULL, "z" }, // fullwidth 'z'
572
{ 0xff5b, NULL, "{" }, // fullwidth left brace
573
{ 0xff5c, NULL, "|" }, // fullwidth vertical bar
574
{ 0xff5d, NULL, "}" }, // fullwidth right brace
575
{ 0xff5e, NULL, "~" }, // fullwidth tilde
576
{ 0xff5f, NULL, "((" }, // fullwidth double left parenthesis
577
{ 0xff60, NULL, "))" }, // fullwidth double right parenthesis
578
{ 0xffe0, NULL, "\xC2\xA2" }, // fullwidth cent sign
579
{ 0xffe1, NULL, "\xC2\xA3" }, // fullwidth pound sign
580
{ 0xffe4, NULL, "\xC2\xA4" }, // fullwidth broken bar
581
{ 0xffe5, NULL, "\xC2\xA5" }, // fullwidth yen sign
582
{ 0xffe6, NULL, "\xE2\x82\xA9" }, // fullwidth won sign
583
{ 0xffe9, NULL, "\xE2\x86\x90" }, // fullwidth left arrow
584
{ 0xffea, NULL, "\xE2\x86\x91" }, // fullwidth up arrow
585
{ 0xffeb, NULL, "\xE2\x86\x92" }, // fullwidth right arrow
586
{ 0xffec, NULL, "\xE2\x86\x93" }, // fullwidth down arrow
587
{ 0xffed, NULL, "\xE2\x96\xAA" }, // fullwidth solid box
588
{ 0xffee, NULL, "\xE2\x97\xA6" }, // fullwidth open circle
589
{ UCHAR_SHIFT_1, "Shift", NULL }, // Shift key
590
{ UCHAR_SHIFT_2, "Ctrl", NULL }, // Ctrl key
591
{ UCHAR_MAMEKEY(F1), "F1", NULL }, // F1 function key
592
{ UCHAR_MAMEKEY(F2), "F2", NULL }, // F2 function key
593
{ UCHAR_MAMEKEY(F3), "F3", NULL }, // F3 function key
594
{ UCHAR_MAMEKEY(F4), "F4", NULL }, // F4 function key
595
{ UCHAR_MAMEKEY(F5), "F5", NULL }, // F5 function key
596
{ UCHAR_MAMEKEY(F6), "F6", NULL }, // F6 function key
597
{ UCHAR_MAMEKEY(F7), "F7", NULL }, // F7 function key
598
{ UCHAR_MAMEKEY(F8), "F8", NULL }, // F8 function key
599
{ UCHAR_MAMEKEY(F9), "F9", NULL }, // F9 function key
600
{ UCHAR_MAMEKEY(F10), "F10", NULL }, // F10 function key
601
{ UCHAR_MAMEKEY(F11), "F11", NULL }, // F11 function key
602
{ UCHAR_MAMEKEY(F12), "F12", NULL }, // F12 function key
603
{ UCHAR_MAMEKEY(F13), "F13", NULL }, // F13 function key
604
{ UCHAR_MAMEKEY(F14), "F14", NULL }, // F14 function key
605
{ UCHAR_MAMEKEY(F15), "F15", NULL }, // F15 function key
606
{ UCHAR_MAMEKEY(ESC), "Esc", "\033" }, // Esc key
607
{ UCHAR_MAMEKEY(INSERT), "Insert", NULL }, // Insert key
608
{ UCHAR_MAMEKEY(DEL), "Delete", "\010" }, // Delete key
609
{ UCHAR_MAMEKEY(HOME), "Home", "\014" }, // Home key
610
{ UCHAR_MAMEKEY(END), "End", NULL }, // End key
611
{ UCHAR_MAMEKEY(PGUP), "Page Up", NULL }, // Page Up key
612
{ UCHAR_MAMEKEY(PGDN), "Page Down", NULL }, // Page Down key
613
{ UCHAR_MAMEKEY(LEFT), "Cursor Left", NULL }, // Cursor Left
614
{ UCHAR_MAMEKEY(RIGHT), "Cursor Right", NULL }, // Cursor Right
615
{ UCHAR_MAMEKEY(UP), "Cursor Up", NULL }, // Cursor Up
616
{ UCHAR_MAMEKEY(DOWN), "Cursor Down", NULL }, // Cursor Down
617
{ UCHAR_MAMEKEY(0_PAD), "Keypad 0", NULL }, // 0 on the numeric keypad
618
{ UCHAR_MAMEKEY(1_PAD), "Keypad 1", NULL }, // 1 on the numeric keypad
619
{ UCHAR_MAMEKEY(2_PAD), "Keypad 2", NULL }, // 2 on the numeric keypad
620
{ UCHAR_MAMEKEY(3_PAD), "Keypad 3", NULL }, // 3 on the numeric keypad
621
{ UCHAR_MAMEKEY(4_PAD), "Keypad 4", NULL }, // 4 on the numeric keypad
622
{ UCHAR_MAMEKEY(5_PAD), "Keypad 5", NULL }, // 5 on the numeric keypad
623
{ UCHAR_MAMEKEY(6_PAD), "Keypad 6", NULL }, // 6 on the numeric keypad
624
{ UCHAR_MAMEKEY(7_PAD), "Keypad 7", NULL }, // 7 on the numeric keypad
625
{ UCHAR_MAMEKEY(8_PAD), "Keypad 8", NULL }, // 8 on the numeric keypad
626
{ UCHAR_MAMEKEY(9_PAD), "Keypad 9", NULL }, // 9 on the numeric keypad
627
{ UCHAR_MAMEKEY(SLASH_PAD), "Keypad /", NULL }, // / on the numeric keypad
628
{ UCHAR_MAMEKEY(ASTERISK), "Keypad *", NULL }, // * on the numeric keypad
629
{ UCHAR_MAMEKEY(MINUS_PAD), "Keypad -", NULL }, // - on the numeric Keypad
630
{ UCHAR_MAMEKEY(PLUS_PAD), "Keypad +", NULL }, // + on the numeric Keypad
631
{ UCHAR_MAMEKEY(DEL_PAD), "Keypad .", NULL }, // . on the numeric keypad
632
{ UCHAR_MAMEKEY(ENTER_PAD), "Keypad Enter", NULL }, // Enter on the numeric keypad
633
{ UCHAR_MAMEKEY(PRTSCR), "Print Screen", NULL }, // Print Screen key
634
{ UCHAR_MAMEKEY(PAUSE), "Pause", NULL }, // Pause key
635
{ UCHAR_MAMEKEY(LSHIFT), "Left Shift", NULL }, // Left Shift key
636
{ UCHAR_MAMEKEY(RSHIFT), "Right Shift", NULL }, // Right Shift key
637
{ UCHAR_MAMEKEY(LCONTROL), "Left Ctrl", NULL }, // Left Control key
638
{ UCHAR_MAMEKEY(RCONTROL), "Right Ctrl", NULL }, // Right Control key
639
{ UCHAR_MAMEKEY(LALT), "Left Alt", NULL }, // Left Alt key
640
{ UCHAR_MAMEKEY(RALT), "Right Alt", NULL }, // Right Alt key
641
{ UCHAR_MAMEKEY(SCRLOCK), "Scroll Lock", NULL }, // Scroll Lock key
642
{ UCHAR_MAMEKEY(NUMLOCK), "Num Lock", NULL }, // Num Lock key
643
{ UCHAR_MAMEKEY(CAPSLOCK), "Caps Lock", NULL }, // Caps Lock key
644
{ UCHAR_MAMEKEY(LWIN), "Left Win", NULL }, // Left Win key
645
{ UCHAR_MAMEKEY(RWIN), "Right Win", NULL }, // Right Win key
646
{ UCHAR_MAMEKEY(MENU), "Menu", NULL }, // Menu key
647
{ UCHAR_MAMEKEY(CANCEL), "Break", NULL } // Break/Pause key
612
static TIMER_CALLBACK(inputx_timerproc);
615
/* Debugging commands and handlers. */
616
static void execute_input(running_machine &machine, int ref, int params, const char *param[]);
617
static void execute_dumpkbd(running_machine &machine, int ref, int params, const char *param[]);
619
/***************************************************************************
620
COMMON SHARED STRINGS
621
***************************************************************************/
652
//**************************************************************************
653
// COMMON SHARED STRINGS
654
//**************************************************************************
623
656
static const struct
752
/***************************************************************************
753
BUILT-IN CORE MAPPINGS
754
***************************************************************************/
785
//**************************************************************************
786
// BUILT-IN CORE MAPPINGS
787
//**************************************************************************
756
789
#include "inpttype.h"
760
/***************************************************************************
762
***************************************************************************/
764
/* core system management */
765
static void input_port_exit(running_machine &machine);
768
static INT32 apply_analog_settings(INT32 current, analog_field_state *analog);
770
/* initialization helpers */
771
static void init_port_types(running_machine &machine);
772
static void init_port_state(running_machine &machine);
773
static void init_autoselect_devices(running_machine &machine, int type1, int type2, int type3, const char *option, const char *ananame);
774
static device_field_info *init_field_device_info(const input_field_config *field,const char *device_name);
775
static analog_field_state *init_field_analog_state(const input_field_config *field);
777
/* once-per-frame updates */
778
static void frame_update_callback(running_machine &machine);
779
static void frame_update(running_machine &machine);
780
static void frame_update_digital_joysticks(running_machine &machine);
781
static void frame_update_analog_field(running_machine &machine, analog_field_state *analog);
782
static int frame_get_digital_field_state(const input_field_config *field, int mouse_down);
784
/* tokenization helpers */
785
static int token_to_input_field_type(running_machine &machine, const char *string, int *player);
786
static const char *input_field_type_to_token(running_machine &machine, int type, int player);
787
static int token_to_seq_type(const char *string);
790
static void load_config_callback(running_machine &machine, int config_type, xml_data_node *parentnode);
791
static void load_remap_table(running_machine &machine, xml_data_node *parentnode);
792
static int load_default_config(running_machine &machine, xml_data_node *portnode, int type, int player, const input_seq *newseq);
793
static int load_game_config(running_machine &machine, xml_data_node *portnode, int type, int player, const input_seq *newseq);
796
static void save_config_callback(running_machine &machine, int config_type, xml_data_node *parentnode);
797
static void save_sequence(running_machine &machine, xml_data_node *parentnode, int type, int porttype, const input_seq &seq);
798
static int save_this_input_field_type(int type);
799
static void save_default_inputs(running_machine &machine, xml_data_node *parentnode);
800
static void save_game_inputs(running_machine &machine, xml_data_node *parentnode);
803
static time_t playback_init(running_machine &machine);
804
static void playback_end(running_machine &machine, const char *message);
805
static void playback_frame(running_machine &machine, attotime curtime);
806
static void playback_port(const input_port_config *port);
808
/* input recording */
809
static void record_init(running_machine &machine);
810
static void record_end(running_machine &machine, const char *message);
811
static void record_frame(running_machine &machine, attotime curtime);
812
static void record_port(const input_port_config *port);
816
/***************************************************************************
818
***************************************************************************/
820
/*-------------------------------------------------
821
apply_analog_min_max - clamp the given input
822
value to the appropriate min/max for the
824
-------------------------------------------------*/
826
INLINE INT32 apply_analog_min_max(const analog_field_state *analog, INT32 value)
828
/* take the analog minimum and maximum values and apply the inverse of the */
829
/* sensitivity so that we can clamp against them before applying sensitivity */
830
INT32 adjmin = APPLY_INVERSE_SENSITIVITY(analog->minimum, analog->sensitivity);
831
INT32 adjmax = APPLY_INVERSE_SENSITIVITY(analog->maximum, analog->sensitivity);
833
/* for absolute devices, clamp to the bounds absolutely */
838
else if (value < adjmin)
842
/* for relative devices, wrap around when we go past the edge */
845
INT32 range = adjmax - adjmin;
846
/* rolls to other end when 1 position past end. */
847
value = (value - adjmin) % range;
857
/*-------------------------------------------------
858
get_port_tag - return a guaranteed tag for
860
-------------------------------------------------*/
862
INLINE const char *get_port_tag(const input_port_config *port, char *tempbuffer)
868
/*-------------------------------------------------
869
condition_equal - TRUE if two conditions are
871
-------------------------------------------------*/
873
INLINE int condition_equal(const input_condition *cond1, const input_condition *cond2)
875
return (cond1->mask == cond2->mask && cond1->value == cond2->value && cond1->condition == cond2->condition && strcmp(cond1->tag, cond2->tag) == 0);
880
/***************************************************************************
881
CORE SYSTEM MANAGEMENT
882
***************************************************************************/
884
/*-------------------------------------------------
885
input_port_init - initialize the input port
887
-------------------------------------------------*/
889
time_t input_port_init(running_machine &machine)
891
//input_port_private *portdata;
894
/* allocate memory for our data structure */
895
machine.input_port_data = auto_alloc_clear(machine, input_port_private);
896
//portdata = machine.input_port_data;
898
/* add an exit callback and a frame callback */
899
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(input_port_exit), &machine));
900
machine.add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(FUNC(frame_update_callback), &machine));
902
/* initialize the default port info from the OSD */
903
init_port_types(machine);
905
/* if we have a token list, proceed */
906
device_iterator iter(machine.root_device());
907
for (device_t *device = iter.first(); device != NULL; device = iter.next())
910
input_port_list_init(*device, machine.m_portlist, errors);
912
mame_printf_error("Input port errors:\n%s", errors.cstr());
915
init_port_state(machine);
916
/* register callbacks for when we load configurations */
917
config_register(machine, "input", config_saveload_delegate(FUNC(load_config_callback), &machine), config_saveload_delegate(FUNC(save_config_callback), &machine));
919
/* open playback and record files if specified */
920
basetime = playback_init(machine);
921
record_init(machine);
927
/*-------------------------------------------------
928
input_port_exit - exit callback to ensure
929
we clean up and close our files
930
-------------------------------------------------*/
932
static void input_port_exit(running_machine &machine)
934
/* close any playback or recording files */
935
playback_end(machine, NULL);
936
record_end(machine, NULL);
941
/***************************************************************************
943
***************************************************************************/
945
/*-------------------------------------------------
946
input_port_list_init - initialize an input
947
port list structure and allocate ports
948
according to the given tokens
949
-------------------------------------------------*/
951
void input_port_list_init(device_t &device, ioport_list &portlist, astring &errorbuf)
953
/* no constructor, no list */
793
//**************************************************************************
794
// PORT CONFIGURATIONS
795
//**************************************************************************
797
//**************************************************************************
799
//**************************************************************************
801
//-------------------------------------------------
802
// append - append the given device's input ports
803
// to the current list
804
//-------------------------------------------------
806
void ioport_list::append(device_t &device, astring &errorbuf)
808
// no constructor, no list
954
809
ioport_constructor constructor = device.input_ports();
955
810
if (constructor == NULL)
958
/* reset error buffer */
813
// reset error buffer
959
814
errorbuf.reset();
961
/* detokenize into the list */
962
(*constructor)(device, portlist, errorbuf);
816
// detokenize into the list
817
(*constructor)(device, *this, errorbuf);
964
819
// collapse fields and sort the list
965
for (input_port_config *port = portlist.first(); port != NULL; port = port->next())
820
for (ioport_port *port = first(); port != NULL; port = port->next())
966
821
port->collapse_fields(errorbuf);
970
/*-------------------------------------------------
971
input_field_by_tag_and_mask - return a pointer
972
to the first field that intersects the given
973
mask on the tagged port
974
-------------------------------------------------*/
976
const input_field_config *input_field_by_tag_and_mask(running_machine &machine, const char *tag, input_port_value mask)
978
const input_port_config *port = machine.port(tag);
980
/* if we got the port, look for the field */
982
for (const input_field_config *field = port->first_field(); field != NULL; field = field->next())
983
if ((field->mask & mask) != 0)
826
//**************************************************************************
828
//**************************************************************************
830
//-------------------------------------------------
831
// input_type_entry - constructors
832
//-------------------------------------------------
834
input_type_entry::input_type_entry(ioport_type type, ioport_group group, int player, const char *token, const char *name, input_seq standard)
842
m_defseq[SEQ_TYPE_STANDARD] = m_seq[SEQ_TYPE_STANDARD] = standard;
845
input_type_entry::input_type_entry(ioport_type type, ioport_group group, int player, const char *token, const char *name, input_seq standard, input_seq decrement, input_seq increment)
853
m_defseq[SEQ_TYPE_STANDARD] = m_seq[SEQ_TYPE_STANDARD] = standard;
854
m_defseq[SEQ_TYPE_INCREMENT] = m_seq[SEQ_TYPE_INCREMENT] = increment;
855
m_defseq[SEQ_TYPE_DECREMENT] = m_seq[SEQ_TYPE_DECREMENT] = decrement;
859
//-------------------------------------------------
860
// configure_osd - set the token and name of an
862
//-------------------------------------------------
864
void input_type_entry::configure_osd(const char *token, const char *name)
866
assert(m_type >= IPT_OSD_1 && m_type <= IPT_OSD_16);
872
//**************************************************************************
874
//**************************************************************************
876
//-------------------------------------------------
877
// digital_joystick - constructor
878
//-------------------------------------------------
880
digital_joystick::digital_joystick(int player, int number)
887
memset(m_field, 0, sizeof(m_field));
891
//-------------------------------------------------
892
// set_axis - configure a single axis of a
894
//-------------------------------------------------
896
digital_joystick::direction_t digital_joystick::set_axis(ioport_field &field)
898
direction_t direction = direction_t((field.type() - (IPT_DIGITAL_JOYSTICK_FIRST + 1)) % 4);
899
m_field[direction] = &field;
904
//-------------------------------------------------
905
// frame_update - update the state of digital
906
// joysticks prior to accumulating the results
908
//-------------------------------------------------
910
void digital_joystick::frame_update()
912
// remember previous state and reset current state
913
m_previous = m_current;
916
// read all the associated ports
917
running_machine *machine = NULL;
918
for (direction_t direction = JOYDIR_UP; direction < JOYDIR_COUNT; direction++)
919
if (m_field[direction] != NULL)
921
machine = &m_field[direction]->machine();
922
if (machine->input().seq_pressed(m_field[direction]->seq(SEQ_TYPE_STANDARD)))
923
m_current |= 1 << direction;
926
// lock out opposing directions (left + right or up + down)
927
if ((m_current & (UP_BIT | DOWN_BIT)) == (UP_BIT | DOWN_BIT))
928
m_current &= ~(UP_BIT | DOWN_BIT);
929
if ((m_current & (LEFT_BIT | RIGHT_BIT)) == (LEFT_BIT | RIGHT_BIT))
930
m_current &= ~(LEFT_BIT | RIGHT_BIT);
932
// only update 4-way case if joystick has moved
933
if (m_current != m_previous)
935
m_current4way = m_current;
938
// If joystick is pointing at a diagonal, acknowledge that the player moved
939
// the joystick by favoring a direction change. This minimizes frustration
940
// when using a keyboard for input, and maximizes responsiveness.
942
// For example, if you are holding "left" then switch to "up" (where both left
943
// and up are briefly pressed at the same time), we'll transition immediately
946
// Zero any switches that didn't change from the previous to current state.
948
if ((m_current4way & (UP_BIT | DOWN_BIT)) &&
949
(m_current4way & (LEFT_BIT | RIGHT_BIT)))
951
m_current4way ^= m_current4way & m_previous;
955
// If we are still pointing at a diagonal, we are in an indeterminant state.
957
// This could happen if the player moved the joystick from the idle position directly
958
// to a diagonal, or from one diagonal directly to an extreme diagonal.
960
// The chances of this happening with a keyboard are slim, but we still need to
961
// constrain this case.
963
// For now, just resolve randomly.
965
if ((m_current4way & (UP_BIT | DOWN_BIT)) &&
966
(m_current4way & (LEFT_BIT | RIGHT_BIT)))
968
if (machine->rand() & 1)
969
m_current4way &= ~(LEFT_BIT | RIGHT_BIT);
971
m_current4way &= ~(UP_BIT | DOWN_BIT);
978
//**************************************************************************
980
//**************************************************************************
982
//-------------------------------------------------
983
// natural_keyboard - constructor
984
//-------------------------------------------------
986
natural_keyboard::natural_keyboard(running_machine &machine)
987
: m_machine(machine),
990
m_status_keydown(false),
993
m_current_rate(attotime::zero)
995
m_queue_chars = ioport_queue_chars_delegate();
996
m_accept_char = ioport_accept_char_delegate();
997
m_charqueue_empty = ioport_charqueue_empty_delegate();
999
// reigster debugger commands
1000
if (machine.debug_flags & DEBUG_FLAG_ENABLED)
1002
debug_console_register_command(machine, "input", CMDFLAG_NONE, 0, 1, 1, execute_input);
1003
debug_console_register_command(machine, "dumpkbd", CMDFLAG_NONE, 0, 0, 1, execute_dumpkbd);
1007
//-------------------------------------------------
1008
// initialize - initialize natural keyboard
1010
//-------------------------------------------------
1012
void natural_keyboard::initialize()
1014
// posting keys directly only makes sense for a computer
1015
if (machine().ioport().has_keyboard())
1017
m_buffer.resize(KEY_BUFFER_SIZE);
1018
m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(natural_keyboard::timer), this));
1019
build_codes(machine().ioport());
1022
//-------------------------------------------------
1023
// configure - configure callbacks for full-
1024
// featured keyboard support
1025
//-------------------------------------------------
1027
void natural_keyboard::configure(ioport_queue_chars_delegate queue_chars, ioport_accept_char_delegate accept_char, ioport_charqueue_empty_delegate charqueue_empty)
1029
// set the callbacks
1030
m_queue_chars = queue_chars;
1031
m_accept_char = accept_char;
1032
m_charqueue_empty = charqueue_empty;
1036
//-------------------------------------------------
1037
// post - post a single character
1038
//-------------------------------------------------
1040
void natural_keyboard::post(unicode_char ch)
1042
// ignore any \n that are preceded by \r
1043
if (m_last_cr && ch == '\n')
1049
// change all eolns to '\r'
1053
m_last_cr = (ch == '\r');
1056
if (LOG_NATURAL_KEYBOARD)
1058
const keycode_map_entry *code = find_code(ch);
1060
logerror("natural_keyboard::post(): code=%i (%s) field->name='%s'\n", int(ch), unicode_to_string(tempstr, ch), (code != NULL && code->field[0] != NULL) ? code->field[0]->name() : "<null>");
1063
// can we post this key in the queue directly?
1064
if (can_post_directly(ch))
1067
// can we post this key with an alternate representation?
1068
else if (can_post_alternate(ch))
1070
const char_info *info = char_info::find(ch);
1071
assert(info != NULL && info->alternate != NULL);
1072
const char *altstring = info->alternate;
1073
while (*altstring != 0)
1075
altstring += uchar_from_utf8(&ch, altstring, strlen(altstring));
1082
//-------------------------------------------------
1083
// post - post a unicode encoded string
1084
//-------------------------------------------------
1086
void natural_keyboard::post(const unicode_char *text, size_t length, attotime rate)
1088
// set the fixed rate
1089
m_current_rate = rate;
1091
// 0 length means strlen
1093
for (const unicode_char *scan = text; *scan != 0; scan++)
1096
// iterate over characters or until the buffer is full up
1097
while (length > 0 && !full())
1099
// fetch next character
1106
//-------------------------------------------------
1107
// post_utf8 - post a UTF-8 encoded string
1108
//-------------------------------------------------
1110
void natural_keyboard::post_utf8(const char *text, size_t length, attotime rate)
1112
// set the fixed rate
1113
m_current_rate = rate;
1115
// 0-length means strlen
1117
length = strlen(text);
1119
// iterate until out of characters
1122
// decode the next character
1124
int count = uchar_from_utf8(&uc, text, length);
1131
// append to the buffer
1139
//-------------------------------------------------
1140
// post_coded - post a coded string
1141
//-------------------------------------------------
1143
void natural_keyboard::post_coded(const char *text, size_t length, attotime rate)
1154
{ "DEL", UCHAR_MAMEKEY(DEL) },
1155
{ "DELETE", UCHAR_MAMEKEY(DEL) },
1156
{ "END", UCHAR_MAMEKEY(END) },
1159
{ "HOME", UCHAR_MAMEKEY(HOME) },
1160
{ "INS", UCHAR_MAMEKEY(INSERT) },
1161
{ "INSERT", UCHAR_MAMEKEY(INSERT) },
1162
{ "PGDN", UCHAR_MAMEKEY(PGDN) },
1163
{ "PGUP", UCHAR_MAMEKEY(PGUP) },
1166
{ "F1", UCHAR_MAMEKEY(F1) },
1167
{ "F2", UCHAR_MAMEKEY(F2) },
1168
{ "F3", UCHAR_MAMEKEY(F3) },
1169
{ "F4", UCHAR_MAMEKEY(F4) },
1170
{ "F5", UCHAR_MAMEKEY(F5) },
1171
{ "F6", UCHAR_MAMEKEY(F6) },
1172
{ "F7", UCHAR_MAMEKEY(F7) },
1173
{ "F8", UCHAR_MAMEKEY(F8) },
1174
{ "F9", UCHAR_MAMEKEY(F9) },
1175
{ "F10", UCHAR_MAMEKEY(F10) },
1176
{ "F11", UCHAR_MAMEKEY(F11) },
1177
{ "F12", UCHAR_MAMEKEY(F12) },
1181
// set the fixed rate
1182
m_current_rate = rate;
1184
// 0-length means strlen
1186
length = strlen(text);
1188
// iterate through the source string
1190
while (curpos < length)
1192
// extract next character
1193
unicode_char ch = text[curpos];
1194
size_t increment = 1;
1196
// look for escape characters
1198
for (int codenum = 0; codenum < ARRAY_LENGTH(codes); codenum++)
1200
size_t keylen = strlen(codes[codenum].key);
1201
if (curpos + keylen + 2 <= length)
1202
if (core_strnicmp(codes[codenum].key, &text[curpos + 1], keylen) == 0 && text[curpos + keylen + 1] == '}')
1204
ch = codes[codenum].code;
1205
increment = keylen + 2;
1209
// if we got a code, post it
1212
curpos += increment;
1217
//-------------------------------------------------
1218
// build_codes - given an input port table, create
1219
// an input code table useful for mapping unicode
1221
//-------------------------------------------------
1223
void natural_keyboard::build_codes(ioport_manager &manager)
1225
// iterate over shift keys
1226
ioport_field *shift[UCHAR_SHIFT_END + 1 - UCHAR_SHIFT_BEGIN] = { 0 };
1227
for (int curshift = 0; curshift <= ARRAY_LENGTH(shift); curshift++)
1228
if (curshift == 0 || shift[curshift - 1] != NULL)
1230
// iterate over ports and fields
1231
for (ioport_port *port = manager.first_port(); port != NULL; port = port->next())
1232
for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
1233
if (field->type() == IPT_KEYBOARD)
1235
// fetch the code, ignoring 0
1236
unicode_char code = field->keyboard_code(curshift);
1240
// is this a shifter key?
1241
if (code >= UCHAR_SHIFT_BEGIN && code <= UCHAR_SHIFT_END)
1242
shift[code - UCHAR_SHIFT_BEGIN] = field;
1244
// not a shifter key; record normally
1247
keycode_map_entry newcode;
1250
newcode.field[0] = field;
1251
newcode.field[1] = 0;
1255
newcode.field[0] = shift[curshift - 1];
1256
newcode.field[1] = field;
1259
m_keycode_map.append(newcode);
1261
if (LOG_NATURAL_KEYBOARD)
1264
logerror("natural_keyboard: code=%i (%s) port=%p field->name='%s'\n", int(code), unicode_to_string(tempstr, code), port, field->name());
1271
//-------------------------------------------------
1272
// can_post_directly - determine if the given
1273
// unicode character can be directly posted
1274
//-------------------------------------------------
1276
bool natural_keyboard::can_post_directly(unicode_char ch)
1278
// if we have a queueing callback, then it depends on whether we can accept the character
1279
if (!m_queue_chars.isnull())
1280
return m_accept_char.isnull() ? true : m_accept_char(ch);
1282
// otherwise, it depends on the input codes
1283
const keycode_map_entry *code = find_code(ch);
1284
return (code != NULL && code->field[0] != NULL);
1288
//-------------------------------------------------
1289
// can_post_alternate - determine if the given
1290
// unicode character can be posted via translation
1291
//-------------------------------------------------
1293
bool natural_keyboard::can_post_alternate(unicode_char ch)
1295
const char_info *info = char_info::find(ch);
1299
const char *altstring = info->alternate;
1300
if (altstring == NULL)
1303
while (*altstring != 0)
1306
int count = uchar_from_utf8(&uchar, altstring, strlen(altstring));
1309
if (!can_post_directly(uchar))
1317
//-------------------------------------------------
1318
// choose_delay - determine the delay between
1319
// posting keyboard events
1320
//-------------------------------------------------
1322
attotime natural_keyboard::choose_delay(unicode_char ch)
1324
// if we have a live rate, just use that
1325
if (m_current_rate != attotime::zero)
1326
return m_current_rate;
1328
// systems with queue_chars can afford a much smaller delay
1329
if (!m_queue_chars.isnull())
1330
return attotime::from_msec(10);
1332
// otherwise, default to constant delay with a longer delay on CR
1333
return attotime::from_msec((ch == '\r') ? 200 : 50);
1337
//-------------------------------------------------
1338
// internal_post - post a keyboard event
1339
//-------------------------------------------------
1341
void natural_keyboard::internal_post(unicode_char ch)
1343
// need to start up the timer?
1346
m_timer->adjust(choose_delay(ch));
1347
m_status_keydown = 0;
1350
// add to the buffer, resizing if necessary
1351
m_buffer[m_bufend++] = ch;
1352
if ((m_bufend + 1) % m_buffer.count() == m_bufbegin)
1353
m_buffer.resize(m_buffer.count() + KEY_BUFFER_SIZE, true);
1354
m_bufend %= m_buffer.count();
1358
//-------------------------------------------------
1359
// timer - timer callback to keep things flowing
1360
// when posting a string of characters
1361
//-------------------------------------------------
1363
void natural_keyboard::timer(void *ptr, int param)
1365
// the driver has a queue_chars handler
1366
if (!m_queue_chars.isnull())
1368
while (!empty() && m_queue_chars(&m_buffer[m_bufbegin], 1))
1370
m_bufbegin = (m_bufbegin + 1) % m_buffer.count();
1371
if (m_current_rate != attotime::zero)
1376
// the driver does not have a queue_chars handler
1379
if (m_status_keydown)
1380
m_bufbegin = (m_bufbegin + 1) % m_buffer.count();
1381
m_status_keydown = !m_status_keydown;
1384
// need to make sure timerproc is called again if buffer not empty
1386
m_timer->adjust(choose_delay(m_buffer[m_bufbegin]));
1390
//-------------------------------------------------
1391
// unicode_to_string - obtain a string
1392
// representation of a given code; used for
1393
// logging and debugging
1394
//-------------------------------------------------
1396
const char *natural_keyboard::unicode_to_string(astring &buffer, unicode_char ch)
1401
// check some magic values
1402
case '\0': buffer.cpy("\\0"); break;
1403
case '\r': buffer.cpy("\\r"); break;
1404
case '\n': buffer.cpy("\\n"); break;
1405
case '\t': buffer.cpy("\\t"); break;
1408
// seven bit ASCII is easy
1409
if (ch >= 32 && ch < 128)
1411
char temp[2] = { char(ch), 0 };
1414
else if (ch >= UCHAR_MAMEKEY_BEGIN)
1416
// try to obtain a codename with code_name(); this can result in an empty string
1417
input_code code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, input_item_id(ch - UCHAR_MAMEKEY_BEGIN));
1418
machine().input().code_name(buffer, code);
1421
// did we fail to resolve? if so, we have a last resort
1422
if (buffer.len() == 0)
1423
buffer.format("U+%04X", unsigned(ch));
1430
//-------------------------------------------------
1431
// find_code - find a code in our lookup table
1432
//-------------------------------------------------
1434
const natural_keyboard::keycode_map_entry *natural_keyboard::find_code(unicode_char ch) const
1436
for (int index = 0; index < m_keycode_map.count(); index++)
1438
if (m_keycode_map[index].ch == ch)
1439
return &m_keycode_map[index];
991
/***************************************************************************
992
ACCESSORS FOR INPUT FIELDS
993
***************************************************************************/
995
/*-------------------------------------------------
996
input_field_name - return the field name for
998
-------------------------------------------------*/
1000
const char *input_field_name(const input_field_config *field)
1002
/* if we have a non-default name, use that */
1003
if ((field->state != NULL) && (field->state->name != NULL))
1004
return field->state->name;
1005
if (field->name != NULL)
1008
/* otherwise, return the name associated with the type */
1009
return input_type_name(field->machine(), field->type, field->player);
1013
/*-------------------------------------------------
1014
input_field_seq - return the input sequence
1015
for the given input field
1016
-------------------------------------------------*/
1018
const input_seq &input_field_seq(const input_field_config *field, input_seq_type seqtype)
1020
/* if the field is disabled, return no key */
1021
if (field->flags & FIELD_FLAG_UNUSED)
1022
return input_seq::empty_seq;
1024
/* select either the live or config state depending on whether we have live state */
1025
const input_seq &portseq = (field->state == NULL) ? field->seq[seqtype] : field->state->seq[seqtype];
1027
/* if the portseq is the special default code, return the expanded default value */
1028
if (portseq.is_default())
1029
return input_type_seq(field->machine(), field->type, field->player, seqtype);
1031
/* otherwise, return the sequence as-is */
1036
/*-------------------------------------------------
1037
input_field_get_user_settings - return the current
1038
settings for the given input field
1039
-------------------------------------------------*/
1041
void input_field_get_user_settings(const input_field_config *field, input_field_user_settings *settings)
1045
/* zap the entire structure */
1046
memset(settings, 0, sizeof(*settings));
1048
/* copy the basics */
1049
for (seqtype = 0; seqtype < ARRAY_LENGTH(settings->seq); seqtype++)
1050
settings->seq[seqtype] = field->state->seq[seqtype];
1052
/* if there's a list of settings or we're an adjuster, copy the current value */
1053
if (field->settinglist().count() != 0 || field->type == IPT_ADJUSTER)
1054
settings->value = field->state->value;
1056
/* if there's analog data, extract the analog settings */
1057
if (field->state->analog != NULL)
1059
settings->sensitivity = field->state->analog->sensitivity;
1060
settings->delta = field->state->analog->delta;
1061
settings->centerdelta = field->state->analog->centerdelta;
1062
settings->reverse = field->state->analog->reverse;
1067
/*-------------------------------------------------
1068
input_field_set_user_settings - modify the current
1069
settings for the given input field
1070
-------------------------------------------------*/
1072
void input_field_set_user_settings(const input_field_config *field, const input_field_user_settings *settings)
1076
/* copy the basics */
1077
for (seqtype = 0; seqtype < ARRAY_LENGTH(settings->seq); seqtype++)
1079
const input_seq &defseq = input_type_seq(field->machine(), field->type, field->player, (input_seq_type)seqtype);
1080
if (defseq == settings->seq[seqtype])
1081
field->state->seq[seqtype].set_default();
1083
field->state->seq[seqtype] = settings->seq[seqtype];
1086
/* if there's a list of settings or we're an adjuster, copy the current value */
1087
if (field->settinglist().count() != 0 || field->type == IPT_ADJUSTER)
1088
field->state->value = settings->value;
1090
/* if there's analog data, extract the analog settings */
1091
if (field->state->analog != NULL)
1093
field->state->analog->sensitivity = settings->sensitivity;
1094
field->state->analog->delta = settings->delta;
1095
field->state->analog->centerdelta = settings->centerdelta;
1096
field->state->analog->reverse = settings->reverse;
1101
/*-------------------------------------------------
1102
input_field_setting_name - return the expanded
1103
setting name for a field
1104
-------------------------------------------------*/
1106
const char *input_field_setting_name(const input_field_config *field)
1108
const input_setting_config *setting;
1110
/* only makes sense if we have settings */
1111
assert(field->settinglist().count() != 0);
1113
/* scan the list of settings looking for a match on the current value */
1114
for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
1115
if (input_condition_true(field->machine(), &setting->condition, field->port().owner()))
1116
if (setting->value == field->state->value)
1117
return setting->name;
1445
//-------------------------------------------------
1446
// frame_update - once per frame update of the
1447
// natural keyboard state
1448
//-------------------------------------------------
1450
void natural_keyboard::frame_update(ioport_port &port, ioport_value &digital)
1452
// is there currently a key down?
1453
if (m_status_keydown && !empty())
1455
// loop through this character's component codes
1456
const keycode_map_entry *code = find_code(m_buffer[m_bufbegin]);
1458
for (int fieldnum = 0; fieldnum < ARRAY_LENGTH(code->field) && code->field[fieldnum] != NULL; fieldnum++)
1459
if (&code->field[fieldnum]->port() == &port)
1460
digital |= code->field[fieldnum]->mask();
1465
//-------------------------------------------------
1466
// key_name - returns the name of a specific key
1467
//-------------------------------------------------
1469
const char *natural_keyboard::key_name(astring &string, unicode_char ch)
1471
// attempt to get the string from the character info table
1472
const char_info *ci = char_info::find(ch);
1473
const char *result = (ci != NULL) ? ci->name : NULL;
1477
// if that doesn't work, convert to UTF-8
1478
else if (ch > 0x7F || isprint(ch))
1481
int count = utf8_from_uchar(buf, ARRAY_LENGTH(buf), ch);
1486
// otherwise, opt for question marks
1493
//-------------------------------------------------
1494
// execute_input - debugger command to enter
1495
// natural keyboard input
1496
//-------------------------------------------------
1498
void natural_keyboard::execute_input(running_machine &machine, int ref, int params, const char *param[])
1500
machine.ioport().natkeyboard().post_coded(param[0]);
1504
//-------------------------------------------------
1505
// execute_dumpkbd - debugger command to natural
1507
//-------------------------------------------------
1509
void natural_keyboard::execute_dumpkbd(running_machine &machine, int ref, int params, const char *param[])
1511
// was there a file specified?
1512
const char *filename = (params > 0) ? param[0] : NULL;
1514
if (filename != NULL)
1517
file = fopen(filename, "w");
1520
debug_console_printf(machine, "Cannot open \"%s\"\n", filename);
1525
// loop through all codes
1526
natural_keyboard &natkeyboard = machine.ioport().natkeyboard();
1527
dynamic_array<keycode_map_entry> &keycode_map = natkeyboard.m_keycode_map;
1528
astring buffer, tempstr;
1529
const size_t left_column_width = 24;
1530
for (int index = 0; index < keycode_map.count(); index++)
1532
// describe the character code
1533
const keycode_map_entry &code = keycode_map[index];
1534
buffer.printf("%08X (%s) ", code.ch, natkeyboard.unicode_to_string(tempstr, code.ch));
1537
while (buffer.len() < left_column_width)
1540
// identify the keys used
1541
for (int field = 0; field < ARRAY_LENGTH(code.field) && code.field[field] != 0; field++)
1542
buffer.catprintf("%s'%s'", (field > 0) ? ", " : "", code.field[field]->name());
1544
// and output it as appropriate
1546
fprintf(file, "%s\n", buffer.cstr());
1548
debug_console_printf(machine, "%s\n", buffer.cstr());
1558
//**************************************************************************
1559
// I/O PORT CONDITION
1560
//**************************************************************************
1562
//-------------------------------------------------
1563
// eval - evaluate condition
1564
//-------------------------------------------------
1566
bool ioport_condition::eval(device_t &device) const
1568
// always condition is always true
1569
if (m_condition == ALWAYS)
1572
// otherwise, read the referenced port and switch off the condition type
1573
ioport_value condvalue = device.ioport(m_tag)->read();
1574
switch (m_condition)
1576
case ALWAYS: return true;
1577
case EQUALS: return ((condvalue & m_mask) == m_value);
1578
case NOTEQUALS: return ((condvalue & m_mask) != m_value);
1579
case GREATERTHAN: return ((condvalue & m_mask) > m_value);
1580
case NOTGREATERTHAN: return ((condvalue & m_mask) <= m_value);
1581
case LESSTHAN: return ((condvalue & m_mask) < m_value);
1582
case NOTLESSTHAN: return ((condvalue & m_mask) >= m_value);
1589
//**************************************************************************
1591
//**************************************************************************
1593
//-------------------------------------------------
1594
// ioport_setting - constructor
1595
//-------------------------------------------------
1597
ioport_setting::ioport_setting(ioport_field &field, ioport_value _value, const char *_name)
1607
//**************************************************************************
1608
// I/O PORT DIP LOCATION
1609
//**************************************************************************
1611
//-------------------------------------------------
1612
// ioport_diplocation - constructor
1613
//-------------------------------------------------
1615
ioport_diplocation::ioport_diplocation(const char *name, UINT8 swnum, bool invert)
1625
//**************************************************************************
1627
//**************************************************************************
1629
//-------------------------------------------------
1630
// ioport_field - constructor
1631
//-------------------------------------------------
1633
ioport_field::ioport_field(ioport_port &port, ioport_type type, ioport_value defvalue, ioport_value maskbits, const char *name)
1637
m_modcount(port.modcount()),
1639
m_defvalue(defvalue & maskbits),
1646
m_write_param(NULL),
1652
m_crosshair_axis(CROSSHAIR_AXIS_NONE),
1653
m_crosshair_scale(1.0),
1654
m_crosshair_offset(0),
1655
m_crosshair_altaxis(0),
1656
m_full_turn_count(0),
1657
m_remap_table(NULL),
1660
// reset sequences and chars
1661
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
1662
m_seq[seqtype].set_default();
1663
m_chars[0] = m_chars[1] = m_chars[2] = m_chars[3] = unicode_char(0);
1665
// for DIP switches and configs, look for a default value from the owner
1666
if (type == IPT_DIPSWITCH || type == IPT_CONFIG)
1668
const input_device_default *def = device().input_ports_defaults();
1671
const char *fulltag = port.tag();
1673
for ( ; def->tag != NULL; def++)
1674
if (device().subtag(fullpath, def->tag) == fulltag && def->mask == m_mask)
1675
m_defvalue = def->defvalue & m_mask;
1681
//-------------------------------------------------
1682
// ~ioport_field - destructor
1683
//-------------------------------------------------
1685
ioport_field::~ioport_field()
1687
global_free(m_live);
1691
//-------------------------------------------------
1692
// name - return the field name for a given input
1694
//-------------------------------------------------
1696
const char *ioport_field::name() const
1698
// if we have a non-default name, use that
1699
if (m_live != NULL && m_live->name)
1700
return m_live->name;
1704
// otherwise, return the name associated with the type
1705
return manager().type_name(m_type, m_player);
1709
//-------------------------------------------------
1710
// seq - return the live input sequence for the
1711
// given input field
1712
//-------------------------------------------------
1714
const input_seq &ioport_field::seq(input_seq_type seqtype) const
1716
// if no live state, return default
1718
return defseq(seqtype);
1720
// if the field is disabled, return no key
1722
return input_seq::empty_seq;
1724
// if the sequence is the special default code, return the expanded default value
1725
if (m_live->seq[seqtype].is_default())
1726
return manager().type_seq(m_type, m_player, seqtype);
1728
// otherwise, return the sequence as-is
1729
return m_live->seq[seqtype];
1733
//-------------------------------------------------
1734
// defseq - return the default input sequence for
1735
// the given input field
1736
//-------------------------------------------------
1738
const input_seq &ioport_field::defseq(input_seq_type seqtype) const
1740
// if the field is disabled, return no key
1742
return input_seq::empty_seq;
1744
// if the sequence is the special default code, return the expanded default value
1745
if (m_seq[seqtype].is_default())
1746
return manager().type_seq(m_type, m_player, seqtype);
1748
// otherwise, return the sequence as-is
1749
return m_seq[seqtype];
1753
//-------------------------------------------------
1754
// type_class - return the type class for this
1756
//-------------------------------------------------
1758
ioport_type_class ioport_field::type_class() const
1760
ioport_type_class result;
1764
case IPT_JOYSTICK_UP:
1765
case IPT_JOYSTICK_DOWN:
1766
case IPT_JOYSTICK_LEFT:
1767
case IPT_JOYSTICK_RIGHT:
1768
case IPT_JOYSTICKLEFT_UP:
1769
case IPT_JOYSTICKLEFT_DOWN:
1770
case IPT_JOYSTICKLEFT_LEFT:
1771
case IPT_JOYSTICKLEFT_RIGHT:
1772
case IPT_JOYSTICKRIGHT_UP:
1773
case IPT_JOYSTICKRIGHT_DOWN:
1774
case IPT_JOYSTICKRIGHT_LEFT:
1775
case IPT_JOYSTICKRIGHT_RIGHT:
1786
case IPT_AD_STICK_X:
1787
case IPT_AD_STICK_Y:
1788
case IPT_AD_STICK_Z:
1789
case IPT_TRACKBALL_X:
1790
case IPT_TRACKBALL_Y:
1791
case IPT_LIGHTGUN_X:
1792
case IPT_LIGHTGUN_Y:
1797
result = INPUT_CLASS_CONTROLLER;
1802
result = INPUT_CLASS_KEYBOARD;
1806
result = INPUT_CLASS_CONFIG;
1810
result = INPUT_CLASS_DIPSWITCH;
1814
if (m_name != NULL && m_name != (const char *)-1)
1815
result = INPUT_CLASS_MISC;
1817
result = INPUT_CLASS_INTERNAL;
1821
result = INPUT_CLASS_INTERNAL;
1828
//-------------------------------------------------
1829
// keyboard_code - accesses a particular keyboard
1831
//-------------------------------------------------
1833
unicode_char ioport_field::keyboard_code(int which) const
1837
if (which >= ARRAY_LENGTH(m_chars))
1838
throw emu_fatalerror("Tried to access keyboard_code with out-of-range index %d\n", which);
1840
ch = m_chars[which];
1842
// special hack to allow for PORT_CODE('\xA3')
1843
if (ch >= 0xffffff80 && ch <= 0xffffffff)
1849
//-------------------------------------------------
1850
// get_user_settings - return the current
1851
// settings for the given input field
1852
//-------------------------------------------------
1854
void ioport_field::get_user_settings(user_settings &settings)
1856
// zap the entire structure
1857
memset(&settings, 0, sizeof(settings));
1860
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
1861
settings.seq[seqtype] = seq(seqtype);
1863
// if there's a list of settings or we're an adjuster, copy the current value
1864
if (first_setting() != NULL || m_type == IPT_ADJUSTER)
1865
settings.value = m_live->value;
1867
// if there's analog data, extract the analog settings
1868
if (m_live->analog != NULL)
1870
settings.sensitivity = m_live->analog->sensitivity();
1871
settings.delta = m_live->analog->delta();
1872
settings.centerdelta = m_live->analog->centerdelta();
1873
settings.reverse = m_live->analog->reverse();
1878
//-------------------------------------------------
1879
// set_user_settings - modify the current
1880
// settings for the given input field
1881
//-------------------------------------------------
1883
void ioport_field::set_user_settings(const user_settings &settings)
1886
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
1888
const input_seq &defseq = manager().type_seq(m_type, m_player, input_seq_type(seqtype));
1889
if (defseq == settings.seq[seqtype])
1890
m_live->seq[seqtype].set_default();
1892
m_live->seq[seqtype] = settings.seq[seqtype];
1895
// if there's a list of settings or we're an adjuster, copy the current value
1896
if (first_setting() != NULL || m_type == IPT_ADJUSTER)
1897
m_live->value = settings.value;
1899
// if there's analog data, extract the analog settings
1900
if (m_live->analog != NULL)
1902
m_live->analog->m_sensitivity = settings.sensitivity;
1903
m_live->analog->m_delta = settings.delta;
1904
m_live->analog->m_centerdelta = settings.centerdelta;
1905
m_live->analog->m_reverse = settings.reverse;
1910
//-------------------------------------------------
1911
// setting_name - return the expanded setting
1913
//-------------------------------------------------
1915
const char *ioport_field::setting_name() const
1917
// only makes sense if we have settings
1918
assert(first_setting() != NULL);
1920
// scan the list of settings looking for a match on the current value
1921
for (ioport_setting *setting = first_setting(); setting != NULL; setting = setting->next())
1922
if (setting->enabled())
1923
if (setting->value() == m_live->value)
1924
return setting->name();
1119
1926
return "INVALID";
1123
/*-------------------------------------------------
1124
input_field_has_previous_setting - return TRUE
1125
if the given field has a "previous" setting
1126
-------------------------------------------------*/
1930
//-------------------------------------------------
1931
// has_previous_setting - return true if the
1932
// given field has a "previous" setting
1933
//-------------------------------------------------
1128
int input_field_has_previous_setting(const input_field_config *field)
1935
bool ioport_field::has_previous_setting() const
1130
const input_setting_config *setting;
1132
/* only makes sense if we have settings */
1133
assert(field->settinglist().count() != 0);
1135
/* scan the list of settings looking for a match on the current value */
1136
for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
1137
if (input_condition_true(field->machine(), &setting->condition, field->port().owner()))
1138
return (setting->value != field->state->value);
1937
// only makes sense if we have settings
1938
assert(first_setting() != NULL);
1940
// scan the list of settings looking for a match on the current value
1941
for (ioport_setting *setting = first_setting(); setting != NULL; setting = setting->next())
1942
if (setting->enabled())
1943
return (setting->value() != m_live->value);
1144
/*-------------------------------------------------
1145
input_field_select_previous_setting - select
1146
the previous item for a DIP switch or
1148
-------------------------------------------------*/
1949
//-------------------------------------------------
1950
// select_previous_setting - select the previous
1951
// item for a DIP switch or configuration field
1952
//-------------------------------------------------
1150
void input_field_select_previous_setting(const input_field_config *field)
1954
void ioport_field::select_previous_setting()
1152
const input_setting_config *setting, *prevsetting;
1153
int found_match = FALSE;
1155
/* only makes sense if we have settings */
1156
assert(field->settinglist().count() != 0);
1158
/* scan the list of settings looking for a match on the current value */
1160
for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
1161
if (input_condition_true(field->machine(), &setting->condition, field->port().owner()))
1956
// only makes sense if we have settings
1957
assert(first_setting() != NULL);
1959
// scan the list of settings looking for a match on the current value
1960
ioport_setting *prevsetting = NULL;
1961
bool found_match = false;
1962
for (ioport_setting *setting = first_setting(); setting != NULL; setting = setting->next())
1963
if (setting->enabled())
1163
if (setting->value == field->state->value)
1965
if (setting->value() == m_live->value)
1166
1968
if (prevsetting != NULL)
1169
1971
prevsetting = setting;
1172
/* if we didn't find a matching value, select the first */
1974
// if we didn't find a matching value, select the first
1173
1975
if (!found_match)
1175
for (prevsetting = field->settinglist().first(); prevsetting != NULL; prevsetting = prevsetting->next())
1176
if (input_condition_true(field->machine(), &prevsetting->condition, field->port().owner()))
1977
for (prevsetting = first_setting(); prevsetting != NULL; prevsetting = prevsetting->next())
1978
if (prevsetting->enabled())
1180
/* update the value to the previous one */
1982
// update the value to the previous one
1181
1983
if (prevsetting != NULL)
1182
field->state->value = prevsetting->value;
1984
m_live->value = prevsetting->value();
1186
/*-------------------------------------------------
1187
input_field_has_next_setting - return TRUE
1188
if the given field has a "next" setting
1189
-------------------------------------------------*/
1988
//-------------------------------------------------
1989
// has_next_setting - return true if the given
1990
// field has a "next" setting
1991
//-------------------------------------------------
1191
int input_field_has_next_setting(const input_field_config *field)
1993
bool ioport_field::has_next_setting() const
1193
const input_setting_config *setting;
1196
/* only makes sense if we have settings */
1197
assert(field->settinglist().count() != 0);
1199
/* scan the list of settings looking for a match on the current value */
1200
for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
1201
if (input_condition_true(field->machine(), &setting->condition, field->port().owner()))
1995
// only makes sense if we have settings
1996
assert(first_setting() != NULL);
1998
// scan the list of settings looking for a match on the current value
2000
for (ioport_setting *setting = first_setting(); setting != NULL; setting = setting->next())
2001
if (setting->enabled())
1205
if (setting->value == field->state->value)
2005
if (setting->value() == m_live->value)
1213
/*-------------------------------------------------
1214
input_field_select_next_setting - select the
1215
next item for a DIP switch or
1217
-------------------------------------------------*/
2013
//-------------------------------------------------
2014
// select_next_setting - select the next item for
2015
// a DIP switch or configuration field
2016
//-------------------------------------------------
1219
void input_field_select_next_setting(const input_field_config *field)
2018
void ioport_field::select_next_setting()
1221
const input_setting_config *setting, *nextsetting;
1223
/* only makes sense if we have settings */
1224
assert(field->settinglist().count() != 0);
1226
/* scan the list of settings looking for a match on the current value */
1228
for (setting = field->settinglist().first(); setting != NULL; setting = setting->next())
1229
if (input_condition_true(field->machine(), &setting->condition, field->port().owner()))
1230
if (setting->value == field->state->value)
2020
// only makes sense if we have settings
2021
assert(first_setting() != NULL);
2023
// scan the list of settings looking for a match on the current value
2024
ioport_setting *nextsetting = NULL;
2025
ioport_setting *setting;
2026
for (setting = first_setting(); setting != NULL; setting = setting->next())
2027
if (setting->enabled())
2028
if (setting->value() == m_live->value)
1233
/* if we found one, scan forward for the next valid one */
2031
// if we found one, scan forward for the next valid one
1234
2032
if (setting != NULL)
1235
2033
for (nextsetting = setting->next(); nextsetting != NULL; nextsetting = nextsetting->next())
1236
if (input_condition_true(field->machine(), &nextsetting->condition, field->port().owner()))
2034
if (nextsetting->enabled())
1239
/* if we hit the end, search from the beginning */
2037
// if we hit the end, search from the beginning
1240
2038
if (nextsetting == NULL)
1241
for (nextsetting = field->settinglist().first(); nextsetting != NULL; nextsetting = nextsetting->next())
1242
if (input_condition_true(field->machine(), &nextsetting->condition, field->port().owner()))
2039
for (nextsetting = first_setting(); nextsetting != NULL; nextsetting = nextsetting->next())
2040
if (nextsetting->enabled())
1245
/* update the value to the previous one */
2043
// update the value to the previous one
1246
2044
if (nextsetting != NULL)
1247
field->state->value = nextsetting->value;
1252
/***************************************************************************
1253
ACCESSORS FOR INPUT TYPES
1254
***************************************************************************/
1256
/*-------------------------------------------------
1257
input_type_is_analog - return TRUE if
1258
the given type represents an analog control
1259
-------------------------------------------------*/
1261
int input_type_is_analog(int type)
1263
return (type >= __ipt_analog_start && type <= __ipt_analog_end);
1267
/*-------------------------------------------------
1268
input_type_name - return the name
1269
for the given type/player
1270
-------------------------------------------------*/
1272
const char *input_type_name(running_machine &machine, int type, int player)
1274
/* if we have a machine, use the live state and quick lookup */
1275
input_port_private *portdata = machine.input_port_data;
1276
input_type_entry *entry = portdata->type_to_entry[type][player];
1280
/* if we find nothing, return an invalid group */
1285
/*-------------------------------------------------
1286
input_type_group - return the group
1287
for the given type/player
1288
-------------------------------------------------*/
1290
int input_type_group(running_machine &machine, int type, int player)
1292
input_port_private *portdata = machine.input_port_data;
1293
input_type_entry *entry = portdata->type_to_entry[type][player];
1295
return entry->group;
1297
/* if we find nothing, return an invalid group */
1302
/*-------------------------------------------------
1303
input_type_seq - return the input
1304
sequence for the given type/player
1305
-------------------------------------------------*/
1307
const input_seq &input_type_seq(running_machine &machine, int type, int player, input_seq_type seqtype)
1309
assert(type >= 0 && type < __ipt_max);
1310
assert(player >= 0 && player < MAX_PLAYERS);
1312
/* if we have a machine, use the live state and quick lookup */
1313
input_port_private *portdata = machine.input_port_data;
1314
input_type_entry *entry = portdata->type_to_entry[type][player];
1316
return entry->seq[seqtype];
1318
/* if we find nothing, return an empty sequence */
1319
return input_seq::empty_seq;
1323
/*-------------------------------------------------
1324
input_type_set_seq - change the input
1325
sequence for the given type/player
1326
-------------------------------------------------*/
1328
void input_type_set_seq(running_machine &machine, int type, int player, input_seq_type seqtype, const input_seq *newseq)
1330
input_port_private *portdata = machine.input_port_data;
1331
input_type_entry *entry = portdata->type_to_entry[type][player];
1333
entry->seq[seqtype] = *newseq;
1337
/*-------------------------------------------------
1338
input_type_pressed - return TRUE if
1339
the sequence for the given input type/player
1341
-------------------------------------------------*/
1343
int input_type_pressed(running_machine &machine, int type, int player)
1345
return machine.input().seq_pressed(input_type_seq(machine, type, player, SEQ_TYPE_STANDARD));
1349
/*-------------------------------------------------
1350
input_type_list - return the list of types
1351
-------------------------------------------------*/
1353
const simple_list<input_type_entry> &input_type_list(running_machine &machine)
1355
input_port_private *portdata = machine.input_port_data;
1356
return portdata->typelist;
1361
/***************************************************************************
1363
***************************************************************************/
1366
/*-------------------------------------------------
1367
input_port_exists - return whether an input
1369
-------------------------------------------------*/
1371
bool input_port_exists(running_machine &machine, const char *tag)
1373
return machine.port(tag) != 0;
1377
/*-------------------------------------------------
1378
input_port_active - return a bitmask of which
1379
bits of an input port are active (i.e. not
1381
-------------------------------------------------*/
1383
input_port_value input_port_active(running_machine &machine, const char *tag)
1385
const input_port_config *port = machine.port(tag);
1387
fatalerror("Unable to locate input port '%s'", tag);
1388
return port->active;
1392
/*-------------------------------------------------
1393
input_port_active_safe - return a bitmask of
1394
which bits of an input port are active (i.e.
1395
not unused or unknown), or a default value if
1396
the port does not exist
1397
-------------------------------------------------*/
1399
input_port_value input_port_active_safe(running_machine &machine, const char *tag, input_port_value defvalue)
1401
const input_port_config *port = machine.port(tag);
1402
return port == NULL ? defvalue : port->active;
1407
/***************************************************************************
1409
***************************************************************************/
1411
/*-------------------------------------------------
1412
input_port_read_direct - return the value of
1414
-------------------------------------------------*/
1416
input_port_value input_port_read_direct(const input_port_config *port)
1418
assert(port != NULL);
1420
input_port_private *portdata = port->machine().input_port_data;
1421
analog_field_state *analog;
1422
device_field_info *device_field;
1423
input_port_value result;
1425
assert_always(portdata->safe_to_read, "Input ports cannot be read at init time!");
1427
/* start with the digital */
1428
result = port->state->digital;
1430
/* update read values */
1431
for (device_field = port->state->readdevicelist; device_field != NULL; device_field = device_field->next)
1432
if (input_condition_true(port->machine(), &device_field->field->condition, port->owner()))
1434
/* replace the bits with bits from the device */
1435
input_port_value newval = device_field->field->read(*device_field->field, device_field->field->read_param);
1436
device_field->oldval = newval;
1437
result = (result & ~device_field->field->mask) | ((newval << device_field->shift) & device_field->field->mask);
1440
/* update VBLANK bits */
1441
if (port->state->vblank != 0)
1443
if (port->machine().primary_screen->vblank())
1444
result |= port->state->vblank;
1446
result &= ~port->state->vblank;
1449
/* apply active high/low state to digital, read, and VBLANK inputs */
1450
result ^= port->state->defvalue;
1452
/* merge in analog portions */
1453
for (analog = port->state->analoglist; analog != NULL; analog = analog->next)
1454
if (input_condition_true(port->machine(), &analog->field->condition, port->owner()))
1456
/* start with the raw value */
1457
INT32 value = analog->accum;
1459
/* interpolate if appropriate and if time has passed since the last update */
1460
if (analog->interpolate && !(analog->field->flags & ANALOG_FLAG_RESET) && portdata->last_delta_nsec != 0)
1462
attoseconds_t nsec_since_last = (port->machine().time() - portdata->last_frame_time).as_attoseconds() / ATTOSECONDS_PER_NANOSECOND;
1463
value = analog->previous + ((INT64)(analog->accum - analog->previous) * nsec_since_last / portdata->last_delta_nsec);
1466
/* apply standard analog settings */
1467
value = apply_analog_settings(value, analog);
1469
/* remap the value if needed */
1470
if (analog->field->remap_table != NULL)
1471
value = analog->field->remap_table[value];
1473
/* invert bits if needed */
1474
if (analog->field->flags & ANALOG_FLAG_INVERT)
1477
/* insert into the port */
1478
result = (result & ~analog->field->mask) | ((value << analog->shift) & analog->field->mask);
1485
/*-------------------------------------------------
1486
input_port_read - return the value of
1487
an input port specified by tag
1488
-------------------------------------------------*/
1490
input_port_value input_port_read(running_machine &machine, const char *tag)
1492
const input_port_config *port = machine.port(tag);
1494
fatalerror("Unable to locate input port '%s'", tag);
1495
return input_port_read_direct(port);
1499
/*-------------------------------------------------
1500
input_port_read - return the value of
1501
a device input port specified by tag
1502
-------------------------------------------------*/
1504
input_port_value input_port_read(device_t &device, const char *tag)
1507
const input_port_config *port = device.machine().port(device.subtag(fullpath, tag));
1509
fatalerror("Unable to locate input port '%s'", tag);
1510
return input_port_read_direct(port);
1514
/*-------------------------------------------------
1515
input_port_read_safe - return the value of
1516
an input port specified by tag, or a default
1517
value if the port does not exist
1518
-------------------------------------------------*/
1520
input_port_value input_port_read_safe(running_machine &machine, const char *tag, UINT32 defvalue)
1522
const input_port_config *port = machine.port(tag);
1523
return (port == NULL) ? defvalue : input_port_read_direct(port);
1527
/*-------------------------------------------------
1528
input_port_read_crosshair - return the
1529
extracted crosshair values for the given
1531
-------------------------------------------------*/
1533
int input_port_get_crosshair_position(running_machine &machine, int player, float *x, float *y)
1535
const input_port_config *port;
1536
const input_field_config *field;
1537
int gotx = FALSE, goty = FALSE;
1539
/* read all the lightgun values */
1540
for (port = machine.m_portlist.first(); port != NULL; port = port->next())
1541
for (field = port->first_field(); field != NULL; field = field->next())
1542
if (field->player == player && field->crossaxis != CROSSHAIR_AXIS_NONE)
1543
if (input_condition_true(machine, &field->condition, port->owner()))
1545
analog_field_state *analog = field->state->analog;
1546
INT32 rawvalue = apply_analog_settings(analog->accum, analog) & (analog->field->mask >> analog->shift);
1547
float value = (float)(rawvalue - field->state->analog->adjmin) / (float)(field->state->analog->adjmax - field->state->analog->adjmin);
1549
/* apply the scale and offset */
1550
if (field->crossscale < 0)
1551
value = -(1.0 - value) * field->crossscale;
1553
value *= field->crossscale;
1554
value += field->crossoffset;
1556
/* apply custom mapping if necessary */
1557
if (!field->crossmapper.isnull())
1558
value = field->crossmapper(*field, value);
1561
if (field->crossaxis == CROSSHAIR_AXIS_X)
1565
if (field->crossaltaxis != 0)
1567
*y = field->crossaltaxis;
1577
if (field->crossaltaxis != 0)
1579
*x = field->crossaltaxis;
1584
/* if we got both, stop */
1589
return (gotx && goty);
1593
/*-------------------------------------------------
1594
input_port_update_defaults - force an update
1595
to the input port values based on current
1597
-------------------------------------------------*/
1599
void input_port_update_defaults(running_machine &machine)
1603
/* two passes to catch conditionals properly */
1604
for (loopnum = 0; loopnum < 2; loopnum++)
1606
const input_port_config *port;
1608
/* loop over all input ports */
1609
for (port = machine.m_portlist.first(); port != NULL; port = port->next())
1611
const input_field_config *field;
1613
/* only clear on the first pass */
1615
port->state->defvalue = 0;
1617
/* first compute the default value for the entire port */
1618
for (field = port->first_field(); field != NULL; field = field->next())
1619
if (input_condition_true(machine, &field->condition, port->owner()))
1620
port->state->defvalue = (port->state->defvalue & ~field->mask) | (field->state->value & field->mask);
1626
/*-------------------------------------------------
1627
apply_analog_settings - return the value of
1629
-------------------------------------------------*/
1631
static INT32 apply_analog_settings(INT32 value, analog_field_state *analog)
1633
/* apply the min/max and then the sensitivity */
1634
value = apply_analog_min_max(analog, value);
1635
value = APPLY_SENSITIVITY(value, analog->sensitivity);
1637
/* apply reversal if needed */
1638
if (analog->reverse)
1639
value = analog->reverse_val - value;
1640
else if (analog->single_scale)
1641
/* it's a pedal or the default value is equal to min/max */
1642
/* so we need to adjust the center to the minimum */
1643
value -= INPUT_ABSOLUTE_MIN;
1645
/* map differently for positive and negative values */
1647
value = APPLY_SCALE(value, analog->scalepos);
1649
value = APPLY_SCALE(value, analog->scaleneg);
1650
value += analog->adjdefvalue;
1656
/***************************************************************************
1658
***************************************************************************/
1660
/*-------------------------------------------------
1661
input_port_write_direct - write a value
1663
-------------------------------------------------*/
1665
void input_port_write_direct(const input_port_config *port, input_port_value data, input_port_value mem_mask)
1667
/* call device line write handlers */
1668
device_field_info *device_field;
1670
COMBINE_DATA(&port->state->outputvalue);
1672
for (device_field = port->state->writedevicelist; device_field; device_field = device_field->next)
1673
if (device_field->field->type == IPT_OUTPUT && input_condition_true(port->machine(), &device_field->field->condition, port->owner()))
1675
input_port_value newval = ( (port->state->outputvalue ^ device_field->field->defvalue ) & device_field->field->mask) >> device_field->shift;
1677
/* if the bits have write, call the handler */
1678
if (device_field->oldval != newval)
1680
device_field->field->write(*device_field->field, device_field->field->write_param, device_field->oldval, newval);
1682
device_field->oldval = newval;
1688
/*-------------------------------------------------
1689
input_port_write - write a value to a
1690
port specified by tag
1691
-------------------------------------------------*/
1693
void input_port_write(running_machine &machine, const char *tag, input_port_value value, input_port_value mask)
1695
const input_port_config *port = machine.port(tag);
1697
fatalerror("Unable to locate input port '%s'", tag);
1698
input_port_write_direct(port, value, mask);
1702
/*-------------------------------------------------
1703
input_port_write_safe - write a value to
1704
a port, ignore if the port does not exist
1705
-------------------------------------------------*/
1707
void input_port_write_safe(running_machine &machine, const char *tag, input_port_value value, input_port_value mask)
1709
const input_port_config *port = machine.port(tag);
1711
input_port_write_direct(port, value, mask);
1716
/***************************************************************************
1717
MISC HELPER FUNCTIONS
1718
***************************************************************************/
1720
/*-------------------------------------------------
1721
input_condition_true - return the TRUE
1722
if the given condition attached is true
1723
-------------------------------------------------*/
1725
int input_condition_true(running_machine &machine, const input_condition *condition, device_t &owner)
1727
input_port_value condvalue;
1729
/* always condition is always true */
1730
if (condition->condition == PORTCOND_ALWAYS)
1733
/* otherwise, read the referenced port */
1734
astring conditiontag;
1735
owner.subtag(conditiontag, condition->tag);
1736
condvalue = input_port_read(machine, conditiontag.cstr());
1738
/* based on the condition encoded, determine truth */
1739
switch (condition->condition)
1741
case PORTCOND_EQUALS:
1742
return ((condvalue & condition->mask) == condition->value);
1744
case PORTCOND_NOTEQUALS:
1745
return ((condvalue & condition->mask) != condition->value);
1747
case PORTCOND_GREATERTHAN:
1748
return ((condvalue & condition->mask) > condition->value);
1750
case PORTCOND_NOTGREATERTHAN:
1751
return ((condvalue & condition->mask) <= condition->value);
1753
case PORTCOND_LESSTHAN:
1754
return ((condvalue & condition->mask) < condition->value);
1756
case PORTCOND_NOTLESSTHAN:
1757
return ((condvalue & condition->mask) >= condition->value);
1763
/*-------------------------------------------------
1764
input_port_string_from_token - convert an
1765
input_port_token to a default string
1766
-------------------------------------------------*/
1768
const char *input_port_string_from_token(const char *string)
1770
/* 0 is an invalid index */
1774
/* if the index is greater than the count, assume it to be a pointer */
1775
if (FPTR(string) >= INPUT_STRING_COUNT)
1778
#if FALSE // Set TRUE, If you want to take care missing-token or wrong-sorting
1780
/* otherwise, scan the list for a matching string and return it */
1783
for (index = 0; index < ARRAY_LENGTH(input_port_default_strings); index++)
1784
if (input_port_default_strings[index].id == FPTR(string))
1785
return input_port_default_strings[index].string;
1787
return "(Unknown Default)";
1791
return input_port_default_strings[FPTR(string)-1].string;
1798
/***************************************************************************
1799
INITIALIZATION HELPERS
1800
***************************************************************************/
1802
/*-------------------------------------------------
1803
init_port_types - initialize the default
1805
-------------------------------------------------*/
1807
static void init_port_types(running_machine &machine)
1809
input_port_private *portdata = machine.input_port_data;
1811
/* convert the array into a list of type states that can be modified */
1812
construct_core_types(portdata->typelist);
1814
/* ask the OSD to customize the list */
1815
machine.osd().customize_input_type_list(portdata->typelist);
1817
/* now iterate over the OSD-modified types */
1818
for (input_type_entry *curtype = portdata->typelist.first(); curtype != NULL; curtype = curtype->next())
1820
/* first copy all the OSD-updated sequences into our current state */
1821
for (int seqtype = 0; seqtype < ARRAY_LENGTH(curtype->seq); seqtype++)
1822
curtype->seq[seqtype] = curtype->defseq[seqtype];
1824
/* also make a lookup table mapping type/player to the appropriate type list entry */
1825
portdata->type_to_entry[curtype->type][curtype->player] = curtype;
1830
/*-------------------------------------------------
1831
get_keyboard_code - accesses a particular
1833
-------------------------------------------------*/
1835
static unicode_char get_keyboard_code(const input_field_config *field, int i)
1837
unicode_char ch = field->chars[i];
1839
/* special hack to allow for PORT_CODE('\xA3') */
1840
if ((ch >= 0xFFFFFF80) && (ch <= 0xFFFFFFFF))
1846
/***************************************************************************
1848
***************************************************************************/
1850
/*-------------------------------------------------
1851
find_charinfo - looks up information about a
1852
particular character
1853
-------------------------------------------------*/
1855
static const char_info *find_charinfo(unicode_char target_char)
1858
int high = ARRAY_LENGTH(charinfo);
1862
/* perform a simple binary search to find the proper alternate */
1865
i = (high + low) / 2;
1866
ch = charinfo[i].ch;
1867
if (ch < target_char)
1869
else if (ch > target_char)
1872
return &charinfo[i];
1877
/*-------------------------------------------------
1878
inputx_key_name - returns the name of a
1880
-------------------------------------------------*/
1882
static const char *inputx_key_name(unicode_char ch)
1884
static char buf[UTF8_CHAR_MAX + 1];
1885
const char_info *ci;
1889
ci = find_charinfo(ch);
1890
result = ci ? ci->name : NULL;
1898
if ((ch > 0x7F) || isprint(ch))
1900
pos = utf8_from_uchar(buf, ARRAY_LENGTH(buf), ch);
1910
/*-------------------------------------------------
1911
get_keyboard_key_name - builds the name of
1912
a key based on natural keyboard characters
1913
-------------------------------------------------*/
1915
static astring &get_keyboard_key_name(astring &name, const input_field_config *field)
1921
/* loop through each character on the field*/
1922
for (i = 0; i < ARRAY_LENGTH(field->chars) && (field->chars[i] != '\0'); i++)
1924
ch = get_keyboard_code(field, i);
1925
name.catprintf("%-*s ", MAX(SPACE_COUNT - 1, 0), inputx_key_name(ch));
1928
/* trim extra spaces */
1932
if (name.len() == 0)
1933
name.cpy("Unnamed Key");
1938
/*-------------------------------------------------
1939
init_port_state - initialize the live port
1940
states based on the tokens
1941
-------------------------------------------------*/
1943
static void init_port_state(running_machine &machine)
1945
const char *joystick_map_default = machine.options().joystick_map();
1946
input_port_private *portdata = machine.input_port_data;
1947
input_field_config *field;
1948
input_port_config *port;
1950
/* allocate live structures to mirror the configuration */
1951
for (port = machine.m_portlist.first(); port != NULL; port = port->next())
1953
analog_field_state **analogstatetail;
1954
device_field_info **readdevicetail;
1955
device_field_info **writedevicetail;
1956
input_port_state *portstate;
1958
/* allocate a new input_port_info structure */
1959
portstate = auto_alloc_clear(machine, input_port_state);
1960
((input_port_config *)port)->state = portstate;
1962
/* start with tail pointers to all the data */
1963
analogstatetail = &portstate->analoglist;
1964
readdevicetail = &portstate->readdevicelist;
1965
writedevicetail = &portstate->writedevicelist;
1967
/* iterate over fields */
1968
for (field = port->first_field(); field != NULL; field = field->next())
1970
input_field_state *fieldstate;
1973
/* allocate a new input_field_info structure */
1974
fieldstate = auto_alloc_clear(machine, input_field_state);
1975
((input_field_config *)field)->state = fieldstate;
1977
/* fill in the basic values */
1978
for (seqtype = 0; seqtype < ARRAY_LENGTH(fieldstate->seq); seqtype++)
1979
fieldstate->seq[seqtype] = field->seq[seqtype];
1980
fieldstate->value = field->defvalue;
1982
/* if this is an analog field, allocate memory for the analog data */
1983
if (field->type >= __ipt_analog_start && field->type <= __ipt_analog_end)
1985
*analogstatetail = fieldstate->analog = init_field_analog_state(field);
1986
analogstatetail = &(*analogstatetail)->next;
1989
/* if this is a digital joystick field, make a note of it */
1990
if (field->type >= __ipt_digital_joystick_start && field->type <= __ipt_digital_joystick_end)
1992
fieldstate->joystick = &portdata->joystick_info[field->player][(field->type - __ipt_digital_joystick_start) / 4];
1993
fieldstate->joydir = (field->type - __ipt_digital_joystick_start) % 4;
1994
fieldstate->joystick->field[fieldstate->joydir] = field;
1995
fieldstate->joystick->inuse = TRUE;
1998
/* if this entry has device input, allocate memory for the tracking structure */
2000
if (!field->read.isnull())
2002
*readdevicetail = init_field_device_info(field, port->owner().subtag(devicetag, field->read_device));
2003
field->read.late_bind(*(*readdevicetail)->device);
2004
readdevicetail = &(*readdevicetail)->next;
2007
/* if this entry has device output, allocate memory for the tracking structure */
2008
if (!field->write.isnull())
2010
*writedevicetail = init_field_device_info(field, port->owner().subtag(devicetag, field->write_device));
2011
field->write.late_bind(*(*writedevicetail)->device);
2012
writedevicetail = &(*writedevicetail)->next;
2015
/* if this entry has device output, allocate memory for the tracking structure */
2016
if (!field->crossmapper.isnull())
2018
device_t *device = machine.device(port->owner().subtag(devicetag, field->crossmapper_device));
2019
field->crossmapper.late_bind(*device);
2022
/* Name keyboard key names */
2023
if ((field->type == IPT_KEYBOARD || field->type == IPT_KEYPAD) && (field->name == NULL))
2026
field->state->name = auto_strdup(machine, get_keyboard_key_name(name, field));
2031
/* handle autoselection of devices */
2032
init_autoselect_devices(machine, IPT_AD_STICK_X, IPT_AD_STICK_Y, IPT_AD_STICK_Z, OPTION_ADSTICK_DEVICE, "analog joystick");
2033
init_autoselect_devices(machine, IPT_PADDLE, IPT_PADDLE_V, 0, OPTION_PADDLE_DEVICE, "paddle");
2034
init_autoselect_devices(machine, IPT_PEDAL, IPT_PEDAL2, IPT_PEDAL3, OPTION_PEDAL_DEVICE, "pedal");
2035
init_autoselect_devices(machine, IPT_LIGHTGUN_X, IPT_LIGHTGUN_Y, 0, OPTION_LIGHTGUN_DEVICE, "lightgun");
2036
init_autoselect_devices(machine, IPT_POSITIONAL, IPT_POSITIONAL_V, 0, OPTION_POSITIONAL_DEVICE, "positional");
2037
init_autoselect_devices(machine, IPT_DIAL, IPT_DIAL_V, 0, OPTION_DIAL_DEVICE, "dial");
2038
init_autoselect_devices(machine, IPT_TRACKBALL_X, IPT_TRACKBALL_Y, 0, OPTION_TRACKBALL_DEVICE, "trackball");
2039
init_autoselect_devices(machine, IPT_MOUSE_X, IPT_MOUSE_Y, 0, OPTION_MOUSE_DEVICE, "mouse");
2041
/* look for 4-way joysticks and change the default map if we find any */
2042
if (joystick_map_default[0] == 0 || strcmp(joystick_map_default, "auto") == 0)
2043
for (port = machine.m_portlist.first(); port != NULL; port = port->next())
2044
for (field = port->first_field(); field != NULL; field = field->next())
2045
if (field->state->joystick != NULL && field->way == 4)
2047
machine.input().set_global_joystick_map((field->flags & FIELD_FLAG_ROTATED) ? joystick_map_4way_diagonal : joystick_map_4way_sticky);
2053
/*-------------------------------------------------
2054
init_autoselect_devices - autoselect a single
2055
device based on the input port list passed
2056
in and the corresponding option
2057
-------------------------------------------------*/
2059
static void init_autoselect_devices(running_machine &machine, int type1, int type2, int type3, const char *option, const char *ananame)
2061
const ioport_list &portlist = machine.m_portlist;
2062
const char *stemp = machine.options().value(option);
2063
input_device_class autoenable = DEVICE_CLASS_KEYBOARD;
2064
const char *autostring = "keyboard";
2065
const input_field_config *field;
2066
const input_port_config *port;
2068
/* if nothing specified, ignore the option */
2072
/* extract valid strings */
2073
if (strcmp(stemp, "mouse") == 0)
2075
autoenable = DEVICE_CLASS_MOUSE;
2076
autostring = "mouse";
2078
else if (strcmp(stemp, "joystick") == 0)
2080
autoenable = DEVICE_CLASS_JOYSTICK;
2081
autostring = "joystick";
2083
else if (strcmp(stemp, "lightgun") == 0)
2085
autoenable = DEVICE_CLASS_LIGHTGUN;
2086
autostring = "lightgun";
2088
else if (strcmp(stemp, "none") == 0)
2090
/* nothing specified */
2093
else if (strcmp(stemp, "keyboard") != 0)
2094
mame_printf_error("Invalid %s value %s; reverting to keyboard\n", option, stemp);
2096
/* only scan the list if we haven't already enabled this class of control */
2097
if (portlist.first() != NULL && !machine.input().device_class(autoenable).enabled())
2098
for (port = portlist.first(); port != NULL; port = port->next())
2099
for (field = port->first_field(); field != NULL; field = field->next())
2101
/* if this port type is in use, apply the autoselect criteria */
2102
if ((type1 != 0 && field->type == type1) ||
2103
(type2 != 0 && field->type == type2) ||
2104
(type3 != 0 && field->type == type3))
2106
mame_printf_verbose("Input: Autoenabling %s due to presence of a %s\n", autostring, ananame);
2107
machine.input().device_class(autoenable).enable();
2113
/*-------------------------------------------------
2114
init_field_device_info - allocate and populate
2115
information about a device callback
2116
-------------------------------------------------*/
2118
static device_field_info *init_field_device_info(const input_field_config *field, const char *device_name)
2120
device_field_info *info;
2121
input_port_value mask;
2123
/* allocate memory */
2124
info = auto_alloc_clear(field->machine(), device_field_info);
2126
/* fill in the data */
2127
info->field = field;
2128
for (mask = field->mask; !(mask & 1); mask >>= 1)
2131
info->device = (device_name != NULL) ? field->machine().device(device_name) : &field->port().owner();
2133
info->oldval = field->defvalue >> info->shift;
2138
/*-------------------------------------------------
2139
init_field_analog_state - allocate and populate
2140
information about an analog port
2141
-------------------------------------------------*/
2143
static analog_field_state *init_field_analog_state(const input_field_config *field)
2145
analog_field_state *state;
2146
input_port_value mask;
2148
/* allocate memory */
2149
state = auto_alloc_clear(field->machine(), analog_field_state);
2151
/* compute the shift amount and number of bits */
2152
for (mask = field->mask; !(mask & 1); mask >>= 1)
2155
/* initialize core data */
2156
state->field = field;
2157
state->adjdefvalue = (field->defvalue & field->mask) >> state->shift;
2158
state->adjmin = (field->min & field->mask) >> state->shift;
2159
state->adjmax = (field->max & field->mask) >> state->shift;
2160
state->sensitivity = field->sensitivity;
2161
state->reverse = ((field->flags & ANALOG_FLAG_REVERSE) != 0);
2162
state->delta = field->delta;
2163
state->centerdelta = field->centerdelta;
2164
state->minimum = INPUT_ABSOLUTE_MIN;
2165
state->maximum = INPUT_ABSOLUTE_MAX;
2167
/* set basic parameters based on the configured type */
2168
switch (field->type)
2170
/* paddles and analog joysticks are absolute and autocenter */
2171
case IPT_AD_STICK_X:
2172
case IPT_AD_STICK_Y:
2173
case IPT_AD_STICK_Z:
2176
state->absolute = TRUE;
2177
state->autocenter = TRUE;
2178
state->interpolate = TRUE;
2181
/* pedals start at and autocenter to the min range */
2185
state->center = INPUT_ABSOLUTE_MIN;
2186
state->accum = APPLY_INVERSE_SENSITIVITY(state->center, state->sensitivity);
2187
state->absolute = TRUE;
2188
state->autocenter = TRUE;
2189
state->interpolate = TRUE;
2192
/* lightguns are absolute as well, but don't autocenter and don't interpolate their values */
2193
case IPT_LIGHTGUN_X:
2194
case IPT_LIGHTGUN_Y:
2195
state->absolute = TRUE;
2196
state->autocenter = FALSE;
2197
state->interpolate = FALSE;
2200
/* positional devices are absolute, but can also wrap like relative devices */
2201
/* set each position to be 512 units */
2202
case IPT_POSITIONAL:
2203
case IPT_POSITIONAL_V:
2204
state->positionalscale = COMPUTE_SCALE(field->max, INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN);
2206
state->adjmax = field->max - 1;
2207
state->wraps = ((field->flags & ANALOG_FLAG_WRAPS) != 0);
2208
state->autocenter = !state->wraps;
2211
/* dials, mice and trackballs are relative devices */
2212
/* these have fixed "min" and "max" values based on how many bits are in the port */
2213
/* in addition, we set the wrap around min/max values to 512 * the min/max values */
2214
/* this takes into account the mapping that one mouse unit ~= 512 analog units */
2217
case IPT_TRACKBALL_X:
2218
case IPT_TRACKBALL_Y:
2221
state->absolute = FALSE;
2222
state->wraps = TRUE;
2223
state->interpolate = TRUE;
2227
fatalerror("Unknown analog port type -- don't know if it is absolute or not");
2231
/* further processing for absolute controls */
2232
if (state->absolute)
2234
/* if the default value is pegged at the min or max, use a single scale value for the whole axis */
2235
state->single_scale = (state->adjdefvalue == state->adjmin) || (state->adjdefvalue == state->adjmax);
2237
/* if not "single scale", compute separate scales for each side of the default */
2238
if (!state->single_scale)
2241
state->scalepos = COMPUTE_SCALE(state->adjmax - state->adjdefvalue, INPUT_ABSOLUTE_MAX - 0);
2242
state->scaleneg = COMPUTE_SCALE(state->adjdefvalue - state->adjmin, 0 - INPUT_ABSOLUTE_MIN);
2244
if (state->adjmin > state->adjmax)
2245
state->scaleneg = -state->scaleneg;
2247
/* reverse point is at center */
2248
state->reverse_val = 0;
2252
/* single axis that increases from default */
2253
state->scalepos = COMPUTE_SCALE(state->adjmax - state->adjmin, INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN);
2255
/* move from default */
2256
if (state->adjdefvalue == state->adjmax)
2257
state->scalepos = -state->scalepos;
2259
/* make the scaling the same for easier coding when we need to scale */
2260
state->scaleneg = state->scalepos;
2262
/* reverse point is at max */
2263
state->reverse_val = state->maximum;
2267
/* relative and positional controls all map directly with a 512x scale factor */
2270
/* The relative code is set up to allow specifing PORT_MINMAX and default values. */
2271
/* The validity checks are purposely set up to not allow you to use anything other */
2272
/* a default of 0 and PORT_MINMAX(0,mask). This is in case the need arises to use */
2273
/* this feature in the future. Keeping the code in does not hurt anything. */
2274
if (state->adjmin > state->adjmax)
2275
/* adjust for signed */
2276
state->adjmin = -state->adjmin;
2281
state->minimum = (state->adjmin - state->adjdefvalue) * INPUT_RELATIVE_PER_PIXEL;
2282
state->maximum = (state->adjmax - state->adjdefvalue) * INPUT_RELATIVE_PER_PIXEL;
2284
/* make the scaling the same for easier coding when we need to scale */
2285
state->scaleneg = state->scalepos = COMPUTE_SCALE(1, INPUT_RELATIVE_PER_PIXEL);
2287
if (field->flags & ANALOG_FLAG_RESET)
2288
/* delta values reverse from center */
2289
state->reverse_val = 0;
2292
/* positional controls reverse from their max range */
2293
state->reverse_val = state->maximum + state->minimum;
2295
/* relative controls reverse from 1 past their max range */
2297
state->reverse_val -= INPUT_RELATIVE_PER_PIXEL;
2301
/* compute scale for keypresses */
2302
state->keyscalepos = RECIP_SCALE(state->scalepos);
2303
state->keyscaleneg = RECIP_SCALE(state->scaleneg);
2310
/***************************************************************************
2311
ONCE-PER-FRAME UPDATES
2312
***************************************************************************/
2314
/*-------------------------------------------------
2315
frame_update_callback - system-wide callback to
2316
update the input ports once per frame, but
2317
only if we are not paused
2318
-------------------------------------------------*/
2320
static void frame_update_callback(running_machine &machine)
2322
/* if we're paused, don't do anything */
2323
if (machine.paused())
2326
/* otherwise, use the common code */
2327
frame_update(machine);
2330
static key_buffer *get_buffer(running_machine &machine)
2332
input_port_private *portdata = machine.input_port_data;
2333
assert(inputx_can_post(machine));
2334
return (key_buffer *)portdata->keybuffer;
2339
static const inputx_code *find_code(inputx_code *codes, unicode_char ch)
2344
for (i = 0; codes[i].ch; i++)
2346
if (codes[i].ch == ch)
2352
/*-------------------------------------------------
2353
input_port_update_hook - hook function
2354
called from core to allow for natural keyboard
2355
-------------------------------------------------*/
2357
static void input_port_update_hook(running_machine &machine, const input_port_config *port, input_port_value *digital)
2359
input_port_private *portdata = machine.input_port_data;
2360
const key_buffer *keybuf;
2361
const inputx_code *code;
2366
if (inputx_can_post(machine))
2368
keybuf = get_buffer(machine);
2370
/* is the key down right now? */
2371
if (keybuf && keybuf->status_keydown && (keybuf->begin_pos != keybuf->end_pos))
2373
/* identify the character that is down right now, and its component codes */
2374
ch = keybuf->buffer[keybuf->begin_pos];
2375
code = find_code(portdata->codes, ch);
2377
/* loop through this character's component codes */
2380
for (i = 0; i < ARRAY_LENGTH(code->field) && (code->field[i] != NULL); i++)
2382
if (&code->field[i]->port() == port)
2384
value = code->field[i]->mask;
2394
/*-------------------------------------------------
2395
frame_update - core logic for per-frame input
2397
-------------------------------------------------*/
2399
static void frame_update(running_machine &machine)
2401
input_port_private *portdata = machine.input_port_data;
2402
const input_field_config *mouse_field = NULL;
2403
int ui_visible = ui_is_menu_active();
2404
attotime curtime = machine.time();
2405
const input_port_config *port;
2406
render_target *mouse_target;
2407
INT32 mouse_target_x;
2408
INT32 mouse_target_y;
2411
g_profiler.start(PROFILER_INPUT);
2413
/* record/playback information about the current frame */
2414
playback_frame(machine, curtime);
2415
record_frame(machine, curtime);
2417
/* track the duration of the previous frame */
2418
portdata->last_delta_nsec = (curtime - portdata->last_frame_time).as_attoseconds() / ATTOSECONDS_PER_NANOSECOND;
2419
portdata->last_frame_time = curtime;
2421
/* update the digital joysticks */
2422
frame_update_digital_joysticks(machine);
2424
/* compute default values for all the ports */
2425
input_port_update_defaults(machine);
2427
/* perform the mouse hit test */
2428
mouse_target = ui_input_find_mouse(machine, &mouse_target_x, &mouse_target_y, &mouse_button);
2429
if (mouse_button && mouse_target)
2431
const char *tag = NULL;
2432
input_port_value mask;
2434
if (mouse_target->map_point_input(mouse_target_x, mouse_target_y, tag, mask, x, y))
2435
mouse_field = input_field_by_tag_and_mask(machine, tag, mask);
2438
/* loop over all input ports */
2439
for (port = machine.m_portlist.first(); port != NULL; port = port->next())
2441
const input_field_config *field;
2442
device_field_info *device_field;
2443
input_port_value newvalue;
2445
/* start with 0 values for the digital and VBLANK bits */
2446
port->state->digital = 0;
2447
port->state->vblank = 0;
2449
/* now loop back and modify based on the inputs */
2450
for (field = port->first_field(); field != NULL; field = field->next())
2451
if (input_condition_true(port->machine(), &field->condition, port->owner()))
2453
/* accumulate VBLANK bits */
2454
if (field->type == IPT_VBLANK)
2455
port->state->vblank ^= field->mask;
2457
/* handle analog inputs */
2458
else if (field->state->analog != NULL)
2459
frame_update_analog_field(machine, field->state->analog);
2461
/* handle non-analog types, but only when the UI isn't visible */
2462
else if (!ui_visible && frame_get_digital_field_state(field, field == mouse_field))
2463
port->state->digital |= field->mask;
2466
/* hook for MESS's natural keyboard support */
2467
input_port_update_hook(machine, port, &port->state->digital);
2469
/* handle playback/record */
2470
playback_port(port);
2473
/* call device line write handlers */
2474
newvalue = input_port_read_direct(port);
2475
for (device_field = port->state->writedevicelist; device_field; device_field = device_field->next)
2476
if (device_field->field->type != IPT_OUTPUT && input_condition_true(port->machine(), &device_field->field->condition, port->owner()))
2478
input_port_value newval = (newvalue & device_field->field->mask) >> device_field->shift;
2480
/* if the bits have write, call the handler */
2481
if (device_field->oldval != newval)
2483
device_field->field->write(*device_field->field, device_field->field->write_param, device_field->oldval, newval);
2485
device_field->oldval = newval;
2494
/*-------------------------------------------------
2495
frame_update_digital_joysticks - update the
2496
state of digital joysticks prior to
2497
accumulating the results in a port
2498
-------------------------------------------------*/
2500
static void frame_update_digital_joysticks(running_machine &machine)
2502
input_port_private *portdata = machine.input_port_data;
2503
int player, joyindex;
2505
/* loop over all the joysticks */
2506
for (player = 0; player < MAX_PLAYERS; player++)
2507
for (joyindex = 0; joyindex < DIGITAL_JOYSTICKS_PER_PLAYER; joyindex++)
2509
digital_joystick_state *joystick = &portdata->joystick_info[player][joyindex];
2510
if (joystick->inuse)
2512
joystick->previous = joystick->current;
2513
joystick->current = 0;
2515
/* read all the associated ports */
2516
if (joystick->field[JOYDIR_UP] != NULL && machine.input().seq_pressed(input_field_seq(joystick->field[JOYDIR_UP], SEQ_TYPE_STANDARD)))
2517
joystick->current |= JOYDIR_UP_BIT;
2518
if (joystick->field[JOYDIR_DOWN] != NULL && machine.input().seq_pressed(input_field_seq(joystick->field[JOYDIR_DOWN], SEQ_TYPE_STANDARD)))
2519
joystick->current |= JOYDIR_DOWN_BIT;
2520
if (joystick->field[JOYDIR_LEFT] != NULL && machine.input().seq_pressed(input_field_seq(joystick->field[JOYDIR_LEFT], SEQ_TYPE_STANDARD)))
2521
joystick->current |= JOYDIR_LEFT_BIT;
2522
if (joystick->field[JOYDIR_RIGHT] != NULL && machine.input().seq_pressed(input_field_seq(joystick->field[JOYDIR_RIGHT], SEQ_TYPE_STANDARD)))
2523
joystick->current |= JOYDIR_RIGHT_BIT;
2525
/* lock out opposing directions (left + right or up + down) */
2526
if ((joystick->current & (JOYDIR_UP_BIT | JOYDIR_DOWN_BIT)) == (JOYDIR_UP_BIT | JOYDIR_DOWN_BIT))
2527
joystick->current &= ~(JOYDIR_UP_BIT | JOYDIR_DOWN_BIT);
2528
if ((joystick->current & (JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT)) == (JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT))
2529
joystick->current &= ~(JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT);
2531
/* only update 4-way case if joystick has moved */
2532
if (joystick->current != joystick->previous)
2534
joystick->current4way = joystick->current;
2537
If joystick is pointing at a diagonal, acknowledge that the player moved
2538
the joystick by favoring a direction change. This minimizes frustration
2539
when using a keyboard for input, and maximizes responsiveness.
2541
For example, if you are holding "left" then switch to "up" (where both left
2542
and up are briefly pressed at the same time), we'll transition immediately
2545
Zero any switches that didn't change from the previous to current state.
2547
if ((joystick->current4way & (JOYDIR_UP_BIT | JOYDIR_DOWN_BIT)) &&
2548
(joystick->current4way & (JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT)))
2550
joystick->current4way ^= joystick->current4way & joystick->previous;
2554
If we are still pointing at a diagonal, we are in an indeterminant state.
2556
This could happen if the player moved the joystick from the idle position directly
2557
to a diagonal, or from one diagonal directly to an extreme diagonal.
2559
The chances of this happening with a keyboard are slim, but we still need to
2560
constrain this case.
2562
For now, just resolve randomly.
2564
if ((joystick->current4way & (JOYDIR_UP_BIT | JOYDIR_DOWN_BIT)) &&
2565
(joystick->current4way & (JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT)))
2567
if (machine.rand() & 1)
2568
joystick->current4way &= ~(JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT);
2570
joystick->current4way &= ~(JOYDIR_UP_BIT | JOYDIR_DOWN_BIT);
2578
/*-------------------------------------------------
2579
frame_update_analog_field - update the
2580
internals of a single analog field
2581
-------------------------------------------------*/
2583
static void frame_update_analog_field(running_machine &machine, analog_field_state *analog)
2585
input_item_class itemclass;
2586
int keypressed = FALSE;
2591
/* clamp the previous value to the min/max range and remember it */
2592
analog->previous = analog->accum = apply_analog_min_max(analog, analog->accum);
2594
/* get the new raw analog value and its type */
2595
rawvalue = machine.input().seq_axis_value(input_field_seq(analog->field, SEQ_TYPE_STANDARD), itemclass);
2597
/* if we got an absolute input, it overrides everything else */
2598
if (itemclass == ITEM_CLASS_ABSOLUTE)
2600
if (analog->previousanalog != rawvalue)
2602
/* only update if analog value changed */
2603
analog->previousanalog = rawvalue;
2605
/* apply the inverse of the sensitivity to the raw value so that */
2606
/* it will still cover the full min->max range requested after */
2607
/* we apply the sensitivity adjustment */
2608
if (analog->absolute || (analog->field->flags & ANALOG_FLAG_RESET))
2610
/* if port is absolute, then just return the absolute data supplied */
2611
analog->accum = APPLY_INVERSE_SENSITIVITY(rawvalue, analog->sensitivity);
2613
else if (analog->positionalscale != 0)
2615
/* if port is positional, we will take the full analog control and divide it */
2616
/* into positions, that way as the control is moved full scale, */
2617
/* it moves through all the positions */
2618
rawvalue = APPLY_SCALE(rawvalue - INPUT_ABSOLUTE_MIN, analog->positionalscale) * INPUT_RELATIVE_PER_PIXEL + analog->minimum;
2620
/* clamp the high value so it does not roll over */
2621
rawvalue = MIN(rawvalue, analog->maximum);
2622
analog->accum = APPLY_INVERSE_SENSITIVITY(rawvalue, analog->sensitivity);
2625
/* if port is relative, we use the value to simulate the speed of relative movement */
2626
/* sensitivity adjustment is allowed for this mode */
2627
analog->accum += rawvalue;
2629
analog->lastdigital = FALSE;
2630
/* do not bother with other control types if the analog data is changing */
2635
/* we still have to update fake relative from joystick control */
2636
if (!analog->absolute && analog->positionalscale == 0)
2637
analog->accum += rawvalue;
2641
/* if we got it from a relative device, use that as the starting delta */
2642
/* also note that the last input was not a digital one */
2643
if (itemclass == ITEM_CLASS_RELATIVE && rawvalue != 0)
2646
analog->lastdigital = FALSE;
2649
keyscale = (analog->accum >= 0) ? analog->keyscalepos : analog->keyscaleneg;
2651
/* if the decrement code sequence is pressed, add the key delta to */
2652
/* the accumulated delta; also note that the last input was a digital one */
2653
if (machine.input().seq_pressed(input_field_seq(analog->field, SEQ_TYPE_DECREMENT)))
2656
if (analog->delta != 0)
2657
delta -= APPLY_SCALE(analog->delta, keyscale);
2658
else if (!analog->lastdigital)
2659
/* decrement only once when first pressed */
2660
delta -= APPLY_SCALE(1, keyscale);
2661
analog->lastdigital = TRUE;
2664
/* same for the increment code sequence */
2665
if (machine.input().seq_pressed(input_field_seq(analog->field, SEQ_TYPE_INCREMENT)))
2669
delta += APPLY_SCALE(analog->delta, keyscale);
2670
else if (!analog->lastdigital)
2671
/* increment only once when first pressed */
2672
delta += APPLY_SCALE(1, keyscale);
2673
analog->lastdigital = TRUE;
2676
/* if resetting is requested, clear the accumulated position to 0 before */
2677
/* applying the deltas so that we only return this frame's delta */
2678
/* note that centering only works for relative controls */
2679
/* no need to check if absolute here because it is checked by the validity tests */
2680
if (analog->field->flags & ANALOG_FLAG_RESET)
2683
/* apply the delta to the accumulated value */
2684
analog->accum += delta;
2686
/* if our last movement was due to a digital input, and if this control */
2687
/* type autocenters, and if neither the increment nor the decrement seq */
2688
/* was pressed, apply autocentering */
2689
if (analog->autocenter)
2691
INT32 center = APPLY_INVERSE_SENSITIVITY(analog->center, analog->sensitivity);
2692
if (analog->lastdigital && !keypressed)
2694
/* autocenter from positive values */
2695
if (analog->accum >= center)
2697
analog->accum -= APPLY_SCALE(analog->centerdelta, analog->keyscalepos);
2698
if (analog->accum < center)
2700
analog->accum = center;
2701
analog->lastdigital = FALSE;
2705
/* autocenter from negative values */
2708
analog->accum += APPLY_SCALE(analog->centerdelta, analog->keyscaleneg);
2709
if (analog->accum > center)
2711
analog->accum = center;
2712
analog->lastdigital = FALSE;
2717
else if (!keypressed)
2718
analog->lastdigital = FALSE;
2722
/*-------------------------------------------------
2723
frame_get_digital_field_state - get the state
2725
-------------------------------------------------*/
2727
static int frame_get_digital_field_state(const input_field_config *field, int mouse_down)
2729
int curstate = mouse_down || field->machine().input().seq_pressed(input_field_seq(field, SEQ_TYPE_STANDARD));
2730
int changed = FALSE;
2731
int temp_field_impulse;
2733
/* if the state changed, look for switch down/switch up */
2734
if (curstate != field->state->last)
2736
field->state->last = curstate;
2740
if (field->type == IPT_KEYBOARD && ui_get_use_natural_keyboard(field->machine()))
2743
/* coin impulse option */
2745
int temp_option_impulse = field->machine().options().coin_impulse();
2746
temp_field_impulse = field->impulse;
2747
if ( temp_option_impulse != 0)
2749
if (temp_option_impulse < 0)
2750
temp_field_impulse = 0;
2751
else if ((field->type >= IPT_COIN1 && field->type <= IPT_COIN12) || field->impulse != 0)
2752
temp_field_impulse = temp_option_impulse;
2756
/* if this is a switch-down event, handle impulse and toggle */
2045
m_live->value = nextsetting->value();
2049
//-------------------------------------------------
2050
// frame_update_digital - get the state of a
2052
//-------------------------------------------------
2054
void ioport_field::frame_update(ioport_value &result, bool mouse_down)
2056
// skip if not enabled
2060
// handle analog inputs first
2061
if (m_live->analog != NULL)
2063
m_live->analog->frame_update(machine());
2067
// if UI is active, ignore digital inputs
2068
if (ui_is_menu_active())
2071
// if the state changed, look for switch down/switch up
2072
bool curstate = mouse_down || machine().input().seq_pressed(seq());
2073
bool changed = false;
2074
if (curstate != m_live->last)
2076
m_live->last = curstate;
2080
// if we're a keyboard type and using natural keyboard, bail
2081
if (m_type == IPT_KEYBOARD && ui_get_use_natural_keyboard(machine()))
2084
// coin impulse option
2085
int effective_impulse = m_impulse;
2086
int impulse_option_val = machine().options().coin_impulse();
2087
if (impulse_option_val != 0)
2089
if (impulse_option_val < 0)
2090
effective_impulse = 0;
2091
else if ((m_type >= IPT_COIN1 && m_type <= IPT_COIN12) || m_impulse != 0)
2092
effective_impulse = impulse_option_val;
2095
// if this is a switch-down event, handle impulse and toggle
2757
2096
if (changed && curstate)
2759
/* impluse controls: reset the impulse counter */
2760
if (temp_field_impulse != 0 && field->state->impulse == 0)
2761
field->state->impulse = temp_field_impulse;
2098
// impluse controls: reset the impulse counter
2099
if (effective_impulse != 0 && m_live->impulse == 0)
2100
m_live->impulse = effective_impulse;
2763
/* toggle controls: flip the toggle state or advance to the next setting */
2764
if (field->flags & FIELD_FLAG_TOGGLE)
2102
// toggle controls: flip the toggle state or advance to the next setting
2766
if (field->settinglist().count() == 0)
2767
field->state->value ^= field->mask;
2105
if (m_settinglist.count() == 0)
2106
m_live->value ^= m_mask;
2769
input_field_select_next_setting(field);
2773
/* update the current state with the impulse state */
2774
if (temp_field_impulse != 0)
2776
if (field->state->impulse != 0)
2778
field->state->impulse--;
2785
/* for toggle switches, the current value is folded into the port's default value */
2786
/* so we always return FALSE here */
2787
if (field->flags & FIELD_FLAG_TOGGLE)
2790
/* additional logic to restrict digital joysticks */
2791
if (curstate && !mouse_down && field->state->joystick != NULL && field->way != 16 && !field->machine().options().joystick_contradictory())
2793
UINT8 mask = (field->way == 4) ? field->state->joystick->current4way : field->state->joystick->current;
2794
if (!(mask & (1 << field->state->joydir)))
2798
/* skip locked-out coin inputs */
2799
if (curstate && field->type >= IPT_COIN1 && field->type <= IPT_COIN12 && coin_lockout_get_state(field->machine(), field->type - IPT_COIN1))
2801
int verbose = field->machine().options().verbose();
2108
select_next_setting();
2112
// update the current state with the impulse state
2113
if (effective_impulse != 0)
2115
curstate = (m_live->impulse != 0);
2120
// for toggle switches, the current value is folded into the port's default value
2121
// so we always return FALSE here
2125
// additional logic to restrict digital joysticks
2126
if (curstate && !mouse_down && m_live->joystick != NULL && m_way != 16 && !machine().options().joystick_contradictory())
2128
UINT8 mask = (m_way == 4) ? m_live->joystick->current4way() : m_live->joystick->current();
2129
if (!(mask & (1 << m_live->joydir)))
2133
// skip locked-out coin inputs
2134
if (curstate && m_type >= IPT_COIN1 && m_type <= IPT_COIN12 && coin_lockout_get_state(machine(), m_type - IPT_COIN1))
2136
bool verbose = machine().options().verbose();
2802
2137
#ifdef MAME_DEBUG
2805
if (field->machine().options().coin_lockout())
2140
if (machine().options().coin_lockout())
2808
ui_popup_time(3, "Coinlock disabled %s.", input_field_name(field));
2809
return FALSE; /* curstate = FALSE; */
2143
ui_popup_time(3, "Coinlock disabled %s.", name());
2813
ui_popup_time(3, "Coinlock disabled, but broken through %s.", input_field_name(field));
2821
/***************************************************************************
2822
PORT CONFIGURATION HELPERS
2823
***************************************************************************/
2825
/*-------------------------------------------------
2826
port_default_value - updates default value
2827
of port settings according to device settings
2828
-------------------------------------------------*/
2830
UINT32 port_default_value(const char *fulltag, UINT32 mask, UINT32 defval, device_t &owner)
2832
const input_device_default *def = owner.input_ports_defaults();
2836
for ( ; def->tag != NULL; def++)
2837
if (owner.subtag(fullpath, def->tag) == fulltag && def->mask == mask)
2838
return def->defvalue;
2844
/*-------------------------------------------------
2845
input_port_config - constructor for an
2846
I/O port configuration object
2847
-------------------------------------------------*/
2849
input_port_config::input_port_config(device_t &owner, const char *tag)
2860
running_machine &input_port_config::machine() const
2862
return m_owner.machine();
2866
/*-------------------------------------------------
2867
field_config_alloc - allocate a new input
2869
-------------------------------------------------*/
2871
input_field_config::input_field_config(input_port_config &port, int _type, input_port_value _defvalue, input_port_value _maskbits, const char *_name)
2873
defvalue(_defvalue & _maskbits),
2880
read_device(DEVICE_SELF),
2882
write_device(DEVICE_SELF),
2892
crossmapper_device(DEVICE_SELF),
2899
m_modcount(port.modcount())
2901
memset(&condition, 0, sizeof(condition));
2902
for (int seqtype = 0; seqtype < ARRAY_LENGTH(seq); seqtype++)
2903
seq[seqtype].set_default();
2904
chars[0] = chars[1] = chars[2] = (unicode_char) 0;
2908
input_setting_config::input_setting_config(input_field_config &field, input_port_value _value, const char *_name)
2914
memset(&condition, 0, sizeof(condition));
2917
input_field_diplocation::input_field_diplocation(const char *string, UINT8 _swnum, bool _invert)
2924
/*-------------------------------------------------
2925
field_config_insert - insert an allocated
2926
input port field config, replacing any
2927
intersecting fields already present and
2928
inserting at the correct sorted location
2929
-------------------------------------------------*/
2931
void input_port_config::collapse_fields(astring &errorbuf)
2933
input_field_config *list = m_fieldlist.detach_all();
2934
input_port_value maskbits = 0;
2935
int lastmodcount = -1;
2936
while (list != NULL)
2938
if (list->modcount() != lastmodcount)
2940
lastmodcount = list->modcount();
2943
input_field_config *current = list;
2944
list = list->next();
2945
field_config_insert(*current, maskbits, errorbuf);
2949
void field_config_insert(input_field_config &newfield, input_port_value &disallowedbits, astring &errorbuf)
2951
input_port_value lowbit;
2953
/* verify against the disallowed bits, but only if we are condition-free */
2954
if (newfield.condition.condition == PORTCOND_ALWAYS)
2956
if ((newfield.mask & disallowedbits) != 0)
2957
errorbuf.catprintf("INPUT_TOKEN_FIELD specifies duplicate port bits (port=%s mask=%X)\n", newfield.port().tag(), newfield.mask);
2958
disallowedbits |= newfield.mask;
2961
/* first modify/nuke any entries that intersect our maskbits */
2962
input_field_config *nextfield;
2963
for (input_field_config *field = newfield.port().fieldlist().first(); field != NULL; field = nextfield)
2965
nextfield = field->next();
2966
if ((field->mask & newfield.mask) != 0 && (newfield.condition.condition == PORTCOND_ALWAYS ||
2967
field->condition.condition == PORTCOND_ALWAYS ||
2968
condition_equal(&field->condition, &newfield.condition)))
2970
/* reduce the mask of the field we found */
2971
field->mask &= ~newfield.mask;
2973
/* if the new entry fully overrides the previous one, we nuke */
2974
if (INPUT_PORT_OVERRIDE_FULLY_NUKES_PREVIOUS || field->mask == 0)
2975
newfield.port().fieldlist().remove(*field);
2979
/* make a mask of just the low bit */
2980
lowbit = (newfield.mask ^ (newfield.mask - 1)) & newfield.mask;
2982
/* scan forward to find where to insert ourselves */
2983
input_field_config *field;
2984
for (field = newfield.port().fieldlist().first(); field != NULL; field = field->next())
2985
if (field->mask > lowbit)
2988
/* insert it into the list */
2989
newfield.port().fieldlist().insert_before(newfield, field);
2993
/*-------------------------------------------------
2994
diplocation_expand - expand a string-based
2995
DIP location into a linked list of
2997
-------------------------------------------------*/
2999
void diplocation_list_alloc(input_field_config &field, const char *location, astring &errorbuf)
3001
/* if nothing present, bail */
2148
ui_popup_time(3, "Coinlock disabled, but broken through %s.", name());
2151
// if we're active, set the appropriate bits in the digital state
2157
//-------------------------------------------------
2158
// crosshair_position - compute the crosshair
2160
//-------------------------------------------------
2162
void ioport_field::crosshair_position(float &x, float &y, bool &gotx, bool &goty)
2164
float value = m_live->analog->crosshair_read();
2166
// apply the scale and offset
2167
if (m_crosshair_scale < 0)
2168
value = -(1.0 - value) * m_crosshair_scale;
2170
value *= m_crosshair_scale;
2171
value += m_crosshair_offset;
2173
// apply custom mapping if necessary
2174
if (!m_crosshair_mapper.isnull())
2175
value = m_crosshair_mapper(*this, value);
2178
if (m_crosshair_axis == CROSSHAIR_AXIS_X)
2182
if (m_crosshair_altaxis != 0)
2184
y = m_crosshair_altaxis;
2194
if (m_crosshair_altaxis != 0)
2196
x = m_crosshair_altaxis;
2203
//-------------------------------------------------
2204
// expand_diplocation - expand a string-based
2205
// DIP location into a linked list of
2207
//-------------------------------------------------
2209
void ioport_field::expand_diplocation(const char *location, astring &errorbuf)
2211
// if nothing present, bail
3002
2212
if (location == NULL)
3005
field.diploclist().reset();
2215
m_diploclist.reset();
3007
/* parse the string */
3008
2218
astring name; // Don't move this variable inside the loop, lastname's lifetime depends on it being outside
3009
2219
const char *lastname = NULL;
3010
2220
const char *curentry = location;
3011
2221
int entries = 0;
3012
2222
while (*curentry != 0)
3014
/* find the end of this entry */
2224
// find the end of this entry
3015
2225
const char *comma = strchr(curentry, ',');
3016
2226
if (comma == NULL)
3017
2227
comma = curentry + strlen(curentry);
3019
/* extract it to tempbuf */
2229
// extract it to tempbuf
3020
2230
astring tempstr;
3021
2231
tempstr.cpy(curentry, comma - curentry);
3023
/* first extract the switch name if present */
2233
// first extract the switch name if present
3024
2234
const char *number = tempstr;
3025
2235
const char *colon = strchr(tempstr, ':');
3027
/* allocate and copy the name if it is present */
2237
// allocate and copy the name if it is present
3028
2238
if (colon != NULL)
3030
2240
lastname = name.cpy(number, colon - number);
3031
2241
number = colon + 1;
3034
/* otherwise, just copy the last name */
2244
// otherwise, just copy the last name
3037
2247
if (lastname == NULL)
3053
/* now scan the switch number */
2263
// now scan the switch number
3054
2264
int swnum = -1;
3055
2265
if (sscanf(number, "%d", &swnum) != 1)
3056
2266
errorbuf.catprintf("Switch location '%s' has invalid format!\n", location);
3058
/* allocate a new entry */
3059
field.diploclist().append(*global_alloc(input_field_diplocation(name, swnum, invert)));
2268
// allocate a new entry
2269
m_diploclist.append(*global_alloc(ioport_diplocation(name, swnum, invert)));
3062
/* advance to the next item */
2272
// advance to the next item
3063
2273
curentry = comma;
3064
2274
if (*curentry != 0)
3068
/* then verify the number of bits in the mask matches */
3069
input_port_value temp;
2278
// then verify the number of bits in the mask matches
3071
for (bits = 0, temp = field.mask; temp != 0 && bits < 32; bits++)
2281
for (bits = 0, temp = m_mask; temp != 0 && bits < 32; bits++)
3072
2282
temp &= temp - 1;
3073
2283
if (bits != entries)
3074
errorbuf.catprintf("Switch location '%s' does not describe enough bits for mask %X\n", location, field.mask);
3079
/***************************************************************************
3080
TOKENIZATION HELPERS
3081
***************************************************************************/
3083
/*-------------------------------------------------
3084
token_to_input_field_type - convert a string
3085
token to an input field type and player
3086
-------------------------------------------------*/
3088
static int token_to_input_field_type(running_machine &machine, const char *string, int *player)
3090
input_port_private *portdata = machine.input_port_data;
3093
/* check for our failsafe case first */
3094
if (sscanf(string, "TYPE_OTHER(%d,%d)", &ipnum, player) == 2)
3097
/* find the token in the list */
3098
for (input_type_entry *entry = portdata->typelist.first(); entry != NULL; entry = entry->next())
3099
if (entry->token != NULL && !strcmp(entry->token, string))
3101
*player = entry->player;
3105
/* if we fail, return IPT_UNKNOWN */
3111
/*-------------------------------------------------
3112
input_field_type_to_token - convert an input
3113
field type and player to a string token
3114
-------------------------------------------------*/
3116
static const char *input_field_type_to_token(running_machine &machine, int type, int player)
3118
input_port_private *portdata = machine.input_port_data;
3119
static char tempbuf[32];
3121
/* look up the port and return the token */
3122
input_type_entry *entry = portdata->type_to_entry[type][player];
3124
return entry->token;
3126
/* if that fails, carry on */
3127
sprintf(tempbuf, "TYPE_OTHER(%d,%d)", type, player);
3132
/*-------------------------------------------------
3133
token_to_seq_type - convert a string to
3135
-------------------------------------------------*/
3137
static int token_to_seq_type(const char *string)
3141
/* look up the string in the table of possible sequence types and return the index */
3142
for (seqindex = 0; seqindex < ARRAY_LENGTH(seqtypestrings); seqindex++)
3143
if (!mame_stricmp(string, seqtypestrings[seqindex]))
3151
/***************************************************************************
3153
***************************************************************************/
3155
/*-------------------------------------------------
3156
load_config_callback - callback to extract
3157
configuration data from the XML nodes
3158
-------------------------------------------------*/
3160
static void load_config_callback(running_machine &machine, int config_type, xml_data_node *parentnode)
3162
input_port_private *portdata = machine.input_port_data;
3163
xml_data_node *portnode;
3166
/* in the completion phase, we finish the initialization with the final ports */
2284
errorbuf.catprintf("Switch location '%s' does not describe enough bits for mask %X\n", location, m_mask);
2288
//-------------------------------------------------
2289
// init_live_state - create live state structures
2290
//-------------------------------------------------
2292
void ioport_field::init_live_state(analog_field *analog)
2294
// resolve callbacks
2295
m_read.bind_relative_to(device());
2296
m_write.bind_relative_to(device());
2297
m_crosshair_mapper.bind_relative_to(device());
2299
// allocate live state
2300
m_live = global_alloc(ioport_field_live(*this, analog));
2305
//**************************************************************************
2306
// I/O PORT FIELD LIVE
2307
//**************************************************************************
2309
//-------------------------------------------------
2310
// ioport_field_live - constructor
2311
//-------------------------------------------------
2313
ioport_field_live::ioport_field_live(ioport_field &field, analog_field *analog)
2316
value(field.defvalue()),
2319
joydir(digital_joystick::JOYDIR_COUNT)
2321
// fill in the basic values
2322
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
2323
seq[seqtype] = field.defseq_unresolved(seqtype);
2325
// if this is a digital joystick field, make a note of it
2326
if (field.is_digital_joystick())
2328
joystick = &field.manager().digjoystick(field.player(), (field.type() - (IPT_DIGITAL_JOYSTICK_FIRST + 1)) / 4);
2329
joydir = joystick->set_axis(field);
2332
// Name keyboard key names
2333
if (field.type_class() == INPUT_CLASS_KEYBOARD && field.specific_name() == NULL)
2335
// loop through each character on the field
2337
for (int which = 0; ; which++)
2339
unicode_char ch = field.keyboard_code(which);
2342
name.catprintf("%-*s ", MAX(SPACE_COUNT - 1, 0), field.manager().natkeyboard().key_name(tempstr, ch));
2345
// trim extra spaces
2349
if (name.len() == 0)
2350
name.cpy("Unnamed Key");
2356
//**************************************************************************
2358
//**************************************************************************
2360
//-------------------------------------------------
2361
// ioport_port - constructor
2362
//-------------------------------------------------
2364
ioport_port::ioport_port(device_t &owner, const char *tag)
2375
//-------------------------------------------------
2376
// ~ioport_port - destructor
2377
//-------------------------------------------------
2379
ioport_port::~ioport_port()
2381
global_free(m_live);
2385
//-------------------------------------------------
2386
// machine - return a reference to the running
2388
//-------------------------------------------------
2390
running_machine &ioport_port::machine() const
2392
return m_device.machine();
2396
//-------------------------------------------------
2397
// manager - return a reference to the
2398
// ioport_manager on the running machine
2399
//-------------------------------------------------
2401
ioport_manager &ioport_port::manager() const
2403
return machine().ioport();
2407
//-------------------------------------------------
2408
// field - return a pointer to the first field
2409
// that intersects the given mask
2410
//-------------------------------------------------
2412
ioport_field *ioport_port::field(ioport_value mask)
2414
// if we got the port, look for the field
2415
for (ioport_field *field = first_field(); field != NULL; field = field->next())
2416
if ((field->mask() & mask) != 0)
2422
//-------------------------------------------------
2423
// read - return the value of an I/O port
2424
//-------------------------------------------------
2426
ioport_value ioport_port::read()
2428
assert_always(manager().safe_to_read(), "Input ports cannot be read at init time!");
2430
// start with the digital state
2431
ioport_value result = m_live->digital;
2433
// insert dynamic read values
2434
for (dynamic_field *dynfield = m_live->readlist.first(); dynfield != NULL; dynfield = dynfield->next())
2435
dynfield->read(result);
2437
// apply active high/low state to digital and dynamic read inputs
2438
result ^= m_live->defvalue;
2440
// insert analog portions
2441
for (analog_field *analog = m_live->analoglist.first(); analog != NULL; analog = analog->next())
2442
analog->read(result);
2448
//-------------------------------------------------
2449
// write - write a value to a port
2450
//-------------------------------------------------
2452
void ioport_port::write(ioport_value data, ioport_value mem_mask)
2454
// call device line write handlers
2455
COMBINE_DATA(&m_live->outputvalue);
2456
for (dynamic_field *dynfield = m_live->writelist.first(); dynfield != NULL; dynfield = dynfield->next())
2457
if (dynfield->field().type() == IPT_OUTPUT)
2458
dynfield->write(m_live->outputvalue ^ dynfield->field().defvalue());
2462
//-------------------------------------------------
2463
// frame_update - once/frame update
2464
//-------------------------------------------------
2466
void ioport_port::frame_update(ioport_field *mouse_field)
2468
// start with 0 values for the digital bits
2469
m_live->digital = 0;
2471
// now loop back and modify based on the inputs
2472
for (ioport_field *field = first_field(); field != NULL; field = field->next())
2473
field->frame_update(m_live->digital, field == mouse_field);
2475
// hook for MESS's natural keyboard support
2476
manager().natkeyboard().frame_update(*this, m_live->digital);
2478
// call device line write handlers
2479
ioport_value newvalue = read();
2480
for (dynamic_field *dynfield = m_live->writelist.first(); dynfield != NULL; dynfield = dynfield->next())
2481
if (dynfield->field().type() != IPT_OUTPUT)
2482
dynfield->write(newvalue);
2486
//-------------------------------------------------
2487
// collapse_fields - remove any fields that are
2488
// wholly overlapped by other fields
2489
//-------------------------------------------------
2491
void ioport_port::collapse_fields(astring &errorbuf)
2493
ioport_value maskbits = 0;
2494
int lastmodcount = -1;
2496
// remove the whole list and start from scratch
2497
ioport_field *field = m_fieldlist.detach_all();
2498
while (field != NULL)
2500
// if this modcount doesn't match, reset
2501
if (field->modcount() != lastmodcount)
2503
lastmodcount = field->modcount();
2507
// reinsert this field
2508
ioport_field *current = field;
2509
field = field->next();
2510
insert_field(*current, maskbits, errorbuf);
2515
//-------------------------------------------------
2516
// insert_field - insert a new field, checking
2518
//-------------------------------------------------
2520
void ioport_port::insert_field(ioport_field &newfield, ioport_value &disallowedbits, astring &errorbuf)
2522
// verify against the disallowed bits, but only if we are condition-free
2523
if (newfield.condition().none())
2525
if ((newfield.mask() & disallowedbits) != 0)
2526
errorbuf.catprintf("INPUT_TOKEN_FIELD specifies duplicate port bits (port=%s mask=%X)\n", tag(), newfield.mask());
2527
disallowedbits |= newfield.mask();
2530
// first modify/nuke any entries that intersect our maskbits
2531
ioport_field *nextfield;
2532
for (ioport_field *field = first_field(); field != NULL; field = nextfield)
2534
nextfield = field->next();
2535
if ((field->mask() & newfield.mask()) != 0 &&
2536
(newfield.condition().none() || field->condition().none() || field->condition() == newfield.condition()))
2538
// reduce the mask of the field we found
2539
field->reduce_mask(newfield.mask());
2541
// if the new entry fully overrides the previous one, we nuke
2542
if (INPUT_PORT_OVERRIDE_FULLY_NUKES_PREVIOUS || field->mask() == 0)
2543
m_fieldlist.remove(*field);
2547
// make a mask of just the low bit
2548
ioport_value lowbit = (newfield.mask() ^ (newfield.mask() - 1)) & newfield.mask();
2550
// scan forward to find where to insert ourselves
2551
ioport_field *field;
2552
for (field = first_field(); field != NULL; field = field->next())
2553
if (field->mask() > lowbit)
2556
// insert it into the list
2557
m_fieldlist.insert_before(newfield, field);
2561
//-------------------------------------------------
2562
// init_live_state - create the live state
2563
//-------------------------------------------------
2565
void ioport_port::init_live_state()
2567
m_live = global_alloc(ioport_port_live(*this));
2572
//**************************************************************************
2573
// I/O PORT LIVE STATE
2574
//**************************************************************************
2576
//-------------------------------------------------
2577
// ioport_port_live - constructor
2578
//-------------------------------------------------
2580
ioport_port_live::ioport_port_live(ioport_port &port)
2585
// iterate over fields
2586
for (ioport_field *field = port.first_field(); field != NULL; field = field->next())
2588
// allocate analog state if it's analog
2589
analog_field *analog = NULL;
2590
if (field->is_analog())
2591
analog = &analoglist.append(*global_alloc(analog_field(*field)));
2593
// allocate a dynamic field for reading
2594
if (field->has_dynamic_read())
2595
readlist.append(*global_alloc(dynamic_field(*field)));
2597
// allocate a dynamic field for writing
2598
if (field->has_dynamic_write())
2599
writelist.append(*global_alloc(dynamic_field(*field)));
2601
// let the field initialize its live state
2602
field->init_live_state(analog);
2608
//**************************************************************************
2610
//**************************************************************************
2612
//-------------------------------------------------
2613
// ioport_manager - constructor
2614
//-------------------------------------------------
2616
ioport_manager::ioport_manager(running_machine &machine)
2617
: m_machine(machine),
2618
m_safe_to_read(false),
2619
m_natkeyboard(machine),
2620
m_last_frame_time(attotime::zero),
2621
m_last_delta_nsec(0),
2622
m_record_file(machine.options().input_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS),
2623
m_playback_file(machine.options().input_directory(), OPEN_FLAG_READ),
2624
m_playback_accumulated_speed(0),
2625
m_playback_accumulated_frames(0)
2627
memset(m_type_to_entry, 0, sizeof(m_type_to_entry));
2631
//-------------------------------------------------
2632
// initialize - walk the configured ports and
2633
// create live state information
2634
//-------------------------------------------------
2636
time_t ioport_manager::initialize()
2638
// add an exit callback and a frame callback
2639
machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(ioport_manager::exit), this));
2640
machine().add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(FUNC(ioport_manager::frame_update_callback), this));
2642
// initialize the default port info from the OSD
2645
// if we have a token list, proceed
2646
device_iterator iter(machine().root_device());
2647
for (device_t *device = iter.first(); device != NULL; device = iter.next())
2650
m_portlist.append(*device, errors);
2652
mame_printf_error("Input port errors:\n%s", errors.cstr());
2655
// allocate live structures to mirror the configuration
2656
for (ioport_port *port = first_port(); port != NULL; port = port->next())
2657
port->init_live_state();
2659
// handle autoselection of devices
2660
init_autoselect_devices(IPT_AD_STICK_X, IPT_AD_STICK_Y, IPT_AD_STICK_Z, OPTION_ADSTICK_DEVICE, "analog joystick");
2661
init_autoselect_devices(IPT_PADDLE, IPT_PADDLE_V, 0, OPTION_PADDLE_DEVICE, "paddle");
2662
init_autoselect_devices(IPT_PEDAL, IPT_PEDAL2, IPT_PEDAL3, OPTION_PEDAL_DEVICE, "pedal");
2663
init_autoselect_devices(IPT_LIGHTGUN_X, IPT_LIGHTGUN_Y, 0, OPTION_LIGHTGUN_DEVICE, "lightgun");
2664
init_autoselect_devices(IPT_POSITIONAL, IPT_POSITIONAL_V, 0, OPTION_POSITIONAL_DEVICE, "positional");
2665
init_autoselect_devices(IPT_DIAL, IPT_DIAL_V, 0, OPTION_DIAL_DEVICE, "dial");
2666
init_autoselect_devices(IPT_TRACKBALL_X, IPT_TRACKBALL_Y, 0, OPTION_TRACKBALL_DEVICE, "trackball");
2667
init_autoselect_devices(IPT_MOUSE_X, IPT_MOUSE_Y, 0, OPTION_MOUSE_DEVICE, "mouse");
2669
// look for 4-way joysticks and change the default map if we find any
2670
const char *joystick_map_default = machine().options().joystick_map();
2671
if (joystick_map_default[0] == 0 || strcmp(joystick_map_default, "auto") == 0)
2672
for (ioport_port *port = first_port(); port != NULL; port = port->next())
2673
for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
2674
if (field->live().joystick != NULL && field->way() == 4)
2676
machine().input().set_global_joystick_map(field->rotated() ? joystick_map_4way_diagonal : joystick_map_4way_sticky);
2680
m_natkeyboard.initialize();
2681
// register callbacks for when we load configurations
2682
config_register(machine(), "input", config_saveload_delegate(FUNC(ioport_manager::load_config), this), config_saveload_delegate(FUNC(ioport_manager::save_config), this));
2684
// open playback and record files if specified
2685
time_t basetime = playback_init();
2691
//-------------------------------------------------
2692
// init_port_types - initialize the default
2694
//-------------------------------------------------
2696
void ioport_manager::init_port_types()
2698
// convert the array into a list of type states that can be modified
2699
construct_core_types(m_typelist);
2701
// ask the OSD to customize the list
2702
machine().osd().customize_input_type_list(m_typelist);
2704
// now iterate over the OSD-modified types
2705
for (input_type_entry *curtype = first_type(); curtype != NULL; curtype = curtype->next())
2707
// first copy all the OSD-updated sequences into our current state
2708
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
2709
curtype->m_seq[seqtype] = curtype->defseq(seqtype);
2711
// also make a lookup table mapping type/player to the appropriate type list entry
2712
m_type_to_entry[curtype->type()][curtype->player()] = curtype;
2717
//-------------------------------------------------
2718
// init_autoselect_devices - autoselect a single
2719
// device based on the input port list passed
2720
// in and the corresponding option
2721
//-------------------------------------------------
2723
void ioport_manager::init_autoselect_devices(int type1, int type2, int type3, const char *option, const char *ananame)
2725
// if nothing specified, ignore the option
2726
const char *stemp = machine().options().value(option);
2730
// extract valid strings
2731
const char *autostring = "keyboard";
2732
input_device_class autoenable = DEVICE_CLASS_KEYBOARD;
2733
if (strcmp(stemp, "mouse") == 0)
2735
autoenable = DEVICE_CLASS_MOUSE;
2736
autostring = "mouse";
2738
else if (strcmp(stemp, "joystick") == 0)
2740
autoenable = DEVICE_CLASS_JOYSTICK;
2741
autostring = "joystick";
2743
else if (strcmp(stemp, "lightgun") == 0)
2745
autoenable = DEVICE_CLASS_LIGHTGUN;
2746
autostring = "lightgun";
2748
else if (strcmp(stemp, "none") == 0)
2750
// nothing specified
2753
else if (strcmp(stemp, "keyboard") != 0)
2754
mame_printf_error("Invalid %s value %s; reverting to keyboard\n", option, stemp);
2756
// only scan the list if we haven't already enabled this class of control
2757
if (first_port() != NULL && !machine().input().device_class(autoenable).enabled())
2758
for (ioport_port *port = first_port(); port != NULL; port = port->next())
2759
for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
2761
// if this port type is in use, apply the autoselect criteria
2762
if ((type1 != 0 && field->type() == type1) || (type2 != 0 && field->type() == type2) || (type3 != 0 && field->type() == type3))
2764
mame_printf_verbose("Input: Autoenabling %s due to presence of a %s\n", autostring, ananame);
2765
machine().input().device_class(autoenable).enable();
2771
//-------------------------------------------------
2772
// exit - exit callback to ensure we clean up
2773
// and close our files
2774
//-------------------------------------------------
2776
void ioport_manager::exit()
2778
// close any playback or recording files
2784
//-------------------------------------------------
2785
// type_name - return the name for the given
2787
//-------------------------------------------------
2789
const char *ioport_manager::type_name(ioport_type type, UINT8 player)
2791
// if we have a machine, use the live state and quick lookup
2792
input_type_entry *entry = m_type_to_entry[type][player];
2794
return entry->name();
2796
// if we find nothing, return an invalid group
2801
//-------------------------------------------------
2802
// type_group - return the group for the given
2804
//-------------------------------------------------
2806
ioport_group ioport_manager::type_group(ioport_type type, int player)
2808
input_type_entry *entry = m_type_to_entry[type][player];
2810
return entry->group();
2812
// if we find nothing, return an invalid group
2817
//-------------------------------------------------
2818
// type_seq - return the input sequence for the
2819
// given type/player
2820
//-------------------------------------------------
2822
const input_seq &ioport_manager::type_seq(ioport_type type, int player, input_seq_type seqtype)
2824
assert(type >= 0 && type < IPT_COUNT);
2825
assert(player >= 0 && player < MAX_PLAYERS);
2827
// if we have a machine, use the live state and quick lookup
2828
input_type_entry *entry = m_type_to_entry[type][player];
2830
return entry->seq(seqtype);
2832
// if we find nothing, return an empty sequence
2833
return input_seq::empty_seq;
2837
//-------------------------------------------------
2838
// set_type_seq - change the input sequence for
2839
// the given type/player
2840
//-------------------------------------------------
2842
void ioport_manager::set_type_seq(ioport_type type, int player, input_seq_type seqtype, const input_seq &newseq)
2844
input_type_entry *entry = m_type_to_entry[type][player];
2846
entry->m_seq[seqtype] = newseq;
2850
//-------------------------------------------------
2851
// type_pressed - return true if the sequence for
2852
// the given input type/player is pressed
2853
//-------------------------------------------------
2855
bool ioport_manager::type_pressed(ioport_type type, int player)
2857
return machine().input().seq_pressed(type_seq(type, player));
2861
//-------------------------------------------------
2862
// type_class_present - return true if the given
2863
// ioport_type_class exists in at least one port
2864
//-------------------------------------------------
2866
bool ioport_manager::type_class_present(ioport_type_class inputclass)
2868
for (ioport_port *port = first_port(); port != NULL; port = port->next())
2869
for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
2870
if (field->type_class() == inputclass)
2876
//-------------------------------------------------
2877
// has_keyboard - determine if there is a
2878
// keyboard present in the control list
2879
//-------------------------------------------------
2881
bool ioport_manager::has_keyboard() const
2883
// iterate over ports and fields
2884
for (ioport_port *port = first_port(); port != NULL; port = port->next())
2885
for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
2887
// if we are at init, check IPT_KEYBOARD
2888
if (!m_safe_to_read && field->type() == IPT_KEYBOARD)
2891
// else, check if there is a keyboard and if such a keyboard is enabled
2892
if (field->type() == IPT_KEYBOARD && field->enabled())
2899
//-------------------------------------------------
2900
// count_players - counts the number of active
2902
//-------------------------------------------------
2904
int ioport_manager::count_players() const
2907
for (ioport_port *port = first_port(); port != NULL; port = port->next())
2908
for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
2909
if (field->type_class() == INPUT_CLASS_CONTROLLER && max_player <= field->player() + 1)
2910
max_player = field->player() + 1;
2916
//-------------------------------------------------
2917
// crosshair_position - return the extracted
2918
// crosshair values for the given player
2919
//-------------------------------------------------
2921
bool ioport_manager::crosshair_position(int player, float &x, float &y)
2923
// read all the lightgun values
2924
bool gotx = false, goty = false;
2925
for (ioport_port *port = first_port(); port != NULL; port = port->next())
2926
for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
2927
if (field->player() == player && field->crosshair_axis() != CROSSHAIR_AXIS_NONE && field->enabled())
2929
field->crosshair_position(x, y, gotx, goty);
2931
// if we got both, stop
2936
return (gotx && goty);
2940
//-------------------------------------------------
2941
// update_defaults - force an update to the input
2942
// port values based on current conditions
2943
//-------------------------------------------------
2945
void ioport_manager::update_defaults()
2947
// two passes to catch conditionals properly
2948
for (int loopnum = 0; loopnum < 2; loopnum++)
2950
// loop over all input ports
2951
for (ioport_port *port = first_port(); port != NULL; port = port->next())
2953
// only clear on the first pass
2955
port->live().defvalue = 0;
2957
// first compute the default value for the entire port
2958
for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
2959
if (field->enabled())
2960
port->live().defvalue = (port->live().defvalue & ~field->mask()) | (field->live().value & field->mask());
2966
//-------------------------------------------------
2967
// frame_update - core logic for per-frame input
2969
//-------------------------------------------------
2971
digital_joystick &ioport_manager::digjoystick(int player, int number)
2973
// find it in the list
2974
for (digital_joystick *joystick = m_joystick_list.first(); joystick != NULL; joystick = joystick->next())
2975
if (joystick->player() == player && joystick->number() == number)
2979
return m_joystick_list.append(*global_alloc(digital_joystick(player, number)));
2983
//-------------------------------------------------
2984
// frame_update - callback for once/frame updating
2985
//-------------------------------------------------
2987
void ioport_manager::frame_update_callback()
2989
// if we're paused, don't do anything
2990
if (!machine().paused())
2995
//-------------------------------------------------
2996
// frame_update_internal - core logic for
2997
// per-frame input port updating
2998
//-------------------------------------------------
3000
void ioport_manager::frame_update()
3002
g_profiler.start(PROFILER_INPUT);
3004
// record/playback information about the current frame
3005
attotime curtime = machine().time();
3006
playback_frame(curtime);
3007
record_frame(curtime);
3009
// track the duration of the previous frame
3010
m_last_delta_nsec = (curtime - m_last_frame_time).as_attoseconds() / ATTOSECONDS_PER_NANOSECOND;
3011
m_last_frame_time = curtime;
3013
// update the digital joysticks
3014
for (digital_joystick *joystick = m_joystick_list.first(); joystick != NULL; joystick = joystick->next())
3015
joystick->frame_update();
3017
// compute default values for all the ports
3020
// perform mouse hit testing
3021
INT32 mouse_target_x, mouse_target_y;
3023
render_target *mouse_target = ui_input_find_mouse(machine(), &mouse_target_x, &mouse_target_y, &mouse_button);
3025
// if the button is pressed, map the point and determine what was hit
3026
ioport_field *mouse_field = NULL;
3027
if (mouse_button && mouse_target != NULL)
3029
const char *tag = NULL;
3032
if (mouse_target->map_point_input(mouse_target_x, mouse_target_y, tag, mask, x, y))
3034
ioport_port *port = machine().root_device().ioport(tag);
3036
mouse_field = port->field(mask);
3040
// loop over all input ports
3041
for (ioport_port *port = first_port(); port != NULL; port = port->next())
3043
port->frame_update(mouse_field);
3045
// handle playback/record
3046
playback_port(*port);
3054
//-------------------------------------------------
3055
// frame_interpolate - interpolate between two
3056
// values based on the time between frames
3057
//-------------------------------------------------
3059
INT32 ioport_manager::frame_interpolate(INT32 oldval, INT32 newval)
3061
// if no last delta, just use new value
3062
if (m_last_delta_nsec == 0)
3065
// otherwise, interpolate
3066
attoseconds_t nsec_since_last = (machine().time() - m_last_frame_time).as_attoseconds() / ATTOSECONDS_PER_NANOSECOND;
3067
return oldval + (INT64(newval - oldval) * nsec_since_last / m_last_delta_nsec);
3071
//-------------------------------------------------
3072
// load_config - callback to extract configuration
3073
// data from the XML nodes
3074
//-------------------------------------------------
3076
void ioport_manager::load_config(int config_type, xml_data_node *parentnode)
3078
// in the completion phase, we finish the initialization with the final ports
3167
3079
if (config_type == CONFIG_TYPE_FINAL)
3169
portdata->safe_to_read = TRUE;
3170
frame_update(machine);
3081
m_safe_to_read = true;
3173
/* early exit if no data to parse */
3085
// early exit if no data to parse
3174
3086
if (parentnode == NULL)
3177
/* iterate over all the remap nodes for controller configs only */
3089
// iterate over all the remap nodes for controller configs only
3178
3090
if (config_type == CONFIG_TYPE_CONTROLLER)
3179
load_remap_table(machine, parentnode);
3091
load_remap_table(parentnode);
3181
/* iterate over all the port nodes */
3182
for (portnode = xml_get_sibling(parentnode->child, "port"); portnode; portnode = xml_get_sibling(portnode->next, "port"))
3093
// iterate over all the port nodes
3094
for (xml_data_node *portnode = xml_get_sibling(parentnode->child, "port"); portnode; portnode = xml_get_sibling(portnode->next, "port"))
3184
input_seq newseq[SEQ_TYPE_TOTAL], tempseq;
3185
xml_data_node *seqnode;
3188
/* get the basic port info from the attributes */
3189
type = token_to_input_field_type(machine, xml_get_attribute_string(portnode, "type", ""), &player);
3191
/* initialize sequences to invalid defaults */
3192
for (seqtype = 0; seqtype < ARRAY_LENGTH(newseq); seqtype++)
3096
// get the basic port info from the attributes
3098
int type = token_to_input_type(xml_get_attribute_string(portnode, "type", ""), player);
3100
// initialize sequences to invalid defaults
3101
input_seq newseq[SEQ_TYPE_TOTAL];
3102
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
3193
3103
newseq[seqtype].set(INPUT_CODE_INVALID);
3195
/* loop over new sequences */
3196
for (seqnode = xml_get_sibling(portnode->child, "newseq"); seqnode; seqnode = xml_get_sibling(seqnode->next, "newseq"))
3105
// loop over new sequences
3106
for (xml_data_node *seqnode = xml_get_sibling(portnode->child, "newseq"); seqnode; seqnode = xml_get_sibling(seqnode->next, "newseq"))
3198
/* with a valid type, parse out the new sequence */
3199
seqtype = token_to_seq_type(xml_get_attribute_string(seqnode, "type", ""));
3108
// with a valid type, parse out the new sequence
3109
input_seq_type seqtype = token_to_seq_type(xml_get_attribute_string(seqnode, "type", ""));
3200
3110
if (seqtype != -1 && seqnode->value != NULL)
3202
3112
if (strcmp(seqnode->value, "NONE") == 0)
3203
3113
newseq[seqtype].set();
3205
machine.input().seq_from_tokens(newseq[seqtype], seqnode->value);
3115
machine().input().seq_from_tokens(newseq[seqtype], seqnode->value);
3209
/* if we're loading default ports, apply to the defaults */
3119
// if we're loading default ports, apply to the defaults
3210
3120
if (config_type != CONFIG_TYPE_GAME)
3211
load_default_config(machine, portnode, type, player, newseq);
3121
load_default_config(portnode, type, player, newseq);
3213
load_game_config(machine, portnode, type, player, newseq);
3123
load_game_config(portnode, type, player, newseq);
3216
/* after applying the controller config, push that back into the backup, since that is */
3217
/* what we will diff against */
3126
// after applying the controller config, push that back into the backup, since that is
3127
// what we will diff against
3218
3128
if (config_type == CONFIG_TYPE_CONTROLLER)
3219
for (input_type_entry *entry = portdata->typelist.first(); entry != NULL; entry = entry->next())
3220
for (seqtype = 0; seqtype < ARRAY_LENGTH(entry->seq); seqtype++)
3221
entry->defseq[seqtype] = entry->seq[seqtype];
3129
for (input_type_entry *entry = m_typelist.first(); entry != NULL; entry = entry->next())
3130
for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
3131
entry->defseq(seqtype) = entry->seq(seqtype);
3225
/*-------------------------------------------------
3226
load_remap_table - extract and apply the
3227
global remapping table
3228
-------------------------------------------------*/
3135
//-------------------------------------------------
3136
// load_remap_table - extract and apply the
3137
// global remapping table
3138
//-------------------------------------------------
3230
static void load_remap_table(running_machine &machine, xml_data_node *parentnode)
3140
void ioport_manager::load_remap_table(xml_data_node *parentnode)
3232
input_port_private *portdata = machine.input_port_data;
3233
input_code *oldtable, *newtable;
3234
xml_data_node *remapnode;
3237
/* count items first so we can allocate */
3239
for (remapnode = xml_get_sibling(parentnode->child, "remap"); remapnode != NULL; remapnode = xml_get_sibling(remapnode->next, "remap"))
3142
// count items first so we can allocate
3144
for (xml_data_node *remapnode = xml_get_sibling(parentnode->child, "remap"); remapnode != NULL; remapnode = xml_get_sibling(remapnode->next, "remap"))
3242
/* if we have some, deal with them */
3147
// if we have some, deal with them
3247
/* allocate tables */
3248
oldtable = global_alloc_array(input_code, count);
3249
newtable = global_alloc_array(input_code, count);
3251
/* build up the remap table */
3151
dynamic_array<input_code> oldtable(count);
3152
dynamic_array<input_code> newtable(count);
3154
// build up the remap table
3253
for (remapnode = xml_get_sibling(parentnode->child, "remap"); remapnode != NULL; remapnode = xml_get_sibling(remapnode->next, "remap"))
3156
for (xml_data_node *remapnode = xml_get_sibling(parentnode->child, "remap"); remapnode != NULL; remapnode = xml_get_sibling(remapnode->next, "remap"))
3255
input_code origcode = machine.input().code_from_token(xml_get_attribute_string(remapnode, "origcode", ""));
3256
input_code newcode = machine.input().code_from_token(xml_get_attribute_string(remapnode, "newcode", ""));
3158
input_code origcode = machine().input().code_from_token(xml_get_attribute_string(remapnode, "origcode", ""));
3159
input_code newcode = machine().input().code_from_token(xml_get_attribute_string(remapnode, "newcode", ""));
3257
3160
if (origcode != INPUT_CODE_INVALID && newcode != INPUT_CODE_INVALID)
3259
3162
oldtable[count] = origcode;
3874
3645
header[0x0f] = systime.time >> 56;
3875
3646
header[0x10] = INP_HEADER_MAJVERSION;
3876
3647
header[0x11] = INP_HEADER_MINVERSION;
3877
strcpy((char *)header + 0x14, machine.system().name);
3648
strcpy((char *)header + 0x14, machine().system().name);
3878
3649
sprintf((char *)header + 0x20, "%s %s", emulator_info::get_appname(), build_version);
3881
portdata->record_file->write(header, sizeof(header));
3652
m_record_file.write(header, sizeof(header));
3883
/* enable compression */
3884
portdata->record_file->compress(FCOMPRESS_MEDIUM);
3654
// enable compression
3655
m_record_file.compress(FCOMPRESS_MEDIUM);
3888
/*-------------------------------------------------
3889
record_end - end INP recording
3890
-------------------------------------------------*/
3659
//-------------------------------------------------
3660
// record_end - end INP recording
3661
//-------------------------------------------------
3892
static void record_end(running_machine &machine, const char *message)
3663
void ioport_manager::record_end(const char *message)
3894
input_port_private *portdata = machine.input_port_data;
3896
/* only applies if we have a live file */
3897
if (portdata->record_file != NULL)
3665
// only applies if we have a live file
3666
if (m_record_file.is_open())
3899
/* close the file */
3900
auto_free(machine, portdata->record_file);
3901
portdata->record_file = NULL;
3669
m_record_file.close();
3904
3672
if (message != NULL)
3905
3673
popmessage("Recording Ended\nReason: %s", message);
3910
/*-------------------------------------------------
3911
record_frame - start of frame callback for
3913
-------------------------------------------------*/
3915
static void record_frame(running_machine &machine, attotime curtime)
3917
input_port_private *portdata = machine.input_port_data;
3919
/* if recording, record information about the current frame */
3920
if (portdata->record_file != NULL)
3922
/* first the absolute time */
3923
record_write_uint32(machine, curtime.seconds);
3924
record_write_uint64(machine, curtime.attoseconds);
3926
/* then the current speed */
3927
record_write_uint32(machine, machine.video().speed_percent() * (double)(1 << 20));
3932
/*-------------------------------------------------
3933
record_port - per-port callback for record
3934
-------------------------------------------------*/
3936
static void record_port(const input_port_config *port)
3938
input_port_private *portdata = port->machine().input_port_data;
3940
/* if recording, store information about this port */
3941
if (portdata->record_file != NULL)
3943
analog_field_state *analog;
3945
/* store the default value and digital state */
3946
record_write_uint32(port->machine(), port->state->defvalue);
3947
record_write_uint32(port->machine(), port->state->digital);
3949
/* loop over analog ports and save their data */
3950
for (analog = port->state->analoglist; analog != NULL; analog = analog->next)
3952
/* store current and previous values */
3953
record_write_uint32(port->machine(), analog->accum);
3954
record_write_uint32(port->machine(), analog->previous);
3956
/* store configuration information */
3957
record_write_uint32(port->machine(), analog->sensitivity);
3958
record_write_uint8(port->machine(), analog->reverse);
3963
int input_machine_has_keyboard(running_machine &machine)
3965
int have_keyboard = FALSE;
3966
const input_field_config *field;
3967
const input_port_config *port;
3968
for (port = machine.m_portlist.first(); port != NULL; port = port->next())
3970
for (field = port->first_field(); field != NULL; field = field->next())
3972
// if we are at init, check IPT_KEYBOARD for inputx_init
3973
if (!port->machine().input_port_data->safe_to_read && field->type == IPT_KEYBOARD)
3975
have_keyboard = TRUE;
3979
// else, check if there is a keyboard and if such a keyboard is enabled
3980
if (field->type == IPT_KEYBOARD && input_condition_true(field->machine(), &field->condition, field->port().owner()))
3982
have_keyboard = TRUE;
3987
return have_keyboard;
3990
/***************************************************************************
3992
***************************************************************************/
3994
/*-------------------------------------------------
3995
code_point_string - obtain a string representation of a
3996
given code; used for logging and debugging
3997
-------------------------------------------------*/
3999
static const char *code_point_string(running_machine &machine, unicode_char ch)
4001
static char buf[16];
4002
const char *result = buf;
4006
/* check some magic values */
4007
case '\0': strcpy(buf, "\\0"); break;
4008
case '\r': strcpy(buf, "\\r"); break;
4009
case '\n': strcpy(buf, "\\n"); break;
4010
case '\t': strcpy(buf, "\\t"); break;
4013
if ((ch >= 32) && (ch < 128))
4015
/* seven bit ASCII is easy */
4019
else if (ch >= UCHAR_MAMEKEY_BEGIN)
4021
/* try to obtain a codename with code_name(); this can result in an empty string */
4022
input_code code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, input_item_id(ch - UCHAR_MAMEKEY_BEGIN));
4024
snprintf(buf, ARRAY_LENGTH(buf), "%s", machine.input().code_name(tempstr, code));
4028
/* empty string; resolve later */
4032
/* did we fail to resolve? if so, we have a last resort */
4034
snprintf(buf, ARRAY_LENGTH(buf), "U+%04X", (unsigned) ch);
4041
/*-------------------------------------------------
4042
scan_keys - scans through input ports and
4043
sets up natural keyboard input mapping
4044
-------------------------------------------------*/
4046
static int scan_keys(running_machine &machine, const input_port_config *portconfig, inputx_code *codes, const input_port_config * *ports, const input_field_config * *shift_ports, int keys, int shift)
4049
const input_port_config *port;
4050
const input_field_config *field;
4053
assert(keys < NUM_SIMUL_KEYS);
4055
for (port = portconfig; port != NULL; port = port->next())
4057
for (field = port->first_field(); field != NULL; field = field->next())
4059
if (field->type == IPT_KEYBOARD)
4061
code = get_keyboard_code(field, shift);
4064
/* is this a shifter key? */
4065
if ((code >= UCHAR_SHIFT_BEGIN) && (code <= UCHAR_SHIFT_END))
4067
shift_ports[keys] = field;
4068
code_count += scan_keys(machine,
4070
codes ? &codes[code_count] : NULL,
4074
code - UCHAR_SHIFT_1 + 1);
4078
/* not a shifter key; record normally */
4081
/* if we have a destination, record the codes used here */
4082
memcpy((void *) codes[code_count].field, shift_ports, sizeof(shift_ports[0]) * keys);
4083
codes[code_count].ch = code;
4084
codes[code_count].field[keys] = field;
4087
/* increment the count */
4091
logerror("inputx: code=%i (%s) port=%p field->name='%s'\n", (int) code, code_point_string(machine, code), port, field->name);
4102
/*-------------------------------------------------
4103
build_codes - given an input port table, create
4104
a input code table useful for mapping unicode
4106
-------------------------------------------------*/
4108
static inputx_code *build_codes(running_machine &machine, const input_port_config *portconfig)
4110
inputx_code *codes = NULL;
4111
const input_port_config *ports[NUM_SIMUL_KEYS];
4112
const input_field_config *fields[NUM_SIMUL_KEYS];
4115
/* first count the number of codes */
4116
code_count = scan_keys(machine, portconfig, NULL, ports, fields, 0, 0);
4119
/* allocate the codes */
4120
codes = auto_alloc_array_clear(machine, inputx_code, code_count + 1);
4122
/* and populate them */
4123
scan_keys(machine, portconfig, codes, ports, fields, 0, 0);
4130
/***************************************************************************
4132
***************************************************************************/
4134
/*-------------------------------------------------
4135
validate_natural_keyboard_statics -
4136
validates natural keyboard static data
4137
-------------------------------------------------*/
4139
int validate_natural_keyboard_statics(void)
4143
unicode_char last_char = 0;
4144
const char_info *ci;
4146
/* check to make sure that charinfo is in order */
4147
for (i = 0; i < ARRAY_LENGTH(charinfo); i++)
4149
if (last_char >= charinfo[i].ch)
4151
mame_printf_error("inputx: charinfo is out of order; 0x%08x should be higher than 0x%08x\n", charinfo[i].ch, last_char);
4154
last_char = charinfo[i].ch;
4157
/* check to make sure that I can look up everything on alternate_charmap */
4158
for (i = 0; i < ARRAY_LENGTH(charinfo); i++)
4160
ci = find_charinfo(charinfo[i].ch);
4161
if (ci != &charinfo[i])
4163
mame_printf_error("inputx: expected find_charinfo(0x%08x) to work properly\n", charinfo[i].ch);
4172
/***************************************************************************
4174
***************************************************************************/
4176
static void clear_keybuffer(running_machine &machine)
4178
input_port_private *portdata = machine.input_port_data;
4179
portdata->keybuffer = NULL;
4180
portdata->queue_chars = NULL;
4181
portdata->codes = NULL;
4186
static void setup_keybuffer(running_machine &machine)
4188
input_port_private *portdata = machine.input_port_data;
4189
portdata->inputx_timer = machine.scheduler().timer_alloc(FUNC(inputx_timerproc));
4190
portdata->keybuffer = auto_alloc_clear(machine, key_buffer);
4191
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(clear_keybuffer), &machine));
4196
void inputx_init(running_machine &machine)
4198
input_port_private *portdata = machine.input_port_data;
4199
portdata->codes = NULL;
4200
portdata->inputx_timer = NULL;
4201
portdata->queue_chars = NULL;
4202
portdata->accept_char = NULL;
4203
portdata->charqueue_empty = NULL;
4204
portdata->keybuffer = NULL;
4206
if (machine.debug_flags & DEBUG_FLAG_ENABLED)
4208
debug_console_register_command(machine, "input", CMDFLAG_NONE, 0, 1, 1, execute_input);
4209
debug_console_register_command(machine, "dumpkbd", CMDFLAG_NONE, 0, 0, 1, execute_dumpkbd);
4212
/* posting keys directly only makes sense for a computer */
4213
if (input_machine_has_keyboard(machine))
4215
portdata->codes = build_codes(machine, machine.m_portlist.first());
4216
setup_keybuffer(machine);
4222
void inputx_setup_natural_keyboard(
4223
running_machine &machine,
4224
int (*queue_chars)(running_machine &machine, const unicode_char *text, size_t text_len),
4225
int (*accept_char)(running_machine &machine, unicode_char ch),
4226
int (*charqueue_empty)(running_machine &machine))
4228
input_port_private *portdata = machine.input_port_data;
4229
portdata->queue_chars = queue_chars;
4230
portdata->accept_char = accept_char;
4231
portdata->charqueue_empty = charqueue_empty;
4234
int inputx_can_post(running_machine &machine)
4236
input_port_private *portdata = machine.input_port_data;
4237
return portdata->queue_chars || portdata->codes;
4241
static int can_post_key_directly(running_machine &machine, unicode_char ch)
4243
input_port_private *portdata = machine.input_port_data;
4245
const inputx_code *code;
4247
if (portdata->queue_chars)
4249
rc = portdata->accept_char ? (*portdata->accept_char)(machine, ch) : TRUE;
4253
code = find_code(portdata->codes, ch);
4255
rc = code->field[0] != NULL;
4262
static int can_post_key_alternate(running_machine &machine, unicode_char ch)
4265
const char_info *ci;
4269
ci = find_charinfo(ch);
4270
s = ci ? ci->alternate : NULL;
4276
rc = uchar_from_utf8(&uchar, s, strlen(s));
4279
if (!can_post_key_directly(machine, uchar))
4286
static attotime choose_delay(input_port_private *portdata, unicode_char ch)
4288
if (portdata->current_rate != attotime::zero)
4289
return portdata->current_rate;
4291
attotime delay = attotime::zero;
4292
if (portdata->queue_chars)
4294
/* systems with queue_chars can afford a much smaller delay */
4295
delay = attotime::from_msec(10);
4301
delay = attotime::from_msec(200);
4305
delay = attotime::from_msec(50);
4314
static void internal_post_key(running_machine &machine, unicode_char ch)
4316
input_port_private *portdata = machine.input_port_data;
4319
keybuf = get_buffer(machine);
4321
/* need to start up the timer? */
4322
if (keybuf->begin_pos == keybuf->end_pos)
4324
portdata->inputx_timer->adjust(choose_delay(portdata, ch));
4325
keybuf->status_keydown = 0;
4328
keybuf->buffer[keybuf->end_pos++] = ch;
4329
keybuf->end_pos %= ARRAY_LENGTH(keybuf->buffer);
4334
static int buffer_full(running_machine &machine)
4337
keybuf = get_buffer(machine);
4338
return ((keybuf->end_pos + 1) % ARRAY_LENGTH(keybuf->buffer)) == keybuf->begin_pos;
4343
static void inputx_postn_rate(running_machine &machine, const unicode_char *text, size_t text_len, attotime rate)
4345
input_port_private *portdata = machine.input_port_data;
4349
const char_info *ci;
4350
const inputx_code *code;
4352
portdata->current_rate = rate;
4354
if (inputx_can_post(machine))
4356
while((text_len > 0) && !buffer_full(machine))
4361
/* change all eolns to '\r' */
4362
if ((ch != '\n') || !last_cr)
4367
last_cr = (ch == '\r');
4371
code = find_code(portdata->codes, ch);
4372
logerror("inputx_postn(): code=%i (%s) field->name='%s'\n", (int) ch, code_point_string(machine, ch), (code && code->field[0]) ? code->field[0]->name : "<null>");
4375
if (can_post_key_directly(machine, ch))
4377
/* we can post this key in the queue directly */
4378
internal_post_key(machine, ch);
4380
else if (can_post_key_alternate(machine, ch))
4382
/* we can post this key with an alternate representation */
4383
ci = find_charinfo(ch);
4384
assert(ci && ci->alternate);
4388
s += uchar_from_utf8(&ch, s, strlen(s));
4389
internal_post_key(machine, ch);
4403
static TIMER_CALLBACK(inputx_timerproc)
4405
input_port_private *portdata = machine.input_port_data;
4409
keybuf = get_buffer(machine);
4411
if (portdata->queue_chars)
4413
/* the driver has a queue_chars handler */
4414
while((keybuf->begin_pos != keybuf->end_pos) && (*portdata->queue_chars)(machine, &keybuf->buffer[keybuf->begin_pos], 1))
4416
keybuf->begin_pos++;
4417
keybuf->begin_pos %= ARRAY_LENGTH(keybuf->buffer);
4419
if (portdata->current_rate != attotime::zero)
4425
/* the driver does not have a queue_chars handler */
4426
if (keybuf->status_keydown)
4428
keybuf->status_keydown = FALSE;
4429
keybuf->begin_pos++;
4430
keybuf->begin_pos %= ARRAY_LENGTH(keybuf->buffer);
4434
keybuf->status_keydown = TRUE;
4438
/* need to make sure timerproc is called again if buffer not empty */
4439
if (keybuf->begin_pos != keybuf->end_pos)
4441
delay = choose_delay(portdata, keybuf->buffer[keybuf->begin_pos]);
4442
portdata->inputx_timer->adjust(delay);
4446
int inputx_is_posting(running_machine &machine)
4448
input_port_private *portdata = machine.input_port_data;
4449
const key_buffer *keybuf;
4450
keybuf = get_buffer(machine);
4451
return (keybuf->begin_pos != keybuf->end_pos) || (portdata->charqueue_empty && !(*portdata->charqueue_empty)(machine));
4454
/***************************************************************************
4458
***************************************************************************/
4459
static void inputx_postc_rate(running_machine &machine, unicode_char ch, attotime rate);
4461
static void inputx_postn_coded_rate(running_machine &machine, const char *text, size_t text_len, attotime rate)
4463
size_t i, j, key_len, increment;
4475
{ "DEL", UCHAR_MAMEKEY(DEL) },
4476
{ "DELETE", UCHAR_MAMEKEY(DEL) },
4477
{ "END", UCHAR_MAMEKEY(END) },
4480
{ "HOME", UCHAR_MAMEKEY(HOME) },
4481
{ "INS", UCHAR_MAMEKEY(INSERT) },
4482
{ "INSERT", UCHAR_MAMEKEY(INSERT) },
4483
{ "PGDN", UCHAR_MAMEKEY(PGDN) },
4484
{ "PGUP", UCHAR_MAMEKEY(PGUP) },
4487
{ "F1", UCHAR_MAMEKEY(F1) },
4488
{ "F2", UCHAR_MAMEKEY(F2) },
4489
{ "F3", UCHAR_MAMEKEY(F3) },
4490
{ "F4", UCHAR_MAMEKEY(F4) },
4491
{ "F5", UCHAR_MAMEKEY(F5) },
4492
{ "F6", UCHAR_MAMEKEY(F6) },
4493
{ "F7", UCHAR_MAMEKEY(F7) },
4494
{ "F8", UCHAR_MAMEKEY(F8) },
4495
{ "F9", UCHAR_MAMEKEY(F9) },
4496
{ "F10", UCHAR_MAMEKEY(F10) },
4497
{ "F11", UCHAR_MAMEKEY(F11) },
4498
{ "F12", UCHAR_MAMEKEY(F12) },
4510
for (j = 0; j < ARRAY_LENGTH(codes); j++)
4512
key_len = strlen(codes[j].key);
4513
if (i + key_len + 2 <= text_len)
4515
if (!core_strnicmp(codes[j].key, &text[i + 1], key_len) && (text[i + key_len + 1] == '}'))
4518
increment = key_len + 2;
4525
inputx_postc_rate(machine, ch, rate);
4532
/***************************************************************************
4536
***************************************************************************/
4538
static void inputx_postc_rate(running_machine &machine, unicode_char ch, attotime rate)
4540
inputx_postn_rate(machine, &ch, 1, rate);
4543
void inputx_postc(running_machine &machine, unicode_char ch)
4545
inputx_postc_rate(machine, ch, attotime::zero);
4548
static void inputx_postn_utf8_rate(running_machine &machine, const char *text, size_t text_len, attotime rate)
4551
unicode_char buf[256];
4557
if (len == ARRAY_LENGTH(buf))
4559
inputx_postn_rate(machine, buf, len, attotime::zero);
4563
rc = uchar_from_utf8(&c, text, text_len);
4573
inputx_postn_rate(machine, buf, len, rate);
4576
void inputx_post_utf8(running_machine &machine, const char *text)
4578
inputx_postn_utf8_rate(machine, text, strlen(text), attotime::zero);
4581
void inputx_post_utf8_rate(running_machine &machine, const char *text, attotime rate)
4583
inputx_postn_utf8_rate(machine, text, strlen(text), rate);
4586
/***************************************************************************
4590
This stuff is here more out of convienience than anything else
4591
***************************************************************************/
4593
int input_classify_port(const input_field_config *field)
4599
case IPT_JOYSTICK_UP:
4600
case IPT_JOYSTICK_DOWN:
4601
case IPT_JOYSTICK_LEFT:
4602
case IPT_JOYSTICK_RIGHT:
4603
case IPT_JOYSTICKLEFT_UP:
4604
case IPT_JOYSTICKLEFT_DOWN:
4605
case IPT_JOYSTICKLEFT_LEFT:
4606
case IPT_JOYSTICKLEFT_RIGHT:
4607
case IPT_JOYSTICKRIGHT_UP:
4608
case IPT_JOYSTICKRIGHT_DOWN:
4609
case IPT_JOYSTICKRIGHT_LEFT:
4610
case IPT_JOYSTICKRIGHT_RIGHT:
4621
case IPT_AD_STICK_X:
4622
case IPT_AD_STICK_Y:
4623
case IPT_AD_STICK_Z:
4624
case IPT_TRACKBALL_X:
4625
case IPT_TRACKBALL_Y:
4626
case IPT_LIGHTGUN_X:
4627
case IPT_LIGHTGUN_Y:
4632
result = INPUT_CLASS_CONTROLLER;
4637
result = INPUT_CLASS_KEYBOARD;
4641
result = INPUT_CLASS_CONFIG;
4645
result = INPUT_CLASS_DIPSWITCH;
4649
if (field->name && (field->name != (const char *) -1))
4650
result = INPUT_CLASS_MISC;
4652
result = INPUT_CLASS_INTERNAL;
4656
result = INPUT_CLASS_INTERNAL;
4664
int input_player_number(const input_field_config *port)
4666
return port->player;
4671
/*-------------------------------------------------
4672
input_has_input_class - checks to see if a
4673
particular input class is present
4674
-------------------------------------------------*/
4676
int input_has_input_class(running_machine &machine, int inputclass)
4678
const input_port_config *port;
4679
const input_field_config *field;
4681
for (port = machine.m_portlist.first(); port != NULL; port = port->next())
4683
for (field = port->first_field(); field != NULL; field = field->next())
4685
if (input_classify_port(field) == inputclass)
4694
/*-------------------------------------------------
4695
input_count_players - counts the number of
4697
-------------------------------------------------*/
4699
int input_count_players(running_machine &machine)
4701
const input_port_config *port;
4702
const input_field_config *field;
4706
for (port = machine.m_portlist.first(); port != NULL; port = port->next())
4708
for (field = port->first_field(); field != NULL; field = field->next())
4710
if (input_classify_port(field) == INPUT_CLASS_CONTROLLER)
4712
if (joystick_count <= field->player + 1)
4713
joystick_count = field->player + 1;
4717
return joystick_count;
4722
/***************************************************************************
4724
***************************************************************************/
4726
/*-------------------------------------------------
4727
execute_input - debugger command to enter
4728
natural keyboard input
4729
-------------------------------------------------*/
4731
static void execute_input(running_machine &machine, int ref, int params, const char *param[])
4733
inputx_postn_coded_rate(machine, param[0], strlen(param[0]), attotime::zero);
4738
/*-------------------------------------------------
4739
execute_dumpkbd - debugger command to natural
4741
-------------------------------------------------*/
4743
static void execute_dumpkbd(running_machine &machine, int ref, int params, const char *param[])
4745
inputx_code *codes = machine.input_port_data->codes;
4746
const char *filename;
4748
const inputx_code *code;
4752
size_t left_column_width = 24;
4754
/* was there a file specified? */
4755
filename = (params > 0) ? param[0] : NULL;
4756
if (filename != NULL)
4758
/* if so, open it */
4759
file = fopen(filename, "w");
4762
debug_console_printf(machine, "Cannot open \"%s\"\n", filename);
4767
if ((codes != NULL) && (codes[0].ch != 0))
4769
/* loop through all codes */
4770
for (i = 0; codes[i].ch; i++)
4775
/* describe the character code */
4776
pos += snprintf(&buffer[pos], ARRAY_LENGTH(buffer) - pos, "%08X (%s) ",
4778
code_point_string(machine, code->ch));
4780
/* pad with spaces */
4781
while(pos < left_column_width)
4782
buffer[pos++] = ' ';
4785
/* identify the keys used */
4786
for (j = 0; j < ARRAY_LENGTH(code->field) && (code->field[j] != NULL); j++)
4788
pos += snprintf(&buffer[pos], ARRAY_LENGTH(buffer) - pos, "%s'%s'",
4789
(j > 0) ? ", " : "",
4790
code->field[j]->name);
4793
/* and output it as appropriate */
4795
fprintf(file, "%s\n", buffer);
4797
debug_console_printf(machine, "%s\n", buffer);
4802
debug_console_printf(machine, "No natural keyboard support\n");
4813
input_port_config *ioconfig_alloc_port(ioport_list &portlist, device_t &device, const char *tag)
4816
device.subtag(fulltag, tag);
4817
mame_printf_verbose("ioport '%s' created\n", fulltag.cstr());
4818
return &portlist.append(fulltag, *global_alloc(input_port_config(device, fulltag)));
4821
input_port_config *ioconfig_modify_port(ioport_list &portlist, device_t &device, const char *tag)
4824
device.subtag(fulltag, tag);
4825
input_port_config *port = portlist.find(fulltag.cstr());
3678
//-------------------------------------------------
3679
// record_frame - start of frame callback for
3681
//-------------------------------------------------
3683
void ioport_manager::record_frame(attotime curtime)
3685
// if recording, record information about the current frame
3686
if (m_record_file.is_open())
3688
// first the absolute time
3689
record_write(curtime.seconds);
3690
record_write(curtime.attoseconds);
3692
// then the current speed
3693
record_write(UINT32(machine().video().speed_percent() * double(1 << 20)));
3698
//-------------------------------------------------
3699
// record_port - per-port callback for record
3700
//-------------------------------------------------
3702
void ioport_manager::record_port(ioport_port &port)
3704
// if recording, store information about this port
3705
if (m_record_file.is_open())
3707
// store the default value and digital state
3708
record_write(port.live().defvalue);
3709
record_write(port.live().digital);
3711
// loop over analog ports and save their data
3712
for (analog_field *analog = port.live().analoglist.first(); analog != NULL; analog = analog->next())
3714
// store current and previous values
3715
record_write(analog->m_accum);
3716
record_write(analog->m_previous);
3718
// store configuration information
3719
record_write(analog->m_sensitivity);
3720
record_write(analog->m_reverse);
3727
//**************************************************************************
3728
// I/O PORT CONFIGURER
3729
//**************************************************************************
3731
//-------------------------------------------------
3732
// ioport_configurer - constructor
3733
//-------------------------------------------------
3735
ioport_configurer::ioport_configurer(device_t &owner, ioport_list &portlist, astring &errorbuf)
3737
m_portlist(portlist),
3738
m_errorbuf(errorbuf),
3746
//-------------------------------------------------
3747
// string_from_token - convert an
3748
// ioport_token to a default string
3749
//-------------------------------------------------
3751
const char *ioport_configurer::string_from_token(const char *string)
3753
// 0 is an invalid index
3757
// if the index is greater than the count, assume it to be a pointer
3758
if (FPTR(string) >= INPUT_STRING_COUNT)
3761
#if FALSE // Set TRUE, If you want to take care missing-token or wrong-sorting
3763
// otherwise, scan the list for a matching string and return it
3766
for (index = 0; index < ARRAY_LENGTH(input_port_default_strings); index++)
3767
if (input_port_default_strings[index].id == FPTR(string))
3768
return input_port_default_strings[index].string;
3770
return "(Unknown Default)";
3774
return input_port_default_strings[FPTR(string)-1].string;
3780
//-------------------------------------------------
3781
// port_alloc - allocate a new port
3782
//-------------------------------------------------
3784
void ioport_configurer::port_alloc(const char *tag)
3786
// create the full tag
3788
m_owner.subtag(fulltag, tag);
3790
// add it to the list, and reset current field/setting
3791
m_curport = &m_portlist.append(fulltag, *global_alloc(ioport_port(m_owner, fulltag)));
3793
m_cursetting = NULL;
3797
//-------------------------------------------------
3798
// port_modify - find an existing port and
3800
//-------------------------------------------------
3802
void ioport_configurer::port_modify(const char *tag)
3804
// create the full tag
3806
m_owner.subtag(fulltag, tag);
3808
// find the existing port
3809
m_curport = m_portlist.find(fulltag.cstr());
3810
if (m_curport == NULL)
4827
3811
throw emu_fatalerror("Requested to modify nonexistent port '%s'", fulltag.cstr());
4828
port->bump_modcount();
3813
// bump the modification count, and reset current field/setting
3814
m_curport->m_modcount++;
3816
m_cursetting = NULL;
4832
input_field_config *ioconfig_alloc_field(input_port_config &port, int type, input_port_value defval, input_port_value mask, const char *name)
3820
//-------------------------------------------------
3821
// field_alloc - allocate a new field
3822
//-------------------------------------------------
3824
void ioport_configurer::field_alloc(ioport_type type, ioport_value defval, ioport_value mask, const char *name)
4835
throw emu_fatalerror("INPUT_TOKEN_FIELD encountered with no active port (mask=%X defval=%X)\n", mask, defval); \
3826
// make sure we have a port
3827
if (m_curport == NULL)
3828
throw emu_fatalerror("alloc_field called with no active port (mask=%X defval=%X)\n", mask, defval); \
4836
3831
if (type != IPT_UNKNOWN && type != IPT_UNUSED)
4837
port.active |= mask;
4838
if (type == IPT_DIPSWITCH || type == IPT_CONFIG)
4839
defval = port_default_value(port.tag(), mask, defval, port.owner());
4840
return &port.fieldlist().append(*global_alloc(input_field_config(port, type, defval, mask, input_port_string_from_token(name))));
4843
input_field_config *ioconfig_alloc_onoff(input_port_config &port, const char *name, input_port_value defval, input_port_value mask, const char *diplocation, astring &errorbuf)
4845
input_field_config *curfield = ioconfig_alloc_field(port, IPT_DIPSWITCH, defval, mask, name);
3832
m_curport->m_active |= mask;
3833
m_curfield = &m_curport->m_fieldlist.append(*global_alloc(ioport_field(*m_curport, type, defval, mask, string_from_token(name))));
3835
// reset the current setting
3836
m_cursetting = NULL;
3840
//-------------------------------------------------
3841
// field_add_char - add a character to a field
3842
//-------------------------------------------------
3844
void ioport_configurer::field_add_char(unicode_char ch)
3846
for (int index = 0; index < ARRAY_LENGTH(m_curfield->m_chars); index++)
3847
if (m_curfield->m_chars[index] == 0)
3849
m_curfield->m_chars[index] = ch;
3853
throw emu_fatalerror("PORT_CHAR(%d) could not be added - maximum amount exceeded\n", ch);
3857
//-------------------------------------------------
3858
// field_add_code - add a character to a field
3859
//-------------------------------------------------
3861
void ioport_configurer::field_add_code(input_seq_type which, input_code code)
3863
m_curfield->m_seq[which] |= code;
3867
//-------------------------------------------------
3868
// setting_alloc - allocate a new setting
3869
//-------------------------------------------------
3871
void ioport_configurer::setting_alloc(ioport_value value, const char *name)
3873
// make sure we have a field
3874
if (m_curfield == NULL)
3875
throw emu_fatalerror("alloc_setting called with no active field (value=%X name=%s)\n", value, name);
3877
m_cursetting = global_alloc(ioport_setting(*m_curfield, value & m_curfield->mask(), string_from_token(name)));
3878
// append a new setting
3879
m_curfield->m_settinglist.append(*m_cursetting);
3883
//-------------------------------------------------
3884
// set_condition - set the condition for either
3885
// the current setting or field
3886
//-------------------------------------------------
3888
void ioport_configurer::set_condition(ioport_condition::condition_t condition, const char *tag, ioport_value mask, ioport_value value)
3890
ioport_condition &target = (m_cursetting != NULL) ? m_cursetting->condition() : m_curfield->condition();
3891
target.set(condition, tag, mask, value);
3895
//-------------------------------------------------
3896
// onoff_alloc - allocate an on/off DIP switch
3897
//-------------------------------------------------
3899
void ioport_configurer::onoff_alloc(const char *name, ioport_value defval, ioport_value mask, const char *diplocation)
3901
// allocate a field normally
3902
field_alloc(IPT_DIPSWITCH, defval, mask, name);
3904
// special case service mode
4846
3905
if (name == DEF_STR(Service_Mode))
4848
curfield->flags |= FIELD_FLAG_TOGGLE;
4849
curfield->seq[SEQ_TYPE_STANDARD].set(KEYCODE_F2);
3908
m_curfield->m_seq[SEQ_TYPE_STANDARD].set(KEYCODE_F2);
3911
// expand the diplocation
4851
3912
if (diplocation != NULL)
4852
diplocation_list_alloc(*curfield, diplocation, errorbuf);
4853
ioconfig_alloc_setting(*curfield, defval & mask, DEF_STR(Off));
4854
ioconfig_alloc_setting(*curfield, ~defval & mask, DEF_STR(On));
4858
input_setting_config *ioconfig_alloc_setting(input_field_config &field, input_port_value value, const char *name)
4860
return &field.settinglist().append(*global_alloc(input_setting_config(field, value, input_port_string_from_token(name))));
4863
void ioconfig_field_add_char(input_field_config &field, unicode_char ch, astring &errorbuf)
4865
for (int index = 0; index < ARRAY_LENGTH(field.chars); index++)
4866
if (field.chars[index] == 0)
4868
field.chars[index] = ch;
4873
void ioconfig_add_code(input_field_config &field, int which, input_code code)
4875
field.seq[which] |= code;
4880
input_type_entry::input_type_entry(UINT32 _type, ioport_group _group, int _player, const char *_token, const char *_name, input_seq standard)
4888
defseq[SEQ_TYPE_STANDARD] = seq[SEQ_TYPE_STANDARD] = standard;
4891
input_type_entry::input_type_entry(UINT32 _type, ioport_group _group, int _player, const char *_token, const char *_name, input_seq standard, input_seq decrement, input_seq increment)
4899
defseq[SEQ_TYPE_STANDARD] = seq[SEQ_TYPE_STANDARD] = standard;
4900
defseq[SEQ_TYPE_INCREMENT] = seq[SEQ_TYPE_INCREMENT] = increment;
4901
defseq[SEQ_TYPE_DECREMENT] = seq[SEQ_TYPE_DECREMENT] = decrement;
3913
field_set_diplocation(diplocation);
3915
// allocate settings
3916
setting_alloc(defval & mask, DEF_STR(Off));
3917
setting_alloc(~defval & mask, DEF_STR(On));
3918
// clear cursettings set by setting_alloc
3919
m_cursetting = NULL;
3924
/***************************************************************************
3926
***************************************************************************/
3928
//-------------------------------------------------
3929
// find - look up information about a particular
3931
//-------------------------------------------------
3933
const char_info *char_info::find(unicode_char target)
3935
// perform a simple binary search to find the proper alternate
3937
int high = ARRAY_LENGTH(charinfo);
3940
int middle = (high + low) / 2;
3941
unicode_char ch = charinfo[middle].ch;
3944
else if (ch > target)
3947
return &charinfo[middle];
3953
//-------------------------------------------------
3954
// dynamic_field - constructor
3955
//-------------------------------------------------
3957
dynamic_field::dynamic_field(ioport_field &field)
3961
m_oldval(field.defvalue())
3964
for (ioport_value mask = field.mask(); !(mask & 1); mask >>= 1)
3966
m_oldval >>= m_shift;
3970
//-------------------------------------------------
3971
// read - read the updated value and merge it
3973
//-------------------------------------------------
3975
void dynamic_field::read(ioport_value &result)
3977
// skip if not enabled
3978
if (!m_field.enabled())
3981
// call the callback to read a new value
3982
ioport_value newval = m_field.m_read(m_field, m_field.m_read_param);
3985
// merge in the bits (don't invert yet, as all digitals are inverted together)
3986
result = (result & ~m_field.mask()) | ((newval << m_shift) & m_field.mask());
3990
//-------------------------------------------------
3991
// write - track a change to a value and call
3992
// the write callback if there's something new
3993
//-------------------------------------------------
3995
void dynamic_field::write(ioport_value newval)
3997
// skip if not enabled
3998
if (!m_field.enabled())
4001
// if the bits have changed, call the handler
4002
newval = (newval & m_field.mask()) >> m_shift;
4003
if (m_oldval != newval)
4005
m_field.m_write(m_field, m_field.m_write_param, m_oldval, newval);
4011
//-------------------------------------------------
4012
// analog_field - constructor
4013
//-------------------------------------------------
4015
analog_field::analog_field(ioport_field &field)
4019
m_adjdefvalue(field.defvalue() & field.mask()),
4020
m_adjmin(field.minval() & field.mask()),
4021
m_adjmax(field.maxval() & field.mask()),
4022
m_sensitivity(field.sensitivity()),
4023
m_reverse(field.analog_reverse()),
4024
m_delta(field.delta()),
4025
m_centerdelta(field.centerdelta()),
4028
m_previousanalog(0),
4029
m_minimum(INPUT_ABSOLUTE_MIN),
4030
m_maximum(INPUT_ABSOLUTE_MAX),
4037
m_positionalscale(0),
4040
m_autocenter(false),
4041
m_single_scale(false),
4042
m_interpolate(false),
4043
m_lastdigital(false)
4045
// compute the shift amount and number of bits
4046
for (ioport_value mask = field.mask(); !(mask & 1); mask >>= 1)
4049
// initialize core data
4050
m_adjdefvalue >>= m_shift;
4051
m_adjmin >>= m_shift;
4052
m_adjmax >>= m_shift;
4054
// set basic parameters based on the configured type
4055
switch (field.type())
4057
// paddles and analog joysticks are absolute and autocenter
4058
case IPT_AD_STICK_X:
4059
case IPT_AD_STICK_Y:
4060
case IPT_AD_STICK_Z:
4064
m_autocenter = true;
4065
m_interpolate = !field.analog_reset();
4068
// pedals start at and autocenter to the min range
4072
m_center = INPUT_ABSOLUTE_MIN;
4073
m_accum = apply_inverse_sensitivity(m_center);
4075
m_autocenter = true;
4076
m_interpolate = !field.analog_reset();
4079
// lightguns are absolute as well, but don't autocenter and don't interpolate their values
4080
case IPT_LIGHTGUN_X:
4081
case IPT_LIGHTGUN_Y:
4083
m_autocenter = false;
4084
m_interpolate = false;
4087
// positional devices are absolute, but can also wrap like relative devices
4088
// set each position to be 512 units
4089
case IPT_POSITIONAL:
4090
case IPT_POSITIONAL_V:
4091
m_positionalscale = compute_scale(field.maxval(), INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN);
4093
m_adjmax = field.maxval() - 1;
4094
m_wraps = field.analog_wraps();
4095
m_autocenter = !m_wraps;
4098
// dials, mice and trackballs are relative devices
4099
// these have fixed "min" and "max" values based on how many bits are in the port
4100
// in addition, we set the wrap around min/max values to 512 * the min/max values
4101
// this takes into account the mapping that one mouse unit ~= 512 analog units
4104
case IPT_TRACKBALL_X:
4105
case IPT_TRACKBALL_Y:
4110
m_interpolate = !field.analog_reset();
4114
fatalerror("Unknown analog port type -- don't know if it is absolute or not");
4118
// further processing for absolute controls
4121
// if the default value is pegged at the min or max, use a single scale value for the whole axis
4122
m_single_scale = (m_adjdefvalue == m_adjmin) || (m_adjdefvalue == m_adjmax);
4124
// if not "single scale", compute separate scales for each side of the default
4125
if (!m_single_scale)
4128
m_scalepos = compute_scale(m_adjmax - m_adjdefvalue, INPUT_ABSOLUTE_MAX - 0);
4129
m_scaleneg = compute_scale(m_adjdefvalue - m_adjmin, 0 - INPUT_ABSOLUTE_MIN);
4131
if (m_adjmin > m_adjmax)
4132
m_scaleneg = -m_scaleneg;
4134
// reverse point is at center
4139
// single axis that increases from default
4140
m_scalepos = compute_scale(m_adjmax - m_adjmin, INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN);
4142
// move from default
4143
if (m_adjdefvalue == m_adjmax)
4144
m_scalepos = -m_scalepos;
4146
// make the scaling the same for easier coding when we need to scale
4147
m_scaleneg = m_scalepos;
4149
// reverse point is at max
4150
m_reverse_val = m_maximum;
4154
// relative and positional controls all map directly with a 512x scale factor
4157
// The relative code is set up to allow specifing PORT_MINMAX and default values.
4158
// The validity checks are purposely set up to not allow you to use anything other
4159
// a default of 0 and PORT_MINMAX(0,mask). This is in case the need arises to use
4160
// this feature in the future. Keeping the code in does not hurt anything.
4161
if (m_adjmin > m_adjmax)
4162
// adjust for signed
4163
m_adjmin = -m_adjmin;
4168
m_minimum = (m_adjmin - m_adjdefvalue) * INPUT_RELATIVE_PER_PIXEL;
4169
m_maximum = (m_adjmax - m_adjdefvalue) * INPUT_RELATIVE_PER_PIXEL;
4171
// make the scaling the same for easier coding when we need to scale
4172
m_scaleneg = m_scalepos = compute_scale(1, INPUT_RELATIVE_PER_PIXEL);
4174
if (m_field.analog_reset())
4175
// delta values reverse from center
4179
// positional controls reverse from their max range
4180
m_reverse_val = m_maximum + m_minimum;
4182
// relative controls reverse from 1 past their max range
4184
m_reverse_val -= INPUT_RELATIVE_PER_PIXEL;
4188
// compute scale for keypresses
4189
m_keyscalepos = recip_scale(m_scalepos);
4190
m_keyscaleneg = recip_scale(m_scaleneg);
4194
//-------------------------------------------------
4195
// apply_min_max - clamp the given input value to
4196
// the appropriate min/max for the analog control
4197
//-------------------------------------------------
4199
inline INT32 analog_field::apply_min_max(INT32 value) const
4201
// take the analog minimum and maximum values and apply the inverse of the
4202
// sensitivity so that we can clamp against them before applying sensitivity
4203
INT32 adjmin = apply_inverse_sensitivity(m_minimum);
4204
INT32 adjmax = apply_inverse_sensitivity(m_maximum);
4206
// for absolute devices, clamp to the bounds absolutely
4211
else if (value < adjmin)
4215
// for relative devices, wrap around when we go past the edge
4218
INT32 range = adjmax - adjmin;
4219
// rolls to other end when 1 position past end.
4220
value = (value - adjmin) % range;
4230
//-------------------------------------------------
4231
// apply_sensitivity - apply a sensitivity
4232
// adjustment for a current value
4233
//-------------------------------------------------
4235
inline INT32 analog_field::apply_sensitivity(INT32 value) const
4237
return INT32((INT64(value) * m_sensitivity) / 100.0 + 0.5);
4241
//-------------------------------------------------
4242
// apply_inverse_sensitivity - reverse-apply the
4243
// sensitivity adjustment for a current value
4244
//-------------------------------------------------
4246
inline INT32 analog_field::apply_inverse_sensitivity(INT32 value) const
4248
return INT32((INT64(value) * 100) / m_sensitivity);
4252
//-------------------------------------------------
4253
// apply_settings - return the value of an
4255
//-------------------------------------------------
4257
INT32 analog_field::apply_settings(INT32 value) const
4259
// apply the min/max and then the sensitivity
4260
value = apply_min_max(value);
4261
value = apply_sensitivity(value);
4263
// apply reversal if needed
4265
value = m_reverse_val - value;
4266
else if (m_single_scale)
4267
// it's a pedal or the default value is equal to min/max
4268
// so we need to adjust the center to the minimum
4269
value -= INPUT_ABSOLUTE_MIN;
4271
// map differently for positive and negative values
4273
value = apply_scale(value, m_scalepos);
4275
value = apply_scale(value, m_scaleneg);
4276
value += m_adjdefvalue;
4282
//-------------------------------------------------
4283
// frame_update - update the internals of a
4284
// single analog field periodically
4285
//-------------------------------------------------
4287
void analog_field::frame_update(running_machine &machine)
4289
// clamp the previous value to the min/max range and remember it
4290
m_previous = m_accum = apply_min_max(m_accum);
4292
// get the new raw analog value and its type
4293
input_item_class itemclass;
4294
INT32 rawvalue = machine.input().seq_axis_value(m_field.seq(SEQ_TYPE_STANDARD), itemclass);
4296
// if we got an absolute input, it overrides everything else
4297
if (itemclass == ITEM_CLASS_ABSOLUTE)
4299
if (m_previousanalog != rawvalue)
4301
// only update if analog value changed
4302
m_previousanalog = rawvalue;
4304
// apply the inverse of the sensitivity to the raw value so that
4305
// it will still cover the full min->max range requested after
4306
// we apply the sensitivity adjustment
4307
if (m_absolute || m_field.analog_reset())
4309
// if port is absolute, then just return the absolute data supplied
4310
m_accum = apply_inverse_sensitivity(rawvalue);
4312
else if (m_positionalscale != 0)
4314
// if port is positional, we will take the full analog control and divide it
4315
// into positions, that way as the control is moved full scale,
4316
// it moves through all the positions
4317
rawvalue = apply_scale(rawvalue - INPUT_ABSOLUTE_MIN, m_positionalscale) * INPUT_RELATIVE_PER_PIXEL + m_minimum;
4319
// clamp the high value so it does not roll over
4320
rawvalue = MIN(rawvalue, m_maximum);
4321
m_accum = apply_inverse_sensitivity(rawvalue);
4324
// if port is relative, we use the value to simulate the speed of relative movement
4325
// sensitivity adjustment is allowed for this mode
4326
m_accum += rawvalue;
4328
m_lastdigital = false;
4329
// do not bother with other control types if the analog data is changing
4334
// we still have to update fake relative from joystick control
4335
if (!m_absolute && m_positionalscale == 0)
4336
m_accum += rawvalue;
4340
// if we got it from a relative device, use that as the starting delta
4341
// also note that the last input was not a digital one
4343
if (itemclass == ITEM_CLASS_RELATIVE && rawvalue != 0)
4346
m_lastdigital = false;
4349
INT64 keyscale = (m_accum >= 0) ? m_keyscalepos : m_keyscaleneg;
4351
// if the decrement code sequence is pressed, add the key delta to
4352
// the accumulated delta; also note that the last input was a digital one
4353
bool keypressed = false;
4354
if (machine.input().seq_pressed(m_field.seq(SEQ_TYPE_DECREMENT)))
4358
delta -= apply_scale(m_delta, keyscale);
4359
else if (!m_lastdigital)
4360
// decrement only once when first pressed
4361
delta -= apply_scale(1, keyscale);
4362
m_lastdigital = true;
4365
// same for the increment code sequence
4366
if (machine.input().seq_pressed(m_field.seq(SEQ_TYPE_INCREMENT)))
4370
delta += apply_scale(m_delta, keyscale);
4371
else if (!m_lastdigital)
4372
// increment only once when first pressed
4373
delta += apply_scale(1, keyscale);
4374
m_lastdigital = true;
4377
// if resetting is requested, clear the accumulated position to 0 before
4378
// applying the deltas so that we only return this frame's delta
4379
// note that centering only works for relative controls
4380
// no need to check if absolute here because it is checked by the validity tests
4381
if (m_field.analog_reset())
4384
// apply the delta to the accumulated value
4387
// if our last movement was due to a digital input, and if this control
4388
// type autocenters, and if neither the increment nor the decrement seq
4389
// was pressed, apply autocentering
4392
INT32 center = apply_inverse_sensitivity(m_center);
4393
if (m_lastdigital && !keypressed)
4395
// autocenter from positive values
4396
if (m_accum >= center)
4398
m_accum -= apply_scale(m_centerdelta, m_keyscalepos);
4399
if (m_accum < center)
4402
m_lastdigital = false;
4406
// autocenter from negative values
4409
m_accum += apply_scale(m_centerdelta, m_keyscaleneg);
4410
if (m_accum > center)
4413
m_lastdigital = false;
4418
else if (!keypressed)
4419
m_lastdigital = false;
4423
//-------------------------------------------------
4424
// read - read the current value and insert into
4425
// the provided ioport_value
4426
//-------------------------------------------------
4428
void analog_field::read(ioport_value &result)
4430
// do nothing if we're not enabled
4431
if (!m_field.enabled())
4434
// start with the raw value
4435
INT32 value = m_accum;
4437
// interpolate if appropriate and if time has passed since the last update
4439
value = manager().frame_interpolate(m_previous, m_accum);
4441
// apply standard analog settings
4442
value = apply_settings(value);
4444
// remap the value if needed
4445
if (m_field.remap_table() != NULL)
4446
value = m_field.remap_table()[value];
4448
// invert bits if needed
4449
if (m_field.analog_invert())
4452
// insert into the port
4453
result = (result & ~m_field.mask()) | ((value << m_shift) & m_field.mask());
4457
//-------------------------------------------------
4458
// crosshair_read - read a value for crosshairs,
4459
// scaled between 0 and 1
4460
//-------------------------------------------------
4462
float analog_field::crosshair_read()
4464
INT32 rawvalue = apply_settings(m_accum) & (m_field.mask() >> m_shift);
4465
return float(rawvalue - m_adjmin) / float(m_adjmax - m_adjmin);
4470
/***************************************************************************
4471
TOKENIZATION HELPERS
4472
***************************************************************************/
4474
//-------------------------------------------------
4475
// token_to_input_type - convert a string token
4476
// to an input field type and player
4477
//-------------------------------------------------
4479
ioport_type ioport_manager::token_to_input_type(const char *string, int &player) const
4481
// check for our failsafe case first
4483
if (sscanf(string, "TYPE_OTHER(%d,%d)", &ipnum, &player) == 2)
4484
return ioport_type(ipnum);
4486
// find the token in the list
4487
for (input_type_entry *entry = m_typelist.first(); entry != NULL; entry = entry->next())
4488
if (entry->token() != NULL && !strcmp(entry->token(), string))
4490
player = entry->player();
4491
return entry->type();
4494
// if we fail, return IPT_UNKNOWN
4500
//-------------------------------------------------
4501
// input_type_to_token - convert an input field
4502
// type and player to a string token
4503
//-------------------------------------------------
4505
const char *ioport_manager::input_type_to_token(astring &string, ioport_type type, int player)
4507
// look up the port and return the token
4508
input_type_entry *entry = m_type_to_entry[type][player];
4510
return string.cpy(entry->token());
4512
// if that fails, carry on
4513
return string.format("TYPE_OTHER(%d,%d)", type, player);
4517
//-------------------------------------------------
4518
// token_to_seq_type - convert a string to
4520
//-------------------------------------------------
4522
input_seq_type ioport_manager::token_to_seq_type(const char *string)
4524
// look up the string in the table of possible sequence types and return the index
4525
for (int seqindex = 0; seqindex < ARRAY_LENGTH(seqtypestrings); seqindex++)
4526
if (!mame_stricmp(string, seqtypestrings[seqindex]))
4527
return input_seq_type(seqindex);
4528
return SEQ_TYPE_INVALID;
4533
//-------------------------------------------------
4534
// validate_natural_keyboard_statics -
4535
// validates natural keyboard static data
4536
//-------------------------------------------------
4539
int validate_natural_keyboard_statics(void)
4543
unicode_char last_char = 0;
4544
const char_info *ci;
4546
// check to make sure that charinfo is in order
4547
for (i = 0; i < ARRAY_LENGTH(charinfo); i++)
4549
if (last_char >= charinfo[i].ch)
4551
mame_printf_error("inputx: charinfo is out of order; 0x%08x should be higher than 0x%08x\n", charinfo[i].ch, last_char);
4554
last_char = charinfo[i].ch;
4557
// check to make sure that I can look up everything on alternate_charmap
4558
for (i = 0; i < ARRAY_LENGTH(charinfo); i++)
4560
ci = char_info::find(charinfo[i].ch);
4561
if (ci != &charinfo[i])
4563
mame_printf_error("ioport: expected char_info::find(0x%08x) to work properly\n", charinfo[i].ch);