~ubuntu-branches/debian/sid/mame/sid

« back to all changes in this revision

Viewing changes to src/emu/ioport.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach, Emmanuel Kasper, Jordi Mallach
  • Date: 2012-06-05 20:02:23 UTC
  • mfrom: (0.3.1) (0.1.4)
  • Revision ID: package-import@ubuntu.com-20120605200223-gnlpogjrg6oqe9md
Tags: 0.146-1
[ Emmanuel Kasper ]
* New upstream release
* Drop patch to fix man pages section and patches to link with flac 
  and jpeg system lib: all this has been pushed upstream by Cesare Falco
* Add DM-Upload-Allowed: yes field.

[ Jordi Mallach ]
* Create a "gnu" TARGETOS stanza that defines NO_AFFINITY_NP.
* Stop setting TARGETOS to "unix" in d/rules. It should be autodetected,
  and set to the appropriate value.
* mame_manpage_section.patch: Change mame's manpage section to 6 (games),
  in the TH declaration.

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
 
5
5
    Input/output port handling.
6
6
 
7
 
    Copyright Nicola Salmoria and the MAME Team.
8
 
    Visit http://mamedev.org for licensing and usage restrictions.
 
7
****************************************************************************
 
8
 
 
9
    Copyright Aaron Giles
 
10
    All rights reserved.
 
11
 
 
12
    Redistribution and use in source and binary forms, with or without
 
13
    modification, are permitted provided that the following conditions are
 
14
    met:
 
15
 
 
16
        * Redistributions of source code must retain the above copyright
 
17
          notice, this list of conditions and the following disclaimer.
 
18
        * Redistributions in binary form must reproduce the above copyright
 
19
          notice, this list of conditions and the following disclaimer in
 
20
          the documentation and/or other materials provided with the
 
21
          distribution.
 
22
        * Neither the name 'MAME' nor the names of its contributors may be
 
23
          used to endorse or promote products derived from this software
 
24
          without specific prior written permission.
 
25
 
 
26
    THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
 
27
    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
28
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
29
    DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
 
30
    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
31
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
32
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
33
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 
34
    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 
35
    IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
36
    POSSIBILITY OF SUCH DAMAGE.
9
37
 
10
38
****************************************************************************
11
39
 
103
131
#include <ctype.h>
104
132
#include <time.h>
105
133
 
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
110
138
 
111
139
 
112
 
/***************************************************************************
113
 
    CONSTANTS
114
 
***************************************************************************/
115
 
 
116
 
#define DIGITAL_JOYSTICKS_PER_PLAYER    3
117
 
 
118
 
/* these constants must match the order of the joystick directions in the IPT definition */
119
 
#define JOYDIR_UP                       0
120
 
#define JOYDIR_DOWN                     1
121
 
#define JOYDIR_LEFT                     2
122
 
#define JOYDIR_RIGHT            3
123
 
 
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)
128
 
 
129
 
#define NUM_SIMUL_KEYS  (UCHAR_SHIFT_END - UCHAR_SHIFT_BEGIN + 1)
130
 
#define LOG_INPUTX              0
131
 
#define SPACE_COUNT             3
132
 
#define INVALID_CHAR    '?'
133
 
#define IP_NAME_DEFAULT NULL
134
 
 
135
 
 
136
 
/***************************************************************************
137
 
    TYPE DEFINITIONS
138
 
***************************************************************************/
139
 
 
140
 
/* live analog field information */
141
 
typedef struct _analog_field_state analog_field_state;
142
 
struct _analog_field_state
143
 
{
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 */
146
 
 
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 */
152
 
 
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 */
158
 
 
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 */
163
 
 
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 */
169
 
 
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 */
176
 
 
177
 
        /* misc flags */
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? */
184
 
};
185
 
 
186
 
 
187
 
/* shared digital joystick state */
188
 
typedef struct _digital_joystick_state digital_joystick_state;
189
 
struct _digital_joystick_state
190
 
{
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 */
196
 
};
197
 
 
198
 
 
199
 
/* live device field information */
200
 
typedef struct _device_field_info device_field_info;
201
 
struct _device_field_info
202
 
{
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 */
208
 
};
209
 
 
210
 
 
211
 
/* internal live state of an input field */
212
 
struct _input_field_state
213
 
{
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 */
222
 
};
223
 
 
224
 
 
225
 
/* internal live state of an input port */
226
 
struct _input_port_state
227
 
{
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 */
235
 
};
236
 
 
237
 
 
238
 
typedef struct _inputx_code inputx_code;
239
 
struct _inputx_code
240
 
{
241
 
        unicode_char ch;
242
 
        const input_field_config * field[NUM_SIMUL_KEYS];
243
 
};
244
 
 
245
 
typedef struct _key_buffer key_buffer;
246
 
struct _key_buffer
247
 
{
248
 
        int begin_pos;
249
 
        int end_pos;
250
 
        unsigned int status_keydown : 1;
251
 
        unicode_char buffer[4096];
252
 
};
253
 
 
254
 
typedef struct _char_info char_info;
255
 
struct _char_info
 
140
//**************************************************************************
 
141
//  DEBUGGING
 
142
//**************************************************************************
 
143
 
 
144
#define LOG_NATURAL_KEYBOARD    0
 
145
 
 
146
 
 
147
 
 
148
//**************************************************************************
 
149
//  CONSTANTS
 
150
//**************************************************************************
 
151
 
 
152
const int SPACE_COUNT = 3;
 
153
const int KEY_BUFFER_SIZE = 4096;
 
154
const unicode_char INVALID_CHAR = '?';
 
155
 
 
156
 
 
157
 
 
158
//**************************************************************************
 
159
//  TYPE DEFINITIONS
 
160
//**************************************************************************
 
161
 
 
162
// live analog field information
 
163
class analog_field
 
164
{
 
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);
 
168
 
 
169
public:
 
170
        // construction/destruction
 
171
        analog_field(ioport_field &field);
 
172
 
 
173
        // getters
 
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; }
 
181
 
 
182
        // readers
 
183
        void read(ioport_value &value);
 
184
        float crosshair_read();
 
185
        void frame_update(running_machine &machine);
 
186
 
 
187
private:
 
188
        // helpers
 
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;
 
193
 
 
194
        // internal state
 
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
 
197
 
 
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
 
203
 
 
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
 
209
 
 
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
 
214
 
 
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
 
220
 
 
221
        // scaling factors
 
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
 
227
 
 
228
        // misc flags
 
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?
 
235
};
 
236
 
 
237
 
 
238
// live device field information
 
239
class dynamic_field
 
240
{
 
241
        friend class simple_list<dynamic_field>;
 
242
 
 
243
public:
 
244
        // construction/destruction
 
245
        dynamic_field(ioport_field &field);
 
246
 
 
247
        // getters
 
248
        dynamic_field *next() const { return m_next; }
 
249
        ioport_field &field() const { return m_field; }
 
250
 
 
251
        // read/write
 
252
        void read(ioport_value &result);
 
253
        void write(ioport_value newval);
 
254
 
 
255
private:
 
256
        // internal state
 
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
 
261
};
 
262
 
 
263
 
 
264
// internal live state of an input field
 
265
struct ioport_field_live
 
266
{
 
267
        // construction/destruction
 
268
        ioport_field_live(ioport_field &field, analog_field *analog);
 
269
 
 
270
        // public state
 
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
 
279
};
 
280
 
 
281
 
 
282
// internal live state of an input port
 
283
struct ioport_port_live
 
284
{
 
285
        // construction/destruction
 
286
        ioport_port_live(ioport_port &port);
 
287
 
 
288
        // public state
 
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
 
295
};
 
296
 
 
297
 
 
298
// character information
 
299
struct char_info
256
300
{
257
301
        unicode_char ch;
258
302
        const char *name;
259
 
        const char *alternate;  /* alternative string, in UTF-8 */
260
 
};
261
 
 
262
 
 
263
 
/* private input port state */
264
 
struct _input_port_private
265
 
{
266
 
        /* global state */
267
 
        UINT8                                           safe_to_read;           /* clear at start; set after state is loaded */
268
 
 
269
 
        /* types */
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 */
272
 
 
273
 
        /* specific special global input states */
274
 
        digital_joystick_state          joystick_info[MAX_PLAYERS][DIGITAL_JOYSTICKS_PER_PLAYER]; /* joystick states */
275
 
 
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 */
279
 
 
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 */
285
 
 
286
 
        /* inputx */
287
 
        inputx_code *codes;
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;
294
 
};
295
 
 
296
 
 
297
 
/***************************************************************************
298
 
    MACROS
299
 
***************************************************************************/
300
 
 
301
 
#define APPLY_SENSITIVITY(x,s)          (((INT64)(x) * (s)) / 100.0 + 0.5)
302
 
#define APPLY_INVERSE_SENSITIVITY(x,s) (((INT64)(x) * 100) / (s))
303
 
 
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)
307
 
 
308
 
 
309
 
 
310
 
/***************************************************************************
311
 
    GLOBAL VARIABLES
312
 
***************************************************************************/
313
 
 
314
 
/* XML attributes for the different types */
 
303
        const char *alternate;  // alternative string, in UTF-8
 
304
 
 
305
        static const char_info *find(unicode_char target);
 
306
};
 
307
 
 
308
 
 
309
 
 
310
//**************************************************************************
 
311
//  INLINE FUNCTIONS
 
312
//**************************************************************************
 
313
 
 
314
//-------------------------------------------------
 
315
//  compute_scale -- compute an 8.24 scale value
 
316
//  from a numerator and a denominator
 
317
//-------------------------------------------------
 
318
 
 
319
inline INT64 compute_scale(INT32 num, INT32 den)
 
320
{
 
321
        return (INT64(num) << 24) / den;
 
322
}
 
323
 
 
324
 
 
325
//-------------------------------------------------
 
326
//  recip_scale -- compute an 8.24 reciprocal of
 
327
//  an 8.24 scale value
 
328
//-------------------------------------------------
 
329
 
 
330
inline INT64 recip_scale(INT64 scale)
 
331
{
 
332
        return (INT64(1) << 48) / scale;
 
333
}
 
334
 
 
335
 
 
336
//-------------------------------------------------
 
337
//  apply_scale -- apply an 8.24 scale value to
 
338
//  a 32-bit value
 
339
//-------------------------------------------------
 
340
 
 
341
inline INT32 apply_scale(INT32 value, INT64 scale)
 
342
{
 
343
        return (INT64(value) * scale) >> 24;
 
344
}
 
345
 
 
346
 
 
347
 
 
348
//**************************************************************************
 
349
//  GLOBAL VARIABLES
 
350
//**************************************************************************
 
351
 
 
352
// XML attributes for the different types
315
353
static const char *const seqtypestrings[] = { "standard", "increment", "decrement" };
316
354
 
317
 
 
 
355
// master character info table
318
356
static const char_info charinfo[] =
319
357
{
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
610
648
};
611
649
 
612
 
static TIMER_CALLBACK(inputx_timerproc);
613
 
 
614
 
 
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[]);
618
 
 
619
 
/***************************************************************************
620
 
    COMMON SHARED STRINGS
621
 
***************************************************************************/
 
650
 
 
651
 
 
652
//**************************************************************************
 
653
//  COMMON SHARED STRINGS
 
654
//**************************************************************************
622
655
 
623
656
static const struct
624
657
{
749
782
 
750
783
 
751
784
 
752
 
/***************************************************************************
753
 
    BUILT-IN CORE MAPPINGS
754
 
***************************************************************************/
 
785
//**************************************************************************
 
786
//  BUILT-IN CORE MAPPINGS
 
787
//**************************************************************************
755
788
 
756
789
#include "inpttype.h"
757
790
 
758
791
 
759
792
 
760
 
/***************************************************************************
761
 
    FUNCTION PROTOTYPES
762
 
***************************************************************************/
763
 
 
764
 
/* core system management */
765
 
static void input_port_exit(running_machine &machine);
766
 
 
767
 
/* port reading */
768
 
static INT32 apply_analog_settings(INT32 current, analog_field_state *analog);
769
 
 
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);
776
 
 
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);
783
 
 
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);
788
 
 
789
 
/* settings load */
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);
794
 
 
795
 
/* settings save */
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);
801
 
 
802
 
/* input playback */
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);
807
 
 
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);
813
 
 
814
 
 
815
 
 
816
 
/***************************************************************************
817
 
    INLINE FUNCTIONS
818
 
***************************************************************************/
819
 
 
820
 
/*-------------------------------------------------
821
 
    apply_analog_min_max - clamp the given input
822
 
    value to the appropriate min/max for the
823
 
    analog control
824
 
-------------------------------------------------*/
825
 
 
826
 
INLINE INT32 apply_analog_min_max(const analog_field_state *analog, INT32 value)
827
 
{
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);
832
 
 
833
 
        /* for absolute devices, clamp to the bounds absolutely */
834
 
        if (!analog->wraps)
835
 
        {
836
 
                if (value > adjmax)
837
 
                        value = adjmax;
838
 
                else if (value < adjmin)
839
 
                        value = adjmin;
840
 
        }
841
 
 
842
 
        /* for relative devices, wrap around when we go past the edge */
843
 
        else
844
 
        {
845
 
                INT32 range = adjmax - adjmin;
846
 
                /* rolls to other end when 1 position past end. */
847
 
                value = (value - adjmin) % range;
848
 
                if (value < 0)
849
 
                        value += range;
850
 
                value += adjmin;
851
 
        }
852
 
 
853
 
        return value;
854
 
}
855
 
 
856
 
 
857
 
/*-------------------------------------------------
858
 
    get_port_tag - return a guaranteed tag for
859
 
    a port
860
 
-------------------------------------------------*/
861
 
 
862
 
INLINE const char *get_port_tag(const input_port_config *port, char *tempbuffer)
863
 
{
864
 
        return port->tag();
865
 
}
866
 
 
867
 
 
868
 
/*-------------------------------------------------
869
 
    condition_equal - TRUE if two conditions are
870
 
    equivalent
871
 
-------------------------------------------------*/
872
 
 
873
 
INLINE int condition_equal(const input_condition *cond1, const input_condition *cond2)
874
 
{
875
 
        return (cond1->mask == cond2->mask && cond1->value == cond2->value && cond1->condition == cond2->condition && strcmp(cond1->tag, cond2->tag) == 0);
876
 
}
877
 
 
878
 
 
879
 
 
880
 
/***************************************************************************
881
 
    CORE SYSTEM MANAGEMENT
882
 
***************************************************************************/
883
 
 
884
 
/*-------------------------------------------------
885
 
    input_port_init - initialize the input port
886
 
    system
887
 
-------------------------------------------------*/
888
 
 
889
 
time_t input_port_init(running_machine &machine)
890
 
{
891
 
        //input_port_private *portdata;
892
 
        time_t basetime;
893
 
 
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;
897
 
 
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));
901
 
 
902
 
        /* initialize the default port info from the OSD */
903
 
        init_port_types(machine);
904
 
 
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())
908
 
        {
909
 
                astring errors;
910
 
                input_port_list_init(*device, machine.m_portlist, errors);
911
 
                if (errors)
912
 
                        mame_printf_error("Input port errors:\n%s", errors.cstr());
913
 
        }
914
 
 
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));
918
 
 
919
 
        /* open playback and record files if specified */
920
 
        basetime = playback_init(machine);
921
 
        record_init(machine);
922
 
 
923
 
        return basetime;
924
 
}
925
 
 
926
 
 
927
 
/*-------------------------------------------------
928
 
    input_port_exit - exit callback to ensure
929
 
    we clean up and close our files
930
 
-------------------------------------------------*/
931
 
 
932
 
static void input_port_exit(running_machine &machine)
933
 
{
934
 
        /* close any playback or recording files */
935
 
        playback_end(machine, NULL);
936
 
        record_end(machine, NULL);
937
 
}
938
 
 
939
 
 
940
 
 
941
 
/***************************************************************************
942
 
    PORT CONFIGURATIONS
943
 
***************************************************************************/
944
 
 
945
 
/*-------------------------------------------------
946
 
    input_port_list_init - initialize an input
947
 
    port list structure and allocate ports
948
 
    according to the given tokens
949
 
-------------------------------------------------*/
950
 
 
951
 
void input_port_list_init(device_t &device, ioport_list &portlist, astring &errorbuf)
952
 
{
953
 
        /* no constructor, no list */
 
793
//**************************************************************************
 
794
//  PORT CONFIGURATIONS
 
795
//**************************************************************************
 
796
 
 
797
//**************************************************************************
 
798
//  I/O PORT LIST
 
799
//**************************************************************************
 
800
 
 
801
//-------------------------------------------------
 
802
//  append - append the given device's input ports
 
803
//  to the current list
 
804
//-------------------------------------------------
 
805
 
 
806
void ioport_list::append(device_t &device, astring &errorbuf)
 
807
{
 
808
        // no constructor, no list
954
809
        ioport_constructor constructor = device.input_ports();
955
810
        if (constructor == NULL)
956
811
                return;
957
812
 
958
 
        /* reset error buffer */
 
813
        // reset error buffer
959
814
        errorbuf.reset();
960
815
 
961
 
        /* detokenize into the list */
962
 
        (*constructor)(device, portlist, errorbuf);
 
816
        // detokenize into the list
 
817
        (*constructor)(device, *this, errorbuf);
963
818
 
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);
967
822
}
968
823
 
969
824
 
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
 
-------------------------------------------------*/
975
 
 
976
 
const input_field_config *input_field_by_tag_and_mask(running_machine &machine, const char *tag, input_port_value mask)
977
 
{
978
 
        const input_port_config *port = machine.port(tag);
979
 
 
980
 
        /* if we got the port, look for the field */
981
 
        if (port != NULL)
982
 
                for (const input_field_config *field = port->first_field(); field != NULL; field = field->next())
983
 
                        if ((field->mask & mask) != 0)
984
 
                                return field;
985
 
 
 
825
 
 
826
//**************************************************************************
 
827
//  INPUT TYPE ENTRY
 
828
//**************************************************************************
 
829
 
 
830
//-------------------------------------------------
 
831
//  input_type_entry - constructors
 
832
//-------------------------------------------------
 
833
 
 
834
input_type_entry::input_type_entry(ioport_type type, ioport_group group, int player, const char *token, const char *name, input_seq standard)
 
835
        : m_next(NULL),
 
836
          m_type(type),
 
837
          m_group(group),
 
838
          m_player(player),
 
839
          m_token(token),
 
840
          m_name(name)
 
841
{
 
842
        m_defseq[SEQ_TYPE_STANDARD] = m_seq[SEQ_TYPE_STANDARD] = standard;
 
843
}
 
844
 
 
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)
 
846
        : m_next(NULL),
 
847
          m_type(type),
 
848
          m_group(group),
 
849
          m_player(player),
 
850
          m_token(token),
 
851
          m_name(name)
 
852
{
 
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;
 
856
}
 
857
 
 
858
 
 
859
//-------------------------------------------------
 
860
//  configure_osd - set the token and name of an
 
861
//  OSD entry
 
862
//-------------------------------------------------
 
863
 
 
864
void input_type_entry::configure_osd(const char *token, const char *name)
 
865
{
 
866
        assert(m_type >= IPT_OSD_1 && m_type <= IPT_OSD_16);
 
867
        m_token = token;
 
868
        m_name = name;
 
869
}
 
870
 
 
871
 
 
872
//**************************************************************************
 
873
//  DIGITAL JOYSTICKS
 
874
//**************************************************************************
 
875
 
 
876
//-------------------------------------------------
 
877
//  digital_joystick - constructor
 
878
//-------------------------------------------------
 
879
 
 
880
digital_joystick::digital_joystick(int player, int number)
 
881
        : m_player(player),
 
882
          m_number(number),
 
883
          m_current(0),
 
884
          m_current4way(0),
 
885
          m_previous(0)
 
886
{
 
887
        memset(m_field, 0, sizeof(m_field));
 
888
}
 
889
 
 
890
 
 
891
//-------------------------------------------------
 
892
//  set_axis - configure a single axis of a
 
893
//  digital joystick
 
894
//-------------------------------------------------
 
895
 
 
896
digital_joystick::direction_t digital_joystick::set_axis(ioport_field &field)
 
897
{
 
898
        direction_t direction = direction_t((field.type() - (IPT_DIGITAL_JOYSTICK_FIRST + 1)) % 4);
 
899
        m_field[direction] = &field;
 
900
        return direction;
 
901
}
 
902
 
 
903
 
 
904
//-------------------------------------------------
 
905
//  frame_update - update the state of digital
 
906
//  joysticks prior to accumulating the results
 
907
//  in a port
 
908
//-------------------------------------------------
 
909
 
 
910
void digital_joystick::frame_update()
 
911
{
 
912
        // remember previous state and reset current state
 
913
        m_previous = m_current;
 
914
        m_current = 0;
 
915
 
 
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)
 
920
                {
 
921
                        machine = &m_field[direction]->machine();
 
922
                        if (machine->input().seq_pressed(m_field[direction]->seq(SEQ_TYPE_STANDARD)))
 
923
                                m_current |= 1 << direction;
 
924
                }
 
925
 
 
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);
 
931
 
 
932
        // only update 4-way case if joystick has moved
 
933
        if (m_current != m_previous)
 
934
        {
 
935
                m_current4way = m_current;
 
936
 
 
937
                //
 
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.
 
941
                //
 
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
 
944
                //  to "up."
 
945
                //
 
946
                //  Zero any switches that didn't change from the previous to current state.
 
947
                //
 
948
                if ((m_current4way & (UP_BIT | DOWN_BIT)) &&
 
949
                        (m_current4way & (LEFT_BIT | RIGHT_BIT)))
 
950
                {
 
951
                        m_current4way ^= m_current4way & m_previous;
 
952
                }
 
953
 
 
954
                //
 
955
                //  If we are still pointing at a diagonal, we are in an indeterminant state.
 
956
                //
 
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.
 
959
                //
 
960
                //  The chances of this happening with a keyboard are slim, but we still need to
 
961
                //  constrain this case.
 
962
                //
 
963
                //  For now, just resolve randomly.
 
964
                //
 
965
                if ((m_current4way & (UP_BIT | DOWN_BIT)) &&
 
966
                        (m_current4way & (LEFT_BIT | RIGHT_BIT)))
 
967
                {
 
968
                        if (machine->rand() & 1)
 
969
                                m_current4way &= ~(LEFT_BIT | RIGHT_BIT);
 
970
                        else
 
971
                                m_current4way &= ~(UP_BIT | DOWN_BIT);
 
972
                }
 
973
        }
 
974
}
 
975
 
 
976
 
 
977
 
 
978
//**************************************************************************
 
979
//  NATURAL KEYBOARD
 
980
//**************************************************************************
 
981
 
 
982
//-------------------------------------------------
 
983
//  natural_keyboard - constructor
 
984
//-------------------------------------------------
 
985
 
 
986
natural_keyboard::natural_keyboard(running_machine &machine)
 
987
        : m_machine(machine),
 
988
          m_bufbegin(0),
 
989
          m_bufend(0),
 
990
          m_status_keydown(false),
 
991
          m_last_cr(false),
 
992
          m_timer(NULL),
 
993
          m_current_rate(attotime::zero)
 
994
{
 
995
        m_queue_chars = ioport_queue_chars_delegate();
 
996
        m_accept_char = ioport_accept_char_delegate();
 
997
        m_charqueue_empty = ioport_charqueue_empty_delegate();
 
998
 
 
999
        // reigster debugger commands
 
1000
        if (machine.debug_flags & DEBUG_FLAG_ENABLED)
 
1001
        {
 
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);
 
1004
        }
 
1005
}
 
1006
 
 
1007
//-------------------------------------------------
 
1008
//  initialize - initialize natural keyboard
 
1009
//  support
 
1010
//-------------------------------------------------
 
1011
 
 
1012
void natural_keyboard::initialize()
 
1013
{
 
1014
        // posting keys directly only makes sense for a computer
 
1015
        if (machine().ioport().has_keyboard())
 
1016
        {
 
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());
 
1020
        }
 
1021
}
 
1022
//-------------------------------------------------
 
1023
//  configure - configure callbacks for full-
 
1024
//  featured keyboard support
 
1025
//-------------------------------------------------
 
1026
 
 
1027
void natural_keyboard::configure(ioport_queue_chars_delegate queue_chars, ioport_accept_char_delegate accept_char, ioport_charqueue_empty_delegate charqueue_empty)
 
1028
{
 
1029
        // set the callbacks
 
1030
        m_queue_chars = queue_chars;
 
1031
        m_accept_char = accept_char;
 
1032
        m_charqueue_empty = charqueue_empty;
 
1033
}
 
1034
 
 
1035
 
 
1036
//-------------------------------------------------
 
1037
//  post - post a single character
 
1038
//-------------------------------------------------
 
1039
 
 
1040
void natural_keyboard::post(unicode_char ch)
 
1041
{
 
1042
        // ignore any \n that are preceded by \r
 
1043
        if (m_last_cr && ch == '\n')
 
1044
        {
 
1045
                m_last_cr = false;
 
1046
                return;
 
1047
        }
 
1048
 
 
1049
        // change all eolns to '\r'
 
1050
        if (ch == '\n')
 
1051
                ch = '\r';
 
1052
        else
 
1053
                m_last_cr = (ch == '\r');
 
1054
 
 
1055
        // logging
 
1056
        if (LOG_NATURAL_KEYBOARD)
 
1057
        {
 
1058
                const keycode_map_entry *code = find_code(ch);
 
1059
                astring tempstr;
 
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>");
 
1061
        }
 
1062
 
 
1063
        // can we post this key in the queue directly?
 
1064
        if (can_post_directly(ch))
 
1065
                internal_post(ch);
 
1066
 
 
1067
        // can we post this key with an alternate representation?
 
1068
        else if (can_post_alternate(ch))
 
1069
        {
 
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)
 
1074
                {
 
1075
                        altstring += uchar_from_utf8(&ch, altstring, strlen(altstring));
 
1076
                        internal_post(ch);
 
1077
                }
 
1078
        }
 
1079
}
 
1080
 
 
1081
 
 
1082
//-------------------------------------------------
 
1083
//  post - post a unicode encoded string
 
1084
//-------------------------------------------------
 
1085
 
 
1086
void natural_keyboard::post(const unicode_char *text, size_t length, attotime rate)
 
1087
{
 
1088
        // set the fixed rate
 
1089
        m_current_rate = rate;
 
1090
 
 
1091
        // 0 length means strlen
 
1092
        if (length == 0)
 
1093
                for (const unicode_char *scan = text; *scan != 0; scan++)
 
1094
                        length++;
 
1095
 
 
1096
        // iterate over characters or until the buffer is full up
 
1097
        while (length > 0 && !full())
 
1098
        {
 
1099
                // fetch next character
 
1100
                post(*text++);
 
1101
                length--;
 
1102
        }
 
1103
}
 
1104
 
 
1105
 
 
1106
//-------------------------------------------------
 
1107
//  post_utf8 - post a UTF-8 encoded string
 
1108
//-------------------------------------------------
 
1109
 
 
1110
void natural_keyboard::post_utf8(const char *text, size_t length, attotime rate)
 
1111
{
 
1112
        // set the fixed rate
 
1113
        m_current_rate = rate;
 
1114
 
 
1115
        // 0-length means strlen
 
1116
        if (length == 0)
 
1117
                length = strlen(text);
 
1118
 
 
1119
        // iterate until out of characters
 
1120
        while (length > 0)
 
1121
        {
 
1122
                // decode the next character
 
1123
                unicode_char uc;
 
1124
                int count = uchar_from_utf8(&uc, text, length);
 
1125
                if (count < 0)
 
1126
                {
 
1127
                        count = 1;
 
1128
                        uc = INVALID_CHAR;
 
1129
                }
 
1130
 
 
1131
                // append to the buffer
 
1132
                post(uc);
 
1133
                text += count;
 
1134
                length -= count;
 
1135
        }
 
1136
}
 
1137
 
 
1138
 
 
1139
//-------------------------------------------------
 
1140
//  post_coded - post a coded string
 
1141
//-------------------------------------------------
 
1142
 
 
1143
void natural_keyboard::post_coded(const char *text, size_t length, attotime rate)
 
1144
{
 
1145
        static const struct
 
1146
        {
 
1147
                const char *key;
 
1148
                unicode_char code;
 
1149
        } codes[] =
 
1150
        {
 
1151
                { "BACKSPACE",  8 },
 
1152
                { "BS",                 8 },
 
1153
                { "BKSP",               8 },
 
1154
                { "DEL",                UCHAR_MAMEKEY(DEL) },
 
1155
                { "DELETE",             UCHAR_MAMEKEY(DEL) },
 
1156
                { "END",                UCHAR_MAMEKEY(END) },
 
1157
                { "ENTER",              13 },
 
1158
                { "ESC",                '\033' },
 
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) },
 
1164
                { "SPACE",              32 },
 
1165
                { "TAB",                9 },
 
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) },
 
1178
                { "QUOTE",              '\"' }
 
1179
        };
 
1180
 
 
1181
        // set the fixed rate
 
1182
        m_current_rate = rate;
 
1183
 
 
1184
        // 0-length means strlen
 
1185
        if (length == 0)
 
1186
                length = strlen(text);
 
1187
 
 
1188
        // iterate through the source string
 
1189
        size_t curpos = 0;
 
1190
        while (curpos < length)
 
1191
        {
 
1192
                // extract next character
 
1193
                unicode_char ch = text[curpos];
 
1194
                size_t increment = 1;
 
1195
 
 
1196
                // look for escape characters
 
1197
                if (ch == '{')
 
1198
                        for (int codenum = 0; codenum < ARRAY_LENGTH(codes); codenum++)
 
1199
                        {
 
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] == '}')
 
1203
                                        {
 
1204
                                                ch = codes[codenum].code;
 
1205
                                                increment = keylen + 2;
 
1206
                                        }
 
1207
                        }
 
1208
 
 
1209
                // if we got a code, post it
 
1210
                if (ch != 0)
 
1211
                        post(ch);
 
1212
                curpos += increment;
 
1213
        }
 
1214
}
 
1215
 
 
1216
 
 
1217
//-------------------------------------------------
 
1218
//  build_codes - given an input port table, create
 
1219
//  an input code table useful for mapping unicode
 
1220
//  chars
 
1221
//-------------------------------------------------
 
1222
 
 
1223
void natural_keyboard::build_codes(ioport_manager &manager)
 
1224
{
 
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)
 
1229
 
 
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)
 
1234
                                        {
 
1235
                                                // fetch the code, ignoring 0
 
1236
                                                unicode_char code = field->keyboard_code(curshift);
 
1237
                                                if (code == 0)
 
1238
                                                        continue;
 
1239
 
 
1240
                                                // is this a shifter key?
 
1241
                                                if (code >= UCHAR_SHIFT_BEGIN && code <= UCHAR_SHIFT_END)
 
1242
                                                        shift[code - UCHAR_SHIFT_BEGIN] = field;
 
1243
 
 
1244
                                                // not a shifter key; record normally
 
1245
                                                else
 
1246
                                                {
 
1247
                                                        keycode_map_entry newcode;
 
1248
                                                        if (curshift == 0)
 
1249
                                                        {
 
1250
                                                                newcode.field[0] = field;
 
1251
                                                                newcode.field[1] = 0;
 
1252
                                                        }
 
1253
                                                        else
 
1254
                                                        {
 
1255
                                                                newcode.field[0] = shift[curshift - 1];
 
1256
                                                                newcode.field[1] = field;
 
1257
                                                        }
 
1258
                                                        newcode.ch = code;
 
1259
                                                        m_keycode_map.append(newcode);
 
1260
 
 
1261
                                                        if (LOG_NATURAL_KEYBOARD)
 
1262
                                                        {
 
1263
                                                                astring tempstr;
 
1264
                                                                logerror("natural_keyboard: code=%i (%s) port=%p field->name='%s'\n", int(code), unicode_to_string(tempstr, code), port, field->name());
 
1265
                                                        }
 
1266
                                                }
 
1267
                                        }
 
1268
}
 
1269
 
 
1270
 
 
1271
//-------------------------------------------------
 
1272
//  can_post_directly - determine if the given
 
1273
//  unicode character can be directly posted
 
1274
//-------------------------------------------------
 
1275
 
 
1276
bool natural_keyboard::can_post_directly(unicode_char ch)
 
1277
{
 
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);
 
1281
 
 
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);
 
1285
}
 
1286
 
 
1287
 
 
1288
//-------------------------------------------------
 
1289
//  can_post_alternate - determine if the given
 
1290
//  unicode character can be posted via translation
 
1291
//-------------------------------------------------
 
