1 /***************************************************************************
2
3 config.c - config file access functions
4
5 ***************************************************************************/
6
7 #include "config.h"
8 #include "mame.h"
9 #include "common.h"
10
11
12
13 /***************************************************************************
14 CONSTANTS
15 ***************************************************************************/
16
17 #define POSITION_BEGIN 0
18 #define POSITION_AFTER_PORTS 1
19 #define POSITION_AFTER_COINS 2
20 #define POSITION_AFTER_MIXER 3
21
22
23
24 /***************************************************************************
25 TYPE DEFINITIONS
26 ***************************************************************************/
27
28 struct cfg_format
29 {
30 char cfg_string[8];
31 char def_string[8];
32 int (*read_input_port)(mame_file *, struct InputPort *);
33 int (*read_seq)(mame_file *, InputSeq *);
34 int coin_counters;
35 };
36
37 struct _config_file
38 {
39 mame_file *file;
40 int is_default;
41 int is_write;
42 const struct cfg_format *format;
43 int position;
44 };
45
46
47
48 /***************************************************************************
49 PROTOTYPES
50 ***************************************************************************/
51
52 static config_file *config_init(const char *name, int save);
53
54
55
56 /***************************************************************************
57 readint
58 ***************************************************************************/
59
readint(mame_file * f,UINT32 * num)60 static int readint(mame_file *f, UINT32 *num)
61 {
62 unsigned i;
63
64 *num = 0;
65 for (i = 0;i < sizeof(UINT32);i++)
66 {
67 unsigned char c;
68 *num <<= 8;
69 if (mame_fread(f,&c,1) != 1)
70 return -1;
71 *num |= c;
72 }
73
74 return 0;
75 }
76
77
78
79 /***************************************************************************
80 writeint
81 ***************************************************************************/
82
writeint(mame_file * f,UINT32 num)83 static void writeint(mame_file *f, UINT32 num)
84 {
85 unsigned i;
86
87 for (i = 0;i < sizeof(UINT32);i++)
88 {
89 unsigned char c;
90 c = (num >> 8 * (sizeof(UINT32)-1)) & 0xff;
91 mame_fwrite(f,&c,1);
92 num <<= 8;
93 }
94 }
95
96
97
98 /***************************************************************************
99 readword
100 ***************************************************************************/
101
readword(mame_file * f,UINT16 * num)102 static int readword(mame_file *f,UINT16 *num)
103 {
104 unsigned i;
105 int res;
106
107 res = 0;
108 for (i = 0;i < sizeof(UINT16);i++)
109 {
110 unsigned char c;
111 res <<= 8;
112 if (mame_fread(f,&c,1) != 1)
113 return -1;
114 res |= c;
115 }
116
117 *num = res;
118 return 0;
119 }
120
121
122
123 /***************************************************************************
124 writeword
125 ***************************************************************************/
126
writeword(mame_file * f,UINT16 num)127 static void writeword(mame_file *f,UINT16 num)
128 {
129 unsigned i;
130
131 for (i = 0;i < sizeof(UINT16);i++)
132 {
133 unsigned char c;
134
135 c = (num >> 8 * (sizeof(UINT16)-1)) & 0xff;
136 mame_fwrite(f,&c,1);
137 num <<= 8;
138 }
139 }
140
141
142
143 /***************************************************************************
144 seq_read_ver_8
145 ***************************************************************************/
146
seq_read_ver_8(mame_file * f,InputSeq * seq)147 static int seq_read_ver_8(mame_file *f, InputSeq *seq)
148 {
149 int j,len;
150 UINT32 i;
151 UINT16 w;
152
153 if (readword(f,&w) != 0)
154 return -1;
155
156 len = w;
157 seq_set_0(seq);
158 for(j=0;j<len;++j)
159 {
160 if (readint(f,&i) != 0)
161 return -1;
162 (*seq)[j] = savecode_to_code(i);
163 }
164
165 return 0;
166 }
167
168
169
170 /***************************************************************************
171 input_port_read_ver_8
172 ***************************************************************************/
173
input_port_read_ver_8(mame_file * f,struct InputPort * in)174 static int input_port_read_ver_8(mame_file *f, struct InputPort *in)
175 {
176 UINT32 i;
177 UINT16 w;
178 if (readint(f,&i) != 0)
179 return -1;
180 in->type = i;
181
182 if (readword(f,&w) != 0)
183 return -1;
184 in->mask = w;
185
186 if (readword(f,&w) != 0)
187 return -1;
188 in->default_value = w;
189
190 if (seq_read_ver_8(f,&in->seq) != 0)
191 return -1;
192
193 return 0;
194 }
195
196
197
198 /***************************************************************************
199 config_init
200 ***************************************************************************/
201
config_init(const char * name,int save)202 static config_file *config_init(const char *name, int save)
203 {
204 static const struct cfg_format formats[] =
205 {
206 /* mame 0.74 with 8 coin counters */
207 { "MAMECFG\x9", "MAMEDEF\x7", input_port_read_ver_8, seq_read_ver_8, 8 },
208 };
209
210 config_file *cfg;
211 char header[8];
212 const char *format_header;
213 int i;
214
215 cfg = malloc(sizeof(struct _config_file));
216 if (!cfg)
217 goto error;
218 memset(cfg, 0, sizeof(*cfg));
219
220 cfg->file = mame_fopen(name ? name : "default", 0, FILETYPE_CONFIG, save);
221 if (!cfg->file)
222 goto error;
223
224 cfg->is_default = name ? 0 : 1;
225 cfg->is_write = save ? 1 : 0;
226
227 if (save)
228 {
229 /* save */
230 cfg->format = &formats[0];
231
232 format_header = cfg->is_default ? formats[0].def_string : formats[0].cfg_string;
233
234 if (mame_fwrite(cfg->file, format_header, sizeof(header)) != sizeof(header))
235 goto error;
236 }
237 else
238 {
239 /* load */
240 if (mame_fread(cfg->file, header, sizeof(header)) != sizeof(header))
241 goto error;
242
243 for (i = 0; i < sizeof(formats) / sizeof(formats[0]); i++)
244 {
245 format_header = cfg->is_default ? formats[i].def_string : formats[i].cfg_string;
246 if (!memcmp(header, format_header, sizeof(header)))
247 {
248 cfg->format = &formats[i];
249 break;
250 }
251 }
252 if (!cfg->format)
253 goto error;
254 }
255
256 cfg->position = POSITION_BEGIN;
257 return cfg;
258
259 error:
260 if (cfg)
261 config_close(cfg);
262 return NULL;
263 }
264
265
266
267 /***************************************************************************
268 count_input_ports
269 ***************************************************************************/
270
count_input_ports(const struct InputPort * in)271 static unsigned int count_input_ports(const struct InputPort *in)
272 {
273 unsigned int total = 0;
274 while (in->type != IPT_END)
275 {
276 total++;
277 in++;
278 }
279 return total;
280 }
281
282
283
284 /***************************************************************************
285 config_open
286 ***************************************************************************/
287
config_open(const char * name)288 config_file *config_open(const char *name)
289 {
290 return config_init(name, 0);
291 }
292
293
294
295 /***************************************************************************
296 config_create
297 ***************************************************************************/
298
config_create(const char * name)299 config_file *config_create(const char *name)
300 {
301 return config_init(name, 1);
302 }
303
304
305
306 /***************************************************************************
307 config_close
308 ***************************************************************************/
309
config_close(config_file * cfg)310 void config_close(config_file *cfg)
311 {
312 if (cfg->file)
313 mame_fclose(cfg->file);
314 free(cfg);
315 }
316
317
318
319 /***************************************************************************
320 config_read_ports
321 ***************************************************************************/
322
config_read_ports(config_file * cfg,struct InputPort * input_ports_default,struct InputPort * input_ports)323 int config_read_ports(config_file *cfg, struct InputPort *input_ports_default, struct InputPort *input_ports)
324 {
325 unsigned int total;
326 unsigned int saved_total;
327 struct InputPort *in;
328 struct InputPort saved;
329 int (*read_input_port)(mame_file *, struct InputPort *);
330
331 if (cfg->is_write || cfg->is_default)
332 return CONFIG_ERROR_BADMODE;
333 if (cfg->position != POSITION_BEGIN)
334 return CONFIG_ERROR_BADPOSITION;
335
336 read_input_port = cfg->format->read_input_port;
337
338 /* calculate the size of the array */
339 total = count_input_ports(input_ports_default);
340
341 /* read array size */
342 if (readint(cfg->file, &saved_total) != 0)
343 return CONFIG_ERROR_CORRUPT;
344
345 /* read the original settings and compare them with the ones defined in the driver */
346 in = (struct InputPort *) input_ports_default;
347 while (in->type != IPT_END)
348 {
349 if (read_input_port(cfg->file, &saved) != 0)
350 return CONFIG_ERROR_CORRUPT;
351
352 if (in->mask != saved.mask ||
353 in->default_value != saved.default_value ||
354 in->type != saved.type ||
355 seq_cmp(&in->seq, &saved.seq) !=0 )
356 {
357 return CONFIG_ERROR_CORRUPT; /* the default values are different */
358 }
359
360 in++;
361 }
362
363 /* read the current settings */
364 in = input_ports;
365 while (in->type != IPT_END)
366 {
367 if (read_input_port(cfg->file, in) != 0)
368 break;
369 in++;
370 }
371
372 cfg->position = POSITION_AFTER_PORTS;
373 return CONFIG_ERROR_SUCCESS;
374 }
375
376
377
378 /***************************************************************************
379 config_read_default_ports
380 ***************************************************************************/
381
config_read_default_ports(config_file * cfg,struct ipd * input_ports_default)382 int config_read_default_ports(config_file *cfg, struct ipd *input_ports_default)
383 {
384 UINT32 type;
385 InputSeq def_seq;
386 InputSeq seq;
387 int i;
388 int (*read_seq)(mame_file *, InputSeq *);
389
390 if (cfg->is_write || !cfg->is_default)
391 return CONFIG_ERROR_BADMODE;
392 if (cfg->position != POSITION_BEGIN)
393 return CONFIG_ERROR_BADPOSITION;
394
395 read_seq = cfg->format->read_seq;
396
397 for (;;)
398 {
399 if (readint(cfg->file, &type) != 0)
400 break;
401
402 if (read_seq(cfg->file, &def_seq)!=0)
403 break;
404 if (read_seq(cfg->file, &seq)!=0)
405 break;
406
407 i = 0;
408 while (input_ports_default[i].type != IPT_END)
409 {
410 if (input_ports_default[i].type == type)
411 {
412 /* load stored settings only if the default hasn't changed */
413 if (seq_cmp(&input_ports_default[i].seq, &def_seq)==0)
414 seq_copy(&input_ports_default[i].seq, &seq);
415 }
416
417 i++;
418 }
419 }
420
421 cfg->position = POSITION_AFTER_PORTS;
422 return CONFIG_ERROR_SUCCESS;
423 }
424
425
426
427 /***************************************************************************
428 config_read_coin_and_ticket_counters
429 ***************************************************************************/
430
config_read_coin_and_ticket_counters(config_file * cfg,unsigned int * coins,unsigned int * lastcoin,unsigned int * coinlockedout,unsigned int * dispensed_tickets)431 int config_read_coin_and_ticket_counters(config_file *cfg, unsigned int *coins, unsigned int *lastcoin,
432 unsigned int *coinlockedout, unsigned int *dispensed_tickets)
433 {
434 int coin_counters;
435 int i;
436
437 if (cfg->is_write)
438 return CONFIG_ERROR_BADMODE;
439 if (cfg->position != POSITION_AFTER_PORTS)
440 return CONFIG_ERROR_BADPOSITION;
441
442 coin_counters = cfg->format->coin_counters;
443
444 /* Clear the coin & ticket counters/flags - LBO 042898 */
445 for (i = 0; i < COIN_COUNTERS; i ++)
446 coins[i] = lastcoin[i] = coinlockedout[i] = 0;
447 *dispensed_tickets = 0;
448
449 /* read in the coin/ticket counters */
450 for (i = 0; i < COIN_COUNTERS; i ++)
451 {
452 if (readint(cfg->file, &coins[i]) != 0)
453 goto done;
454 }
455 if (readint(cfg->file, dispensed_tickets) != 0)
456 goto done;
457
458 done:
459 cfg->position = POSITION_AFTER_COINS;
460 return 0;
461 }
462
463
464
465 /***************************************************************************
466 config_read_mixer_config
467 ***************************************************************************/
468
config_read_mixer_config(config_file * cfg,struct mixer_config * mixercfg)469 int config_read_mixer_config(config_file *cfg, struct mixer_config *mixercfg)
470 {
471 if (cfg->is_write)
472 return CONFIG_ERROR_BADMODE;
473 if (cfg->position != POSITION_AFTER_COINS)
474 return CONFIG_ERROR_BADPOSITION;
475
476 memset(mixercfg->default_levels, 0xff, sizeof(mixercfg->default_levels));
477 memset(mixercfg->mixing_levels, 0xff, sizeof(mixercfg->mixing_levels));
478 mame_fread(cfg->file, mixercfg->default_levels, MIXER_MAX_CHANNELS);
479 mame_fread(cfg->file, mixercfg->mixing_levels, MIXER_MAX_CHANNELS);
480 cfg->position = POSITION_AFTER_MIXER;
481 return CONFIG_ERROR_SUCCESS;
482 }
483
484
485
486 /***************************************************************************
487 seq_write
488 ***************************************************************************/
489
seq_write(mame_file * f,const InputSeq * seq)490 static void seq_write(mame_file *f, const InputSeq *seq)
491 {
492 int j, len;
493
494 for (len = 0; len < SEQ_MAX; ++len)
495 if ((*seq)[len] == CODE_NONE)
496 break;
497
498 writeword(f, len);
499 for (j = 0; j < len; ++j)
500 writeint(f, code_to_savecode((*seq)[j]));
501 }
502
503
504
505 /***************************************************************************
506 input_port_write
507 ***************************************************************************/
508
input_port_write(mame_file * f,const struct InputPort * in)509 static void input_port_write(mame_file *f, const struct InputPort *in)
510 {
511 writeint(f, in->type);
512 writeword(f, in->mask);
513 writeword(f, in->default_value);
514 seq_write(f, &in->seq);
515 }
516
517
518
519 /***************************************************************************
520 config_write_ports
521 ***************************************************************************/
522
config_write_ports(config_file * cfg,const struct InputPort * input_ports_default,const struct InputPort * input_ports)523 int config_write_ports(config_file *cfg, const struct InputPort *input_ports_default, const struct InputPort *input_ports)
524 {
525 unsigned int total;
526 const struct InputPort *in;
527
528 if (!cfg->is_write || cfg->is_default)
529 return CONFIG_ERROR_BADMODE;
530 if (cfg->position != POSITION_BEGIN)
531 return CONFIG_ERROR_BADPOSITION;
532
533 /* calculate the size of the array */
534 total = count_input_ports(input_ports_default);
535
536 /* write array size */
537 writeint(cfg->file, total);
538
539 /* write the original settings as defined in the driver */
540 in = input_ports_default;
541 while (in->type != IPT_END)
542 {
543 input_port_write(cfg->file, in);
544 in++;
545 }
546
547 /* write the current settings */
548 in = input_ports;
549 while (in->type != IPT_END)
550 {
551 input_port_write(cfg->file, in);
552 in++;
553 }
554
555 cfg->position = POSITION_AFTER_PORTS;
556 return CONFIG_ERROR_SUCCESS;
557 }
558
559
560
561 /***************************************************************************
562 config_write_default_ports
563 ***************************************************************************/
564
config_write_default_ports(config_file * cfg,const struct ipd * input_ports_default_backup,const struct ipd * input_ports_default)565 int config_write_default_ports(config_file *cfg, const struct ipd *input_ports_default_backup, const struct ipd *input_ports_default)
566 {
567 int i = 0;
568
569 if (!cfg->is_write || !cfg->is_default)
570 return CONFIG_ERROR_BADMODE;
571 if (cfg->position != POSITION_BEGIN)
572 return CONFIG_ERROR_BADPOSITION;
573
574 while (input_ports_default[i].type != IPT_END)
575 {
576 if (input_ports_default[i].type != IPT_OSD_DESCRIPTION)
577 {
578 writeint(cfg->file, input_ports_default[i].type);
579 seq_write(cfg->file, &input_ports_default_backup[i].seq);
580 seq_write(cfg->file, &input_ports_default[i].seq);
581 }
582 i++;
583 }
584
585 cfg->position = POSITION_AFTER_PORTS;
586 return CONFIG_ERROR_SUCCESS;
587 }
588
589
590
591 /***************************************************************************
592 config_write_coin_and_ticket_counters
593 ***************************************************************************/
594
config_write_coin_and_ticket_counters(config_file * cfg,const unsigned int * coins,const unsigned int * lastcoin,const unsigned int * coinlockedout,unsigned int dispensed_tickets)595 int config_write_coin_and_ticket_counters(config_file *cfg, const unsigned int *coins, const unsigned int *lastcoin,
596 const unsigned int *coinlockedout, unsigned int dispensed_tickets)
597 {
598 int i;
599
600 /* write out the coin/ticket counters for this machine - LBO 042898 */
601 for (i = 0; i < COIN_COUNTERS; i ++)
602 writeint(cfg->file, coins[i]);
603 writeint(cfg->file, dispensed_tickets);
604 cfg->position = POSITION_AFTER_COINS;
605 return CONFIG_ERROR_SUCCESS;
606 }
607
608
609
610 /***************************************************************************
611 config_write_mixer_config
612 ***************************************************************************/
613
config_write_mixer_config(config_file * cfg,const struct mixer_config * mixercfg)614 int config_write_mixer_config(config_file *cfg, const struct mixer_config *mixercfg)
615 {
616 if (!cfg->is_write)
617 return CONFIG_ERROR_BADMODE;
618 if (cfg->position != POSITION_AFTER_COINS)
619 return CONFIG_ERROR_BADPOSITION;
620
621 mame_fwrite(cfg->file, mixercfg->default_levels, MIXER_MAX_CHANNELS);
622 mame_fwrite(cfg->file, mixercfg->mixing_levels, MIXER_MAX_CHANNELS);
623 cfg->position = POSITION_AFTER_MIXER;
624 return CONFIG_ERROR_SUCCESS;
625 }
626
627