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