1292
 
 
1293
bool natural_keyboard::can_post_alternate(unicode_char ch)
 
1294
{
 
1295
        const char_info *info = char_info::find(ch);
 
1296
        if (info == NULL)
 
1297
                return false;
 
1298
 
 
1299
        const char *altstring = info->alternate;
 
1300
        if (altstring == NULL)
 
1301
                return false;
 
1302
 
 
1303
        while (*altstring != 0)
 
1304
        {
 
1305
                unicode_char uchar;
 
1306
                int count = uchar_from_utf8(&uchar, altstring, strlen(altstring));
 
1307
                if (count <= 0)
 
1308
                        return false;
 
1309
                if (!can_post_directly(uchar))
 
1310
                        return false;
 
1311
                altstring += count;
 
1312
        }
 
1313
        return true;
 
1314
}
 
1315
 
 
1316
 
 
1317
//-------------------------------------------------
 
1318
//  choose_delay - determine the delay between
 
1319
//  posting keyboard events
 
1320
//-------------------------------------------------
 
1321
 
 
1322
attotime natural_keyboard::choose_delay(unicode_char ch)
 
1323
{
 
1324
        // if we have a live rate, just use that
 
1325
        if (m_current_rate != attotime::zero)
 
1326
                return m_current_rate;
 
1327
 
 
1328
        // systems with queue_chars can afford a much smaller delay
 
1329
        if (!m_queue_chars.isnull())
 
1330
                return attotime::from_msec(10);
 
1331
 
 
1332
        // otherwise, default to constant delay with a longer delay on CR
 
1333
        return attotime::from_msec((ch == '\r') ? 200 : 50);
 
1334
}
 
1335
 
 
1336
 
 
1337
//-------------------------------------------------
 
1338
//  internal_post - post a keyboard event
 
1339
//-------------------------------------------------
 
1340
 
 
1341
void natural_keyboard::internal_post(unicode_char ch)
 
1342
{
 
1343
        // need to start up the timer?
 
1344
        if (empty())
 
1345
        {
 
1346
                m_timer->adjust(choose_delay(ch));
 
1347
                m_status_keydown = 0;
 
1348
        }
 
1349
 
 
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();
 
1355
}
 
1356
 
 
1357
 
 
1358
//-------------------------------------------------
 
1359
//  timer - timer callback to keep things flowing
 
1360
//  when posting a string of characters
 
1361
//-------------------------------------------------
 
1362
 
 
1363
void natural_keyboard::timer(void *ptr, int param)
 
1364
{
 
1365
        // the driver has a queue_chars handler
 
1366
        if (!m_queue_chars.isnull())
 
1367
        {
 
1368
                while (!empty() && m_queue_chars(&m_buffer[m_bufbegin], 1))
 
1369
                {
 
1370
                        m_bufbegin = (m_bufbegin + 1) % m_buffer.count();
 
1371
                        if (m_current_rate != attotime::zero)
 
1372
                                break;
 
1373
                }
 
1374
        }
 
1375
 
 
1376
        // the driver does not have a queue_chars handler
 
1377
        else
 
1378
        {
 
1379
                if (m_status_keydown)
 
1380
                        m_bufbegin = (m_bufbegin + 1) % m_buffer.count();
 
1381
                m_status_keydown = !m_status_keydown;
 
1382
        }
 
1383
 
 
1384
        // need to make sure timerproc is called again if buffer not empty
 
1385
        if (!empty())
 
1386
                m_timer->adjust(choose_delay(m_buffer[m_bufbegin]));
 
1387
}
 
1388
 
 
1389
 
 
1390
//-------------------------------------------------
 
1391
//  unicode_to_string - obtain a string
 
1392
//  representation of a given code; used for
 
1393
//  logging and debugging
 
1394
//-------------------------------------------------
 
1395
 
 
1396
const char *natural_keyboard::unicode_to_string(astring &buffer, unicode_char ch)
 
1397
{
 
1398
        buffer.reset();
 
1399
        switch (ch)
 
1400
        {
 
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;
 
1406
 
 
1407
                default:
 
1408
                        // seven bit ASCII is easy
 
1409
                        if (ch >= 32 && ch < 128)
 
1410
                        {
 
1411
                                char temp[2] = { char(ch), 0 };
 
1412
                                buffer.cpy(temp);
 
1413
                        }
 
1414
                        else if (ch >= UCHAR_MAMEKEY_BEGIN)
 
1415
                        {
 
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);
 
1419
                        }
 
1420
 
 
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));
 
1424
                        break;
 
1425
        }
 
1426
        return buffer;
 
1427
}
 
1428
 
 
1429
 
 
1430
//-------------------------------------------------
 
1431
//  find_code - find a code in our lookup table
 
1432
//-------------------------------------------------
 
1433
 
 
1434
const natural_keyboard::keycode_map_entry *natural_keyboard::find_code(unicode_char ch) const
 
1435
{
 
1436
        for (int index = 0; index < m_keycode_map.count(); index++)
 
1437
        {
 
1438
                if (m_keycode_map[index].ch == ch)
 
1439
                        return &m_keycode_map[index];
 
1440
        }
986
1441
        return NULL;
987
1442
}
988
1443
 
989
1444
 
990
 
 
991
 
/***************************************************************************
992
 
    ACCESSORS FOR INPUT FIELDS
993
 
***************************************************************************/
994
 
 
995
 
/*-------------------------------------------------
996
 
    input_field_name - return the field name for
997
 
    a given input field
998
 
-------------------------------------------------*/
999
 
 
1000
 
const char *input_field_name(const input_field_config *field)
1001
 
{
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)
1006
 
                return field->name;
1007
 
 
1008
 
        /* otherwise, return the name associated with the type */
1009
 
        return input_type_name(field->machine(), field->type, field->player);
1010
 
}
1011
 
 
1012
 
 
1013
 
/*-------------------------------------------------
1014
 
    input_field_seq - return the input sequence
1015
 
    for the given input field
1016
 
-------------------------------------------------*/
1017
 
 
1018
 
const input_seq &input_field_seq(const input_field_config *field, input_seq_type seqtype)
1019
 
{
1020
 
        /* if the field is disabled, return no key */
1021
 
        if (field->flags & FIELD_FLAG_UNUSED)
1022
 
                return input_seq::empty_seq;
1023
 
 
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];
1026
 
 
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);
1030
 
 
1031
 
        /* otherwise, return the sequence as-is */
1032
 
        return portseq;
1033
 
}
1034
 
 
1035
 
 
1036
 
/*-------------------------------------------------
1037
 
    input_field_get_user_settings - return the current
1038
 
    settings for the given input field
1039
 
-------------------------------------------------*/
1040
 
 
1041
 
void input_field_get_user_settings(const input_field_config *field, input_field_user_settings *settings)
1042
 
{
1043
 
        int seqtype;
1044
 
 
1045
 
        /* zap the entire structure */
1046
 
        memset(settings, 0, sizeof(*settings));
1047
 
 
1048
 
        /* copy the basics */
1049
 
        for (seqtype = 0; seqtype < ARRAY_LENGTH(settings->seq); seqtype++)
1050
 
                settings->seq[seqtype] = field->state->seq[seqtype];
1051
 
 
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;
1055
 
 
1056
 
        /* if there's analog data, extract the analog settings */
1057
 
        if (field->state->analog != NULL)
1058
 
        {
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;
1063
 
        }
1064
 
}
1065
 
 
1066
 
 
1067
 
/*-------------------------------------------------
1068
 
    input_field_set_user_settings - modify the current
1069
 
    settings for the given input field
1070
 
-------------------------------------------------*/
1071
 
 
1072
 
void input_field_set_user_settings(const input_field_config *field, const input_field_user_settings *settings)
1073
 
{
1074
 
        int seqtype;
1075
 
 
1076
 
        /* copy the basics */
1077
 
        for (seqtype = 0; seqtype < ARRAY_LENGTH(settings->seq); seqtype++)
1078
 
        {
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();
1082
 
                else
1083
 
                        field->state->seq[seqtype] = settings->seq[seqtype];
1084
 
        }
1085
 
 
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;
1089
 
 
1090
 
        /* if there's analog data, extract the analog settings */
1091
 
        if (field->state->analog != NULL)
1092
 
        {
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;
1097
 
        }
1098
 
}
1099
 
 
1100
 
 
1101
 
/*-------------------------------------------------
1102
 
    input_field_setting_name - return the expanded
1103
 
    setting name for a field
1104
 
-------------------------------------------------*/
1105
 
 
1106
 
const char *input_field_setting_name(const input_field_config *field)
1107
 
{
1108
 
        const input_setting_config *setting;
1109
 
 
1110
 
        /* only makes sense if we have settings */
1111
 
        assert(field->settinglist().count() != 0);
1112
 
 
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
//-------------------------------------------------
 
1449
 
 
1450
void natural_keyboard::frame_update(ioport_port &port, ioport_value &digital)
 
1451
{
 
1452
        // is there currently a key down?
 
1453
        if (m_status_keydown && !empty())
 
1454
        {
 
1455
                // loop through this character's component codes
 
1456
                const keycode_map_entry *code = find_code(m_buffer[m_bufbegin]);
 
1457
                if (code != NULL)
 
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();
 
1461
        }
 
1462
}
 
1463
 
 
1464
 
 
1465
//-------------------------------------------------
 
1466
//  key_name - returns the name of a specific key
 
1467
//-------------------------------------------------
 
1468
 
 
1469
const char *natural_keyboard::key_name(astring &string, unicode_char ch)
 
1470
{
 
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;
 
1474
        if (result != NULL)
 
1475
                string.cpy(result);
 
1476
 
 
1477
        // if that doesn't work, convert to UTF-8
 
1478
        else if (ch > 0x7F || isprint(ch))
 
1479
        {
 
1480
                char buf[10];
 
1481
                int count = utf8_from_uchar(buf, ARRAY_LENGTH(buf), ch);
 
1482
                buf[count] = 0;
 
1483
                string.cpy(buf);
 
1484
        }
 
1485
 
 
1486
        // otherwise, opt for question marks
 
1487
        else
 
1488
                string.cpy("???");
 
1489
        return string;
 
1490
}
 
1491
 
 
1492
 
 
1493
//-------------------------------------------------
 
1494
//  execute_input - debugger command to enter
 
1495
//  natural keyboard input
 
1496
//-------------------------------------------------
 
1497
 
 
1498
void natural_keyboard::execute_input(running_machine &machine, int ref, int params, const char *param[])
 
1499
{
 
1500
        machine.ioport().natkeyboard().post_coded(param[0]);
 
1501
}
 
1502
 
 
1503
 
 
1504
//-------------------------------------------------
 
1505
//  execute_dumpkbd - debugger command to natural
 
1506
//  keyboard codes
 
1507
//-------------------------------------------------
 
1508
 
 
1509
void natural_keyboard::execute_dumpkbd(running_machine &machine, int ref, int params, const char *param[])
 
1510
{
 
1511
        // was there a file specified?
 
1512
        const char *filename = (params > 0) ? param[0] : NULL;
 
1513
        FILE *file = NULL;
 
1514
        if (filename != NULL)
 
1515
        {
 
1516
                // if so, open it
 
1517
                file = fopen(filename, "w");
 
1518
                if (file == NULL)
 
1519
                {
 
1520
                        debug_console_printf(machine, "Cannot open \"%s\"\n", filename);
 
1521
                        return;
 
1522
                }
 
1523
        }
 
1524
 
 
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++)
 
1531
        {
 
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));
 
1535
 
 
1536
                // pad with spaces
 
1537
                while (buffer.len() < left_column_width)
 
1538
                        buffer.cat(' ');
 
1539
 
 
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());
 
1543
 
 
1544
                // and output it as appropriate
 
1545
                if (file != NULL)
 
1546
                        fprintf(file, "%s\n", buffer.cstr());
 
1547
                else
 
1548
                        debug_console_printf(machine, "%s\n", buffer.cstr());
 
1549
        }
 
1550
 
 
1551
        // cleanup
 
1552
        if (file != NULL)
 
1553
                fclose(file);
 
1554
}
 
1555
 
 
1556
 
 
1557
 
 
1558
//**************************************************************************
 
1559
//  I/O PORT CONDITION
 
1560
//**************************************************************************
 
1561
 
 
1562
//-------------------------------------------------
 
1563
//  eval - evaluate condition
 
1564
//-------------------------------------------------
 
1565
 
 
1566
bool ioport_condition::eval(device_t &device) const
 
1567
{
 
1568
        // always condition is always true
 
1569
        if (m_condition == ALWAYS)
 
1570
                return true;
 
1571
 
 
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)
 
1575
        {
 
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);
 
1583
        }
 
1584
        return true;
 
1585
}
 
1586
 
 
1587
 
 
1588
 
 
1589
//**************************************************************************
 
1590
//  I/O PORT SETTING
 
1591
//**************************************************************************
 
1592
 
 
1593
//-------------------------------------------------
 
1594
//  ioport_setting - constructor
 
1595
//-------------------------------------------------
 
1596
 
 
1597
ioport_setting::ioport_setting(ioport_field &field, ioport_value _value, const char *_name)
 
1598
        : m_next(NULL),
 
1599
          m_field(field),
 
1600
          m_value(_value),
 
1601
          m_name(_name)
 
1602
{
 
1603
}
 
1604
 
 
1605
 
 
1606
 
 
1607
//**************************************************************************
 
1608
//  I/O PORT DIP LOCATION
 
1609
//**************************************************************************
 
1610
 
 
1611
//-------------------------------------------------
 
1612
//  ioport_diplocation - constructor
 
1613
//-------------------------------------------------
 
1614
 
 
1615
ioport_diplocation::ioport_diplocation(const char *name, UINT8 swnum, bool invert)
 
1616
        : m_next(NULL),
 
1617
          m_name(name),
 
1618
          m_number(swnum),
 
1619
          m_invert(invert)
 
1620
{
 
1621
}
 
1622
 
 
1623
 
 
1624
 
 
1625
//**************************************************************************
 
1626
//  I/O PORT FIELD
 
1627
//**************************************************************************
 
1628
 
 
1629
//-------------------------------------------------
 
1630
//  ioport_field - constructor
 
1631
//-------------------------------------------------
 
1632
 
 
1633
ioport_field::ioport_field(ioport_port &port, ioport_type type, ioport_value defvalue, ioport_value maskbits, const char *name)
 
1634
        : m_next(NULL),
 
1635
          m_port(port),
 
1636
          m_live(NULL),
 
1637
          m_modcount(port.modcount()),
 
1638
          m_mask(maskbits),
 
1639
          m_defvalue(defvalue & maskbits),
 
1640
          m_type(type),
 
1641
          m_player(0),
 
1642
          m_flags(0),
 
1643
          m_impulse(0),
 
1644
          m_name(name),
 
1645
          m_read_param(NULL),
 
1646
          m_write_param(NULL),
 
1647
          m_min(0),
 
1648
          m_max(maskbits),
 
1649
          m_sensitivity(0),
 
1650
          m_delta(0),
 
1651
          m_centerdelta(0),
 
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),
 
1658
          m_way(0)
 
1659
{
 
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);
 
1664
 
 
1665
        // for DIP switches and configs, look for a default value from the owner
 
1666
        if (type == IPT_DIPSWITCH || type == IPT_CONFIG)
 
1667
        {
 
1668
                const input_device_default *def = device().input_ports_defaults();
 
1669
                if (def != NULL)
 
1670
                {
 
1671
                        const char *fulltag = port.tag();
 
1672
                        astring fullpath;
 
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;
 
1676
                }
 
1677
        }
 
1678
}
 
1679
 
 
1680
 
 
1681
//-------------------------------------------------
 
1682
//  ~ioport_field - destructor
 
1683
//-------------------------------------------------
 
1684
 
 
1685
ioport_field::~ioport_field()
 
1686
{
 
1687
        global_free(m_live);
 
1688
}
 
1689
 
 
1690
 
 
1691
//-------------------------------------------------
 
1692
//  name - return the field name for a given input
 
1693
//  field
 
1694
//-------------------------------------------------
 
1695
 
 
1696
const char *ioport_field::name() const
 
1697
{
 
1698
        // if we have a non-default name, use that
 
1699
        if (m_live != NULL && m_live->name)
 
1700
                return m_live->name;
 
1701
        if (m_name != NULL)
 
1702
                return m_name;
 
1703
 
 
1704
        // otherwise, return the name associated with the type
 
1705
        return manager().type_name(m_type, m_player);
 
1706
}
 
1707
 
 
1708
 
 
1709
//-------------------------------------------------
 
1710
//  seq - return the live input sequence for the
 
1711
//  given input field
 
1712
//-------------------------------------------------
 
1713
 
 
1714
const input_seq &ioport_field::seq(input_seq_type seqtype) const
 
1715
{
 
1716
        // if no live state, return default
 
1717
        if (m_live == NULL)
 
1718
                return defseq(seqtype);
 
1719
 
 
1720
        // if the field is disabled, return no key
 
1721
        if (unused())
 
1722
                return input_seq::empty_seq;
 
1723
 
 
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);
 
1727
 
 
1728
        // otherwise, return the sequence as-is
 
1729
        return m_live->seq[seqtype];
 
1730
}
 
1731
 
 
1732
 
 
1733
//-------------------------------------------------
 
1734
//  defseq - return the default input sequence for
 
1735
//  the given input field
 
1736
//-------------------------------------------------
 
1737
 
 
1738
const input_seq &ioport_field::defseq(input_seq_type seqtype) const
 
1739
{
 
1740
        // if the field is disabled, return no key
 
1741
        if (unused())
 
1742
                return input_seq::empty_seq;
 
1743
 
 
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);
 
1747
 
 
1748
        // otherwise, return the sequence as-is
 
1749
        return m_seq[seqtype];
 
1750
}
 
1751
 
 
1752
 
 
1753
//-------------------------------------------------
 
1754
//  type_class - return the type class for this
 
1755
//  field
 
1756
//-------------------------------------------------
 
1757
 
 
1758
ioport_type_class ioport_field::type_class() const
 
1759
{
 
1760
        ioport_type_class result;
 
1761
 
 
1762
        switch (m_type)
 
1763
        {
 
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:
 
1776
                case IPT_BUTTON1:
 
1777
                case IPT_BUTTON2:
 
1778
                case IPT_BUTTON3:
 
1779
                case IPT_BUTTON4:
 
1780
                case IPT_BUTTON5:
 
1781
                case IPT_BUTTON6:
 
1782
                case IPT_BUTTON7:
 
1783
                case IPT_BUTTON8:
 
1784
                case IPT_BUTTON9:
 
1785
                case IPT_BUTTON10:
 
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:
 
1793
                case IPT_MOUSE_X:
 
1794
                case IPT_MOUSE_Y:
 
1795
                case IPT_START:
 
1796
                case IPT_SELECT:
 
1797
                        result = INPUT_CLASS_CONTROLLER;
 
1798
                        break;
 
1799
 
 
1800
                case IPT_KEYPAD:
 
1801
                case IPT_KEYBOARD:
 
1802
                        result = INPUT_CLASS_KEYBOARD;
 
1803
                        break;
 
1804
 
 
1805
                case IPT_CONFIG:
 
1806
                        result = INPUT_CLASS_CONFIG;
 
1807
                        break;
 
1808
 
 
1809
                case IPT_DIPSWITCH:
 
1810
                        result = INPUT_CLASS_DIPSWITCH;
 
1811
                        break;
 
1812
 
 
1813
                case 0:
 
1814
                        if (m_name != NULL && m_name != (const char *)-1)
 
1815
                                result = INPUT_CLASS_MISC;
 
1816
                        else
 
1817
                                result = INPUT_CLASS_INTERNAL;
 
1818
                        break;
 
1819
 
 
1820
                default:
 
1821
                        result = INPUT_CLASS_INTERNAL;
 
1822
                        break;
 
1823
        }
 
1824
        return result;
 
1825
}
 
1826
 
 
1827
 
 
1828
//-------------------------------------------------
 
1829
//  keyboard_code - accesses a particular keyboard
 
1830
//  code
 
1831
//-------------------------------------------------
 
1832
 
 
1833
unicode_char ioport_field::keyboard_code(int which) const
 
1834
{
 
1835
        unicode_char ch;
 
1836
 
 
1837
        if (which >= ARRAY_LENGTH(m_chars))
 
1838
                throw emu_fatalerror("Tried to access keyboard_code with out-of-range index %d\n", which);
 
1839
 
 
1840
        ch = m_chars[which];
 
1841
 
 
1842
        // special hack to allow for PORT_CODE('\xA3')
 
1843
        if (ch >= 0xffffff80 && ch <= 0xffffffff)
 
1844
                ch &= 0xff;
 
1845
        return ch;
 
1846
}
 
1847
 
 
1848
 
 
1849
//-------------------------------------------------
 
1850
//  get_user_settings - return the current
 
1851
//  settings for the given input field
 
1852
//-------------------------------------------------
 
1853
 
 
1854
void ioport_field::get_user_settings(user_settings &settings)
 
1855
{
 
1856
        // zap the entire structure
 
1857
        memset(&settings, 0, sizeof(settings));
 
1858
 
 
1859
        // copy the basics
 
1860
        for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
 
1861
                settings.seq[seqtype] = seq(seqtype);
 
1862
 
 
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;
 
1866
 
 
1867
        // if there's analog data, extract the analog settings
 
1868
        if (m_live->analog != NULL)
 
1869
        {
 
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();
 
1874
        }
 
1875
}
 
1876
 
 
1877
 
 
1878
//-------------------------------------------------
 
1879
//  set_user_settings - modify the current
 
1880
//  settings for the given input field
 
1881
//-------------------------------------------------
 
1882
 
 
1883
void ioport_field::set_user_settings(const user_settings &settings)
 
1884
{
 
1885
        // copy the basics
 
1886
        for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
 
1887
        {
 
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();
 
1891
                else
 
1892
                        m_live->seq[seqtype] = settings.seq[seqtype];
 
1893
        }
 
1894
 
 
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;
 
1898
 
 
1899
        // if there's analog data, extract the analog settings
 
1900
        if (m_live->analog != NULL)
 
1901
        {
 
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;
 
1906
        }
 
1907
}
 
1908
 
 
1909
 
 
1910
//-------------------------------------------------
 
1911
//  setting_name - return the expanded setting
 
1912
//  name for a field
 
1913
//-------------------------------------------------
 
1914
 
 
1915
const char *ioport_field::setting_name() const
 
1916
{
 
1917
        // only makes sense if we have settings
 
1918
        assert(first_setting() != NULL);
 
1919
 
 
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();
1118
1925
 
1119
1926
        return "INVALID";
1120
1927
}
1121
1928
 
1122
1929
 
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
//-------------------------------------------------
1127
1934
 
1128
 
int input_field_has_previous_setting(const input_field_config *field)
 
1935
bool ioport_field::has_previous_setting() const
1129
1936
{
1130
 
        const input_setting_config *setting;
1131
 
 
1132
 
        /* only makes sense if we have settings */
1133
 
        assert(field->settinglist().count() != 0);
1134
 
 
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);
1139
 
 
1140
 
        return FALSE;
 
1937
        // only makes sense if we have settings
 
1938
        assert(first_setting() != NULL);
 
1939
 
 
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);
 
1944
 
 
1945
        return false;
1141
1946
}
1142
1947
 
1143
1948
 
1144
 
/*-------------------------------------------------
1145
 
    input_field_select_previous_setting - select
1146
 
    the previous item for a DIP switch or
1147
 
    configuration field
1148
 
-------------------------------------------------*/
 
1949
//-------------------------------------------------
 
1950
//  select_previous_setting - select the previous
 
1951
//  item for a DIP switch or configuration field
 
1952
//-------------------------------------------------
1149
1953
 
1150
 
void input_field_select_previous_setting(const input_field_config *field)
 
1954
void ioport_field::select_previous_setting()
1151
1955
{
1152
 
        const input_setting_config *setting, *prevsetting;
1153
 
        int found_match = FALSE;
1154
 
 
1155
 
        /* only makes sense if we have settings */
1156
 
        assert(field->settinglist().count() != 0);
1157
 
 
1158
 
        /* scan the list of settings looking for a match on the current value */
1159
 
        prevsetting = NULL;
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);
 
1958
 
 
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())
1162
1964
                {
1163
 
                        if (setting->value == field->state->value)
 
1965
                        if (setting->value() == m_live->value)
1164
1966
                        {
1165
 
                                found_match = TRUE;
 
1967
                                found_match = true;
1166
1968
                                if (prevsetting != NULL)
1167
1969
                                        break;
1168
1970
                        }
1169
1971
                        prevsetting = setting;
1170
1972
                }
1171
1973
 
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)
1174
1976
        {
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())
1177
1979
                                break;
1178
1980
        }
1179
1981
 
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();
1183
1985
}
1184
1986
 
1185
1987
 
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
//-------------------------------------------------
1190
1992
 
1191
 
int input_field_has_next_setting(const input_field_config *field)
 
1993
bool ioport_field::has_next_setting() const
1192
1994
{
1193
 
        const input_setting_config *setting;
1194
 
        int found = FALSE;
1195
 
 
1196
 
        /* only makes sense if we have settings */
1197
 
        assert(field->settinglist().count() != 0);
1198
 
 
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);
 
1997
 
 
1998
        // scan the list of settings looking for a match on the current value
 
1999
        bool found = false;
 
2000
        for (ioport_setting *setting = first_setting(); setting != NULL; setting = setting->next())
 
2001
                if (setting->enabled())
1202
2002
                {
1203
2003
                        if (found)
1204
 
                                return TRUE;
1205
 
                        if (setting->value == field->state->value)
1206
 
                                found = TRUE;
 
2004
                                return true;
 
2005
                        if (setting->value() == m_live->value)
 
2006
                                found = true;
1207
2007
                }
1208
2008
 
1209
 
        return FALSE;
 
2009
        return false;
1210
2010
}
1211
2011
 
1212
2012
 
1213
 
/*-------------------------------------------------
1214
 
    input_field_select_next_setting - select the
1215
 
    next item for a DIP switch or
1216
 
    configuration field
1217
 
-------------------------------------------------*/
 
2013
//-------------------------------------------------
 
2014
//  select_next_setting - select the next item for
 
2015
//  a DIP switch or configuration field
 
2016
//-------------------------------------------------
1218
2017
 
1219
 
void input_field_select_next_setting(const input_field_config *field)
 
2018
void ioport_field::select_next_setting()
1220
2019
{
1221
 
        const input_setting_config *setting, *nextsetting;
1222
 
 
1223
 
        /* only makes sense if we have settings */
1224
 
        assert(field->settinglist().count() != 0);
1225
 
 
1226
 
        /* scan the list of settings looking for a match on the current value */
1227
 
        nextsetting = NULL;
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);
 
2022
 
 
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)
1231
2029
                                break;
1232
2030
 
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())
1237
2035
                                break;
1238
2036
 
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())
1243
2041
                                break;
1244
2042
 
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;
1248
 
}
1249
 
 
1250
 
 
1251
 
 
1252
 
/***************************************************************************
1253
 
    ACCESSORS FOR INPUT TYPES
1254
 
***************************************************************************/
1255
 
 
1256
 
/*-------------------------------------------------
1257
 
    input_type_is_analog - return TRUE if
1258
 
    the given type represents an analog control
1259
 
-------------------------------------------------*/
1260
 
 
1261
 
int input_type_is_analog(int type)
1262
 
{
1263
 
        return (type >= __ipt_analog_start && type <= __ipt_analog_end);
1264
 
}
1265
 
 
1266
 
 
1267
 
/*-------------------------------------------------
1268
 
    input_type_name - return the name
1269
 
    for the given type/player
1270
 
-------------------------------------------------*/
1271
 
 
1272
 
const char *input_type_name(running_machine &machine, int type, int player)
1273
 
{
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];
1277
 
        if (entry != NULL)
1278
 
                return entry->name;
1279
 
 
1280
 
        /* if we find nothing, return an invalid group */
1281
 
        return "???";
1282
 
}
1283
 
 
1284
 
 
1285
 
/*-------------------------------------------------
1286
 
    input_type_group - return the group
1287
 
    for the given type/player
1288
 
-------------------------------------------------*/
1289
 
 
1290
 
int input_type_group(running_machine &machine, int type, int player)
1291
 
{
1292
 
        input_port_private *portdata = machine.input_port_data;
1293
 
        input_type_entry *entry = portdata->type_to_entry[type][player];
1294
 
        if (entry != NULL)
1295
 
                return entry->group;
1296
 
 
1297
 
        /* if we find nothing, return an invalid group */
1298
 
        return IPG_INVALID;
1299
 
}
1300
 
 
1301
 
 
1302
 
/*-------------------------------------------------
1303
 
    input_type_seq - return the input
1304
 
    sequence for the given type/player
1305
 
-------------------------------------------------*/
1306
 
 
1307
 
const input_seq &input_type_seq(running_machine &machine, int type, int player, input_seq_type seqtype)
1308
 
{
1309
 
        assert(type >= 0 && type < __ipt_max);
1310
 
        assert(player >= 0 && player < MAX_PLAYERS);
1311
 
 
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];
1315
 
        if (entry != NULL)
1316
 
                return entry->seq[seqtype];
1317
 
 
1318
 
        /* if we find nothing, return an empty sequence */
1319
 
        return input_seq::empty_seq;
1320
 
}
1321
 
 
1322
 
 
1323
 
/*-------------------------------------------------
1324
 
    input_type_set_seq - change the input
1325
 
    sequence for the given type/player
1326
 
-------------------------------------------------*/
1327
 
 
1328
 
void input_type_set_seq(running_machine &machine, int type, int player, input_seq_type seqtype, const input_seq *newseq)
1329
 
{
1330
 
        input_port_private *portdata = machine.input_port_data;
1331
 
        input_type_entry *entry = portdata->type_to_entry[type][player];
1332
 
        if (entry != NULL)
1333
 
                entry->seq[seqtype] = *newseq;
1334
 
}
1335
 
 
1336
 
 
1337
 
/*-------------------------------------------------
1338
 
    input_type_pressed - return TRUE if
1339
 
    the sequence for the given input type/player
1340
 
    is pressed
1341
 
-------------------------------------------------*/
1342
 
 
1343
 
int input_type_pressed(running_machine &machine, int type, int player)
1344
 
{
1345
 
        return machine.input().seq_pressed(input_type_seq(machine, type, player, SEQ_TYPE_STANDARD));
1346
 
}
1347
 
 
1348
 
 
1349
 
/*-------------------------------------------------
1350
 
    input_type_list - return the list of types
1351
 
-------------------------------------------------*/
1352
 
 
1353
 
const simple_list<input_type_entry> &input_type_list(running_machine &machine)
1354
 
{
1355
 
        input_port_private *portdata = machine.input_port_data;
1356
 
        return portdata->typelist;
1357
 
}
1358
 
 
1359
 
 
1360
 
 
1361
 
/***************************************************************************
1362
 
    PORT CHECKING
1363
 
***************************************************************************/
1364
 
 
1365
 
 
1366
 
/*-------------------------------------------------
1367
 
    input_port_exists - return whether an input
1368
 
    port exists
1369
 
-------------------------------------------------*/
1370
 
 
1371
 
bool input_port_exists(running_machine &machine, const char *tag)
1372
 
{
1373
 
        return machine.port(tag) != 0;
1374
 
}
1375
 
 
1376
 
 
1377
 
/*-------------------------------------------------
1378
 
    input_port_active - return a bitmask of which
1379
 
    bits of an input port are active (i.e. not
1380
 
    unused or unknown)
1381
 
-------------------------------------------------*/
1382
 
 
1383
 
input_port_value input_port_active(running_machine &machine, const char *tag)
1384
 
{
1385
 
        const input_port_config *port = machine.port(tag);
1386
 
        if (port == NULL)
1387
 
                fatalerror("Unable to locate input port '%s'", tag);
1388
 
        return port->active;
1389
 
}
1390
 
 
1391
 
 
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
 
-------------------------------------------------*/
1398
 
 
1399
 
input_port_value input_port_active_safe(running_machine &machine, const char *tag, input_port_value defvalue)
1400
 
{
1401
 
        const input_port_config *port = machine.port(tag);
1402
 
        return port == NULL ? defvalue : port->active;
1403
 
}
1404
 
 
1405
 
 
1406
 
 
1407
 
/***************************************************************************
1408
 
    PORT READING
1409
 
***************************************************************************/
1410
 
 
1411
 
/*-------------------------------------------------
1412
 
    input_port_read_direct - return the value of
1413
 
    an input port
1414
 
-------------------------------------------------*/
1415
 
 
1416
 
input_port_value input_port_read_direct(const input_port_config *port)
1417
 
{
1418
 
        assert(port != NULL);
1419
 
 
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;
1424
 
 
1425
 
        assert_always(portdata->safe_to_read, "Input ports cannot be read at init time!");
1426
 
 
1427
 
        /* start with the digital */
1428
 
        result = port->state->digital;
1429
 
 
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()))
1433
 
                {
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);
1438
 
                }
1439
 
 
1440
 
        /* update VBLANK bits */
1441
 
        if (port->state->vblank != 0)
1442
 
        {
1443
 
                if (port->machine().primary_screen->vblank())
1444
 
                        result |= port->state->vblank;
1445
 
                else
1446
 
                        result &= ~port->state->vblank;
1447
 
        }
1448
 
 
1449
 
        /* apply active high/low state to digital, read, and VBLANK inputs */
1450
 
        result ^= port->state->defvalue;
1451
 
 
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()))
1455
 
                {
1456
 
                        /* start with the raw value */
1457
 
                        INT32 value = analog->accum;
1458
 
 
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)
1461
 
                        {
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);
1464
 
                        }
1465
 
 
1466
 
                        /* apply standard analog settings */
1467
 
                        value = apply_analog_settings(value, analog);
1468
 
 
1469
 
                        /* remap the value if needed */
1470
 
                        if (analog->field->remap_table != NULL)
1471
 
                                value = analog->field->remap_table[value];
1472
 
 
1473
 
                        /* invert bits if needed */
1474
 
                        if (analog->field->flags & ANALOG_FLAG_INVERT)
1475
 
                                value = ~value;
1476
 
 
1477
 
                        /* insert into the port */
1478
 
                        result = (result & ~analog->field->mask) | ((value << analog->shift) & analog->field->mask);
1479
 
                }
1480
 
 
1481
 
        return result;
1482
 
}
1483
 
 
1484
 
 
1485
 
/*-------------------------------------------------
1486
 
    input_port_read - return the value of
1487
 
    an input port specified by tag
1488
 
-------------------------------------------------*/
1489
 
 
1490
 
input_port_value input_port_read(running_machine &machine, const char *tag)
1491
 
{
1492
 
        const input_port_config *port = machine.port(tag);
1493
 
        if (port == NULL)
1494
 
                fatalerror("Unable to locate input port '%s'", tag);
1495
 
        return input_port_read_direct(port);
1496
 
}
1497
 
 
1498
 
 
1499
 
/*-------------------------------------------------
1500
 
    input_port_read - return the value of
1501
 
    a device input port specified by tag
1502
 
-------------------------------------------------*/
1503
 
 
1504
 
input_port_value input_port_read(device_t &device, const char *tag)
1505
 
{
1506
 
        astring fullpath;
1507
 
        const input_port_config *port = device.machine().port(device.subtag(fullpath, tag));
1508
 
        if (port == NULL)
1509
 
                fatalerror("Unable to locate input port '%s'", tag);
1510
 
        return input_port_read_direct(port);
1511
 
}
1512
 
 
1513
 
 
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
 
-------------------------------------------------*/
1519
 
 
1520
 
input_port_value input_port_read_safe(running_machine &machine, const char *tag, UINT32 defvalue)
1521
 
{
1522
 
        const input_port_config *port = machine.port(tag);
1523
 
        return (port == NULL) ? defvalue : input_port_read_direct(port);
1524
 
}
1525
 
 
1526
 
 
1527
 
/*-------------------------------------------------
1528
 
    input_port_read_crosshair - return the
1529
 
    extracted crosshair values for the given
1530
 
    player
1531
 
-------------------------------------------------*/
1532
 
 
1533
 
int input_port_get_crosshair_position(running_machine &machine, int player, float *x, float *y)
1534
 
{
1535
 
        const input_port_config *port;
1536
 
        const input_field_config *field;
1537
 
        int gotx = FALSE, goty = FALSE;
1538
 
 
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()))
1544
 
                                {
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);
1548
 
 
1549
 
                                        /* apply the scale and offset */
1550
 
                                        if (field->crossscale < 0)
1551
 
                                                value = -(1.0 - value) * field->crossscale;
1552
 
                                        else
1553
 
                                                value *= field->crossscale;
1554
 
                                        value += field->crossoffset;
1555
 
 
1556
 
                                        /* apply custom mapping if necessary */
1557
 
                                        if (!field->crossmapper.isnull())
1558
 
                                                value = field->crossmapper(*field, value);
1559
 
 
1560
 
                                        /* handle X axis */
1561
 
                                        if (field->crossaxis == CROSSHAIR_AXIS_X)
1562
 
                                        {
1563
 
                                                *x = value;
1564
 
                                                gotx = TRUE;
1565
 
                                                if (field->crossaltaxis != 0)
1566
 
                                                {
1567
 
                                                        *y = field->crossaltaxis;
1568
 
                                                        goty = TRUE;
1569
 
                                                }
1570
 
                                        }
1571
 
 
1572
 
                                        /* handle Y axis */
1573
 
                                        else
1574
 
                                        {
1575
 
                                                *y = value;
1576
 
                                                goty = TRUE;
1577
 
                                                if (field->crossaltaxis != 0)
1578
 
                                                {
1579
 
                                                        *x = field->crossaltaxis;
1580
 
                                                        gotx = TRUE;
1581
 
                                                }
1582
 
                                        }
1583
 
 
1584
 
                                        /* if we got both, stop */
1585
 
                                        if (gotx && goty)
1586
 
                                                break;
1587
 
                                }
1588
 
 
1589
 
        return (gotx && goty);
1590
 
}
1591
 
 
1592
 
 
1593
 
/*-------------------------------------------------
1594
 
    input_port_update_defaults - force an update
1595
 
    to the input port values based on current
1596
 
    conditions
1597
 
-------------------------------------------------*/
1598
 
 
1599
 
void input_port_update_defaults(running_machine &machine)
1600
 
{
1601
 
        int loopnum;
1602
 
 
1603
 
        /* two passes to catch conditionals properly */
1604
 
        for (loopnum = 0; loopnum < 2; loopnum++)
1605
 
        {
1606
 
                const input_port_config *port;
1607
 
 
1608
 
                /* loop over all input ports */
1609
 
                for (port = machine.m_portlist.first(); port != NULL; port = port->next())
1610
 
                {
1611
 
                        const input_field_config *field;
1612
 
 
1613
 
                        /* only clear on the first pass */
1614
 
                        if (loopnum == 0)
1615
 
                                port->state->defvalue = 0;
1616
 
 
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);
1621
 
                }
1622
 
        }
1623
 
}
1624
 
 
1625
 
 
1626
 
/*-------------------------------------------------
1627
 
    apply_analog_settings - return the value of
1628
 
    an input port
1629
 
-------------------------------------------------*/
1630
 
 
1631
 
static INT32 apply_analog_settings(INT32 value, analog_field_state *analog)
1632
 
{
1633
 
        /* apply the min/max and then the sensitivity */
1634
 
        value = apply_analog_min_max(analog, value);
1635
 
        value = APPLY_SENSITIVITY(value, analog->sensitivity);
1636
 
 
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;
1644
 
 
1645
 
        /* map differently for positive and negative values */
1646
 
        if (value >= 0)
1647
 
                value = APPLY_SCALE(value, analog->scalepos);
1648
 
        else
1649
 
                value = APPLY_SCALE(value, analog->scaleneg);
1650
 
        value += analog->adjdefvalue;
1651
 
 
1652
 
        return value;
1653
 
}
1654
 
 
1655
 
 
1656
 
/***************************************************************************
1657
 
    PORT WRITING
1658
 
***************************************************************************/
1659
 
 
1660
 
/*-------------------------------------------------
1661
 
    input_port_write_direct - write a value
1662
 
    to a port
1663
 
-------------------------------------------------*/
1664
 
 
1665
 
void input_port_write_direct(const input_port_config *port, input_port_value data, input_port_value mem_mask)
1666
 
{
1667
 
        /* call device line write handlers */
1668
 
        device_field_info *device_field;
1669
 
 
1670
 
        COMBINE_DATA(&port->state->outputvalue);
1671
 
 
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()))
1674
 
                {
1675
 
                        input_port_value newval = ( (port->state->outputvalue ^ device_field->field->defvalue ) & device_field->field->mask) >> device_field->shift;
1676
 
 
1677
 
                        /* if the bits have write, call the handler */
1678
 
                        if (device_field->oldval != newval)
1679
 
                        {
1680
 
                                device_field->field->write(*device_field->field, device_field->field->write_param, device_field->oldval, newval);
1681
 
 
1682
 
                                device_field->oldval = newval;
1683
 
                        }
1684
 
                }
1685
 
}
1686
 
 
1687
 
 
1688
 
/*-------------------------------------------------
1689
 
    input_port_write - write a value to a
1690
 
    port specified by tag
1691
 
-------------------------------------------------*/
1692
 
 
1693
 
void input_port_write(running_machine &machine, const char *tag, input_port_value value, input_port_value mask)
1694
 
{
1695
 
        const input_port_config *port = machine.port(tag);
1696
 
        if (port == NULL)
1697
 
                fatalerror("Unable to locate input port '%s'", tag);
1698
 
        input_port_write_direct(port, value, mask);
1699
 
}
1700
 
 
1701
 
 
1702
 
/*-------------------------------------------------
1703
 
    input_port_write_safe - write a value to
1704
 
    a port, ignore if the port does not exist
1705
 
-------------------------------------------------*/
1706
 
 
1707
 
void input_port_write_safe(running_machine &machine, const char *tag, input_port_value value, input_port_value mask)
1708
 
{
1709
 
        const input_port_config *port = machine.port(tag);
1710
 
        if (port != NULL)
1711
 
                input_port_write_direct(port, value, mask);
1712
 
}
1713
 
 
1714
 
 
1715
 
 
1716
 
/***************************************************************************
1717
 
    MISC HELPER FUNCTIONS
1718
 
***************************************************************************/
1719
 
 
1720
 
/*-------------------------------------------------
1721
 
    input_condition_true - return the TRUE
1722
 
    if the given condition attached is true
1723
 
-------------------------------------------------*/
1724
 
 
1725
 
int input_condition_true(running_machine &machine, const input_condition *condition, device_t &owner)
1726
 
{
1727
 
        input_port_value condvalue;
1728
 
 
1729
 
        /* always condition is always true */
1730
 
        if (condition->condition == PORTCOND_ALWAYS)
1731
 
                return TRUE;
1732
 
 
1733
 
        /* otherwise, read the referenced port */
1734
 
        astring conditiontag;
1735
 
        owner.subtag(conditiontag, condition->tag);
1736
 
        condvalue = input_port_read(machine, conditiontag.cstr());
1737
 
 
1738
 
        /* based on the condition encoded, determine truth */
1739
 
        switch (condition->condition)
1740
 
        {
1741
 
                case PORTCOND_EQUALS:
1742
 
                        return ((condvalue & condition->mask) == condition->value);
1743
 
 
1744
 
                case PORTCOND_NOTEQUALS:
1745
 
                        return ((condvalue & condition->mask) != condition->value);
1746
 
 
1747
 
                case PORTCOND_GREATERTHAN:
1748
 
                        return ((condvalue & condition->mask) > condition->value);
1749
 
 
1750
 
                case PORTCOND_NOTGREATERTHAN:
1751
 
                        return ((condvalue & condition->mask) <= condition->value);
1752
 
 
1753
 
                case PORTCOND_LESSTHAN:
1754
 
                        return ((condvalue & condition->mask) < condition->value);
1755
 
 
1756
 
                case PORTCOND_NOTLESSTHAN:
1757
 
                        return ((condvalue & condition->mask) >= condition->value);
1758
 
        }
1759
 
        return TRUE;
1760
 
}
1761
 
 
1762
 
 
1763
 
/*-------------------------------------------------
1764
 
    input_port_string_from_token - convert an
1765
 
    input_port_token to a default string
1766
 
-------------------------------------------------*/
1767
 
 
1768
 
const char *input_port_string_from_token(const char *string)
1769
 
{
1770
 
        /* 0 is an invalid index */
1771
 
        if (string == NULL)
1772
 
                return NULL;
1773
 
 
1774
 
        /* if the index is greater than the count, assume it to be a pointer */
1775
 
        if (FPTR(string) >= INPUT_STRING_COUNT)
1776
 
                return string;
1777
 
 
1778
 
#if FALSE // Set TRUE, If you want to take care missing-token or wrong-sorting
1779
 
 
1780
 
        /* otherwise, scan the list for a matching string and return it */
1781
 
        {
1782
 
        int index;
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;
1786
 
        }
1787
 
        return "(Unknown Default)";
1788
 
 
1789
 
#else
1790
 
 
1791
 
        return input_port_default_strings[FPTR(string)-1].string;
1792
 
 
1793
 
#endif
1794
 
}
1795
 
 
1796
 
 
1797
 
 
1798
 
/***************************************************************************
1799
 
    INITIALIZATION HELPERS
1800
 
***************************************************************************/
1801
 
 
1802
 
/*-------------------------------------------------
1803
 
    init_port_types - initialize the default
1804
 
    type list
1805
 
-------------------------------------------------*/
1806
 
 
1807
 
static void init_port_types(running_machine &machine)
1808
 
{
1809
 
        input_port_private *portdata = machine.input_port_data;
1810
 
 
1811
 
        /* convert the array into a list of type states that can be modified */
1812
 
        construct_core_types(portdata->typelist);
1813
 
 
1814
 
        /* ask the OSD to customize the list */
1815
 
        machine.osd().customize_input_type_list(portdata->typelist);
1816
 
 
1817
 
        /* now iterate over the OSD-modified types */
1818
 
        for (input_type_entry *curtype = portdata->typelist.first(); curtype != NULL; curtype = curtype->next())
1819
 
        {
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];
1823
 
 
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;
1826
 
        }
1827
 
}
1828
 
 
1829
 
 
1830
 
/*-------------------------------------------------
1831
 
    get_keyboard_code - accesses a particular
1832
 
    keyboard code
1833
 
-------------------------------------------------*/
1834
 
 
1835
 
static unicode_char get_keyboard_code(const input_field_config *field, int i)
1836
 
{
1837
 
        unicode_char ch = field->chars[i];
1838
 
 
1839
 
        /* special hack to allow for PORT_CODE('\xA3') */
1840
 
        if ((ch >= 0xFFFFFF80) && (ch <= 0xFFFFFFFF))
1841
 
                ch &= 0xFF;
1842
 
        return ch;
1843
 
}
1844
 
 
1845
 
 
1846
 
/***************************************************************************
1847
 
    MISCELLANEOUS
1848
 
***************************************************************************/
1849
 
 
1850
 
/*-------------------------------------------------
1851
 
    find_charinfo - looks up information about a
1852
 
    particular character
1853
 
-------------------------------------------------*/
1854
 
 
1855
 
static const char_info *find_charinfo(unicode_char target_char)
1856
 
{
1857
 
        int low = 0;
1858
 
        int high = ARRAY_LENGTH(charinfo);
1859
 
        int i;
1860
 
        unicode_char ch;
1861
 
 
1862
 
        /* perform a simple binary search to find the proper alternate */
1863
 
        while(high > low)
1864
 
        {
1865
 
                i = (high + low) / 2;
1866
 
                ch = charinfo[i].ch;
1867
 
                if (ch < target_char)
1868
 
                        low = i + 1;
1869
 
                else if (ch > target_char)
1870
 
                        high = i;
1871
 
                else
1872
 
                        return &charinfo[i];
1873
 
        }
1874
 
        return NULL;
1875
 
}
1876
 
 
1877
 
/*-------------------------------------------------
1878
 
    inputx_key_name - returns the name of a
1879
 
    specific key
1880
 
-------------------------------------------------*/
1881
 
 
1882
 
static const char *inputx_key_name(unicode_char ch)
1883
 
{
1884
 
        static char buf[UTF8_CHAR_MAX + 1];
1885
 
        const char_info *ci;
1886
 
        const char *result;
1887
 
        int pos;
1888
 
 
1889
 
        ci = find_charinfo(ch);
1890
 
        result = ci ? ci->name : NULL;
1891
 
 
1892
 
        if (ci && ci->name)
1893
 
        {
1894
 
                result = ci->name;
1895
 
        }
1896
 
        else
1897
 
        {
1898
 
                if ((ch > 0x7F) || isprint(ch))
1899
 
                {
1900
 
                        pos = utf8_from_uchar(buf, ARRAY_LENGTH(buf), ch);
1901
 
                        buf[pos] = '\0';
1902
 
                        result = buf;
1903
 
                }
1904
 
                else
1905
 
                        result = "???";
1906
 
        }
1907
 
        return result;
1908
 
}
1909
 
 
1910
 
/*-------------------------------------------------
1911
 
    get_keyboard_key_name - builds the name of
1912
 
    a key based on natural keyboard characters
1913
 
-------------------------------------------------*/
1914
 
 
1915
 
static astring &get_keyboard_key_name(astring &name, const input_field_config *field)
1916
 
{
1917
 
        int i;
1918
 
        unicode_char ch;
1919
 
 
1920
 
        name.reset();
1921
 
        /* loop through each character on the field*/
1922
 
        for (i = 0; i < ARRAY_LENGTH(field->chars) && (field->chars[i] != '\0'); i++)
1923
 
        {
1924
 
                ch = get_keyboard_code(field, i);
1925
 
                name.catprintf("%-*s ", MAX(SPACE_COUNT - 1, 0), inputx_key_name(ch));
1926
 
        }
1927
 
 
1928
 
        /* trim extra spaces */
1929
 
        name.trimspace();
1930
 
 
1931
 
        /* special case */
1932
 
        if (name.len() == 0)
1933
 
                name.cpy("Unnamed Key");
1934
 
 
1935
 
        return name;
1936
 
}
1937
 
 
1938
 
/*-------------------------------------------------
1939
 
    init_port_state - initialize the live port
1940
 
    states based on the tokens
1941
 
-------------------------------------------------*/
1942
 
 
1943
 
static void init_port_state(running_machine &machine)
1944
 
{
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;
1949
 
 
1950
 
        /* allocate live structures to mirror the configuration */
1951
 
        for (port = machine.m_portlist.first(); port != NULL; port = port->next())
1952
 
        {
1953
 
                analog_field_state **analogstatetail;
1954
 
                device_field_info **readdevicetail;
1955
 
                device_field_info **writedevicetail;
1956
 
                input_port_state *portstate;
1957
 
 
1958
 
                /* allocate a new input_port_info structure */
1959
 
                portstate = auto_alloc_clear(machine, input_port_state);
1960
 
                ((input_port_config *)port)->state = portstate;
1961
 
 
1962
 
                /* start with tail pointers to all the data */
1963
 
                analogstatetail = &portstate->analoglist;
1964
 
                readdevicetail = &portstate->readdevicelist;
1965
 
                writedevicetail = &portstate->writedevicelist;
1966
 
 
1967
 
                /* iterate over fields */
1968
 
                for (field = port->first_field(); field != NULL; field = field->next())
1969
 
                {
1970
 
                        input_field_state *fieldstate;
1971
 
                        int seqtype;
1972
 
 
1973
 
                        /* allocate a new input_field_info structure */
1974
 
                        fieldstate = auto_alloc_clear(machine, input_field_state);
1975
 
                        ((input_field_config *)field)->state = fieldstate;
1976
 
 
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;
1981
 
 
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)
1984
 
                        {
1985
 
                                *analogstatetail = fieldstate->analog = init_field_analog_state(field);
1986
 
                                analogstatetail = &(*analogstatetail)->next;
1987
 
                        }
1988
 
 
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)
1991
 
                        {
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;
1996
 
                        }
1997
 
 
1998
 
                        /* if this entry has device input, allocate memory for the tracking structure */
1999
 
                        astring devicetag;
2000
 
                        if (!field->read.isnull())
2001
 
                        {
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;
2005
 
                        }
2006
 
 
2007
 
                        /* if this entry has device output, allocate memory for the tracking structure */
2008
 
                        if (!field->write.isnull())
2009
 
                        {
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;
2013
 
                        }
2014
 
 
2015
 
                        /* if this entry has device output, allocate memory for the tracking structure */
2016
 
                        if (!field->crossmapper.isnull())
2017
 
                        {
2018
 
                                device_t *device = machine.device(port->owner().subtag(devicetag, field->crossmapper_device));
2019
 
                                field->crossmapper.late_bind(*device);
2020
 
                        }
2021
 
 
2022
 
                        /* Name keyboard key names */
2023
 
                        if ((field->type == IPT_KEYBOARD || field->type == IPT_KEYPAD) && (field->name == NULL))
2024
 
                        {
2025
 
                                astring name;
2026
 
                                field->state->name = auto_strdup(machine, get_keyboard_key_name(name, field));
2027
 
                        }
2028
 
                }
2029
 
        }
2030
 
 
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");
2040
 
 
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)
2046
 
                                {
2047
 
                                        machine.input().set_global_joystick_map((field->flags & FIELD_FLAG_ROTATED) ? joystick_map_4way_diagonal : joystick_map_4way_sticky);
2048
 
                                        break;
2049
 
                                }
2050
 
}
2051
 
 
2052
 
 
2053
 
/*-------------------------------------------------
2054
 
    init_autoselect_devices - autoselect a single
2055
 
    device based on the input port list passed
2056
 
    in and the corresponding option
2057
 
-------------------------------------------------*/
2058
 
 
2059
 
static void init_autoselect_devices(running_machine &machine, int type1, int type2, int type3, const char *option, const char *ananame)
2060
 
{
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;
2067
 
 
2068
 
        /* if nothing specified, ignore the option */
2069
 
        if (stemp[0] == 0)
2070
 
                return;
2071
 
 
2072
 
        /* extract valid strings */
2073
 
        if (strcmp(stemp, "mouse") == 0)
2074
 
        {
2075
 
                autoenable = DEVICE_CLASS_MOUSE;
2076
 
                autostring = "mouse";
2077
 
        }
2078
 
        else if (strcmp(stemp, "joystick") == 0)
2079
 
        {
2080
 
                autoenable = DEVICE_CLASS_JOYSTICK;
2081
 
                autostring = "joystick";
2082
 
        }
2083
 
        else if (strcmp(stemp, "lightgun") == 0)
2084
 
        {
2085
 
                autoenable = DEVICE_CLASS_LIGHTGUN;
2086
 
                autostring = "lightgun";
2087
 
        }
2088
 
        else if (strcmp(stemp, "none") == 0)
2089
 
        {
2090
 
                /* nothing specified */
2091
 
                return;
2092
 
        }
2093
 
        else if (strcmp(stemp, "keyboard") != 0)
2094
 
                mame_printf_error("Invalid %s value %s; reverting to keyboard\n", option, stemp);
2095
 
 
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())
2100
 
 
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))
2105
 
                                {
2106
 
                                        mame_printf_verbose("Input: Autoenabling %s due to presence of a %s\n", autostring, ananame);
2107
 
                                        machine.input().device_class(autoenable).enable();
2108
 
                                        break;
2109
 
                                }
2110
 
}
2111
 
 
2112
 
 
2113
 
/*-------------------------------------------------
2114
 
    init_field_device_info - allocate and populate
2115
 
    information about a device callback
2116
 
-------------------------------------------------*/
2117
 
 
2118
 
static device_field_info *init_field_device_info(const input_field_config *field, const char *device_name)
2119
 
{
2120
 
        device_field_info *info;
2121
 
        input_port_value mask;
2122
 
 
2123
 
        /* allocate memory */
2124
 
        info = auto_alloc_clear(field->machine(), device_field_info);
2125
 
 
2126
 
        /* fill in the data */
2127
 
        info->field = field;
2128
 
        for (mask = field->mask; !(mask & 1); mask >>= 1)
2129
 
                info->shift++;
2130
 
 
2131
 
        info->device = (device_name != NULL) ? field->machine().device(device_name) : &field->port().owner();
2132
 
 
2133
 
        info->oldval = field->defvalue >> info->shift;
2134
 
        return info;
2135
 
}
2136
 
 
2137
 
 
2138
 
/*-------------------------------------------------
2139
 
    init_field_analog_state - allocate and populate
2140
 
    information about an analog port
2141
 
-------------------------------------------------*/
2142
 
 
2143
 
static analog_field_state *init_field_analog_state(const input_field_config *field)
2144
 
{
2145
 
        analog_field_state *state;
2146
 
        input_port_value mask;
2147
 
 
2148
 
        /* allocate memory */
2149
 
        state = auto_alloc_clear(field->machine(), analog_field_state);
2150
 
 
2151
 
        /* compute the shift amount and number of bits */
2152
 
        for (mask = field->mask; !(mask & 1); mask >>= 1)
2153
 
                state->shift++;
2154
 
 
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;
2166
 
 
2167
 
        /* set basic parameters based on the configured type */
2168
 
        switch (field->type)
2169
 
        {
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:
2174
 
                case IPT_PADDLE:
2175
 
                case IPT_PADDLE_V:
2176
 
                        state->absolute = TRUE;
2177
 
                        state->autocenter = TRUE;
2178
 
                        state->interpolate = TRUE;
2179
 
                        break;
2180
 
 
2181
 
                /* pedals start at and autocenter to the min range */
2182
 
                case IPT_PEDAL:
2183
 
                case IPT_PEDAL2:
2184
 
                case IPT_PEDAL3:
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;
2190
 
                        break;
2191
 
 
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;
2198
 
                        break;
2199
 
 
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);
2205
 
                        state->adjmin = 0;
2206
 
                        state->adjmax = field->max - 1;
2207
 
                        state->wraps = ((field->flags & ANALOG_FLAG_WRAPS) != 0);
2208
 
                        state->autocenter = !state->wraps;
2209
 
                        break;
2210
 
 
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 */
2215
 
                case IPT_DIAL:
2216
 
                case IPT_DIAL_V:
2217
 
                case IPT_TRACKBALL_X:
2218
 
                case IPT_TRACKBALL_Y:
2219
 
                case IPT_MOUSE_X:
2220
 
                case IPT_MOUSE_Y:
2221
 
                        state->absolute = FALSE;
2222
 
                        state->wraps = TRUE;
2223
 
                        state->interpolate = TRUE;
2224
 
                        break;
2225
 
 
2226
 
                default:
2227
 
                        fatalerror("Unknown analog port type -- don't know if it is absolute or not");
2228
 
                        break;
2229
 
        }
2230
 
 
2231
 
        /* further processing for absolute controls */
2232
 
        if (state->absolute)
2233
 
        {
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);
2236
 
 
2237
 
                /* if not "single scale", compute separate scales for each side of the default */
2238
 
                if (!state->single_scale)
2239
 
                {
2240
 
                        /* unsigned */
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);
2243
 
 
2244
 
                        if (state->adjmin > state->adjmax)
2245
 
                                state->scaleneg = -state->scaleneg;
2246
 
 
2247
 
                        /* reverse point is at center */
2248
 
                        state->reverse_val = 0;
2249
 
                }
2250
 
                else
2251
 
                {
2252
 
                        /* single axis that increases from default */
2253
 
                        state->scalepos = COMPUTE_SCALE(state->adjmax - state->adjmin, INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN);
2254
 
 
2255
 
                        /* move from default */
2256
 
                        if (state->adjdefvalue == state->adjmax)
2257
 
                                state->scalepos = -state->scalepos;
2258
 
 
2259
 
                        /* make the scaling the same for easier coding when we need to scale */
2260
 
                        state->scaleneg = state->scalepos;
2261
 
 
2262
 
                        /* reverse point is at max */
2263
 
                        state->reverse_val = state->maximum;
2264
 
                }
2265
 
        }
2266
 
 
2267
 
        /* relative and positional controls all map directly with a 512x scale factor */
2268
 
        else
2269
 
        {
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;
2277
 
 
2278
 
                if (state->wraps)
2279
 
                        state->adjmax++;
2280
 
 
2281
 
                state->minimum = (state->adjmin - state->adjdefvalue) * INPUT_RELATIVE_PER_PIXEL;
2282
 
                state->maximum = (state->adjmax - state->adjdefvalue) * INPUT_RELATIVE_PER_PIXEL;
2283
 
 
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);
2286
 
 
2287
 
                if (field->flags & ANALOG_FLAG_RESET)
2288
 
                        /* delta values reverse from center */
2289
 
                        state->reverse_val = 0;
2290
 
                else
2291
 
                {
2292
 
                        /* positional controls reverse from their max range */
2293
 
                        state->reverse_val = state->maximum + state->minimum;
2294
 
 
2295
 
                        /* relative controls reverse from 1 past their max range */
2296
 
                        if (state->wraps)
2297
 
                                state->reverse_val -= INPUT_RELATIVE_PER_PIXEL;
2298
 
                }
2299
 
        }
2300
 
 
2301
 
        /* compute scale for keypresses */
2302
 
        state->keyscalepos = RECIP_SCALE(state->scalepos);
2303
 
        state->keyscaleneg = RECIP_SCALE(state->scaleneg);
2304
 
 
2305
 
        return state;
2306
 
}
2307
 
 
2308
 
 
2309
 
 
2310
 
/***************************************************************************
2311
 
    ONCE-PER-FRAME UPDATES
2312
 
***************************************************************************/
2313
 
 
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
 
-------------------------------------------------*/
2319
 
 
2320
 
static void frame_update_callback(running_machine &machine)
2321
 
{
2322
 
        /* if we're paused, don't do anything */
2323
 
        if (machine.paused())
2324
 
                return;
2325
 
 
2326
 
        /* otherwise, use the common code */
2327
 
        frame_update(machine);
2328
 
}
2329
 
 
2330
 
static key_buffer *get_buffer(running_machine &machine)
2331
 
{
2332
 
        input_port_private *portdata = machine.input_port_data;
2333
 
        assert(inputx_can_post(machine));
2334
 
        return (key_buffer *)portdata->keybuffer;
2335
 
}
2336
 
 
2337
 
 
2338
 
 
2339
 
static const inputx_code *find_code(inputx_code *codes, unicode_char ch)
2340
 
{
2341
 
        int i;
2342
 
 
2343
 
        assert(codes);
2344
 
        for (i = 0; codes[i].ch; i++)
2345
 
        {
2346
 
                if (codes[i].ch == ch)
2347
 
                        return &codes[i];
2348
 
        }
2349
 
        return NULL;
2350
 
}
2351
 
 
2352
 
/*-------------------------------------------------
2353
 
    input_port_update_hook - hook function
2354
 
    called from core to allow for natural keyboard
2355
 
-------------------------------------------------*/
2356
 
 
2357
 
static void input_port_update_hook(running_machine &machine, const input_port_config *port, input_port_value *digital)
2358
 
{
2359
 
        input_port_private *portdata = machine.input_port_data;
2360
 
        const key_buffer *keybuf;
2361
 
        const inputx_code *code;
2362
 
        unicode_char ch;
2363
 
        int i;
2364
 
        UINT32 value;
2365
 
 
2366
 
        if (inputx_can_post(machine))
2367
 
        {
2368
 
                keybuf = get_buffer(machine);
2369
 
 
2370
 
                /* is the key down right now? */
2371
 
                if (keybuf && keybuf->status_keydown && (keybuf->begin_pos != keybuf->end_pos))
2372
 
                {
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);
2376
 
 
2377
 
                        /* loop through this character's component codes */
2378
 
                        if (code != NULL)
2379
 
                        {
2380
 
                                for (i = 0; i < ARRAY_LENGTH(code->field) && (code->field[i] != NULL); i++)
2381
 
                                {
2382
 
                                        if (&code->field[i]->port() == port)
2383
 
                                        {
2384
 
                                                value = code->field[i]->mask;
2385
 
                                                *digital |= value;
2386
 
                                        }
2387
 
                                }
2388
 
                        }
2389
 
                }
2390
 
        }
2391
 
}
2392
 
 
2393
 
 
2394
 
/*-------------------------------------------------
2395
 
    frame_update - core logic for per-frame input
2396
 
    port updating
2397
 
-------------------------------------------------*/
2398
 
 
2399
 
static void frame_update(running_machine &machine)
2400
 
{
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;
2409
 
        int mouse_button;
2410
 
 
2411
 
g_profiler.start(PROFILER_INPUT);
2412
 
 
2413
 
        /* record/playback information about the current frame */
2414
 
        playback_frame(machine, curtime);
2415
 
        record_frame(machine, curtime);
2416
 
 
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;
2420
 
 
2421
 
        /* update the digital joysticks */
2422
 
        frame_update_digital_joysticks(machine);
2423
 
 
2424
 
        /* compute default values for all the ports */
2425
 
        input_port_update_defaults(machine);
2426
 
 
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)
2430
 
        {
2431
 
                const char *tag = NULL;
2432
 
                input_port_value mask;
2433
 
                float x, y;
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);
2436
 
        }
2437
 
 
2438
 
        /* loop over all input ports */
2439
 
        for (port = machine.m_portlist.first(); port != NULL; port = port->next())
2440
 
        {
2441
 
                const input_field_config *field;
2442
 
                device_field_info *device_field;
2443
 
                input_port_value newvalue;
2444
 
 
2445
 
                /* start with 0 values for the digital and VBLANK bits */
2446
 
                port->state->digital = 0;
2447
 
                port->state->vblank = 0;
2448
 
 
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()))
2452
 
                        {
2453
 
                                /* accumulate VBLANK bits */
2454
 
                                if (field->type == IPT_VBLANK)
2455
 
                                        port->state->vblank ^= field->mask;
2456
 
 
2457
 
                                /* handle analog inputs */
2458
 
                                else if (field->state->analog != NULL)
2459
 
                                        frame_update_analog_field(machine, field->state->analog);
2460
 
 
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;
2464
 
                        }
2465
 
 
2466
 
                /* hook for MESS's natural keyboard support */
2467
 
                input_port_update_hook(machine, port, &port->state->digital);
2468
 
 
2469
 
                /* handle playback/record */
2470
 
                playback_port(port);
2471
 
                record_port(port);
2472
 
 
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()))
2477
 
                        {
2478
 
                                input_port_value newval = (newvalue & device_field->field->mask) >> device_field->shift;
2479
 
 
2480
 
                                /* if the bits have  write, call the handler */
2481
 
                                if (device_field->oldval != newval)
2482
 
                                {
2483
 
                                        device_field->field->write(*device_field->field, device_field->field->write_param, device_field->oldval, newval);
2484
 
 
2485
 
                                        device_field->oldval = newval;
2486
 
                                }
2487
 
                        }
2488
 
        }
2489
 
 
2490
 
g_profiler.stop();
2491
 
}
2492
 
 
2493
 
 
2494
 
/*-------------------------------------------------
2495
 
    frame_update_digital_joysticks - update the
2496
 
    state of digital joysticks prior to
2497
 
    accumulating the results in a port
2498
 
-------------------------------------------------*/
2499
 
 
2500
 
static void frame_update_digital_joysticks(running_machine &machine)
2501
 
{
2502
 
        input_port_private *portdata = machine.input_port_data;
2503
 
        int player, joyindex;
2504
 
 
2505
 
        /* loop over all the joysticks */
2506
 
        for (player = 0; player < MAX_PLAYERS; player++)
2507
 
                for (joyindex = 0; joyindex < DIGITAL_JOYSTICKS_PER_PLAYER; joyindex++)
2508
 
                {
2509
 
                        digital_joystick_state *joystick = &portdata->joystick_info[player][joyindex];
2510
 
                        if (joystick->inuse)
2511
 
                        {
2512
 
                                joystick->previous = joystick->current;
2513
 
                                joystick->current = 0;
2514
 
 
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;
2524
 
 
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);
2530
 
 
2531
 
                                /* only update 4-way case if joystick has moved */
2532
 
                                if (joystick->current != joystick->previous)
2533
 
                                {
2534
 
                                        joystick->current4way = joystick->current;
2535
 
 
2536
 
                                        /*
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.
2540
 
 
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
2543
 
                        to "up."
2544
 
 
2545
 
                        Zero any switches that didn't change from the previous to current state.
2546
 
                     */
2547
 
                                        if ((joystick->current4way & (JOYDIR_UP_BIT | JOYDIR_DOWN_BIT)) &&
2548
 
                                                (joystick->current4way & (JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT)))
2549
 
                                        {
2550
 
                                                joystick->current4way ^= joystick->current4way & joystick->previous;
2551
 
                                        }
2552
 
 
2553
 
                                        /*
2554
 
                        If we are still pointing at a diagonal, we are in an indeterminant state.
2555
 
 
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.
2558
 
 
2559
 
                        The chances of this happening with a keyboard are slim, but we still need to
2560
 
                        constrain this case.
2561
 
 
2562
 
                        For now, just resolve randomly.
2563
 
                     */
2564
 
                                        if ((joystick->current4way & (JOYDIR_UP_BIT | JOYDIR_DOWN_BIT)) &&
2565
 
                                                (joystick->current4way & (JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT)))
2566
 
                                        {
2567
 
                                                if (machine.rand() & 1)
2568
 
                                                        joystick->current4way &= ~(JOYDIR_LEFT_BIT | JOYDIR_RIGHT_BIT);
2569
 
                                                else
2570
 
                                                        joystick->current4way &= ~(JOYDIR_UP_BIT | JOYDIR_DOWN_BIT);
2571
 
                                        }
2572
 
                                }
2573
 
                        }
2574
 
                }
2575
 
}
2576
 
 
2577
 
 
2578
 
/*-------------------------------------------------
2579
 
    frame_update_analog_field - update the
2580
 
    internals of a single analog field
2581
 
-------------------------------------------------*/
2582
 
 
2583
 
static void frame_update_analog_field(running_machine &machine, analog_field_state *analog)
2584
 
{
2585
 
        input_item_class itemclass;
2586
 
        int keypressed = FALSE;
2587
 
        INT64 keyscale;
2588
 
        INT32 rawvalue;
2589
 
        INT32 delta = 0;
2590
 
 
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);
2593
 
 
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);
2596
 
 
2597
 
        /* if we got an absolute input, it overrides everything else */
2598
 
        if (itemclass == ITEM_CLASS_ABSOLUTE)
2599
 
        {
2600
 
                if (analog->previousanalog != rawvalue)
2601
 
                {
2602
 
                        /* only update if analog value changed */
2603
 
                        analog->previousanalog = rawvalue;
2604
 
 
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))
2609
 
                        {
2610
 
                                /* if port is absolute, then just return the absolute data supplied */
2611
 
                                analog->accum = APPLY_INVERSE_SENSITIVITY(rawvalue, analog->sensitivity);
2612
 
                        }
2613
 
                        else if (analog->positionalscale != 0)
2614
 
                        {
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;
2619
 
 
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);
2623
 
                        }
2624
 
                        else
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;
2628
 
 
2629
 
                        analog->lastdigital = FALSE;
2630
 
                        /* do not bother with other control types if the analog data is changing */
2631
 
                        return;
2632
 
                }
2633
 
                else
2634
 
                {
2635
 
                        /* we still have to update fake relative from joystick control */
2636
 
                        if (!analog->absolute && analog->positionalscale == 0)
2637
 
                                analog->accum += rawvalue;
2638
 
                }
2639
 
        }
2640
 
 
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)
2644
 
        {
2645
 
                delta = rawvalue;
2646
 
                analog->lastdigital = FALSE;
2647
 
        }
2648
 
 
2649
 
        keyscale = (analog->accum >= 0) ? analog->keyscalepos : analog->keyscaleneg;
2650
 
 
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)))
2654
 
        {
2655
 
                keypressed = TRUE;
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;
2662
 
        }
2663
 
 
2664
 
        /* same for the increment code sequence */
2665
 
        if (machine.input().seq_pressed(input_field_seq(analog->field, SEQ_TYPE_INCREMENT)))
2666
 
        {
2667
 
                keypressed = TRUE;
2668
 
                if (analog->delta)
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;
2674
 
        }
2675
 
 
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)
2681
 
                analog->accum = 0;
2682
 
 
2683
 
        /* apply the delta to the accumulated value */
2684
 
        analog->accum += delta;
2685
 
 
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)
2690
 
        {
2691
 
                INT32 center = APPLY_INVERSE_SENSITIVITY(analog->center, analog->sensitivity);
2692
 
                if (analog->lastdigital && !keypressed)
2693
 
                {
2694
 
                        /* autocenter from positive values */
2695
 
                        if (analog->accum >= center)
2696
 
                        {
2697
 
                                analog->accum -= APPLY_SCALE(analog->centerdelta, analog->keyscalepos);
2698
 
                                if (analog->accum < center)
2699
 
                                {
2700
 
                                        analog->accum = center;
2701
 
                                        analog->lastdigital = FALSE;
2702
 
                                }
2703
 
                        }
2704
 
 
2705
 
                        /* autocenter from negative values */
2706
 
                        else
2707
 
                        {
2708
 
                                analog->accum += APPLY_SCALE(analog->centerdelta, analog->keyscaleneg);
2709
 
                                if (analog->accum > center)
2710
 
                                {
2711
 
                                        analog->accum = center;
2712
 
                                        analog->lastdigital = FALSE;
2713
 
                                }
2714
 
                        }
2715
 
                }
2716
 
        }
2717
 
        else if (!keypressed)
2718
 
                analog->lastdigital = FALSE;
2719
 
}
2720
 
 
2721
 
 
2722
 
/*-------------------------------------------------
2723
 
    frame_get_digital_field_state - get the state
2724
 
    of a digital field
2725
 
-------------------------------------------------*/
2726
 
 
2727
 
static int frame_get_digital_field_state(const input_field_config *field, int mouse_down)
2728
 
{
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;
2732
 
 
2733
 
        /* if the state changed, look for switch down/switch up */
2734
 
        if (curstate != field->state->last)
2735
 
        {
2736
 
                field->state->last = curstate;
2737
 
                changed = TRUE;
2738
 
        }
2739
 
 
2740
 
        if (field->type == IPT_KEYBOARD && ui_get_use_natural_keyboard(field->machine()))
2741
 
                return FALSE;
2742
 
 
2743
 
        /* coin impulse option */
2744
 
        {
2745
 
                int temp_option_impulse = field->machine().options().coin_impulse();
2746
 
                temp_field_impulse = field->impulse;
2747
 
                if ( temp_option_impulse != 0)
2748
 
                {
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;
2753
 
                }
2754
 
        }
2755
 
 
2756
 
        /* if this is a switch-down event, handle impulse and toggle */
 
2045
                m_live->value = nextsetting->value();
 
2046
}
 
2047
 
 
2048
 
 
2049
//-------------------------------------------------
 
2050
//  frame_update_digital - get the state of a
 
2051
//  digital field
 
2052
//-------------------------------------------------
 
2053
 
 
2054
void ioport_field::frame_update(ioport_value &result, bool mouse_down)
 
2055
{
 
2056
        // skip if not enabled
 
2057
        if (!enabled())
 
2058
                return;
 
2059
 
 
2060
        // handle analog inputs first
 
2061
        if (m_live->analog != NULL)
 
2062
        {
 
2063
                m_live->analog->frame_update(machine());
 
2064
                return;
 
2065
        }
 
2066
 
 
2067
        // if UI is active, ignore digital inputs
 
2068
        if (ui_is_menu_active())
 
2069
                return;
 
2070
 
 
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)
 
2075
        {
 
2076
                m_live->last = curstate;
 
2077
                changed = true;
 
2078
        }
 
2079
 
 
2080
        // if we're a keyboard type and using natural keyboard, bail
 
2081
        if (m_type == IPT_KEYBOARD && ui_get_use_natural_keyboard(machine()))
 
2082
                return;
 
2083
 
 
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)
 
2088
        {
 
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;
 
2093
        }
 
2094
 
 
2095
        // if this is a switch-down event, handle impulse and toggle
2757
2096
        if (changed && curstate)
2758
2097
        {
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;
2762
2101
 
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
 
2103
                if (toggle())
2765
2104
                {
2766
 
                        if (field->settinglist().count() == 0)
2767
 
                                field->state->value ^= field->mask;
 
2105
                        if (m_settinglist.count() == 0)
 
2106
                                m_live->value ^= m_mask;
2768
2107
                        else
2769
 
                                input_field_select_next_setting(field);
2770
 
                }
2771
 
        }
2772
 
 
2773
 
        /* update the current state with the impulse state */
2774
 
        if (temp_field_impulse != 0)
2775
 
        {
2776
 
                if (field->state->impulse != 0)
2777
 
                {
2778
 
                        field->state->impulse--;
2779
 
                        curstate = TRUE;
2780
 
                }
2781
 
                else
2782
 
                        curstate = FALSE;
2783
 
        }
2784
 
 
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)
2788
 
                curstate = FALSE;
2789
 
 
2790
 
        /* additional logic to restrict digital joysticks */
2791
 
        if (curstate && !mouse_down && field->state->joystick != NULL && field->way != 16 && !field->machine().options().joystick_contradictory())
2792
 
        {
2793
 
                UINT8 mask = (field->way == 4) ? field->state->joystick->current4way : field->state->joystick->current;
2794
 
                if (!(mask & (1 << field->state->joydir)))
2795
 
                        curstate = FALSE;
2796
 
        }
2797
 
 
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))
2800
 
        {
2801
 
                int verbose = field->machine().options().verbose();
 
2108
                                select_next_setting();
 
2109
                }
 
2110
        }
 
2111
 
 
2112
        // update the current state with the impulse state
 
2113
        if (effective_impulse != 0)
 
2114
        {
 
2115
                curstate = (m_live->impulse != 0);
 
2116
                if (curstate)
 
2117
                        m_live->impulse--;
 
2118
        }
 
2119
 
 
2120
        // for toggle switches, the current value is folded into the port's default value
 
2121
        // so we always return FALSE here
 
2122
        if (toggle())
 
2123
                curstate = false;
 
2124
 
 
2125
        // additional logic to restrict digital joysticks
 
2126
        if (curstate && !mouse_down && m_live->joystick != NULL && m_way != 16 && !machine().options().joystick_contradictory())
 
2127
        {
 
2128
                UINT8 mask = (m_way == 4) ? m_live->joystick->current4way() : m_live->joystick->current();
 
2129
                if (!(mask & (1 << m_live->joydir)))
 
2130
                        curstate = false;
 
2131
        }
 
2132
 
 
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))
 
2135
        {
 
2136
                bool verbose = machine().options().verbose();
2802
2137
#ifdef MAME_DEBUG
2803
 
                verbose = 1;
 
2138
                verbose = true;
2804
2139
#endif
2805
 
                if (field->machine().options().coin_lockout())
 
2140
                if (machine().options().coin_lockout())
2806
2141
                {
2807
2142
                        if (verbose)
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());
 
2144
                        curstate = false;
2810
2145
                }
2811
2146
                else
2812
2147
                        if (verbose)
2813
 
                                ui_popup_time(3, "Coinlock disabled, but broken through %s.", input_field_name(field));
2814
 
        }
2815
 
 
2816
 
        return curstate;
2817
 
}
2818
 
 
2819
 
 
2820
 
 
2821
 
/***************************************************************************
2822
 
    PORT CONFIGURATION HELPERS
2823
 
***************************************************************************/
2824
 
 
2825
 
/*-------------------------------------------------
2826
 
    port_default_value - updates default value
2827
 
    of port settings according to device settings
2828
 
-------------------------------------------------*/
2829
 
 
2830
 
UINT32 port_default_value(const char *fulltag, UINT32 mask, UINT32 defval, device_t &owner)
2831
 
{
2832
 
        const input_device_default *def = owner.input_ports_defaults();
2833
 
        if (def != NULL)
2834
 
        {
2835
 
                astring fullpath;
2836
 
                for ( ; def->tag != NULL; def++)
2837
 
                        if (owner.subtag(fullpath, def->tag) == fulltag && def->mask == mask)
2838
 
                                return def->defvalue;
2839
 
        }
2840
 
        return defval;
2841
 
}
2842
 
 
2843
 
 
2844
 
/*-------------------------------------------------
2845
 
    input_port_config - constructor for an
2846
 
    I/O port configuration object
2847
 
-------------------------------------------------*/
2848
 
 
2849
 
input_port_config::input_port_config(device_t &owner, const char *tag)
2850
 
        : state(NULL),
2851
 
          active(0),
2852
 
          m_next(NULL),
2853
 
          m_owner(owner),
2854
 
          m_tag(tag),
2855
 
          m_modcount(0)
2856
 
{
2857
 
}
2858
 
 
2859
 
 
2860
 
running_machine &input_port_config::machine() const
2861
 
{
2862
 
        return m_owner.machine();
2863
 
}
2864
 
 
2865
 
 
2866
 
/*-------------------------------------------------
2867
 
    field_config_alloc - allocate a new input
2868
 
    port field config
2869
 
-------------------------------------------------*/
2870
 
 
2871
 
input_field_config::input_field_config(input_port_config &port, int _type, input_port_value _defvalue, input_port_value _maskbits, const char *_name)
2872
 
        : mask(_maskbits),
2873
 
          defvalue(_defvalue & _maskbits),
2874
 
          type(_type),
2875
 
          player(0),
2876
 
          flags(0),
2877
 
          impulse(0),
2878
 
          name(_name),
2879
 
          read_param(NULL),
2880
 
          read_device(DEVICE_SELF),
2881
 
          write_param(NULL),
2882
 
          write_device(DEVICE_SELF),
2883
 
          min(0),
2884
 
          max(_maskbits),
2885
 
          sensitivity(0),
2886
 
          delta(0),
2887
 
          centerdelta(0),
2888
 
          crossaxis(0),
2889
 
          crossscale(0),
2890
 
          crossoffset(0),
2891
 
          crossaltaxis(0),
2892
 
          crossmapper_device(DEVICE_SELF),
2893
 
          full_turn_count(0),
2894
 
          remap_table(NULL),
2895
 
          way(0),
2896
 
          state(NULL),
2897
 
          m_next(NULL),
2898
 
          m_port(port),
2899
 
          m_modcount(port.modcount())
2900
 
{
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;
2905
 
}
2906
 
 
2907
 
 
2908
 
input_setting_config::input_setting_config(input_field_config &field, input_port_value _value, const char *_name)
2909
 
        : value(_value),
2910
 
          name(_name),
2911
 
          m_field(field),
2912
 
          m_next(NULL)
2913
 
{
2914
 
        memset(&condition, 0, sizeof(condition));
2915
 
}
2916
 
 
2917
 
input_field_diplocation::input_field_diplocation(const char *string, UINT8 _swnum, bool _invert)
2918
 
        : swname(string),
2919
 
          swnum(_swnum),
2920
 
          invert(_invert)
2921
 
{
2922
 
}
2923
 
 
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
 
-------------------------------------------------*/
2930
 
 
2931
 
void input_port_config::collapse_fields(astring &errorbuf)
2932
 
{
2933
 
        input_field_config *list = m_fieldlist.detach_all();
2934
 
        input_port_value maskbits = 0;
2935
 
        int lastmodcount = -1;
2936
 
        while (list != NULL)
2937
 
        {
2938
 
                if (list->modcount() != lastmodcount)
2939
 
                {
2940
 
                        lastmodcount = list->modcount();
2941
 
                        maskbits = 0;
2942
 
                }
2943
 
                input_field_config *current = list;
2944
 
                list = list->next();
2945
 
                field_config_insert(*current, maskbits, errorbuf);
2946
 
        }
2947
 
}
2948
 
 
2949
 
void field_config_insert(input_field_config &newfield, input_port_value &disallowedbits, astring &errorbuf)
2950
 
{
2951
 
        input_port_value lowbit;
2952
 
 
2953
 
        /* verify against the disallowed bits, but only if we are condition-free */
2954
 
        if (newfield.condition.condition == PORTCOND_ALWAYS)
2955
 
        {
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;
2959
 
        }
2960
 
 
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)
2964
 
        {
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)))
2969
 
                {
2970
 
                        /* reduce the mask of the field we found */
2971
 
                        field->mask &= ~newfield.mask;
2972
 
 
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);
2976
 
                }
2977
 
        }
2978
 
 
2979
 
        /* make a mask of just the low bit */
2980
 
        lowbit = (newfield.mask ^ (newfield.mask - 1)) & newfield.mask;
2981
 
 
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)
2986
 
                        break;
2987
 
 
2988
 
        /* insert it into the list */
2989
 
        newfield.port().fieldlist().insert_before(newfield, field);
2990
 
}
2991
 
 
2992
 
 
2993
 
/*-------------------------------------------------
2994
 
    diplocation_expand - expand a string-based
2995
 
    DIP location into a linked list of
2996
 
    descriptions
2997
 
-------------------------------------------------*/
2998
 
 
2999
 
void diplocation_list_alloc(input_field_config &field, const char *location, astring &errorbuf)
3000
 
{
3001
 
        /* if nothing present, bail */
 
2148
                                ui_popup_time(3, "Coinlock disabled, but broken through %s.", name());
 
2149
        }
 
2150
 
 
2151
        // if we're active, set the appropriate bits in the digital state
 
2152
        if (curstate)
 
2153
                result |= m_mask;
 
2154
}
 
2155
 
 
2156
 
 
2157
//-------------------------------------------------
 
2158
//  crosshair_position - compute the crosshair
 
2159
//  position
 
2160
//-------------------------------------------------
 
2161
 
 
2162
void ioport_field::crosshair_position(float &x, float &y, bool &gotx, bool &goty)
 
2163
{
 
2164
        float value = m_live->analog->crosshair_read();
 
2165
 
 
2166
        // apply the scale and offset
 
2167
        if (m_crosshair_scale < 0)
 
2168
                value = -(1.0 - value) * m_crosshair_scale;
 
2169
        else
 
2170
                value *= m_crosshair_scale;
 
2171
        value += m_crosshair_offset;
 
2172
 
 
2173
        // apply custom mapping if necessary
 
2174
        if (!m_crosshair_mapper.isnull())
 
2175
                value = m_crosshair_mapper(*this, value);
 
2176
 
 
2177
        // handle X axis
 
2178
        if (m_crosshair_axis == CROSSHAIR_AXIS_X)
 
2179
        {
 
2180
                x = value;
 
2181
                gotx = true;
 
2182
                if (m_crosshair_altaxis != 0)
 
2183
                {
 
2184
                        y = m_crosshair_altaxis;
 
2185
                        goty = true;
 
2186
                }
 
2187
        }
 
2188
 
 
2189
        // handle Y axis
 
2190
        else
 
2191
        {
 
2192
                y = value;
 
2193
                goty = true;
 
2194
                if (m_crosshair_altaxis != 0)
 
2195
                {
 
2196
                        x = m_crosshair_altaxis;
 
2197
                        gotx = true;
 
2198
                }
 
2199
        }
 
2200
}
 
2201
 
 
2202
 
 
2203
//-------------------------------------------------
 
2204
//  expand_diplocation - expand a string-based
 
2205
//  DIP location into a linked list of
 
2206
//  descriptions
 
2207
//-------------------------------------------------
 
2208
 
 
2209
void ioport_field::expand_diplocation(const char *location, astring &errorbuf)
 
2210
{
 
2211
        // if nothing present, bail
3002
2212
        if (location == NULL)
3003
2213
                return;
3004
2214
 
3005
 
        field.diploclist().reset();
 
2215
        m_diploclist.reset();
3006
2216
 
3007
 
        /* parse the string */
 
2217
        // 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)
3013
2223
        {
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);
3018
2228
 
3019
 
                /* extract it to tempbuf */
 
2229
                // extract it to tempbuf
3020
2230
                astring tempstr;
3021
2231
                tempstr.cpy(curentry, comma - curentry);
3022
2232
 
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, ':');
3026
2236
 
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)
3029
2239
                {
3030
2240
                        lastname = name.cpy(number, colon - number);
3031
2241
                        number = colon + 1;
3032
2242
                }
3033
2243
 
3034
 
                /* otherwise, just copy the last name */
 
2244
                // otherwise, just copy the last name
3035
2245
                else
3036
2246
                {
3037
2247
                        if (lastname == NULL)
3042
2252
                        name.cpy(lastname);
3043
2253
                }
3044
2254
 
3045
 
                /* if the number is preceded by a '!' it's active high */
 
2255
                // if the number is preceded by a '!' it's active high
3046
2256
                bool invert = false;
3047
2257
                if (*number == '!')
3048
2258
                {
3050
2260
                        number++;
3051
2261
                }
3052
2262
 
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);
3057
2267
 
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)));
3060
2270
                entries++;
3061
2271
 
3062
 
                /* advance to the next item */
 
2272
                // advance to the next item
3063
2273
                curentry = comma;
3064
2274
                if (*curentry != 0)
3065
2275
                        curentry++;
3066
2276
        }
3067
2277
 
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
 
2279
        ioport_value temp;
3070
2280
        int bits;
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);
3075
 
}
3076
 
 
3077
 
 
3078
 
 
3079
 
/***************************************************************************
3080
 
    TOKENIZATION HELPERS
3081
 
***************************************************************************/
3082
 
 
3083
 
/*-------------------------------------------------
3084
 
    token_to_input_field_type - convert a string
3085
 
    token to an input field type and player
3086
 
-------------------------------------------------*/
3087
 
 
3088
 
static int token_to_input_field_type(running_machine &machine, const char *string, int *player)
3089
 
{
3090
 
        input_port_private *portdata = machine.input_port_data;
3091
 
        int ipnum;
3092
 
 
3093
 
        /* check for our failsafe case first */
3094
 
        if (sscanf(string, "TYPE_OTHER(%d,%d)", &ipnum, player) == 2)
3095
 
                return ipnum;
3096
 
 
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))
3100
 
                {
3101
 
                        *player = entry->player;
3102
 
                        return entry->type;
3103
 
                }
3104
 
 
3105
 
        /* if we fail, return IPT_UNKNOWN */
3106
 
        *player = 0;
3107
 
        return IPT_UNKNOWN;
3108
 
}
3109
 
 
3110
 
 
3111
 
/*-------------------------------------------------
3112
 
    input_field_type_to_token - convert an input
3113
 
    field type and player to a string token
3114
 
-------------------------------------------------*/
3115
 
 
3116
 
static const char *input_field_type_to_token(running_machine &machine, int type, int player)
3117
 
{
3118
 
        input_port_private *portdata = machine.input_port_data;
3119
 
        static char tempbuf[32];
3120
 
 
3121
 
        /* look up the port and return the token */
3122
 
        input_type_entry *entry = portdata->type_to_entry[type][player];
3123
 
        if (entry != NULL)
3124
 
                return entry->token;
3125
 
 
3126
 
        /* if that fails, carry on */
3127
 
        sprintf(tempbuf, "TYPE_OTHER(%d,%d)", type, player);
3128
 
        return tempbuf;
3129
 
}
3130
 
 
3131
 
 
3132
 
/*-------------------------------------------------
3133
 
    token_to_seq_type - convert a string to
3134
 
    a sequence type
3135
 
-------------------------------------------------*/
3136
 
 
3137
 
static int token_to_seq_type(const char *string)
3138
 
{
3139
 
        int seqindex;
3140
 
 
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]))
3144
 
                        return seqindex;
3145
 
 
3146
 
        return -1;
3147
 
}
3148
 
 
3149
 
 
3150
 
 
3151
 
/***************************************************************************
3152
 
    SETTINGS LOAD
3153
 
***************************************************************************/
3154
 
 
3155
 
/*-------------------------------------------------
3156
 
    load_config_callback - callback to extract
3157
 
    configuration data from the XML nodes
3158
 
-------------------------------------------------*/
3159
 
 
3160
 
static void load_config_callback(running_machine &machine, int config_type, xml_data_node *parentnode)
3161
 
{
3162
 
        input_port_private *portdata = machine.input_port_data;
3163
 
        xml_data_node *portnode;
3164
 
        int seqtype;
3165
 
 
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);
 
2285
}
 
2286
 
 
2287
 
 
2288
//-------------------------------------------------
 
2289
//  init_live_state - create live state structures
 
2290
//-------------------------------------------------
 
2291
 
 
2292
void ioport_field::init_live_state(analog_field *analog)
 
2293
{
 
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());
 
2298
 
 
2299
        // allocate live state
 
2300
        m_live = global_alloc(ioport_field_live(*this, analog));
 
2301
}
 
2302
 
 
2303
 
 
2304
 
 
2305
//**************************************************************************
 
2306
//  I/O PORT FIELD LIVE
 
2307
//**************************************************************************
 
2308
 
 
2309
//-------------------------------------------------
 
2310
//  ioport_field_live - constructor
 
2311
//-------------------------------------------------
 
2312
 
 
2313
ioport_field_live::ioport_field_live(ioport_field &field, analog_field *analog)
 
2314
        : analog(analog),
 
2315
          joystick(NULL),
 
2316
          value(field.defvalue()),
 
2317
          impulse(0),
 
2318
          last(0),
 
2319
          joydir(digital_joystick::JOYDIR_COUNT)
 
2320
{
 
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);
 
2324
 
 
2325
        // if this is a digital joystick field, make a note of it
 
2326
        if (field.is_digital_joystick())
 
2327
        {
 
2328
                joystick = &field.manager().digjoystick(field.player(), (field.type() - (IPT_DIGITAL_JOYSTICK_FIRST + 1)) / 4);
 
2329
                joydir = joystick->set_axis(field);
 
2330
        }
 
2331
 
 
2332
        // Name keyboard key names
 
2333
        if (field.type_class() == INPUT_CLASS_KEYBOARD && field.specific_name() == NULL)
 
2334
        {
 
2335
                // loop through each character on the field
 
2336
                astring tempstr;
 
2337
                for (int which = 0; ; which++)
 
2338
                {
 
2339
                        unicode_char ch = field.keyboard_code(which);
 
2340
                        if (ch == 0)
 
2341
                                break;
 
2342
                        name.catprintf("%-*s ", MAX(SPACE_COUNT - 1, 0), field.manager().natkeyboard().key_name(tempstr, ch));
 
2343
                }
 
2344
 
 
2345
                // trim extra spaces
 
2346
                name.trimspace();
 
2347
 
 
2348
                // special case
 
2349
                if (name.len() == 0)
 
2350
                        name.cpy("Unnamed Key");
 
2351
        }
 
2352
}
 
2353
 
 
2354
 
 
2355
 
 
2356
//**************************************************************************
 
2357
//  I/O PORT
 
2358
//**************************************************************************
 
2359
 
 
2360
//-------------------------------------------------
 
2361
//  ioport_port - constructor
 
2362
//-------------------------------------------------
 
2363
 
 
2364
ioport_port::ioport_port(device_t &owner, const char *tag)
 
2365
        : m_next(NULL),
 
2366
          m_device(owner),
 
2367
          m_tag(tag),
 
2368
          m_modcount(0),
 
2369
          m_active(0),
 
2370
          m_live(NULL)
 
2371
{
 
2372
}
 
2373
 
 
2374
 
 
2375
//-------------------------------------------------
 
2376
//  ~ioport_port - destructor
 
2377
//-------------------------------------------------
 
2378
 
 
2379
ioport_port::~ioport_port()
 
2380
{
 
2381
        global_free(m_live);
 
2382
}
 
2383
 
 
2384
 
 
2385
//-------------------------------------------------
 
2386
//  machine - return a reference to the running
 
2387
//  machine
 
2388
//-------------------------------------------------
 
2389
 
 
2390
running_machine &ioport_port::machine() const
 
2391
{
 
2392
        return m_device.machine();
 
2393
}
 
2394
 
 
2395
 
 
2396
//-------------------------------------------------
 
2397
//  manager - return a reference to the
 
2398
//  ioport_manager on the running machine
 
2399
//-------------------------------------------------
 
2400
 
 
2401
ioport_manager &ioport_port::manager() const
 
2402
{
 
2403
        return machine().ioport();
 
2404
}
 
2405
 
 
2406
 
 
2407
//-------------------------------------------------
 
2408
//  field - return a pointer to the first field
 
2409
//  that intersects the given mask
 
2410
//-------------------------------------------------
 
2411
 
 
2412
ioport_field *ioport_port::field(ioport_value mask)
 
2413
{
 
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)
 
2417
                        return field;
 
2418
        return NULL;
 
2419
}
 
2420
 
 
2421
 
 
2422
//-------------------------------------------------
 
2423
//  read - return the value of an I/O port
 
2424
//-------------------------------------------------
 
2425
 
 
2426
ioport_value ioport_port::read()
 
2427
{
 
2428
        assert_always(manager().safe_to_read(), "Input ports cannot be read at init time!");
 
2429
 
 
2430
        // start with the digital state
 
2431
        ioport_value result = m_live->digital;
 
2432
 
 
2433
        // insert dynamic read values
 
2434
        for (dynamic_field *dynfield = m_live->readlist.first(); dynfield != NULL; dynfield = dynfield->next())
 
2435
                dynfield->read(result);
 
2436
 
 
2437
        // apply active high/low state to digital and dynamic read inputs
 
2438
        result ^= m_live->defvalue;
 
2439
 
 
2440
        // insert analog portions
 
2441
        for (analog_field *analog = m_live->analoglist.first(); analog != NULL; analog = analog->next())
 
2442
                analog->read(result);
 
2443
 
 
2444
        return result;
 
2445
}
 
2446
 
 
2447
 
 
2448
//-------------------------------------------------
 
2449
//  write - write a value to a port
 
2450
//-------------------------------------------------
 
2451
 
 
2452
void ioport_port::write(ioport_value data, ioport_value mem_mask)
 
2453
{
 
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());
 
2459
}
 
2460
 
 
2461
 
 
2462
//-------------------------------------------------
 
2463
//  frame_update - once/frame update
 
2464
//-------------------------------------------------
 
2465
 
 
2466
void ioport_port::frame_update(ioport_field *mouse_field)
 
2467
{
 
2468
        // start with 0 values for the digital bits
 
2469
        m_live->digital = 0;
 
2470
 
 
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);
 
2474
 
 
2475
        // hook for MESS's natural keyboard support
 
2476
        manager().natkeyboard().frame_update(*this, m_live->digital);
 
2477
 
 
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);
 
2483
}
 
2484
 
 
2485
 
 
2486
//-------------------------------------------------
 
2487
//  collapse_fields - remove any fields that are
 
2488
//  wholly overlapped by other fields
 
2489
//-------------------------------------------------
 
2490
 
 
2491
void ioport_port::collapse_fields(astring &errorbuf)
 
2492
{
 
2493
        ioport_value maskbits = 0;
 
2494
        int lastmodcount = -1;
 
2495
 
 
2496
        // remove the whole list and start from scratch
 
2497
        ioport_field *field = m_fieldlist.detach_all();
 
2498
        while (field != NULL)
 
2499
        {
 
2500
                // if this modcount doesn't match, reset
 
2501
                if (field->modcount() != lastmodcount)
 
2502
                {
 
2503
                        lastmodcount = field->modcount();
 
2504
                        maskbits = 0;
 
2505
                }
 
2506
 
 
2507
                // reinsert this field
 
2508
                ioport_field *current = field;
 
2509
                field = field->next();
 
2510
                insert_field(*current, maskbits, errorbuf);
 
2511
        }
 
2512
}
 
2513
 
 
2514
 
 
2515
//-------------------------------------------------
 
2516
//  insert_field - insert a new field, checking
 
2517
//  for errors
 
2518
//-------------------------------------------------
 
2519
 
 
2520
void ioport_port::insert_field(ioport_field &newfield, ioport_value &disallowedbits, astring &errorbuf)
 
2521
{
 
2522
        // verify against the disallowed bits, but only if we are condition-free
 
2523
        if (newfield.condition().none())
 
2524
        {
 
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();
 
2528
        }
 
2529
 
 
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)
 
2533
        {
 
2534
                nextfield = field->next();
 
2535
                if ((field->mask() & newfield.mask()) != 0 &&
 
2536
                        (newfield.condition().none() || field->condition().none() || field->condition() == newfield.condition()))
 
2537
                {
 
2538
                        // reduce the mask of the field we found
 
2539
                        field->reduce_mask(newfield.mask());
 
2540
 
 
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);
 
2544
                }
 
2545
        }
 
2546
 
 
2547
        // make a mask of just the low bit
 
2548
        ioport_value lowbit = (newfield.mask() ^ (newfield.mask() - 1)) & newfield.mask();
 
2549
 
 
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)
 
2554
                        break;
 
2555
 
 
2556
        // insert it into the list
 
2557
        m_fieldlist.insert_before(newfield, field);
 
2558
}
 
2559
 
 
2560
 
 
2561
//-------------------------------------------------
 
2562
//  init_live_state - create the live state
 
2563
//-------------------------------------------------
 
2564
 
 
2565
void ioport_port::init_live_state()
 
2566
{
 
2567
        m_live = global_alloc(ioport_port_live(*this));
 
2568
}
 
2569
 
 
2570
 
 
2571
 
 
2572
//**************************************************************************
 
2573
//  I/O PORT LIVE STATE
 
2574
//**************************************************************************
 
2575
 
 
2576
//-------------------------------------------------
 
2577
//  ioport_port_live - constructor
 
2578
//-------------------------------------------------
 
2579
 
 
2580
ioport_port_live::ioport_port_live(ioport_port &port)
 
2581
        : defvalue(0),
 
2582
          digital(0),
 
2583
          outputvalue(0)
 
2584
{
 
2585
        // iterate over fields
 
2586
        for (ioport_field *field = port.first_field(); field != NULL; field = field->next())
 
2587
        {
 
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)));
 
2592
 
 
2593
                // allocate a dynamic field for reading
 
2594
                if (field->has_dynamic_read())
 
2595
                        readlist.append(*global_alloc(dynamic_field(*field)));
 
2596
 
 
2597
                // allocate a dynamic field for writing
 
2598
                if (field->has_dynamic_write())
 
2599
                        writelist.append(*global_alloc(dynamic_field(*field)));
 
2600
 
 
2601
                // let the field initialize its live state
 
2602
                field->init_live_state(analog);
 
2603
        }
 
2604
}
 
2605
 
 
2606
 
 
2607
 
 
2608
//**************************************************************************
 
2609
//  I/O PORT MANAGER
 
2610
//**************************************************************************
 
2611
 
 
2612
//-------------------------------------------------
 
2613
//  ioport_manager - constructor
 
2614
//-------------------------------------------------
 
2615
 
 
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)
 
2626
{
 
2627
        memset(m_type_to_entry, 0, sizeof(m_type_to_entry));
 
2628
}
 
2629
 
 
2630
 
 
2631
//-------------------------------------------------
 
2632
//  initialize - walk the configured ports and
 
2633
//  create live state information
 
2634
//-------------------------------------------------
 
2635
 
 
2636
time_t ioport_manager::initialize()
 
2637
{
 
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));
 
2641
 
 
2642
        // initialize the default port info from the OSD
 
2643
        init_port_types();
 
2644
 
 
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())
 
2648
        {
 
2649
                astring errors;
 
2650
                m_portlist.append(*device, errors);
 
2651
                if (errors)
 
2652
                        mame_printf_error("Input port errors:\n%s", errors.cstr());
 
2653
        }
 
2654
 
 
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();
 
2658
 
 
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");
 
2668
 
 
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)
 
2675
                                {
 
2676
                                        machine().input().set_global_joystick_map(field->rotated() ? joystick_map_4way_diagonal : joystick_map_4way_sticky);
 
2677
                                        break;
 
2678
                                }
 
2679
 
 
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));
 
2683
 
 
2684
        // open playback and record files if specified
 
2685
        time_t basetime = playback_init();
 
2686
        record_init();
 
2687
        return basetime;
 
2688
}
 
2689
 
 
2690
 
 
2691
//-------------------------------------------------
 
2692
//  init_port_types - initialize the default
 
2693
//  type list
 
2694
//-------------------------------------------------
 
2695
 
 
2696
void ioport_manager::init_port_types()
 
2697
{
 
2698
        // convert the array into a list of type states that can be modified
 
2699
        construct_core_types(m_typelist);
 
2700
 
 
2701
        // ask the OSD to customize the list
 
2702
        machine().osd().customize_input_type_list(m_typelist);
 
2703
 
 
2704
        // now iterate over the OSD-modified types
 
2705
        for (input_type_entry *curtype = first_type(); curtype != NULL; curtype = curtype->next())
 
2706
        {
 
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);
 
2710
 
 
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;
 
2713
        }
 
2714
}
 
2715
 
 
2716
 
 
2717
//-------------------------------------------------
 
2718
//  init_autoselect_devices - autoselect a single
 
2719
//  device based on the input port list passed
 
2720
//  in and the corresponding option
 
2721
//-------------------------------------------------
 
2722
 
 
2723
void ioport_manager::init_autoselect_devices(int type1, int type2, int type3, const char *option, const char *ananame)
 
2724
{
 
2725
        // if nothing specified, ignore the option
 
2726
        const char *stemp = machine().options().value(option);
 
2727
        if (stemp[0] == 0)
 
2728
                return;
 
2729
 
 
2730
        // extract valid strings
 
2731
        const char *autostring = "keyboard";
 
2732
        input_device_class autoenable = DEVICE_CLASS_KEYBOARD;
 
2733
        if (strcmp(stemp, "mouse") == 0)
 
2734
        {
 
2735
                autoenable = DEVICE_CLASS_MOUSE;
 
2736
                autostring = "mouse";
 
2737
        }
 
2738
        else if (strcmp(stemp, "joystick") == 0)
 
2739
        {
 
2740
                autoenable = DEVICE_CLASS_JOYSTICK;
 
2741
                autostring = "joystick";
 
2742
        }
 
2743
        else if (strcmp(stemp, "lightgun") == 0)
 
2744
        {
 
2745
                autoenable = DEVICE_CLASS_LIGHTGUN;
 
2746
                autostring = "lightgun";
 
2747
        }
 
2748
        else if (strcmp(stemp, "none") == 0)
 
2749
        {
 
2750
                // nothing specified
 
2751
                return;
 
2752
        }
 
2753
        else if (strcmp(stemp, "keyboard") != 0)
 
2754
                mame_printf_error("Invalid %s value %s; reverting to keyboard\n", option, stemp);
 
2755
 
 
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())
 
2760
 
 
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))
 
2763
                                {
 
2764
                                        mame_printf_verbose("Input: Autoenabling %s due to presence of a %s\n", autostring, ananame);
 
2765
                                        machine().input().device_class(autoenable).enable();
 
2766
                                        break;
 
2767
                                }
 
2768
}
 
2769
 
 
2770
 
 
2771
//-------------------------------------------------
 
2772
//  exit - exit callback to ensure we clean up
 
2773
//  and close our files
 
2774
//-------------------------------------------------
 
2775
 
 
2776
void ioport_manager::exit()
 
2777
{
 
2778
        // close any playback or recording files
 
2779
        playback_end();
 
2780
        record_end();
 
2781
}
 
2782
 
 
2783
 
 
2784
//-------------------------------------------------
 
2785
//  type_name - return the name for the given
 
2786
//  type/player
 
2787
//-------------------------------------------------
 
2788
 
 
2789
const char *ioport_manager::type_name(ioport_type type, UINT8 player)
 
2790
{
 
2791
        // if we have a machine, use the live state and quick lookup
 
2792
        input_type_entry *entry = m_type_to_entry[type][player];
 
2793
        if (entry != NULL)
 
2794
                return entry->name();
 
2795
 
 
2796
        // if we find nothing, return an invalid group
 
2797
        return "???";
 
2798
}
 
2799
 
 
2800
 
 
2801
//-------------------------------------------------
 
2802
//  type_group - return the group for the given
 
2803
//  type/player
 
2804
//-------------------------------------------------
 
2805
 
 
2806
ioport_group ioport_manager::type_group(ioport_type type, int player)
 
2807
{
 
2808
        input_type_entry *entry = m_type_to_entry[type][player];
 
2809
        if (entry != NULL)
 
2810
                return entry->group();
 
2811
 
 
2812
        // if we find nothing, return an invalid group
 
2813
        return IPG_INVALID;
 
2814
}
 
2815
 
 
2816
 
 
2817
//-------------------------------------------------
 
2818
//  type_seq - return the input sequence for the
 
2819
//  given type/player
 
2820
//-------------------------------------------------
 
2821
 
 
2822
const input_seq &ioport_manager::type_seq(ioport_type type, int player, input_seq_type seqtype)
 
2823
{
 
2824
        assert(type >= 0 && type < IPT_COUNT);
 
2825
        assert(player >= 0 && player < MAX_PLAYERS);
 
2826
 
 
2827
        // if we have a machine, use the live state and quick lookup
 
2828
        input_type_entry *entry = m_type_to_entry[type][player];
 
2829
        if (entry != NULL)
 
2830
                return entry->seq(seqtype);
 
2831
 
 
2832
        // if we find nothing, return an empty sequence
 
2833
        return input_seq::empty_seq;
 
2834
}
 
2835
 
 
2836
 
 
2837
//-------------------------------------------------
 
2838
//  set_type_seq - change the input sequence for
 
2839
//  the given type/player
 
2840
//-------------------------------------------------
 
2841
 
 
2842
void ioport_manager::set_type_seq(ioport_type type, int player, input_seq_type seqtype, const input_seq &newseq)
 
2843
{
 
2844
        input_type_entry *entry = m_type_to_entry[type][player];
 
2845
        if (entry != NULL)
 
2846
                entry->m_seq[seqtype] = newseq;
 
2847
}
 
2848
 
 
2849
 
 
2850
//-------------------------------------------------
 
2851
//  type_pressed - return true if the sequence for
 
2852
//  the given input type/player is pressed
 
2853
//-------------------------------------------------
 
2854
 
 
2855
bool ioport_manager::type_pressed(ioport_type type, int player)
 
2856
{
 
2857
        return machine().input().seq_pressed(type_seq(type, player));
 
2858
}
 
2859
 
 
2860
 
 
2861
//-------------------------------------------------
 
2862
//  type_class_present - return true if the given
 
2863
//  ioport_type_class exists in at least one port
 
2864
//-------------------------------------------------
 
2865
 
 
2866
bool ioport_manager::type_class_present(ioport_type_class inputclass)
 
2867
{
 
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)
 
2871
                                return true;
 
2872
        return false;
 
2873
}
 
2874
 
 
2875
 
 
2876
//-------------------------------------------------
 
2877
//  has_keyboard - determine if there is a
 
2878
//  keyboard present in the control list
 
2879
//-------------------------------------------------
 
2880
 
 
2881
bool ioport_manager::has_keyboard() const
 
2882
{
 
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())
 
2886
                {
 
2887
                        // if we are at init, check IPT_KEYBOARD
 
2888
                        if (!m_safe_to_read && field->type() == IPT_KEYBOARD)
 
2889
                                return true;
 
2890
 
 
2891
                        // else, check if there is a keyboard and if such a keyboard is enabled
 
2892
                        if (field->type() == IPT_KEYBOARD && field->enabled())
 
2893
                                return true;
 
2894
                }
 
2895
 
 
2896
        return false;
 
2897
}
 
2898
 
 
2899
//-------------------------------------------------
 
2900
//  count_players - counts the number of active
 
2901
//  players
 
2902
//-------------------------------------------------
 
2903
 
 
2904
int ioport_manager::count_players() const
 
2905
{
 
2906
        int max_player = 0;
 
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;
 
2911
 
 
2912
        return max_player;
 
2913
}
 
2914
 
 
2915
 
 
2916
//-------------------------------------------------
 
2917
//  crosshair_position - return the extracted
 
2918
//  crosshair values for the given player
 
2919
//-------------------------------------------------
 
2920
 
 
2921
bool ioport_manager::crosshair_position(int player, float &x, float &y)
 
2922
{
 
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())
 
2928
                        {
 
2929
                                field->crosshair_position(x, y, gotx, goty);
 
2930
 
 
2931
                                // if we got both, stop
 
2932
                                if (gotx && goty)
 
2933
                                        break;
 
2934
                        }
 
2935
 
 
2936
        return (gotx && goty);
 
2937
}
 
2938
 
 
2939
 
 
2940
//-------------------------------------------------
 
2941
//  update_defaults - force an update to the input
 
2942
//  port values based on current conditions
 
2943
//-------------------------------------------------
 
2944
 
 
2945
void ioport_manager::update_defaults()
 
2946
{
 
2947
        // two passes to catch conditionals properly
 
2948
        for (int loopnum = 0; loopnum < 2; loopnum++)
 
2949
        {
 
2950
                // loop over all input ports
 
2951
                for (ioport_port *port = first_port(); port != NULL; port = port->next())
 
2952
                {
 
2953
                        // only clear on the first pass
 
2954
                        if (loopnum == 0)
 
2955
                                port->live().defvalue = 0;
 
2956
 
 
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());
 
2961
                }
 
2962
        }
 
2963
}
 
2964
 
 
2965
 
 
2966
//-------------------------------------------------
 
2967
//  frame_update - core logic for per-frame input
 
2968
//  port updating
 
2969
//-------------------------------------------------
 
2970
 
 
2971
digital_joystick &ioport_manager::digjoystick(int player, int number)
 
2972
{
 
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)
 
2976
                        return *joystick;
 
2977
 
 
2978
        // create a new one
 
2979
        return m_joystick_list.append(*global_alloc(digital_joystick(player, number)));
 
2980
}
 
2981
 
 
2982
 
 
2983
//-------------------------------------------------
 
2984
//  frame_update - callback for once/frame updating
 
2985
//-------------------------------------------------
 
2986
 
 
2987
void ioport_manager::frame_update_callback()
 
2988
{
 
2989
        // if we're paused, don't do anything
 
2990
        if (!machine().paused())
 
2991
                frame_update();
 
2992
}
 
2993
 
 
2994
 
 
2995
//-------------------------------------------------
 
2996
//  frame_update_internal - core logic for
 
2997
//  per-frame input port updating
 
2998
//-------------------------------------------------
 
2999
 
 
3000
void ioport_manager::frame_update()
 
3001
{
 
3002
g_profiler.start(PROFILER_INPUT);
 
3003
 
 
3004
        // record/playback information about the current frame
 
3005
        attotime curtime = machine().time();
 
3006
        playback_frame(curtime);
 
3007
        record_frame(curtime);
 
3008
 
 
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;
 
3012
 
 
3013
        // update the digital joysticks
 
3014
        for (digital_joystick *joystick = m_joystick_list.first(); joystick != NULL; joystick = joystick->next())
 
3015
                joystick->frame_update();
 
3016
 
 
3017
        // compute default values for all the ports
 
3018
        update_defaults();
 
3019
 
 
3020
        // perform mouse hit testing
 
3021
        INT32 mouse_target_x, mouse_target_y;
 
3022
        int mouse_button;
 
3023
        render_target *mouse_target = ui_input_find_mouse(machine(), &mouse_target_x, &mouse_target_y, &mouse_button);
 
3024
 
 
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)
 
3028
        {
 
3029
                const char *tag = NULL;
 
3030
                ioport_value mask;
 
3031
                float x, y;
 
3032
                if (mouse_target->map_point_input(mouse_target_x, mouse_target_y, tag, mask, x, y))
 
3033
                {
 
3034
                        ioport_port *port = machine().root_device().ioport(tag);
 
3035
                        if (port != NULL)
 
3036
                                mouse_field = port->field(mask);
 
3037
                }
 
3038
        }
 
3039
 
 
3040
        // loop over all input ports
 
3041
        for (ioport_port *port = first_port(); port != NULL; port = port->next())
 
3042
        {
 
3043
                port->frame_update(mouse_field);
 
3044
 
 
3045
                // handle playback/record
 
3046
                playback_port(*port);
 
3047
                record_port(*port);
 
3048
        }
 
3049
 
 
3050
g_profiler.stop();
 
3051
}
 
3052
 
 
3053
 
 
3054
//-------------------------------------------------
 
3055
//  frame_interpolate - interpolate between two
 
3056
//  values based on the time between frames
 
3057
//-------------------------------------------------
 
3058
 
 
3059
INT32 ioport_manager::frame_interpolate(INT32 oldval, INT32 newval)
 
3060
{
 
3061
        // if no last delta, just use new value
 
3062
        if (m_last_delta_nsec == 0)
 
3063
                return newval;
 
3064
 
 
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);
 
3068
}
 
3069
 
 
3070
 
 
3071
//-------------------------------------------------
 
3072
//  load_config - callback to extract configuration
 
3073
//  data from the XML nodes
 
3074
//-------------------------------------------------
 
3075
 
 
3076
void ioport_manager::load_config(int config_type, xml_data_node *parentnode)
 
3077
{
 
3078
        // in the completion phase, we finish the initialization with the final ports
3167
3079
        if (config_type == CONFIG_TYPE_FINAL)
3168
3080
        {
3169
 
                portdata->safe_to_read = TRUE;
3170
 
                frame_update(machine);
 
3081
                m_safe_to_read = true;
 
3082
                frame_update();
3171
3083
        }
3172
3084
 
3173
 
        /* early exit if no data to parse */
 
3085
        // early exit if no data to parse
3174
3086
        if (parentnode == NULL)
3175
3087
                return;
3176
3088
 
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);
3180
3092
 
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"))
3183
3095
        {
3184
 
                input_seq newseq[SEQ_TYPE_TOTAL], tempseq;
3185
 
                xml_data_node *seqnode;
3186
 
                int type, player;
3187
 
 
3188
 
                /* get the basic port info from the attributes */
3189
 
                type = token_to_input_field_type(machine, xml_get_attribute_string(portnode, "type", ""), &player);
3190
 
 
3191
 
                /* initialize sequences to invalid defaults */
3192
 
                for (seqtype = 0; seqtype < ARRAY_LENGTH(newseq); seqtype++)
 
3096
                // get the basic port info from the attributes
 
3097
                int player;
 
3098
                int type = token_to_input_type(xml_get_attribute_string(portnode, "type", ""), player);
 
3099
 
 
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);
3194
3104
 
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"))
3197
3107
                {
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)
3201
3111
                        {
3202
3112
                                if (strcmp(seqnode->value, "NONE") == 0)
3203
3113
                                        newseq[seqtype].set();
3204
3114
                                else
3205
 
                                        machine.input().seq_from_tokens(newseq[seqtype], seqnode->value);
 
3115
                                        machine().input().seq_from_tokens(newseq[seqtype], seqnode->value);
3206
3116
                        }
3207
3117
                }
3208
3118
 
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);
3212
3122
                else
3213
 
                        load_game_config(machine, portnode, type, player, newseq);
 
3123
                        load_game_config(portnode, type, player, newseq);
3214
3124
        }
3215
3125
 
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);
3222
3132
}
3223
3133
 
3224
3134
 
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
//-------------------------------------------------
3229
3139
 
3230
 
static void load_remap_table(running_machine &machine, xml_data_node *parentnode)
 
3140
void ioport_manager::load_remap_table(xml_data_node *parentnode)
3231
3141
{
3232
 
        input_port_private *portdata = machine.input_port_data;
3233
 
        input_code *oldtable, *newtable;
3234
 
        xml_data_node *remapnode;
3235
 
        int count;
3236
 
 
3237
 
        /* count items first so we can allocate */
3238
 
        count = 0;
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
 
3143
        int count = 0;
 
3144
        for (xml_data_node *remapnode = xml_get_sibling(parentnode->child, "remap"); remapnode != NULL; remapnode = xml_get_sibling(remapnode->next, "remap"))
3240
3145
                count++;
3241
3146
 
3242
 
        /* if we have some, deal with them */
 
3147
        // if we have some, deal with them
3243
3148
        if (count > 0)
3244
3149
        {
3245
 
                int remapnum;
3246
 
 
3247
 
                /* allocate tables */
3248
 
                oldtable = global_alloc_array(input_code, count);
3249
 
                newtable = global_alloc_array(input_code, count);
3250
 
 
3251
 
                /* build up the remap table */
 
3150
                // allocate tables
 
3151
                dynamic_array<input_code> oldtable(count);
 
3152
                dynamic_array<input_code> newtable(count);
 
3153
 
 
3154
                // build up the remap table
3252
3155
                count = 0;
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"))
3254
3157
                {
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)
3258
3161
                        {
3259
3162
                                oldtable[count] = origcode;
3262
3165
                        }
3263
3166
                }
3264
3167
 
3265
 
                /* loop over the remapping table, operating only if something was specified */
3266
 
                for (remapnum = 0; remapnum < count; remapnum++)
3267
 
                {
3268
 
                        input_code oldcode = oldtable[remapnum];
3269
 
                        input_code newcode = newtable[remapnum];
3270
 
 
3271
 
                        /* loop over all default ports, remapping the requested keys */
3272
 
                        for (input_type_entry *entry = portdata->typelist.first(); entry != NULL; entry = entry->next())
3273
 
                        {
3274
 
                                /* remap anything in the default sequences */
3275
 
                                for (int seqtype = 0; seqtype < ARRAY_LENGTH(entry->seq); seqtype++)
3276
 
                                        entry->seq[seqtype].replace(oldcode, newcode);
3277
 
                        }
3278
 
                }
3279
 
 
3280
 
                /* release the tables */
3281
 
                global_free(oldtable);
3282
 
                global_free(newtable);
 
3168
                // loop over the remapping table, then over default ports, replacing old with new
 
3169
                for (int remapnum = 0; remapnum < count; remapnum++)
 
3170
                        for (input_type_entry *entry = m_typelist.first(); entry != NULL; entry = entry->next())
 
3171
                                for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
 
3172
                                        entry->m_seq[seqtype].replace(oldtable[remapnum], newtable[remapnum]);
3283
3173
        }
3284
3174
}
3285
3175
 
3286
3176
 
3287
 
/*-------------------------------------------------
3288
 
    load_default_config - apply configuration
3289
 
    data to the default mappings
3290
 
-------------------------------------------------*/
 
3177
//-------------------------------------------------
 
3178
//  load_default_config - apply configuration
 
3179
//  data to the default mappings
 
3180
//-------------------------------------------------
3291
3181
 
3292
 
static int load_default_config(running_machine &machine, xml_data_node *portnode, int type, int player, const input_seq *newseq)
 
3182
bool ioport_manager::load_default_config(xml_data_node *portnode, int type, int player, const input_seq *newseq)
3293
3183
{
3294
 
        input_port_private *portdata = machine.input_port_data;
3295
 
 
3296
 
        /* find a matching port in the list */
3297
 
        for (input_type_entry *entry = portdata->typelist.first(); entry != NULL; entry = entry->next())
3298
 
                if (entry->type == type && entry->player == player)
 
3184
        // find a matching port in the list
 
3185
        for (input_type_entry *entry = m_typelist.first(); entry != NULL; entry = entry->next())
 
3186
                if (entry->type() == type && entry->player() == player)
3299
3187
                {
3300
 
                        for (int seqtype = 0; seqtype < ARRAY_LENGTH(entry->seq); seqtype++)
 
3188
                        for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
3301
3189
                                if (newseq[seqtype][0] != INPUT_CODE_INVALID)
3302
 
                                        entry->seq[seqtype] = newseq[seqtype];
3303
 
                        return TRUE;
 
3190
                                        entry->m_seq[seqtype] = newseq[seqtype];
 
3191
                        return true;
3304
3192
                }
3305
3193
 
3306
 
        return FALSE;
 
3194
        return false;
3307
3195
}
3308
3196
 
3309
3197
 
3310
 
/*-------------------------------------------------
3311
 
    load_game_config - apply configuration
3312
 
    data to the current set of input ports
3313
 
-------------------------------------------------*/
 
3198
//-------------------------------------------------
 
3199
//  load_game_config - apply configuration
 
3200
//  data to the current set of input ports
 
3201
//-------------------------------------------------
3314
3202
 
3315
 
static int load_game_config(running_machine &machine, xml_data_node *portnode, int type, int player, const input_seq *newseq)
 
3203
bool ioport_manager::load_game_config(xml_data_node *portnode, int type, int player, const input_seq *newseq)
3316
3204
{
3317
 
        input_port_value mask, defvalue;
3318
 
        const input_field_config *field;
3319
 
        const input_port_config *port;
3320
 
        char tempbuffer[20];
3321
 
        const char *tag;
3322
 
 
3323
 
        /* read the mask, index, and defvalue attributes */
3324
 
        tag = xml_get_attribute_string(portnode, "tag", NULL);
3325
 
        mask = xml_get_attribute_int(portnode, "mask", 0);
3326
 
        defvalue = xml_get_attribute_int(portnode, "defvalue", 0);
3327
 
 
3328
 
        /* find the port we want; if no tag, search them all */
3329
 
        for (port = machine.m_portlist.first(); port != NULL; port = port->next())
3330
 
                if (tag == NULL || strcmp(get_port_tag(port, tempbuffer), tag) == 0)
3331
 
                        for (field = port->first_field(); field != NULL; field = field->next())
3332
 
 
3333
 
                                /* find the matching mask and defvalue */
3334
 
                                if (field->type == type && field->player == player &&
3335
 
                                        field->mask == mask && (field->defvalue & mask) == (defvalue & mask))
 
3205
        // read the mask, index, and defvalue attributes
 
3206
        const char *tag = xml_get_attribute_string(portnode, "tag", NULL);
 
3207
        ioport_value mask = xml_get_attribute_int(portnode, "mask", 0);
 
3208
        ioport_value defvalue = xml_get_attribute_int(portnode, "defvalue", 0);
 
3209
 
 
3210
        // find the port we want; if no tag, search them all
 
3211
        for (ioport_port *port = first_port(); port != NULL; port = port->next())
 
3212
                if (tag == NULL || strcmp(port->tag(), tag) == 0)
 
3213
                        for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
 
3214
 
 
3215
                                // find the matching mask and defvalue
 
3216
                                if (field->type() == type && field->player() == player &&
 
3217
                                        field->mask() == mask && (field->defvalue() & mask) == (defvalue & mask))
3336
3218
                                {
3337
 
                                        const char *revstring;
3338
 
                                        int seqtype;
3339
 
 
3340
 
                                        /* if a sequence was specified, copy it in */
3341
 
                                        for (seqtype = 0; seqtype < ARRAY_LENGTH(field->state->seq); seqtype++)
 
3219
                                        // if a sequence was specified, copy it in
 
3220
                                        for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
3342
3221
                                                if (newseq[seqtype][0] != INPUT_CODE_INVALID)
3343
 
                                                        field->state->seq[seqtype] = newseq[seqtype];
3344
 
 
3345
 
                                        /* for non-analog fields, fetch the value */
3346
 
                                        if (field->state->analog == NULL)
3347
 
                                                field->state->value = xml_get_attribute_int(portnode, "value", field->defvalue);
3348
 
 
3349
 
                                        /* for analog fields, fetch configurable analog attributes */
 
3222
                                                        field->live().seq[seqtype] = newseq[seqtype];
 
3223
 
 
3224
                                        // for non-analog fields, fetch the value
 
3225
                                        if (field->live().analog == NULL)
 
3226
                                                field->live().value = xml_get_attribute_int(portnode, "value", field->defvalue());
 
3227
 
 
3228
                                        // for analog fields, fetch configurable analog attributes
3350
3229
                                        else
3351
3230
                                        {
3352
 
                                                /* get base attributes */
3353
 
                                                field->state->analog->delta = xml_get_attribute_int(portnode, "keydelta", field->delta);
3354
 
                                                field->state->analog->centerdelta = xml_get_attribute_int(portnode, "centerdelta", field->centerdelta);
3355
 
                                                field->state->analog->sensitivity = xml_get_attribute_int(portnode, "sensitivity", field->sensitivity);
 
3231
                                                // get base attributes
 
3232
                                                field->live().analog->m_delta = xml_get_attribute_int(portnode, "keydelta", field->delta());
 
3233
                                                field->live().analog->m_centerdelta = xml_get_attribute_int(portnode, "centerdelta", field->centerdelta());
 
3234
                                                field->live().analog->m_sensitivity = xml_get_attribute_int(portnode, "sensitivity", field->sensitivity());
3356
3235
 
3357
 
                                                /* fetch yes/no for reverse setting */
3358
 
                                                revstring = xml_get_attribute_string(portnode, "reverse", NULL);
 
3236
                                                // fetch yes/no for reverse setting
 
3237
                                                const char *revstring = xml_get_attribute_string(portnode, "reverse", NULL);
3359
3238
                                                if (revstring != NULL)
3360
 
                                                        field->state->analog->reverse = (strcmp(revstring, "yes") == 0);
 
3239
                                                        field->live().analog->m_reverse = (strcmp(revstring, "yes") == 0);
3361
3240
                                        }
3362
 
                                        return TRUE;
 
3241
                                        return true;
3363
3242
                                }
3364
3243
 
3365
 
        return FALSE;
 
3244
        return false;
3366
3245
}
3367
3246
 
3368
3247
 
3369
3248
 
3370
 
/***************************************************************************
3371
 
    SETTINGS SAVE
3372
 
***************************************************************************/
3373
 
 
3374
 
/*-------------------------------------------------
3375
 
    save_config_callback - config callback for
3376
 
    saving input port configuration
3377
 
-------------------------------------------------*/
3378
 
 
3379
 
static void save_config_callback(running_machine &machine, int config_type, xml_data_node *parentnode)
 
3249
//**************************************************************************
 
3250
//  SETTINGS SAVE
 
3251
//**************************************************************************
 
3252
 
 
3253
//-------------------------------------------------
 
3254
//  save_config - config callback for saving input
 
3255
//  port configuration
 
3256
//-------------------------------------------------
 
3257
 
 
3258
void ioport_manager::save_config(int config_type, xml_data_node *parentnode)
3380
3259
{
3381
 
        /* if no parentnode, ignore */
 
3260
        // if no parentnode, ignore
3382
3261
        if (parentnode == NULL)
3383
3262
                return;
3384
3263
 
3385
 
        /* default ports save differently */
 
3264
        // default ports save differently
3386
3265
        if (config_type == CONFIG_TYPE_DEFAULT)
3387
 
                save_default_inputs(machine, parentnode);
 
3266
                save_default_inputs(parentnode);
3388
3267
        else
3389
 
                save_game_inputs(machine, parentnode);
 
3268
                save_game_inputs(parentnode);
3390
3269
}
3391
3270
 
3392
3271
 
3393
 
/*-------------------------------------------------
3394
 
    save_sequence - add a node for an input
3395
 
    sequence
3396
 
-------------------------------------------------*/
 
3272
//-------------------------------------------------
 
3273
//  save_sequence - add a node for an input
 
3274
//  sequence
 
3275
//-------------------------------------------------
3397
3276
 
3398
 
static void save_sequence(running_machine &machine, xml_data_node *parentnode, int type, int porttype, const input_seq &seq)
 
3277
void ioport_manager::save_sequence(xml_data_node *parentnode, input_seq_type type, ioport_type porttype, const input_seq &seq)
3399
3278
{
 
3279
        // get the string for the sequence
3400
3280
        astring seqstring;
3401
 
        xml_data_node *seqnode;
3402
 
 
3403
 
        /* get the string for the sequence */
3404
3281
        if (seq.length() == 0)
3405
3282
                seqstring.cpy("NONE");
3406
3283
        else
3407
 
                machine.input().seq_to_tokens(seqstring, seq);
 
3284
                machine().input().seq_to_tokens(seqstring, seq);
3408
3285
 
3409
 
        /* add the new node */
3410
 
        seqnode = xml_add_child(parentnode, "newseq", seqstring);
 
3286
        // add the new node
 
3287
        xml_data_node *seqnode = xml_add_child(parentnode, "newseq", seqstring);
3411
3288
        if (seqnode != NULL)
3412
3289
                xml_set_attribute(seqnode, "type", seqtypestrings[type]);
3413
3290
}
3414
3291
 
3415
3292
 
3416
 
/*-------------------------------------------------
3417
 
    save_this_input_field_type - determine if the given
3418
 
    port type is worth saving
3419
 
-------------------------------------------------*/
 
3293
//-------------------------------------------------
 
3294
//  save_this_input_field_type - determine if the
 
3295
//  given port type is worth saving
 
3296
//-------------------------------------------------
3420
3297
 
3421
 
static int save_this_input_field_type(int type)
 
3298
bool ioport_manager::save_this_input_field_type(ioport_type type)
3422
3299
{
3423
3300
        switch (type)
3424
3301
        {
3425
3302
                case IPT_UNUSED:
3426
3303
                case IPT_END:
3427
3304
                case IPT_PORT:
3428
 
                case IPT_VBLANK:
3429
3305
                case IPT_UNKNOWN:
3430
 
                        return FALSE;
 
3306
                        return false;
 
3307
 
 
3308
                default:
 
3309
                        break;
3431
3310
        }
3432
 
        return TRUE;
 
3311
        return true;
3433
3312
}
3434
3313
 
3435
3314
 
3436
 
/*-------------------------------------------------
3437
 
    save_default_inputs - add nodes for any default
3438
 
    mappings that have changed
3439
 
-------------------------------------------------*/
 
3315
//-------------------------------------------------
 
3316
//  save_default_inputs - add nodes for any default
 
3317
//  mappings that have changed
 
3318
//-------------------------------------------------
3440
3319
 
3441
 
static void save_default_inputs(running_machine &machine, xml_data_node *parentnode)
 
3320
void ioport_manager::save_default_inputs(xml_data_node *parentnode)
3442
3321
{
3443
 
        input_port_private *portdata = machine.input_port_data;
3444
 
        input_type_entry *entry;
3445
 
 
3446
 
        /* iterate over ports */
3447
 
        for (entry = portdata->typelist.first(); entry != NULL; entry = entry->next())
 
3322
        // iterate over ports
 
3323
        for (input_type_entry *entry = m_typelist.first(); entry != NULL; entry = entry->next())
3448
3324
        {
3449
 
                /* only save if this port is a type we save */
3450
 
                if (save_this_input_field_type(entry->type))
 
3325
                // only save if this port is a type we save
 
3326
                if (save_this_input_field_type(entry->type()))
3451
3327
                {
3452
 
                        int seqtype;
3453
 
 
3454
 
                        /* see if any of the sequences have changed */
3455
 
                        for (seqtype = 0; seqtype < ARRAY_LENGTH(entry->seq); seqtype++)
3456
 
                                if (entry->seq[seqtype] != entry->defseq[seqtype])
 
3328
                        // see if any of the sequences have changed
 
3329
                        input_seq_type seqtype;
 
3330
                        for (seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
 
3331
                                if (entry->seq(seqtype) != entry->defseq(seqtype))
3457
3332
                                        break;
3458
3333
 
3459
 
                        /* if so, we need to add a node */
3460
 
                        if (seqtype < ARRAY_LENGTH(entry->seq))
 
3334
                        // if so, we need to add a node
 
3335
                        if (seqtype < SEQ_TYPE_TOTAL)
3461
3336
                        {
3462
 
                                /* add a new port node */
 
3337
                                // add a new port node
3463
3338
                                xml_data_node *portnode = xml_add_child(parentnode, "port", NULL);
3464
3339
                                if (portnode != NULL)
3465
3340
                                {
3466
 
                                        /* add the port information and attributes */
3467
 
                                        xml_set_attribute(portnode, "type", input_field_type_to_token(machine, entry->type, entry->player));
 
3341
                                        // add the port information and attributes
 
3342
                                        astring tempstr;
 
3343
                                        xml_set_attribute(portnode, "type", input_type_to_token(tempstr, entry->type(), entry->player()));
3468
3344
 
3469
 
                                        /* add only the sequences that have changed from the defaults */
3470
 
                                        for (seqtype = 0; seqtype < ARRAY_LENGTH(entry->seq); seqtype++)
3471
 
                                                if (entry->seq[seqtype] != entry->defseq[seqtype])
3472
 
                                                        save_sequence(machine, portnode, seqtype, entry->type, entry->seq[seqtype]);
 
3345
                                        // add only the sequences that have changed from the defaults
 
3346
                                        for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
 
3347
                                                if (entry->seq(seqtype) != entry->defseq(seqtype))
 
3348
                                                        save_sequence(portnode, seqtype, entry->type(), entry->seq(seqtype));
3473
3349
                                }
3474
3350
                        }
3475
3351
                }
3477
3353
}
3478
3354
 
3479
3355
 
3480
 
/*-------------------------------------------------
3481
 
    save_game_inputs - add nodes for any game
3482
 
    mappings that have changed
3483
 
-------------------------------------------------*/
 
3356
//-------------------------------------------------
 
3357
//  save_game_inputs - add nodes for any game
 
3358
//  mappings that have changed
 
3359
//-------------------------------------------------
3484
3360
 
3485
 
static void save_game_inputs(running_machine &machine, xml_data_node *parentnode)
 
3361
void ioport_manager::save_game_inputs(xml_data_node *parentnode)
3486
3362
{
3487
 
        const input_field_config *field;
3488
 
        const input_port_config *port;
3489
 
 
3490
 
        /* iterate over ports */
3491
 
        for (port = machine.m_portlist.first(); port != NULL; port = port->next())
3492
 
                for (field = port->first_field(); field != NULL; field = field->next())
3493
 
                        if (save_this_input_field_type(field->type))
 
3363
        // iterate over ports
 
3364
        for (ioport_port *port = first_port(); port != NULL; port = port->next())
 
3365
                for (ioport_field *field = port->first_field(); field != NULL; field = field->next())
 
3366
                        if (save_this_input_field_type(field->type()))
3494
3367
                        {
 
3368
                                // determine if we changed
3495
3369
                                bool changed = false;
3496
 
                                int seqtype;
3497
 
 
3498
 
                                /* determine if we changed */
3499
 
                                for (seqtype = 0; seqtype < ARRAY_LENGTH(field->state->seq); seqtype++)
3500
 
                                        changed |= (field->state->seq[seqtype] != field->seq[seqtype]);
3501
 
 
3502
 
                                /* non-analog changes */
3503
 
                                if (field->state->analog == NULL)
3504
 
                                        changed |= ((field->state->value & field->mask) != (field->defvalue & field->mask));
3505
 
 
3506
 
                                /* analog changes */
 
3370
                                for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
 
3371
                                        changed |= (field->seq(seqtype) != field->defseq(seqtype));
 
3372
 
 
3373
                                // non-analog changes
 
3374
                                if (!field->is_analog())
 
3375
                                        changed |= ((field->live().value & field->mask()) != (field->defvalue() & field->mask()));
 
3376
 
 
3377
                                // analog changes
3507
3378
                                else
3508
3379
                                {
3509
 
                                        changed |= (field->state->analog->delta != field->delta);
3510
 
                                        changed |= (field->state->analog->centerdelta != field->centerdelta);
3511
 
                                        changed |= (field->state->analog->sensitivity != field->sensitivity);
3512
 
                                        changed |= (field->state->analog->reverse != ((field->flags & ANALOG_FLAG_REVERSE) != 0));
 
3380
                                        changed |= (field->live().analog->m_delta != field->delta());
 
3381
                                        changed |= (field->live().analog->m_centerdelta != field->centerdelta());
 
3382
                                        changed |= (field->live().analog->m_sensitivity != field->sensitivity());
 
3383
                                        changed |= (field->live().analog->m_reverse != field->analog_reverse());
3513
3384
                                }
3514
3385
 
3515
 
                                /* if we did change, add a new node */
 
3386
                                // if we did change, add a new node
3516
3387
                                if (changed)
3517
3388
                                {
3518
 
                                        /* add a new port node */
 
3389
                                        // add a new port node
3519
3390
                                        xml_data_node *portnode = xml_add_child(parentnode, "port", NULL);
3520
3391
                                        if (portnode != NULL)
3521
3392
                                        {
3522
 
                                                char tempbuffer[20];
3523
 
 
3524
 
                                                /* add the identifying information and attributes */
3525
 
                                                xml_set_attribute(portnode, "tag", get_port_tag(port, tempbuffer));
3526
 
                                                xml_set_attribute(portnode, "type", input_field_type_to_token(machine, field->type, field->player));
3527
 
                                                xml_set_attribute_int(portnode, "mask", field->mask);
3528
 
                                                xml_set_attribute_int(portnode, "defvalue", field->defvalue & field->mask);
3529
 
 
3530
 
                                                /* add sequences if changed */
3531
 
                                                for (seqtype = 0; seqtype < ARRAY_LENGTH(field->state->seq); seqtype++)
3532
 
                                                        if (field->state->seq[seqtype] != field->seq[seqtype])
3533
 
                                                                save_sequence(machine, portnode, seqtype, field->type, field->state->seq[seqtype]);
3534
 
 
3535
 
                                                /* write out non-analog changes */
3536
 
                                                if (field->state->analog == NULL)
 
3393
                                                // add the identifying information and attributes
 
3394
                                                astring tempstr;
 
3395
                                                xml_set_attribute(portnode, "tag", port->tag());
 
3396
                                                xml_set_attribute(portnode, "type", input_type_to_token(tempstr, field->type(), field->player()));
 
3397
                                                xml_set_attribute_int(portnode, "mask", field->mask());
 
3398
                                                xml_set_attribute_int(portnode, "defvalue", field->defvalue() & field->mask());
 
3399
 
 
3400
                                                // add sequences if changed
 
3401
                                                for (input_seq_type seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
 
3402
                                                        if (field->seq(seqtype) != field->defseq(seqtype))
 
3403
                                                                save_sequence(portnode, seqtype, field->type(), field->seq(seqtype));
 
3404
 
 
3405
                                                // write out non-analog changes
 
3406
                                                if (!field->is_analog())
3537
3407
                                                {
3538
 
                                                        if ((field->state->value & field->mask) != (field->defvalue & field->mask))
3539
 
                                                                xml_set_attribute_int(portnode, "value", field->state->value & field->mask);
 
3408
                                                        if ((field->live().value & field->mask()) != (field->defvalue() & field->mask()))
 
3409
                                                                xml_set_attribute_int(portnode, "value", field->live().value & field->mask());
3540
3410
                                                }
3541
3411
 
3542
 
                                                /* write out analog changes */
 
3412
                                                // write out analog changes
3543
3413
                                                else
3544
3414
                                                {
3545
 
                                                        if (field->state->analog->delta != field->delta)
3546
 
                                                                xml_set_attribute_int(portnode, "keydelta", field->state->analog->delta);
3547
 
                                                        if (field->state->analog->centerdelta != field->centerdelta)
3548
 
                                                                xml_set_attribute_int(portnode, "centerdelta", field->state->analog->centerdelta);
3549
 
                                                        if (field->state->analog->sensitivity != field->sensitivity)
3550
 
                                                                xml_set_attribute_int(portnode, "sensitivity", field->state->analog->sensitivity);
3551
 
                                                        if (field->state->analog->reverse != ((field->flags & ANALOG_FLAG_REVERSE) != 0))
3552
 
                                                                xml_set_attribute(portnode, "reverse", field->state->analog->reverse ? "yes" : "no");
 
3415
                                                        if (field->live().analog->m_delta != field->delta())
 
3416
                                                                xml_set_attribute_int(portnode, "keydelta", field->live().analog->m_delta);
 
3417
                                                        if (field->live().analog->m_centerdelta != field->centerdelta())
 
3418
                                                                xml_set_attribute_int(portnode, "centerdelta", field->live().analog->m_centerdelta);
 
3419
                                                        if (field->live().analog->m_sensitivity != field->sensitivity())
 
3420
                                                                xml_set_attribute_int(portnode, "sensitivity", field->live().analog->m_sensitivity);
 
3421
                                                        if (field->live().analog->m_reverse != field->analog_reverse())
 
3422
                                                                xml_set_attribute(portnode, "reverse", field->live().analog->m_reverse ? "yes" : "no");
3553
3423
                                                }
3554
3424
                                        }
3555
3425
                                }
3558
3428
 
3559
3429
 
3560
3430
 
3561
 
/***************************************************************************
3562
 
    INPUT PLAYBACK
3563
 
***************************************************************************/
3564
 
 
3565
 
/*-------------------------------------------------
3566
 
    playback_read_uint8 - read an 8-bit value
3567
 
    from the playback file
3568
 
-------------------------------------------------*/
3569
 
 
3570
 
static UINT8 playback_read_uint8(running_machine &machine)
 
3431
//**************************************************************************
 
3432
//  INPUT PLAYBACK
 
3433
//**************************************************************************
 
3434
 
 
3435
//-------------------------------------------------
 
3436
//  playback_read - read a value from the playback
 
3437
//  file
 
3438
//-------------------------------------------------
 
3439
 
 
3440
template<typename _Type>
 
3441
_Type ioport_manager::playback_read(_Type &result)
3571
3442
{
3572
 
        input_port_private *portdata = machine.input_port_data;
3573
 
        UINT8 result;
3574
 
 
3575
 
        /* protect against NULL handles if previous reads fail */
3576
 
        if (portdata->playback_file == NULL)
3577
 
                return 0;
3578
 
 
3579
 
        /* read the value; if we fail, end playback */
3580
 
        if (portdata->playback_file->read(&result, sizeof(result)) != sizeof(result))
 
3443
        // protect against NULL handles if previous reads fail
 
3444
        if (!m_playback_file.is_open())
 
3445
                result = 0;
 
3446
 
 
3447
        // read the value; if we fail, end playback
 
3448
        else if (m_playback_file.read(&result, sizeof(result)) != sizeof(result))
3581
3449
        {
3582
 
                playback_end(machine, "End of file");
3583
 
                return 0;
 
3450
                playback_end("End of file");
 
3451
                result = 0;
3584
3452
        }
3585
3453
 
3586
 
        /* return the appropriate value */
 
3454
        // return the appropriate value
 
3455
        else if (sizeof(result) == 8)
 
3456
                result = LITTLE_ENDIANIZE_INT64(result);
 
3457
        else if (sizeof(result) == 4)
 
3458
                result = LITTLE_ENDIANIZE_INT32(result);
 
3459
        else if (sizeof(result) == 2)
 
3460
                result = LITTLE_ENDIANIZE_INT16(result);
3587
3461
        return result;
3588
3462
}
3589
3463
 
3590
 
 
3591
 
/*-------------------------------------------------
3592
 
    playback_read_uint32 - read a 32-bit value
3593
 
    from the playback file
3594
 
-------------------------------------------------*/
3595
 
 
3596
 
static UINT32 playback_read_uint32(running_machine &machine)
3597
 
{
3598
 
        input_port_private *portdata = machine.input_port_data;
3599
 
        UINT32 result;
3600
 
 
3601
 
        /* protect against NULL handles if previous reads fail */
3602
 
        if (portdata->playback_file == NULL)
3603
 
                return 0;
3604
 
 
3605
 
        /* read the value; if we fail, end playback */
3606
 
        if (portdata->playback_file->read(&result, sizeof(result)) != sizeof(result))
3607
 
        {
3608
 
                playback_end(machine, "End of file");
3609
 
                return 0;
3610
 
        }
3611
 
 
3612
 
        /* return the appropriate value */
3613
 
        return LITTLE_ENDIANIZE_INT32(result);
3614
 
}
3615
 
 
3616
 
 
3617
 
/*-------------------------------------------------
3618
 
    playback_read_uint64 - read a 64-bit value
3619
 
    from the playback file
3620
 
-------------------------------------------------*/
3621
 
 
3622
 
static UINT64 playback_read_uint64(running_machine &machine)
3623
 
{
3624
 
        input_port_private *portdata = machine.input_port_data;
3625
 
        UINT64 result;
3626
 
 
3627
 
        /* protect against NULL handles if previous reads fail */
3628
 
        if (portdata->playback_file == NULL)
3629
 
                return 0;
3630
 
 
3631
 
        /* read the value; if we fail, end playback */
3632
 
        if (portdata->playback_file->read(&result, sizeof(result)) != sizeof(result))
3633
 
        {
3634
 
                playback_end(machine, "End of file");
3635
 
                return 0;
3636
 
        }
3637
 
 
3638
 
        /* return the appropriate value */
3639
 
        return LITTLE_ENDIANIZE_INT64(result);
3640
 
}
3641
 
 
3642
 
 
3643
 
/*-------------------------------------------------
3644
 
    playback_init - initialize INP playback
3645
 
-------------------------------------------------*/
3646
 
 
3647
 
static time_t playback_init(running_machine &machine)
3648
 
{
3649
 
        const char *filename = machine.options().playback();
3650
 
        input_port_private *portdata = machine.input_port_data;
3651
 
        UINT8 header[INP_HEADER_SIZE];
3652
 
        time_t basetime;
3653
 
 
3654
 
        /* if no file, nothing to do */
 
3464
template<>
 
3465
bool ioport_manager::playback_read<bool>(bool &result)
 
3466
{
 
3467
        UINT8 temp;
 
3468
        playback_read(temp);
 
3469
        return result = bool(temp);
 
3470
}
 
3471
 
 
3472
 
 
3473
//-------------------------------------------------
 
3474
//  playback_init - initialize INP playback
 
3475
//-------------------------------------------------
 
3476
 
 
3477
time_t ioport_manager::playback_init()
 
3478
{
 
3479
        // if no file, nothing to do
 
3480
        const char *filename = machine().options().playback();
3655
3481
        if (filename[0] == 0)
3656
3482
                return 0;
3657
3483
 
3658
 
        /* open the playback file */
3659
 
        portdata->playback_file = auto_alloc(machine, emu_file(machine.options().input_directory(), OPEN_FLAG_READ));
3660
 
        file_error filerr = portdata->playback_file->open(filename);
 
3484
        // open the playback file
 
3485
        file_error filerr = m_playback_file.open(filename);
3661
3486
        assert_always(filerr == FILERR_NONE, "Failed to open file for playback");
3662
3487
 
3663
 
        /* read the header and verify that it is a modern version; if not, print an error */
3664
 
        if (portdata->playback_file->read(header, sizeof(header)) != sizeof(header))
 
3488
        // read the header and verify that it is a modern version; if not, print an error
 
3489
        UINT8 header[INP_HEADER_SIZE];
 
3490
        if (m_playback_file.read(header, sizeof(header)) != sizeof(header))
3665
3491
                fatalerror("Input file is corrupt or invalid (missing header)");
3666
3492
        if (memcmp(header, "MAMEINP\0", 8) != 0)
3667
3493
                fatalerror("Input file invalid or in an older, unsupported format");
3668
3494
        if (header[0x10] != INP_HEADER_MAJVERSION)
3669
3495
                fatalerror("Input file format version mismatch");
3670
3496
 
3671
 
        /* output info to console */
 
3497
        // output info to console
3672
3498
        mame_printf_info("Input file: %s\n", filename);
3673
3499
        mame_printf_info("INP version %d.%d\n", header[0x10], header[0x11]);
3674
 
        basetime = header[0x08] | (header[0x09] << 8) | (header[0x0a] << 16) | (header[0x0b] << 24) |
3675
 
                                ((UINT64)header[0x0c] << 32) | ((UINT64)header[0x0d] << 40) | ((UINT64)header[0x0e] << 48) | ((UINT64)header[0x0f] << 56);
 
3500
        time_t basetime = header[0x08] | (header[0x09] << 8) | (header[0x0a] << 16) | (header[0x0b] << 24) |
 
3501
                                                ((UINT64)header[0x0c] << 32) | ((UINT64)header[0x0d] << 40) | ((UINT64)header[0x0e] << 48) | ((UINT64)header[0x0f] << 56);
3676
3502
        mame_printf_info("Created %s", ctime(&basetime));
3677
3503
        mame_printf_info("Recorded using %s\n", header + 0x20);
3678
3504
 
3679
 
        /* verify the header against the current game */
3680
 
        if (memcmp(machine.system().name, header + 0x14, strlen(machine.system().name) + 1) != 0)
3681
 
                mame_printf_info("Input file is for %s '%s', not for current %s '%s'\n", emulator_info::get_gamenoun(), header + 0x14, emulator_info::get_gamenoun(), machine.system().name);
3682
 
 
3683
 
        /* enable compression */
3684
 
        portdata->playback_file->compress(FCOMPRESS_MEDIUM);
3685
 
 
 
3505
        // verify the header against the current game
 
3506
        if (memcmp(machine().system().name, header + 0x14, strlen(machine().system().name) + 1) != 0)
 
3507
                mame_printf_info("Input file is for %s '%s', not for current %s '%s'\n", emulator_info::get_gamenoun(), header + 0x14, emulator_info::get_gamenoun(), machine().system().name);
 
3508
 
 
3509
        // enable compression
 
3510
        m_playback_file.compress(FCOMPRESS_MEDIUM);
3686
3511
        return basetime;
3687
3512
}
3688
3513
 
3689
3514
 
3690
 
/*-------------------------------------------------
3691
 
    playback_end - end INP playback
3692
 
-------------------------------------------------*/
 
3515
//-------------------------------------------------
 
3516
//  playback_end - end INP playback
 
3517
//-------------------------------------------------
3693
3518
 
3694
 
static void playback_end(running_machine &machine, const char *message)
 
3519
void ioport_manager::playback_end(const char *message)
3695
3520
{
3696
 
        input_port_private *portdata = machine.input_port_data;
3697
 
 
3698
 
        /* only applies if we have a live file */
3699
 
        if (portdata->playback_file != NULL)
 
3521
        // only applies if we have a live file
 
3522
        if (m_playback_file.is_open())
3700
3523
        {
3701
 
                /* close the file */
3702
 
                auto_free(machine, portdata->playback_file);
3703
 
                portdata->playback_file = NULL;
 
3524
                // close the file
 
3525
                m_playback_file.close();
3704
3526
 
3705
 
                /* pop a message */
 
3527
                // pop a message
3706
3528
                if (message != NULL)
3707
3529
                        popmessage("Playback Ended\nReason: %s", message);
3708
3530
 
3709
 
                /* display speed stats */
3710
 
                portdata->playback_accumulated_speed /= portdata->playback_accumulated_frames;
3711
 
                mame_printf_info("Total playback frames: %d\n", (UINT32)portdata->playback_accumulated_frames);
3712
 
                mame_printf_info("Average recorded speed: %d%%\n", (UINT32)((portdata->playback_accumulated_speed * 200 + 1) >> 21));
 
3531
                // display speed stats
 
3532
                m_playback_accumulated_speed /= m_playback_accumulated_frames;
 
3533
                mame_printf_info("Total playback frames: %d\n", UINT32(m_playback_accumulated_frames));
 
3534
                mame_printf_info("Average recorded speed: %d%%\n", UINT32((m_playback_accumulated_speed * 200 + 1) >> 21));
3713
3535
        }
3714
3536
}
3715
3537
 
3716
3538
 
3717
 
/*-------------------------------------------------
3718
 
    playback_frame - start of frame callback for
3719
 
    playback
3720
 
-------------------------------------------------*/
 
3539
//-------------------------------------------------
 
3540
//  playback_frame - start of frame callback for
 
3541
//  playback
 
3542
//-------------------------------------------------
3721
3543
 
3722
 
static void playback_frame(running_machine &machine, attotime curtime)
 
3544
void ioport_manager::playback_frame(attotime curtime)
3723
3545
{
3724
 
        input_port_private *portdata = machine.input_port_data;
3725
 
 
3726
 
        /* if playing back, fetch the information and verify */
3727
 
        if (portdata->playback_file != NULL)
 
3546
        // if playing back, fetch the information and verify
 
3547
        if (m_playback_file.is_open())
3728
3548
        {
 
3549
                // first the absolute time
3729
3550
                attotime readtime;
3730
 
 
3731
 
                /* first the absolute time */
3732
 
                readtime.seconds = playback_read_uint32(machine);
3733
 
                readtime.attoseconds = playback_read_uint64(machine);
 
3551
                playback_read(readtime.seconds);
 
3552
                playback_read(readtime.attoseconds);
3734
3553
                if (readtime != curtime)
3735
 
                        playback_end(machine, "Out of sync");
 
3554
                        playback_end("Out of sync");
3736
3555
 
3737
 
                /* then the speed */
3738
 
                portdata->playback_accumulated_speed += playback_read_uint32(machine);
3739
 
                portdata->playback_accumulated_frames++;
 
3556
                // then the speed
 
3557
                UINT32 curspeed;
 
3558
                m_playback_accumulated_speed += playback_read(curspeed);
 
3559
                m_playback_accumulated_frames++;
3740
3560
        }
3741
3561
}
3742
3562
 
3743
3563
 
3744
 
/*-------------------------------------------------
3745
 
    playback_port - per-port callback for playback
3746
 
-------------------------------------------------*/
 
3564
//-------------------------------------------------
 
3565
//  playback_port - per-port callback for playback
 
3566
//-------------------------------------------------
3747
3567
 
3748
 
static void playback_port(const input_port_config *port)
 
3568
void ioport_manager::playback_port(ioport_port &port)
3749
3569
{
3750
 
        input_port_private *portdata = port->machine().input_port_data;
3751
 
 
3752
 
        /* if playing back, fetch information about this port */
3753
 
        if (portdata->playback_file != NULL)
 
3570
        // if playing back, fetch information about this port
 
3571
        if (m_playback_file.is_open())
3754
3572
        {
3755
 
                analog_field_state *analog;
3756
 
 
3757
 
                /* read the default value and the digital state */
3758
 
                port->state->defvalue = playback_read_uint32(port->machine());
3759
 
                port->state->digital = playback_read_uint32(port->machine());
3760
 
 
3761
 
                /* loop over analog ports and save their data */
3762
 
                for (analog = port->state->analoglist; analog != NULL; analog = analog->next)
 
3573
                // read the default value and the digital state
 
3574
                playback_read(port.live().defvalue);
 
3575
                playback_read(port.live().digital);
 
3576
 
 
3577
                // loop over analog ports and save their data
 
3578
                for (analog_field *analog = port.live().analoglist.first(); analog != NULL; analog = analog->next())
3763
3579
                {
3764
 
                        /* read current and previous values */
3765
 
                        analog->accum = playback_read_uint32(port->machine());
3766
 
                        analog->previous = playback_read_uint32(port->machine());
 
3580
                        // read current and previous values
 
3581
                        playback_read(analog->m_accum);
 
3582
                        playback_read(analog->m_previous);
3767
3583
 
3768
 
                        /* read configuration information */
3769
 
                        analog->sensitivity = playback_read_uint32(port->machine());
3770
 
                        analog->reverse = playback_read_uint8(port->machine());
 
3584
                        // read configuration information
 
3585
                        playback_read(analog->m_sensitivity);
 
3586
                        playback_read(analog->m_reverse);
3771
3587
                }
3772
3588
        }
3773
3589
}
3774
3590
 
3775
3591
 
3776
 
 
3777
 
/***************************************************************************
3778
 
    INPUT RECORDING
3779
 
***************************************************************************/
3780
 
 
3781
 
/*-------------------------------------------------
3782
 
    record_write_uint8 - write an 8-bit value
3783
 
    to the record file
3784
 
-------------------------------------------------*/
3785
 
 
3786
 
static void record_write_uint8(running_machine &machine, UINT8 data)
3787
 
{
3788
 
        input_port_private *portdata = machine.input_port_data;
3789
 
        UINT8 result = data;
3790
 
 
3791
 
        /* protect against NULL handles if previous reads fail */
3792
 
        if (portdata->record_file == NULL)
3793
 
                return;
3794
 
 
3795
 
        /* read the value; if we fail, end playback */
3796
 
        if (portdata->record_file->write(&result, sizeof(result)) != sizeof(result))
3797
 
                record_end(machine, "Out of space");
3798
 
}
3799
 
 
3800
 
 
3801
 
/*-------------------------------------------------
3802
 
    record_write_uint32 - write a 32-bit value
3803
 
    to the record file
3804
 
-------------------------------------------------*/
3805
 
 
3806
 
static void record_write_uint32(running_machine &machine, UINT32 data)
3807
 
{
3808
 
        input_port_private *portdata = machine.input_port_data;
3809
 
        UINT32 result = LITTLE_ENDIANIZE_INT32(data);
3810
 
 
3811
 
        /* protect against NULL handles if previous reads fail */
3812
 
        if (portdata->record_file == NULL)
3813
 
                return;
3814
 
 
3815
 
        /* read the value; if we fail, end playback */
3816
 
        if (portdata->record_file->write(&result, sizeof(result)) != sizeof(result))
3817
 
                record_end(machine, "Out of space");
3818
 
}
3819
 
 
3820
 
 
3821
 
/*-------------------------------------------------
3822
 
    record_write_uint64 - write a 64-bit value
3823
 
    to the record file
3824
 
-------------------------------------------------*/
3825
 
 
3826
 
static void record_write_uint64(running_machine &machine, UINT64 data)
3827
 
{
3828
 
        input_port_private *portdata = machine.input_port_data;
3829
 
        UINT64 result = LITTLE_ENDIANIZE_INT64(data);
3830
 
 
3831
 
        /* protect against NULL handles if previous reads fail */
3832
 
        if (portdata->record_file == NULL)
3833
 
                return;
3834
 
 
3835
 
        /* read the value; if we fail, end playback */
3836
 
        if (portdata->record_file->write(&result, sizeof(result)) != sizeof(result))
3837
 
                record_end(machine, "Out of space");
3838
 
}
3839
 
 
3840
 
 
3841
 
/*-------------------------------------------------
3842
 
    record_init - initialize INP recording
3843
 
-------------------------------------------------*/
3844
 
 
3845
 
static void record_init(running_machine &machine)
3846
 
{
3847
 
        const char *filename = machine.options().record();
3848
 
        input_port_private *portdata = machine.input_port_data;
3849
 
        UINT8 header[INP_HEADER_SIZE];
 
3592
//-------------------------------------------------
 
3593
//  record_write - write a value to the record file
 
3594
//-------------------------------------------------
 
3595
 
 
3596
template<typename _Type>
 
3597
void ioport_manager::record_write(_Type value)
 
3598
{
 
3599
        // protect against NULL handles if previous reads fail
 
3600
        if (!m_record_file.is_open())
 
3601
                return;
 
3602
 
 
3603
        // read the value; if we fail, end playback
 
3604
        if (m_record_file.write(&value, sizeof(value)) != sizeof(value))
 
3605
                record_end("Out of space");
 
3606
}
 
3607
 
 
3608
template<>
 
3609
void ioport_manager::record_write<bool>(bool value)
 
3610
{
 
3611
        UINT8 byte = UINT8(value);
 
3612
        record_write(byte);
 
3613
}
 
3614
 
 
3615
 
 
3616
//-------------------------------------------------
 
3617
//  record_init - initialize INP recording
 
3618
//-------------------------------------------------
 
3619
 
 
3620
void ioport_manager::record_init()
 
3621
{
 
3622
        // if no file, nothing to do
 
3623
        const char *filename = machine().options().record();
 
3624
        if (filename[0] == 0)
 
3625
                return;
 
3626
 
 
3627
        // open the record file
 
3628
        file_error filerr = m_record_file.open(filename);
 
3629
        assert_always(filerr == FILERR_NONE, "Failed to open file for recording");
 
3630
 
 
3631
        // get the base time
3850
3632
        system_time systime;
3851
 
 
3852
 
        /* if no file, nothing to do */
3853
 
        if (filename[0] == 0)
3854
 
                return;
3855
 
 
3856
 
        /* open the record file  */
3857
 
        portdata->record_file = auto_alloc(machine, emu_file(machine.options().input_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS));
3858
 
        file_error filerr = portdata->record_file->open(filename);
3859
 
        assert_always(filerr == FILERR_NONE, "Failed to open file for recording");
3860
 
 
3861
 
        /* get the base time */
3862
 
        machine.base_datetime(systime);
3863
 
 
3864
 
        /* fill in the header */
3865
 
        memset(header, 0, sizeof(header));
 
3633
        machine().base_datetime(systime);
 
3634
 
 
3635
        // fill in the header
 
3636
        UINT8 header[INP_HEADER_SIZE] = { 0 };
3866
3637
        memcpy(header, "MAMEINP\0", 8);
3867
3638
        header[0x08] = systime.time >> 0;
3868
3639
        header[0x09] = systime.time >> 8;
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);
3879
3650
 
3880
 
        /* write it */
3881
 
        portdata->record_file->write(header, sizeof(header));
 
3651
        // write it
 
3652
        m_record_file.write(header, sizeof(header));
3882
3653
 
3883
 
        /* enable compression */
3884
 
        portdata->record_file->compress(FCOMPRESS_MEDIUM);
 
3654
        // enable compression
 
3655
        m_record_file.compress(FCOMPRESS_MEDIUM);
3885
3656
}
3886
3657
 
3887
3658
 
3888
 
/*-------------------------------------------------
3889
 
    record_end - end INP recording
3890
 
-------------------------------------------------*/
 
3659
//-------------------------------------------------
 
3660
//  record_end - end INP recording
 
3661
//-------------------------------------------------
3891
3662
 
3892
 
static void record_end(running_machine &machine, const char *message)
 
3663
void ioport_manager::record_end(const char *message)
3893
3664
{
3894
 
        input_port_private *portdata = machine.input_port_data;
3895
 
 
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())
3898
3667
        {
3899
 
                /* close the file */
3900
 
                auto_free(machine, portdata->record_file);
3901
 
                portdata->record_file = NULL;
 
3668
                // close the file
 
3669
                m_record_file.close();
3902
3670
 
3903
 
                /* pop a message */
 
3671
                // pop a message
3904
3672
                if (message != NULL)
3905
3673
                        popmessage("Recording Ended\nReason: %s", message);
3906
3674
        }
3907
3675
}
3908
3676
 
3909
3677
 
3910
 
/*-------------------------------------------------
3911
 
    record_frame - start of frame callback for
3912
 
    recording
3913
 
-------------------------------------------------*/
3914
 
 
3915
 
static void record_frame(running_machine &machine, attotime curtime)
3916
 
{
3917
 
        input_port_private *portdata = machine.input_port_data;
3918
 
 
3919
 
        /* if recording, record information about the current frame */
3920
 
        if (portdata->record_file != NULL)
3921
 
        {
3922
 
                /* first the absolute time */
3923
 
                record_write_uint32(machine, curtime.seconds);
3924
 
                record_write_uint64(machine, curtime.attoseconds);
3925
 
 
3926
 
                /* then the current speed */
3927
 
                record_write_uint32(machine, machine.video().speed_percent() * (double)(1 << 20));
3928
 
        }
3929
 
}
3930
 
 
3931
 
 
3932
 
/*-------------------------------------------------
3933
 
    record_port - per-port callback for record
3934
 
-------------------------------------------------*/
3935
 
 
3936
 
static void record_port(const input_port_config *port)
3937
 
{
3938
 
        input_port_private *portdata = port->machine().input_port_data;
3939
 
 
3940
 
        /* if recording, store information about this port */
3941
 
        if (portdata->record_file != NULL)
3942
 
        {
3943
 
                analog_field_state *analog;
3944
 
 
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);
3948
 
 
3949
 
                /* loop over analog ports and save their data */
3950
 
                for (analog = port->state->analoglist; analog != NULL; analog = analog->next)
3951
 
                {
3952
 
                        /* store current and previous values */
3953
 
                        record_write_uint32(port->machine(), analog->accum);
3954
 
                        record_write_uint32(port->machine(), analog->previous);
3955
 
 
3956
 
                        /* store configuration information */
3957
 
                        record_write_uint32(port->machine(), analog->sensitivity);
3958
 
                        record_write_uint8(port->machine(), analog->reverse);
3959
 
                }
3960
 
        }
3961
 
}
3962
 
 
3963
 
int input_machine_has_keyboard(running_machine &machine)
3964
 
{
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())
3969
 
        {
3970
 
                for (field = port->first_field(); field != NULL; field = field->next())
3971
 
                {
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)
3974
 
                        {
3975
 
                                have_keyboard = TRUE;
3976
 
                                break;
3977
 
                        }
3978
 
 
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()))
3981
 
                        {
3982
 
                                have_keyboard = TRUE;
3983
 
                                break;
3984
 
                        }
3985
 
                }
3986
 
        }
3987
 
        return have_keyboard;
3988
 
}
3989
 
 
3990
 
/***************************************************************************
3991
 
    CODE ASSEMBLING
3992
 
***************************************************************************/
3993
 
 
3994
 
/*-------------------------------------------------
3995
 
    code_point_string - obtain a string representation of a
3996
 
    given code; used for logging and debugging
3997
 
-------------------------------------------------*/
3998
 
 
3999
 
static const char *code_point_string(running_machine &machine, unicode_char ch)
4000
 
{
4001
 
        static char buf[16];
4002
 
        const char *result = buf;
4003
 
 
4004
 
        switch(ch)
4005
 
        {
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;
4011
 
 
4012
 
                default:
4013
 
                        if ((ch >= 32) && (ch < 128))
4014
 
                        {
4015
 
                                /* seven bit ASCII is easy */
4016
 
                                buf[0] = (char) ch;
4017
 
                                buf[1] = '\0';
4018
 
                        }
4019
 
                        else if (ch >= UCHAR_MAMEKEY_BEGIN)
4020
 
                        {
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));
4023
 
                                astring tempstr;
4024
 
                                snprintf(buf, ARRAY_LENGTH(buf), "%s", machine.input().code_name(tempstr, code));
4025
 
                        }
4026
 
                        else
4027
 
                        {
4028
 
                                /* empty string; resolve later */
4029
 
                                buf[0] = '\0';
4030
 
                        }
4031
 
 
4032
 
                        /* did we fail to resolve? if so, we have a last resort */
4033
 
                        if (buf[0] == '\0')
4034
 
                                snprintf(buf, ARRAY_LENGTH(buf), "U+%04X", (unsigned) ch);
4035
 
                        break;
4036
 
        }
4037
 
        return result;
4038
 
}
4039
 
 
4040
 
 
4041
 
/*-------------------------------------------------
4042
 
    scan_keys - scans through input ports and
4043
 
    sets up natural keyboard input mapping
4044
 
-------------------------------------------------*/
4045
 
 
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)
4047
 
{
4048
 
        int code_count = 0;
4049
 
        const input_port_config *port;
4050
 
        const input_field_config *field;
4051
 
        unicode_char code;
4052
 
 
4053
 
        assert(keys < NUM_SIMUL_KEYS);
4054
 
 
4055
 
        for (port = portconfig; port != NULL; port = port->next())
4056
 
        {
4057
 
                for (field = port->first_field(); field != NULL; field = field->next())
4058
 
                {
4059
 
                        if (field->type == IPT_KEYBOARD)
4060
 
                        {
4061
 
                                code = get_keyboard_code(field, shift);
4062
 
                                if (code != 0)
4063
 
                                {
4064
 
                                        /* is this a shifter key? */
4065
 
                                        if ((code >= UCHAR_SHIFT_BEGIN) && (code <= UCHAR_SHIFT_END))
4066
 
                                        {
4067
 
                                                shift_ports[keys] = field;
4068
 
                                                code_count += scan_keys(machine,
4069
 
                                                        portconfig,
4070
 
                                                        codes ? &codes[code_count] : NULL,
4071
 
                                                        ports,
4072
 
                                                        shift_ports,
4073
 
                                                        keys+1,
4074
 
                                                        code - UCHAR_SHIFT_1 + 1);
4075
 
                                        }
4076
 
                                        else
4077
 
                                        {
4078
 
                                                /* not a shifter key; record normally */
4079
 
                                                if (codes)
4080
 
                                                {
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;
4085
 
                                                }
4086
 
 
4087
 
                                                /* increment the count */
4088
 
                                                code_count++;
4089
 
 
4090
 
                                                if (LOG_INPUTX)
4091
 
                                                        logerror("inputx: code=%i (%s) port=%p field->name='%s'\n", (int) code, code_point_string(machine, code), port, field->name);
4092
 
                                        }
4093
 
                                }
4094
 
                        }
4095
 
                }
4096
 
        }
4097
 
        return code_count;
4098
 
}
4099
 
 
4100
 
 
4101
 
 
4102
 
/*-------------------------------------------------
4103
 
    build_codes - given an input port table, create
4104
 
    a input code table useful for mapping unicode
4105
 
    chars
4106
 
-------------------------------------------------*/
4107
 
 
4108
 
static inputx_code *build_codes(running_machine &machine, const input_port_config *portconfig)
4109
 
{
4110
 
        inputx_code *codes = NULL;
4111
 
        const input_port_config *ports[NUM_SIMUL_KEYS];
4112
 
        const input_field_config *fields[NUM_SIMUL_KEYS];
4113
 
        int code_count;
4114
 
 
4115
 
        /* first count the number of codes */
4116
 
        code_count = scan_keys(machine, portconfig, NULL, ports, fields, 0, 0);
4117
 
        if (code_count > 0)
4118
 
        {
4119
 
                /* allocate the codes */
4120
 
                codes = auto_alloc_array_clear(machine, inputx_code, code_count + 1);
4121
 
 
4122
 
                /* and populate them */
4123
 
                scan_keys(machine, portconfig, codes, ports, fields, 0, 0);
4124
 
        }
4125
 
        return codes;
4126
 
}
4127
 
 
4128
 
 
4129
 
 
4130
 
/***************************************************************************
4131
 
    VALIDITY CHECKS
4132
 
***************************************************************************/
4133
 
 
4134
 
/*-------------------------------------------------
4135
 
    validate_natural_keyboard_statics -
4136
 
    validates natural keyboard static data
4137
 
-------------------------------------------------*/
4138
 
 
4139
 
int validate_natural_keyboard_statics(void)
4140
 
{
4141
 
        int i;
4142
 
        int error = FALSE;
4143
 
        unicode_char last_char = 0;
4144
 
        const char_info *ci;
4145
 
 
4146
 
        /* check to make sure that charinfo is in order */
4147
 
        for (i = 0; i < ARRAY_LENGTH(charinfo); i++)
4148
 
        {
4149
 
                if (last_char >= charinfo[i].ch)
4150
 
                {
4151
 
                        mame_printf_error("inputx: charinfo is out of order; 0x%08x should be higher than 0x%08x\n", charinfo[i].ch, last_char);
4152
 
                        error = TRUE;
4153
 
                }
4154
 
                last_char = charinfo[i].ch;
4155
 
        }
4156
 
 
4157
 
        /* check to make sure that I can look up everything on alternate_charmap */
4158
 
        for (i = 0; i < ARRAY_LENGTH(charinfo); i++)
4159
 
        {
4160
 
                ci = find_charinfo(charinfo[i].ch);
4161
 
                if (ci != &charinfo[i])
4162
 
                {
4163
 
                        mame_printf_error("inputx: expected find_charinfo(0x%08x) to work properly\n", charinfo[i].ch);
4164
 
                        error = TRUE;
4165
 
                }
4166
 
        }
4167
 
        return error;
4168
 
}
4169
 
 
4170
 
 
4171
 
 
4172
 
/***************************************************************************
4173
 
    CORE IMPLEMENTATION
4174
 
***************************************************************************/
4175
 
 
4176
 
static void clear_keybuffer(running_machine &machine)
4177
 
{
4178
 
        input_port_private *portdata = machine.input_port_data;
4179
 
        portdata->keybuffer = NULL;
4180
 
        portdata->queue_chars = NULL;
4181
 
        portdata->codes = NULL;
4182
 
}
4183
 
 
4184
 
 
4185
 
 
4186
 
static void setup_keybuffer(running_machine &machine)
4187
 
{
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));
4192
 
}
4193
 
 
4194
 
 
4195
 
 
4196
 
void inputx_init(running_machine &machine)
4197
 
{
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;
4205
 
 
4206
 
        if (machine.debug_flags & DEBUG_FLAG_ENABLED)
4207
 
        {
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);
4210
 
        }
4211
 
 
4212
 
        /* posting keys directly only makes sense for a computer */
4213
 
        if (input_machine_has_keyboard(machine))
4214
 
        {
4215
 
                portdata->codes = build_codes(machine, machine.m_portlist.first());
4216
 
                setup_keybuffer(machine);
4217
 
        }
4218
 
}
4219
 
 
4220
 
 
4221
 
 
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))
4227
 
{
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;
4232
 
}
4233
 
 
4234
 
int inputx_can_post(running_machine &machine)
4235
 
{
4236
 
        input_port_private *portdata = machine.input_port_data;
4237
 
        return portdata->queue_chars || portdata->codes;
4238
 
}
4239
 
 
4240
 
 
4241
 
static int can_post_key_directly(running_machine &machine, unicode_char ch)
4242
 
{
4243
 
        input_port_private *portdata = machine.input_port_data;
4244
 
        int rc = FALSE;
4245
 
        const inputx_code *code;
4246
 
 
4247
 
        if (portdata->queue_chars)
4248
 
        {
4249
 
                rc = portdata->accept_char ? (*portdata->accept_char)(machine, ch) : TRUE;
4250
 
        }
4251
 
        else
4252
 
        {
4253
 
                code = find_code(portdata->codes, ch);
4254
 
                if (code)
4255
 
                        rc = code->field[0] != NULL;
4256
 
        }
4257
 
        return rc;
4258
 
}
4259
 
 
4260
 
 
4261
 
 
4262
 
static int can_post_key_alternate(running_machine &machine, unicode_char ch)
4263
 
{
4264
 
        const char *s;
4265
 
        const char_info *ci;
4266
 
        unicode_char uchar;
4267
 
        int rc;
4268
 
 
4269
 
        ci = find_charinfo(ch);
4270
 
        s = ci ? ci->alternate : NULL;
4271
 
        if (!s)
4272
 
                return 0;
4273
 
 
4274
 
        while(*s)
4275
 
        {
4276
 
                rc = uchar_from_utf8(&uchar, s, strlen(s));
4277
 
                if (rc <= 0)
4278
 
                        return 0;
4279
 
                if (!can_post_key_directly(machine, uchar))
4280
 
                        return 0;
4281
 
                s += rc;
4282
 
        }
4283
 
        return 1;
4284
 
}
4285
 
 
4286
 
static attotime choose_delay(input_port_private *portdata, unicode_char ch)
4287
 
{
4288
 
        if (portdata->current_rate != attotime::zero)
4289
 
                return portdata->current_rate;
4290
 
 
4291
 
        attotime delay = attotime::zero;
4292
 
        if (portdata->queue_chars)
4293
 
        {
4294
 
                /* systems with queue_chars can afford a much smaller delay */
4295
 
                delay = attotime::from_msec(10);
4296
 
        }
4297
 
        else
4298
 
        {
4299
 
                switch(ch) {
4300
 
                case '\r':
4301
 
                        delay = attotime::from_msec(200);
4302
 
                        break;
4303
 
 
4304
 
                default:
4305
 
                        delay = attotime::from_msec(50);
4306
 
                        break;
4307
 
                }
4308
 
        }
4309
 
        return delay;
4310
 
}
4311
 
 
4312
 
 
4313
 
 
4314
 
static void internal_post_key(running_machine &machine, unicode_char ch)
4315
 
{
4316
 
        input_port_private *portdata = machine.input_port_data;
4317
 
        key_buffer *keybuf;
4318
 
 
4319
 
        keybuf = get_buffer(machine);
4320
 
 
4321
 
        /* need to start up the timer? */
4322
 
        if (keybuf->begin_pos == keybuf->end_pos)
4323
 
        {
4324
 
                portdata->inputx_timer->adjust(choose_delay(portdata, ch));
4325
 
                keybuf->status_keydown = 0;
4326
 
        }
4327
 
 
4328
 
        keybuf->buffer[keybuf->end_pos++] = ch;
4329
 
        keybuf->end_pos %= ARRAY_LENGTH(keybuf->buffer);
4330
 
}
4331
 
 
4332
 
 
4333
 
 
4334
 
static int buffer_full(running_machine &machine)
4335
 
{
4336
 
        key_buffer *keybuf;
4337
 
        keybuf = get_buffer(machine);
4338
 
        return ((keybuf->end_pos + 1) % ARRAY_LENGTH(keybuf->buffer)) == keybuf->begin_pos;
4339
 
}
4340
 
 
4341
 
 
4342
 
 
4343
 
static void inputx_postn_rate(running_machine &machine, const unicode_char *text, size_t text_len, attotime rate)
4344
 
{
4345
 
        input_port_private *portdata = machine.input_port_data;
4346
 
        int last_cr = 0;
4347
 
        unicode_char ch;
4348
 
        const char *s;
4349
 
        const char_info *ci;
4350
 
        const inputx_code *code;
4351
 
 
4352
 
        portdata->current_rate = rate;
4353
 
 
4354
 
        if (inputx_can_post(machine))
4355
 
        {
4356
 
                while((text_len > 0) && !buffer_full(machine))
4357
 
                {
4358
 
                        ch = *(text++);
4359
 
                        text_len--;
4360
 
 
4361
 
                        /* change all eolns to '\r' */
4362
 
                        if ((ch != '\n') || !last_cr)
4363
 
                        {
4364
 
                                if (ch == '\n')
4365
 
                                        ch = '\r';
4366
 
                                else
4367
 
                                        last_cr = (ch == '\r');
4368
 
 
4369
 
                                if (LOG_INPUTX)
4370
 
                                {
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>");
4373
 
                                }
4374
 
 
4375
 
                                if (can_post_key_directly(machine, ch))
4376
 
                                {
4377
 
                                        /* we can post this key in the queue directly */
4378
 
                                        internal_post_key(machine, ch);
4379
 
                                }
4380
 
                                else if (can_post_key_alternate(machine, ch))
4381
 
                                {
4382
 
                                        /* we can post this key with an alternate representation */
4383
 
                                        ci = find_charinfo(ch);
4384
 
                                        assert(ci && ci->alternate);
4385
 
                                        s = ci->alternate;
4386
 
                                        while(*s)
4387
 
                                        {
4388
 
                                                s += uchar_from_utf8(&ch, s, strlen(s));
4389
 
                                                internal_post_key(machine, ch);
4390
 
                                        }
4391
 
                                }
4392
 
                        }
4393
 
                        else
4394
 
                        {
4395
 
                                last_cr = 0;
4396
 
                        }
4397
 
                }
4398
 
        }
4399
 
}
4400
 
 
4401
 
 
4402
 
 
4403
 
static TIMER_CALLBACK(inputx_timerproc)
4404
 
{
4405
 
        input_port_private *portdata = machine.input_port_data;
4406
 
        key_buffer *keybuf;
4407
 
        attotime delay;
4408
 
 
4409
 
        keybuf = get_buffer(machine);
4410
 
 
4411
 
        if (portdata->queue_chars)
4412
 
        {
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))
4415
 
                {
4416
 
                        keybuf->begin_pos++;
4417
 
                        keybuf->begin_pos %= ARRAY_LENGTH(keybuf->buffer);
4418
 
 
4419
 
                        if (portdata->current_rate != attotime::zero)
4420
 
                                break;
4421
 
                }
4422
 
        }
4423
 
        else
4424
 
        {
4425
 
                /* the driver does not have a queue_chars handler */
4426
 
                if (keybuf->status_keydown)
4427
 
                {
4428
 
                        keybuf->status_keydown = FALSE;
4429
 
                        keybuf->begin_pos++;
4430
 
                        keybuf->begin_pos %= ARRAY_LENGTH(keybuf->buffer);
4431
 
                }
4432
 
                else
4433
 
                {
4434
 
                        keybuf->status_keydown = TRUE;
4435
 
                }
4436
 
        }
4437
 
 
4438
 
        /* need to make sure timerproc is called again if buffer not empty */
4439
 
        if (keybuf->begin_pos != keybuf->end_pos)
4440
 
        {
4441
 
                delay = choose_delay(portdata, keybuf->buffer[keybuf->begin_pos]);
4442
 
                portdata->inputx_timer->adjust(delay);
4443
 
        }
4444
 
}
4445
 
 
4446
 
int inputx_is_posting(running_machine &machine)
4447
 
{
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));
4452
 
}
4453
 
 
4454
 
/***************************************************************************
4455
 
 
4456
 
    Coded input
4457
 
 
4458
 
***************************************************************************/
4459
 
static void inputx_postc_rate(running_machine &machine, unicode_char ch, attotime rate);
4460
 
 
4461
 
static void inputx_postn_coded_rate(running_machine &machine, const char *text, size_t text_len, attotime rate)
4462
 
{
4463
 
        size_t i, j, key_len, increment;
4464
 
        unicode_char ch;
4465
 
 
4466
 
        static const struct
4467
 
        {
4468
 
                const char *key;
4469
 
                unicode_char code;
4470
 
        } codes[] =
4471
 
        {
4472
 
                { "BACKSPACE",  8 },
4473
 
                { "BS",                 8 },
4474
 
                { "BKSP",               8 },
4475
 
                { "DEL",                UCHAR_MAMEKEY(DEL) },
4476
 
                { "DELETE",             UCHAR_MAMEKEY(DEL) },
4477
 
                { "END",                UCHAR_MAMEKEY(END) },
4478
 
                { "ENTER",              13 },
4479
 
                { "ESC",                '\033' },
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) },
4485
 
                { "SPACE",              32 },
4486
 
                { "TAB",                9 },
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) },
4499
 
                { "QUOTE",              '\"' }
4500
 
        };
4501
 
 
4502
 
        i = 0;
4503
 
        while(i < text_len)
4504
 
        {
4505
 
                ch = text[i];
4506
 
                increment = 1;
4507
 
 
4508
 
                if (ch == '{')
4509
 
                {
4510
 
                        for (j = 0; j < ARRAY_LENGTH(codes); j++)
4511
 
                        {
4512
 
                                key_len = strlen(codes[j].key);
4513
 
                                if (i + key_len + 2 <= text_len)
4514
 
                                {
4515
 
                                        if (!core_strnicmp(codes[j].key, &text[i + 1], key_len) && (text[i + key_len + 1] == '}'))
4516
 
                                        {
4517
 
                                                ch = codes[j].code;
4518
 
                                                increment = key_len + 2;
4519
 
                                        }
4520
 
                                }
4521
 
                        }
4522
 
                }
4523
 
 
4524
 
                if (ch)
4525
 
                        inputx_postc_rate(machine, ch, rate);
4526
 
                i += increment;
4527
 
        }
4528
 
}
4529
 
 
4530
 
 
4531
 
 
4532
 
/***************************************************************************
4533
 
 
4534
 
    Alternative calls
4535
 
 
4536
 
***************************************************************************/
4537
 
 
4538
 
static void inputx_postc_rate(running_machine &machine, unicode_char ch, attotime rate)
4539
 
{
4540
 
        inputx_postn_rate(machine, &ch, 1, rate);
4541
 
}
4542
 
 
4543
 
void inputx_postc(running_machine &machine, unicode_char ch)
4544
 
{
4545
 
        inputx_postc_rate(machine, ch, attotime::zero);
4546
 
}
4547
 
 
4548
 
static void inputx_postn_utf8_rate(running_machine &machine, const char *text, size_t text_len, attotime rate)
4549
 
{
4550
 
        size_t len = 0;
4551
 
        unicode_char buf[256];
4552
 
        unicode_char c;
4553
 
        int rc;
4554
 
 
4555
 
        while(text_len > 0)
4556
 
        {
4557
 
                if (len == ARRAY_LENGTH(buf))
4558
 
                {
4559
 
                        inputx_postn_rate(machine, buf, len, attotime::zero);
4560
 
                        len = 0;
4561
 
                }
4562
 
 
4563
 
                rc = uchar_from_utf8(&c, text, text_len);
4564
 
                if (rc < 0)
4565
 
                {
4566
 
                        rc = 1;
4567
 
                        c = INVALID_CHAR;
4568
 
                }
4569
 
                text += rc;
4570
 
                text_len -= rc;
4571
 
                buf[len++] = c;
4572
 
        }
4573
 
        inputx_postn_rate(machine, buf, len, rate);
4574
 
}
4575
 
 
4576
 
void inputx_post_utf8(running_machine &machine, const char *text)
4577
 
{
4578
 
        inputx_postn_utf8_rate(machine, text, strlen(text), attotime::zero);
4579
 
}
4580
 
 
4581
 
void inputx_post_utf8_rate(running_machine &machine, const char *text, attotime rate)
4582
 
{
4583
 
        inputx_postn_utf8_rate(machine, text, strlen(text), rate);
4584
 
}
4585
 
 
4586
 
/***************************************************************************
4587
 
 
4588
 
    Other stuff
4589
 
 
4590
 
    This stuff is here more out of convienience than anything else
4591
 
***************************************************************************/
4592
 
 
4593
 
int input_classify_port(const input_field_config *field)
4594
 
{
4595
 
        int result;
4596
 
 
4597
 
        switch(field->type)
4598
 
        {
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:
4611
 
                case IPT_BUTTON1:
4612
 
                case IPT_BUTTON2:
4613
 
                case IPT_BUTTON3:
4614
 
                case IPT_BUTTON4:
4615
 
                case IPT_BUTTON5:
4616
 
                case IPT_BUTTON6:
4617
 
                case IPT_BUTTON7:
4618
 
                case IPT_BUTTON8:
4619
 
                case IPT_BUTTON9:
4620
 
                case IPT_BUTTON10:
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:
4628
 
                case IPT_MOUSE_X:
4629
 
                case IPT_MOUSE_Y:
4630
 
                case IPT_START:
4631
 
                case IPT_SELECT:
4632
 
                        result = INPUT_CLASS_CONTROLLER;
4633
 
                        break;
4634
 
 
4635
 
                case IPT_KEYPAD:
4636
 
                case IPT_KEYBOARD:
4637
 
                        result = INPUT_CLASS_KEYBOARD;
4638
 
                        break;
4639
 
 
4640
 
                case IPT_CONFIG:
4641
 
                        result = INPUT_CLASS_CONFIG;
4642
 
                        break;
4643
 
 
4644
 
                case IPT_DIPSWITCH:
4645
 
                        result = INPUT_CLASS_DIPSWITCH;
4646
 
                        break;
4647
 
 
4648
 
                case 0:
4649
 
                        if (field->name && (field->name != (const char *) -1))
4650
 
                                result = INPUT_CLASS_MISC;
4651
 
                        else
4652
 
                                result = INPUT_CLASS_INTERNAL;
4653
 
                        break;
4654
 
 
4655
 
                default:
4656
 
                        result = INPUT_CLASS_INTERNAL;
4657
 
                        break;
4658
 
        }
4659
 
        return result;
4660
 
}
4661
 
 
4662
 
 
4663
 
 
4664
 
int input_player_number(const input_field_config *port)
4665
 
{
4666
 
        return port->player;
4667
 
}
4668
 
 
4669
 
 
4670
 
 
4671
 
/*-------------------------------------------------
4672
 
    input_has_input_class - checks to see if a
4673
 
    particular input class is present
4674
 
-------------------------------------------------*/
4675
 
 
4676
 
int input_has_input_class(running_machine &machine, int inputclass)
4677
 
{
4678
 
        const input_port_config *port;
4679
 
        const input_field_config *field;
4680
 
 
4681
 
        for (port = machine.m_portlist.first(); port != NULL; port = port->next())
4682
 
        {
4683
 
                for (field = port->first_field(); field != NULL; field = field->next())
4684
 
                {
4685
 
                        if (input_classify_port(field) == inputclass)
4686
 
                                return TRUE;
4687
 
                }
4688
 
        }
4689
 
        return FALSE;
4690
 
}
4691
 
 
4692
 
 
4693
 
 
4694
 
/*-------------------------------------------------
4695
 
    input_count_players - counts the number of
4696
 
    active players
4697
 
-------------------------------------------------*/
4698
 
 
4699
 
int input_count_players(running_machine &machine)
4700
 
{
4701
 
        const input_port_config *port;
4702
 
        const input_field_config *field;
4703
 
        int joystick_count;
4704
 
 
4705
 
        joystick_count = 0;
4706
 
        for (port = machine.m_portlist.first(); port != NULL; port = port->next())
4707
 
        {
4708
 
                for (field = port->first_field(); field != NULL; field = field->next())
4709
 
                {
4710
 
                        if (input_classify_port(field) == INPUT_CLASS_CONTROLLER)
4711
 
                        {
4712
 
                                if (joystick_count <= field->player + 1)
4713
 
                                        joystick_count = field->player + 1;
4714
 
                        }
4715
 
                }
4716
 
        }
4717
 
        return joystick_count;
4718
 
}
4719
 
 
4720
 
 
4721
 
 
4722
 
/***************************************************************************
4723
 
    DEBUGGER SUPPORT
4724
 
***************************************************************************/
4725
 
 
4726
 
/*-------------------------------------------------
4727
 
    execute_input - debugger command to enter
4728
 
    natural keyboard input
4729
 
-------------------------------------------------*/
4730
 
 
4731
 
static void execute_input(running_machine &machine, int ref, int params, const char *param[])
4732
 
{
4733
 
        inputx_postn_coded_rate(machine, param[0], strlen(param[0]), attotime::zero);
4734
 
}
4735
 
 
4736
 
 
4737
 
 
4738
 
/*-------------------------------------------------
4739
 
    execute_dumpkbd - debugger command to natural
4740
 
    keyboard codes
4741
 
-------------------------------------------------*/
4742
 
 
4743
 
static void execute_dumpkbd(running_machine &machine, int ref, int params, const char *param[])
4744
 
{
4745
 
        inputx_code *codes = machine.input_port_data->codes;
4746
 
        const char *filename;
4747
 
        FILE *file = NULL;
4748
 
        const inputx_code *code;
4749
 
        char buffer[512];
4750
 
        size_t pos;
4751
 
        int i, j;
4752
 
        size_t left_column_width = 24;
4753
 
 
4754
 
        /* was there a file specified? */
4755
 
        filename = (params > 0) ? param[0] : NULL;
4756
 
        if (filename != NULL)
4757
 
        {
4758
 
                /* if so, open it */
4759
 
                file = fopen(filename, "w");
4760
 
                if (file == NULL)
4761
 
                {
4762
 
                        debug_console_printf(machine, "Cannot open \"%s\"\n", filename);
4763
 
                        return;
4764
 
                }
4765
 
        }
4766
 
 
4767
 
        if ((codes != NULL) && (codes[0].ch != 0))
4768
 
        {
4769
 
                /* loop through all codes */
4770
 
                for (i = 0; codes[i].ch; i++)
4771
 
                {
4772
 
                        code = &codes[i];
4773
 
                        pos = 0;
4774
 
 
4775
 
                        /* describe the character code */
4776
 
                        pos += snprintf(&buffer[pos], ARRAY_LENGTH(buffer) - pos, "%08X (%s) ",
4777
 
                                code->ch,
4778
 
                                code_point_string(machine, code->ch));
4779
 
 
4780
 
                        /* pad with spaces */
4781
 
                        while(pos < left_column_width)
4782
 
                                buffer[pos++] = ' ';
4783
 
                        buffer[pos] = '\0';
4784
 
 
4785
 
                        /* identify the keys used */
4786
 
                        for (j = 0; j < ARRAY_LENGTH(code->field) && (code->field[j] != NULL); j++)
4787
 
                        {
4788
 
                                pos += snprintf(&buffer[pos], ARRAY_LENGTH(buffer) - pos, "%s'%s'",
4789
 
                                        (j > 0) ? ", " : "",
4790
 
                                        code->field[j]->name);
4791
 
                        }
4792
 
 
4793
 
                        /* and output it as appropriate */
4794
 
                        if (file != NULL)
4795
 
                                fprintf(file, "%s\n", buffer);
4796
 
                        else
4797
 
                                debug_console_printf(machine, "%s\n", buffer);
4798
 
                }
4799
 
        }
4800
 
        else
4801
 
        {
4802
 
                debug_console_printf(machine, "No natural keyboard support\n");
4803
 
        }
4804
 
 
4805
 
        /* cleanup */
4806
 
        if (file != NULL)
4807
 
                fclose(file);
4808
 
 
4809
 
}
4810
 
 
4811
 
 
4812
 
 
4813
 
input_port_config *ioconfig_alloc_port(ioport_list &portlist, device_t &device, const char *tag)
4814
 
{
4815
 
        astring fulltag;
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)));
4819
 
}
4820
 
 
4821
 
input_port_config *ioconfig_modify_port(ioport_list &portlist, device_t &device, const char *tag)
4822
 
{
4823
 
        astring fulltag;
4824
 
        device.subtag(fulltag, tag);
4825
 
        input_port_config *port = portlist.find(fulltag.cstr());
4826
 
        if (port == NULL)
 
3678
//-------------------------------------------------
 
3679
//  record_frame - start of frame callback for
 
3680
//  recording
 
3681
//-------------------------------------------------
 
3682
 
 
3683
void ioport_manager::record_frame(attotime curtime)
 
3684
{
 
3685
        // if recording, record information about the current frame
 
3686
        if (m_record_file.is_open())
 
3687
        {
 
3688
                // first the absolute time
 
3689
                record_write(curtime.seconds);
 
3690
                record_write(curtime.attoseconds);
 
3691
 
 
3692
                // then the current speed
 
3693
                record_write(UINT32(machine().video().speed_percent() * double(1 << 20)));
 
3694
        }
 
3695
}
 
3696
 
 
3697
 
 
3698
//-------------------------------------------------
 
3699
//  record_port - per-port callback for record
 
3700
//-------------------------------------------------
 
3701
 
 
3702
void ioport_manager::record_port(ioport_port &port)
 
3703
{
 
3704
        // if recording, store information about this port
 
3705
        if (m_record_file.is_open())
 
3706
        {
 
3707
                // store the default value and digital state
 
3708
                record_write(port.live().defvalue);
 
3709
                record_write(port.live().digital);
 
3710
 
 
3711
                // loop over analog ports and save their data
 
3712
                for (analog_field *analog = port.live().analoglist.first(); analog != NULL; analog = analog->next())
 
3713
                {
 
3714
                        // store current and previous values
 
3715
                        record_write(analog->m_accum);
 
3716
                        record_write(analog->m_previous);
 
3717
 
 
3718
                        // store configuration information
 
3719
                        record_write(analog->m_sensitivity);
 
3720
                        record_write(analog->m_reverse);
 
3721
                }
 
3722
        }
 
3723
}
 
3724
 
 
3725
 
 
3726
 
 
3727
//**************************************************************************
 
3728
//  I/O PORT CONFIGURER
 
3729
//**************************************************************************
 
3730
 
 
3731
//-------------------------------------------------
 
3732
//  ioport_configurer - constructor
 
3733
//-------------------------------------------------
 
3734
 
 
3735
ioport_configurer::ioport_configurer(device_t &owner, ioport_list &portlist, astring &errorbuf)
 
3736
        : m_owner(owner),
 
3737
          m_portlist(portlist),
 
3738
          m_errorbuf(errorbuf),
 
3739
          m_curport(NULL),
 
3740
          m_curfield(NULL),
 
3741
          m_cursetting(NULL)
 
3742
{
 
3743
}
 
3744
 
 
3745
 
 
3746
//-------------------------------------------------
 
3747
//  string_from_token - convert an
 
3748
//  ioport_token to a default string
 
3749
//-------------------------------------------------
 
3750
 
 
3751
const char *ioport_configurer::string_from_token(const char *string)
 
3752
{
 
3753
        // 0 is an invalid index
 
3754
        if (string == NULL)
 
3755
                return NULL;
 
3756
 
 
3757
        // if the index is greater than the count, assume it to be a pointer
 
3758
        if (FPTR(string) >= INPUT_STRING_COUNT)
 
3759
                return string;
 
3760
 
 
3761
#if FALSE // Set TRUE, If you want to take care missing-token or wrong-sorting
 
3762
 
 
3763
        // otherwise, scan the list for a matching string and return it
 
3764
        {
 
3765
        int index;
 
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;
 
3769
        }
 
3770
        return "(Unknown Default)";
 
3771
 
 
3772
#else
 
3773
 
 
3774
        return input_port_default_strings[FPTR(string)-1].string;
 
3775
 
 
3776
#endif
 
3777
}
 
3778
 
 
3779
 
 
3780
//-------------------------------------------------
 
3781
//  port_alloc - allocate a new port
 
3782
//-------------------------------------------------
 
3783
 
 
3784
void ioport_configurer::port_alloc(const char *tag)
 
3785
{
 
3786
        // create the full tag
 
3787
        astring fulltag;
 
3788
        m_owner.subtag(fulltag, tag);
 
3789
 
 
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)));
 
3792
        m_curfield = NULL;
 
3793
        m_cursetting = NULL;
 
3794
}
 
3795
 
 
3796
 
 
3797
//-------------------------------------------------
 
3798
//  port_modify - find an existing port and
 
3799
//  modify it
 
3800
//-------------------------------------------------
 
3801
 
 
3802
void ioport_configurer::port_modify(const char *tag)
 
3803
{
 
3804
        // create the full tag
 
3805
        astring fulltag;
 
3806
        m_owner.subtag(fulltag, tag);
 
3807
 
 
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();
4829
 
        return port;
 
3812
 
 
3813
        // bump the modification count, and reset current field/setting
 
3814
        m_curport->m_modcount++;
 
3815
        m_curfield = NULL;
 
3816
        m_cursetting = NULL;
4830
3817
}
4831
3818
 
4832
 
input_field_config *ioconfig_alloc_field(input_port_config &port, int type, input_port_value defval, input_port_value mask, const char *name)
 
3819
 
 
3820
//-------------------------------------------------
 
3821
//  field_alloc - allocate a new field
 
3822
//-------------------------------------------------
 
3823
 
 
3824
void ioport_configurer::field_alloc(ioport_type type, ioport_value defval, ioport_value mask, const char *name)
4833
3825
{
4834
 
        if (&port == NULL)
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); \
 
3829
 
 
3830
        // append the field
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))));
4841
 
}
4842
 
 
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)
4844
 
{
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))));
 
3834
 
 
3835
        // reset the current setting
 
3836
        m_cursetting = NULL;
 
3837
}
 
3838
 
 
3839
 
 
3840
//-------------------------------------------------
 
3841
//  field_add_char - add a character to a field
 
3842
//-------------------------------------------------
 
3843
 
 
3844
void ioport_configurer::field_add_char(unicode_char ch)
 
3845
{
 
3846
        for (int index = 0; index < ARRAY_LENGTH(m_curfield->m_chars); index++)
 
3847
                if (m_curfield->m_chars[index] == 0)
 
3848
                {
 
3849
                        m_curfield->m_chars[index] = ch;
 
3850
                        return;
 
3851
                }
 
3852
 
 
3853
        throw emu_fatalerror("PORT_CHAR(%d) could not be added - maximum amount exceeded\n", ch);
 
3854
}
 
3855
 
 
3856
 
 
3857
//-------------------------------------------------
 
3858
//  field_add_code - add a character to a field
 
3859
//-------------------------------------------------
 
3860
 
 
3861
void ioport_configurer::field_add_code(input_seq_type which, input_code code)
 
3862
{
 
3863
        m_curfield->m_seq[which] |= code;
 
3864
}
 
3865
 
 
3866
 
 
3867
//-------------------------------------------------
 
3868
//  setting_alloc - allocate a new setting
 
3869
//-------------------------------------------------
 
3870
 
 
3871
void ioport_configurer::setting_alloc(ioport_value value, const char *name)
 
3872
{
 
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);
 
3876
 
 
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);
 
3880
}
 
3881
 
 
3882
 
 
3883
//-------------------------------------------------
 
3884
//  set_condition - set the condition for either
 
3885
//  the current setting or field
 
3886
//-------------------------------------------------
 
3887
 
 
3888
void ioport_configurer::set_condition(ioport_condition::condition_t condition, const char *tag, ioport_value mask, ioport_value value)
 
3889
{
 
3890
        ioport_condition &target = (m_cursetting != NULL) ? m_cursetting->condition() : m_curfield->condition();
 
3891
        target.set(condition, tag, mask, value);
 
3892
}
 
3893
 
 
3894
 
 
3895
//-------------------------------------------------
 
3896
//  onoff_alloc - allocate an on/off DIP switch
 
3897
//-------------------------------------------------
 
3898
 
 
3899
void ioport_configurer::onoff_alloc(const char *name, ioport_value defval, ioport_value mask, const char *diplocation)
 
3900
{
 
3901
        // allocate a field normally
 
3902
        field_alloc(IPT_DIPSWITCH, defval, mask, name);
 
3903
 
 
3904
        // special case service mode
4846
3905
        if (name == DEF_STR(Service_Mode))
4847
3906
        {
4848
 
                curfield->flags |= FIELD_FLAG_TOGGLE;
4849
 
                curfield->seq[SEQ_TYPE_STANDARD].set(KEYCODE_F2);
 
3907
                field_set_toggle();
 
3908
                m_curfield->m_seq[SEQ_TYPE_STANDARD].set(KEYCODE_F2);
4850
3909
        }
 
3910
 
 
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));
4855
 
        return curfield;
4856
 
}
4857
 
 
4858
 
input_setting_config *ioconfig_alloc_setting(input_field_config &field, input_port_value value, const char *name)
4859
 
{
4860
 
        return &field.settinglist().append(*global_alloc(input_setting_config(field, value, input_port_string_from_token(name))));
4861
 
}
4862
 
 
4863
 
void ioconfig_field_add_char(input_field_config &field, unicode_char ch, astring &errorbuf)
4864
 
{
4865
 
        for (int index = 0; index < ARRAY_LENGTH(field.chars); index++)
4866
 
                if (field.chars[index] == 0)
4867
 
                {
4868
 
                        field.chars[index] = ch;
4869
 
                        break;
4870
 
                }
4871
 
}
4872
 
 
4873
 
void ioconfig_add_code(input_field_config &field, int which, input_code code)
4874
 
{
4875
 
        field.seq[which] |= code;
4876
 
}
4877
 
 
4878
 
 
4879
 
 
4880
 
input_type_entry::input_type_entry(UINT32 _type, ioport_group _group, int _player, const char *_token, const char *_name, input_seq standard)
4881
 
        : type(_type),
4882
 
          group(_group),
4883
 
          player(_player),
4884
 
          token(_token),
4885
 
          name(_name),
4886
 
          m_next(NULL)
4887
 
{
4888
 
        defseq[SEQ_TYPE_STANDARD] = seq[SEQ_TYPE_STANDARD] = standard;
4889
 
}
4890
 
 
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)
4892
 
        : type(_type),
4893
 
          group(_group),
4894
 
          player(_player),
4895
 
          token(_token),
4896
 
          name(_name),
4897
 
          m_next(NULL)
4898
 
{
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;
4902
 
}
 
3913
                field_set_diplocation(diplocation);
 
3914
 
 
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;
 
3920
}
 
3921
 
 
3922
 
 
3923
 
 
3924
/***************************************************************************
 
3925
    MISCELLANEOUS
 
3926
***************************************************************************/
 
3927
 
 
3928
//-------------------------------------------------
 
3929
//  find - look up information about a particular
 
3930
//  character
 
3931
//-------------------------------------------------
 
3932
 
 
3933
const char_info *char_info::find(unicode_char target)
 
3934
{
 
3935
        // perform a simple binary search to find the proper alternate
 
3936
        int low = 0;
 
3937
        int high = ARRAY_LENGTH(charinfo);
 
3938
        while (high > low)
 
3939
        {
 
3940
                int middle = (high + low) / 2;
 
3941
                unicode_char ch = charinfo[middle].ch;
 
3942
                if (ch < target)
 
3943
                        low = middle + 1;
 
3944
                else if (ch > target)
 
3945
                        high = middle;
 
3946
                else
 
3947
                        return &charinfo[middle];
 
3948
        }
 
3949
        return NULL;
 
3950
}
 
3951
 
 
3952
 
 
3953
//-------------------------------------------------
 
3954
//  dynamic_field - constructor
 
3955
//-------------------------------------------------
 
3956
 
 
3957
dynamic_field::dynamic_field(ioport_field &field)
 
3958
        : m_next(NULL),
 
3959
          m_field(field),
 
3960
          m_shift(0),
 
3961
          m_oldval(field.defvalue())
 
3962
{
 
3963
        // fill in the data
 
3964
        for (ioport_value mask = field.mask(); !(mask & 1); mask >>= 1)
 
3965
                m_shift++;
 
3966
        m_oldval >>= m_shift;
 
3967
}
 
3968
 
 
3969
 
 
3970
//-------------------------------------------------
 
3971
//  read - read the updated value and merge it
 
3972
//  into the target
 
3973
//-------------------------------------------------
 
3974
 
 
3975
void dynamic_field::read(ioport_value &result)
 
3976
{
 
3977
        // skip if not enabled
 
3978
        if (!m_field.enabled())
 
3979
                return;
 
3980
 
 
3981
        // call the callback to read a new value
 
3982
        ioport_value newval = m_field.m_read(m_field, m_field.m_read_param);
 
3983
        m_oldval = newval;
 
3984
 
 
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());
 
3987
}
 
3988
 
 
3989
 
 
3990
//-------------------------------------------------
 
3991
//  write - track a change to a value and call
 
3992
//  the write callback if there's something new
 
3993
//-------------------------------------------------
 
3994
 
 
3995
void dynamic_field::write(ioport_value newval)
 
3996
{
 
3997
        // skip if not enabled
 
3998
        if (!m_field.enabled())
 
3999
                return;
 
4000
 
 
4001
        // if the bits have changed, call the handler
 
4002
        newval = (newval & m_field.mask()) >> m_shift;
 
4003
        if (m_oldval != newval)
 
4004
        {
 
4005
                m_field.m_write(m_field, m_field.m_write_param, m_oldval, newval);
 
4006
                m_oldval = newval;
 
4007
        }
 
4008
}
 
4009
 
 
4010
 
 
4011
//-------------------------------------------------
 
4012
//  analog_field - constructor
 
4013
//-------------------------------------------------
 
4014
 
 
4015
analog_field::analog_field(ioport_field &field)
 
4016
        : m_next(NULL),
 
4017
          m_field(field),
 
4018
          m_shift(0),
 
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()),
 
4026
          m_accum(0),
 
4027
          m_previous(0),
 
4028
          m_previousanalog(0),
 
4029
          m_minimum(INPUT_ABSOLUTE_MIN),
 
4030
          m_maximum(INPUT_ABSOLUTE_MAX),
 
4031
          m_center(0),
 
4032
          m_reverse_val(0),
 
4033
          m_scalepos(0),
 
4034
          m_scaleneg(0),
 
4035
          m_keyscalepos(0),
 
4036
          m_keyscaleneg(0),
 
4037
          m_positionalscale(0),
 
4038
          m_absolute(false),
 
4039
          m_wraps(false),
 
4040
          m_autocenter(false),
 
4041
          m_single_scale(false),
 
4042
          m_interpolate(false),
 
4043
          m_lastdigital(false)
 
4044
{
 
4045
        // compute the shift amount and number of bits
 
4046
        for (ioport_value mask = field.mask(); !(mask & 1); mask >>= 1)
 
4047
                m_shift++;
 
4048
 
 
4049
        // initialize core data
 
4050
        m_adjdefvalue >>= m_shift;
 
4051
        m_adjmin >>= m_shift;
 
4052
        m_adjmax >>= m_shift;
 
4053
 
 
4054
        // set basic parameters based on the configured type
 
4055
        switch (field.type())
 
4056
        {
 
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:
 
4061
                case IPT_PADDLE:
 
4062
                case IPT_PADDLE_V:
 
4063
                        m_absolute = true;
 
4064
                        m_autocenter = true;
 
4065
                        m_interpolate = !field.analog_reset();
 
4066
                        break;
 
4067
 
 
4068
                // pedals start at and autocenter to the min range
 
4069
                case IPT_PEDAL:
 
4070
                case IPT_PEDAL2:
 
4071
                case IPT_PEDAL3:
 
4072
                        m_center = INPUT_ABSOLUTE_MIN;
 
4073
                        m_accum = apply_inverse_sensitivity(m_center);
 
4074
                        m_absolute = true;
 
4075
                        m_autocenter = true;
 
4076
                        m_interpolate = !field.analog_reset();
 
4077
                        break;
 
4078
 
 
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:
 
4082
                        m_absolute = true;
 
4083
                        m_autocenter = false;
 
4084
                        m_interpolate = false;
 
4085
                        break;
 
4086
 
 
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);
 
4092
                        m_adjmin = 0;
 
4093
                        m_adjmax = field.maxval() - 1;
 
4094
                        m_wraps = field.analog_wraps();
 
4095
                        m_autocenter = !m_wraps;
 
4096
                        break;
 
4097
 
 
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
 
4102
                case IPT_DIAL:
 
4103
                case IPT_DIAL_V:
 
4104
                case IPT_TRACKBALL_X:
 
4105
                case IPT_TRACKBALL_Y:
 
4106
                case IPT_MOUSE_X:
 
4107
                case IPT_MOUSE_Y:
 
4108
                        m_absolute = false;
 
4109
                        m_wraps = true;
 
4110
                        m_interpolate = !field.analog_reset();
 
4111
                        break;
 
4112
 
 
4113
                default:
 
4114
                        fatalerror("Unknown analog port type -- don't know if it is absolute or not");
 
4115
                        break;
 
4116
        }
 
4117
 
 
4118
        // further processing for absolute controls
 
4119
        if (m_absolute)
 
4120
        {
 
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);
 
4123
 
 
4124
                // if not "single scale", compute separate scales for each side of the default
 
4125
                if (!m_single_scale)
 
4126
                {
 
4127
                        // unsigned
 
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);
 
4130
 
 
4131
                        if (m_adjmin > m_adjmax)
 
4132
                                m_scaleneg = -m_scaleneg;
 
4133
 
 
4134
                        // reverse point is at center
 
4135
                        m_reverse_val = 0;
 
4136
                }
 
4137
                else
 
4138
                {
 
4139
                        // single axis that increases from default
 
4140
                        m_scalepos = compute_scale(m_adjmax - m_adjmin, INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN);
 
4141
 
 
4142
                        // move from default
 
4143
                        if (m_adjdefvalue == m_adjmax)
 
4144
                                m_scalepos = -m_scalepos;
 
4145
 
 
4146
                        // make the scaling the same for easier coding when we need to scale
 
4147
                        m_scaleneg = m_scalepos;
 
4148
 
 
4149
                        // reverse point is at max
 
4150
                        m_reverse_val = m_maximum;
 
4151
                }
 
4152
        }
 
4153
 
 
4154
        // relative and positional controls all map directly with a 512x scale factor
 
4155
        else
 
4156
        {
 
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;
 
4164
 
 
4165
                if (m_wraps)
 
4166
                        m_adjmax++;
 
4167
 
 
4168
                m_minimum = (m_adjmin - m_adjdefvalue) * INPUT_RELATIVE_PER_PIXEL;
 
4169
                m_maximum = (m_adjmax - m_adjdefvalue) * INPUT_RELATIVE_PER_PIXEL;
 
4170
 
 
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);
 
4173
 
 
4174
                if (m_field.analog_reset())
 
4175
                        // delta values reverse from center
 
4176
                        m_reverse_val = 0;
 
4177
                else
 
4178
                {
 
4179
                        // positional controls reverse from their max range
 
4180
                        m_reverse_val = m_maximum + m_minimum;
 
4181
 
 
4182
                        // relative controls reverse from 1 past their max range
 
4183
                        if (m_wraps)
 
4184
                                m_reverse_val -= INPUT_RELATIVE_PER_PIXEL;
 
4185
                }
 
4186
        }
 
4187
 
 
4188
        // compute scale for keypresses
 
4189
        m_keyscalepos = recip_scale(m_scalepos);
 
4190
        m_keyscaleneg = recip_scale(m_scaleneg);
 
4191
}
 
4192
 
 
4193
 
 
4194
//-------------------------------------------------
 
4195
//  apply_min_max - clamp the given input value to
 
4196
//  the appropriate min/max for the analog control
 
4197
//-------------------------------------------------
 
4198
 
 
4199
inline INT32 analog_field::apply_min_max(INT32 value) const
 
4200
{
 
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);
 
4205
 
 
4206
        // for absolute devices, clamp to the bounds absolutely
 
4207
        if (!m_wraps)
 
4208
        {
 
4209
                if (value > adjmax)
 
4210
                        value = adjmax;
 
4211
                else if (value < adjmin)
 
4212
                        value = adjmin;
 
4213
        }
 
4214
 
 
4215
        // for relative devices, wrap around when we go past the edge
 
4216
        else
 
4217
        {
 
4218
                INT32 range = adjmax - adjmin;
 
4219
                // rolls to other end when 1 position past end.
 
4220
                value = (value - adjmin) % range;
 
4221
                if (value < 0)
 
4222
                        value += range;
 
4223
                value += adjmin;
 
4224
        }
 
4225
 
 
4226
        return value;
 
4227
}
 
4228
 
 
4229
 
 
4230
//-------------------------------------------------
 
4231
//  apply_sensitivity - apply a sensitivity
 
4232
//  adjustment for a current value
 
4233
//-------------------------------------------------
 
4234
 
 
4235
inline INT32 analog_field::apply_sensitivity(INT32 value) const
 
4236
{
 
4237
        return INT32((INT64(value) * m_sensitivity) / 100.0 + 0.5);
 
4238
}
 
4239
 
 
4240
 
 
4241
//-------------------------------------------------
 
4242
//  apply_inverse_sensitivity - reverse-apply the
 
4243
//  sensitivity adjustment for a current value
 
4244
//-------------------------------------------------
 
4245
 
 
4246
inline INT32 analog_field::apply_inverse_sensitivity(INT32 value) const
 
4247
{
 
4248
        return INT32((INT64(value) * 100) / m_sensitivity);
 
4249
}
 
4250
 
 
4251
 
 
4252
//-------------------------------------------------
 
4253
//  apply_settings - return the value of an
 
4254
//  analog input
 
4255
//-------------------------------------------------
 
4256
 
 
4257
INT32 analog_field::apply_settings(INT32 value) const
 
4258
{
 
4259
        // apply the min/max and then the sensitivity
 
4260
        value = apply_min_max(value);
 
4261
        value = apply_sensitivity(value);
 
4262
 
 
4263
        // apply reversal if needed
 
4264
        if (m_reverse)
 
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;
 
4270
 
 
4271
        // map differently for positive and negative values
 
4272
        if (value >= 0)
 
4273
                value = apply_scale(value, m_scalepos);
 
4274
        else
 
4275
                value = apply_scale(value, m_scaleneg);
 
4276
        value += m_adjdefvalue;
 
4277
 
 
4278
        return value;
 
4279
}
 
4280
 
 
4281
 
 
4282
//-------------------------------------------------
 
4283
//  frame_update - update the internals of a
 
4284
//  single analog field periodically
 
4285
//-------------------------------------------------
 
4286
 
 
4287
void analog_field::frame_update(running_machine &machine)
 
4288
{
 
4289
        // clamp the previous value to the min/max range and remember it
 
4290
        m_previous = m_accum = apply_min_max(m_accum);
 
4291
 
 
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);
 
4295
 
 
4296
        // if we got an absolute input, it overrides everything else
 
4297
        if (itemclass == ITEM_CLASS_ABSOLUTE)
 
4298
        {
 
4299
                if (m_previousanalog != rawvalue)
 
4300
                {
 
4301
                        // only update if analog value changed
 
4302
                        m_previousanalog = rawvalue;
 
4303
 
 
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())
 
4308
                        {
 
4309
                                // if port is absolute, then just return the absolute data supplied
 
4310
                                m_accum = apply_inverse_sensitivity(rawvalue);
 
4311
                        }
 
4312
                        else if (m_positionalscale != 0)
 
4313
                        {
 
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;
 
4318
 
 
4319
                                // clamp the high value so it does not roll over
 
4320
                                rawvalue = MIN(rawvalue, m_maximum);
 
4321
                                m_accum = apply_inverse_sensitivity(rawvalue);
 
4322
                        }
 
4323
                        else
 
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;
 
4327
 
 
4328
                        m_lastdigital = false;
 
4329
                        // do not bother with other control types if the analog data is changing
 
4330
                        return;
 
4331
                }
 
4332
                else
 
4333
                {
 
4334
                        // we still have to update fake relative from joystick control
 
4335
                        if (!m_absolute && m_positionalscale == 0)
 
4336
                                m_accum += rawvalue;
 
4337
                }
 
4338
        }
 
4339
 
 
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
 
4342
        INT32 delta = 0;
 
4343
        if (itemclass == ITEM_CLASS_RELATIVE && rawvalue != 0)
 
4344
        {
 
4345
                delta = rawvalue;
 
4346
                m_lastdigital = false;
 
4347
        }
 
4348
 
 
4349
        INT64 keyscale = (m_accum >= 0) ? m_keyscalepos : m_keyscaleneg;
 
4350
 
 
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)))
 
4355
        {
 
4356
                keypressed = true;
 
4357
                if (m_delta != 0)
 
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;
 
4363
        }
 
4364
 
 
4365
        // same for the increment code sequence
 
4366
        if (machine.input().seq_pressed(m_field.seq(SEQ_TYPE_INCREMENT)))
 
4367
        {
 
4368
                keypressed = true;
 
4369
                if (m_delta)
 
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;
 
4375
        }
 
4376
 
 
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())
 
4382
                m_accum = 0;
 
4383
 
 
4384
        // apply the delta to the accumulated value
 
4385
        m_accum += delta;
 
4386
 
 
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
 
4390
        if (m_autocenter)
 
4391
        {
 
4392
                INT32 center = apply_inverse_sensitivity(m_center);
 
4393
                if (m_lastdigital && !keypressed)
 
4394
                {
 
4395
                        // autocenter from positive values
 
4396
                        if (m_accum >= center)
 
4397
                        {
 
4398
                                m_accum -= apply_scale(m_centerdelta, m_keyscalepos);
 
4399
                                if (m_accum < center)
 
4400
                                {
 
4401
                                        m_accum = center;
 
4402
                                        m_lastdigital = false;
 
4403
                                }
 
4404
                        }
 
4405
 
 
4406
                        // autocenter from negative values
 
4407
                        else
 
4408
                        {
 
4409
                                m_accum += apply_scale(m_centerdelta, m_keyscaleneg);
 
4410
                                if (m_accum > center)
 
4411
                                {
 
4412
                                        m_accum = center;
 
4413
                                        m_lastdigital = false;
 
4414
                                }
 
4415
                        }
 
4416
                }
 
4417
        }
 
4418
        else if (!keypressed)
 
4419
                m_lastdigital = false;
 
4420
}
 
4421
 
 
4422
 
 
4423
//-------------------------------------------------
 
4424
//  read - read the current value and insert into
 
4425
//  the provided ioport_value
 
4426
//-------------------------------------------------
 
4427
 
 
4428
void analog_field::read(ioport_value &result)
 
4429
{
 
4430
        // do nothing if we're not enabled
 
4431
        if (!m_field.enabled())
 
4432
                return;
 
4433
 
 
4434
        // start with the raw value
 
4435
        INT32 value = m_accum;
 
4436
 
 
4437
        // interpolate if appropriate and if time has passed since the last update
 
4438
        if (m_interpolate)
 
4439
                value = manager().frame_interpolate(m_previous, m_accum);
 
4440
 
 
4441
        // apply standard analog settings
 
4442
        value = apply_settings(value);
 
4443
 
 
4444
        // remap the value if needed
 
4445
        if (m_field.remap_table() != NULL)
 
4446
                value = m_field.remap_table()[value];
 
4447
 
 
4448
        // invert bits if needed
 
4449
        if (m_field.analog_invert())
 
4450
                value = ~value;
 
4451
 
 
4452
        // insert into the port
 
4453
        result = (result & ~m_field.mask()) | ((value << m_shift) & m_field.mask());
 
4454
}
 
4455
 
 
4456
 
 
4457
//-------------------------------------------------
 
4458
//  crosshair_read - read a value for crosshairs,
 
4459
//  scaled between 0 and 1
 
4460
//-------------------------------------------------
 
4461
 
 
4462
float analog_field::crosshair_read()
 
4463
{
 
4464
        INT32 rawvalue = apply_settings(m_accum) & (m_field.mask() >> m_shift);
 
4465
        return float(rawvalue - m_adjmin) / float(m_adjmax - m_adjmin);
 
4466
}
 
4467
 
 
4468
 
 
4469
 
 
4470
/***************************************************************************
 
4471
    TOKENIZATION HELPERS
 
4472
***************************************************************************/
 
4473
 
 
4474
//-------------------------------------------------
 
4475
//  token_to_input_type - convert a string token
 
4476
//  to an input field type and player
 
4477
//-------------------------------------------------
 
4478
 
 
4479
ioport_type ioport_manager::token_to_input_type(const char *string, int &player) const
 
4480
{
 
4481
        // check for our failsafe case first
 
4482
        int ipnum;
 
4483
        if (sscanf(string, "TYPE_OTHER(%d,%d)", &ipnum, &player) == 2)
 
4484
                return ioport_type(ipnum);
 
4485
 
 
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))
 
4489
                {
 
4490
                        player = entry->player();
 
4491
                        return entry->type();
 
4492
                }
 
4493
 
 
4494
        // if we fail, return IPT_UNKNOWN
 
4495
        player = 0;
 
4496
        return IPT_UNKNOWN;
 
4497
}
 
4498
 
 
4499
 
 
4500
//-------------------------------------------------
 
4501
//  input_type_to_token - convert an input field
 
4502
//  type and player to a string token
 
4503
//-------------------------------------------------
 
4504
 
 
4505
const char *ioport_manager::input_type_to_token(astring &string, ioport_type type, int player)
 
4506
{
 
4507
        // look up the port and return the token
 
4508
        input_type_entry *entry = m_type_to_entry[type][player];
 
4509
        if (entry != NULL)
 
4510
                return string.cpy(entry->token());
 
4511
 
 
4512
        // if that fails, carry on
 
4513
        return string.format("TYPE_OTHER(%d,%d)", type, player);
 
4514
}
 
4515
 
 
4516
 
 
4517
//-------------------------------------------------
 
4518
//  token_to_seq_type - convert a string to
 
4519
//  a sequence type
 
4520
//-------------------------------------------------
 
4521
 
 
4522
input_seq_type ioport_manager::token_to_seq_type(const char *string)
 
4523
{
 
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;
 
4529
}
 
4530
 
 
4531
 
 
4532
 
 
4533
//-------------------------------------------------
 
4534
//  validate_natural_keyboard_statics -
 
4535
//  validates natural keyboard static data
 
4536
//-------------------------------------------------
 
4537
 
 
4538
/*
 
4539
int validate_natural_keyboard_statics(void)
 
4540
{
 
4541
    int i;
 
4542
    int error = FALSE;
 
4543
    unicode_char last_char = 0;
 
4544
    const char_info *ci;
 
4545
 
 
4546
    // check to make sure that charinfo is in order
 
4547
    for (i = 0; i < ARRAY_LENGTH(charinfo); i++)
 
4548
    {
 
4549
        if (last_char >= charinfo[i].ch)
 
4550
        {
 
4551
            mame_printf_error("inputx: charinfo is out of order; 0x%08x should be higher than 0x%08x\n", charinfo[i].ch, last_char);
 
4552
            error = TRUE;
 
4553
        }
 
4554
        last_char = charinfo[i].ch;
 
4555
    }
 
4556
 
 
4557
    // check to make sure that I can look up everything on alternate_charmap
 
4558
    for (i = 0; i < ARRAY_LENGTH(charinfo); i++)
 
4559
    {
 
4560
        ci = char_info::find(charinfo[i].ch);
 
4561
        if (ci != &charinfo[i])
 
4562
        {
 
4563
            mame_printf_error("ioport: expected char_info::find(0x%08x) to work properly\n", charinfo[i].ch);
 
4564
            error = TRUE;
 
4565
        }
 
4566
    }
 
4567
    return error;
 
4568
}
 
4569
*/
 
4570
 
 
4571