1 /*
2  * ============================================================================
3  *  Title:    Configuration Manager
4  *  Author:   J. Zbiciak
5  * ============================================================================
6  *  This module manages the machine configuration.  It does commandline
7  *  parsing and processes the configuration elements that were read in
8  *  via the config-file parser.
9  *
10  *  CFG owns the entire machine -- it is encapsulated in a cfg_t.
11  * ============================================================================
12  *  CFG_INIT     -- Parse command line and get started
13  *  CFG_FILE     -- Parse a config file and extend the state of the machine.
14  * ============================================================================
15  */
16 
17 
18 #include "config.h"
19 #include "lzoe/lzoe.h"
20 #include "file/file.h"
21 #include "periph/periph.h"
22 #include "cp1600/cp1600.h"
23 #include "cp1600/emu_link.h"
24 #include "cheat/cheat.h"
25 #include "mem/mem.h"
26 #include "ecs/ecs.h"
27 #include "icart/icart.h"
28 #include "bincfg/bincfg.h"
29 #include "bincfg/legacy.h"
30 #include "pads/pads.h"
31 #include "pads/pads_cgc.h"
32 #include "pads/pads_intv2pc.h"
33 #include "avi/avi.h"
34 #include "gfx/gfx.h"
35 #include "gfx/palette.h"
36 #include "snd/snd.h"
37 #include "ay8910/ay8910.h"
38 #include "demo/demo.h"
39 #include "stic/stic.h"
40 #include "ivoice/ivoice.h"
41 #include "speed/speed.h"
42 #include "debug/debug_.h"
43 #include "event/event.h"
44 #include "joy/joy.h"
45 #include "serializer/serializer.h"
46 #include "jlp/jlp.h"
47 #include "plat/plat.h"
48 #include "plat/plat_lib.h"
49 #include "misc/file_crc32.h"
50 #include "metadata/metadata.h"
51 #include "metadata/print_metadata.h"
52 #include "name/name.h"
53 #include "debug/source.h"
54 #include "file/elfi.h"
55 #include "locutus/locutus_adapt.h"
56 #include "mapping.h"
57 #include "cfg.h"
58 
59 #include <errno.h>
60 
61 LOCAL path_t *rom_path;
62 
63 void cfg_default(event_t *event);
64 
65 /* ======================================================================== */
66 /*  CFG_GET_EVTACT   -- Convert an event action name into an event action   */
67 /*                      index.  This is a horrible linear search.  :-P      */
68 /*                      Hey, it works for now.                              */
69 /* ======================================================================== */
cfg_get_evtact(const char * event_action_name)70 int cfg_get_evtact(const char *event_action_name)
71 {
72     int i;
73 
74     for (i = 0; i < cfg_event_action_cnt; i++)
75     {
76         if (!strcmp(cfg_event_action[i].name, event_action_name))
77             return i;
78     }
79 
80     return -1;
81 }
82 
83 /* ======================================================================== */
84 /*  CFG_SETBIND  -- Set all of the key-bindings for the Intellivision.      */
85 /* ======================================================================== */
cfg_setbind(cfg_t * cfg,const char * kbdhackfile)86 int cfg_setbind(cfg_t *cfg, const char *kbdhackfile)
87 {
88     int i, j, map;
89     LZFILE *f = NULL;
90     int action;
91     char buf[256];
92 
93     /* -------------------------------------------------------------------- */
94     /*  Iterate over the bindings table.                                    */
95     /* -------------------------------------------------------------------- */
96     for (i = 0; cfg->binding[i].key != NULL; i++)
97     {
98         /* ---------------------------------------------------------------- */
99         /*  Iterate over the four possible "event spaces" that the user     */
100         /*  may have configured.  For instance, the user may have set up    */
101         /*  "Normal", "Swapped", "Alpha-numeric", and one other.            */
102         /* ---------------------------------------------------------------- */
103         for (j = 0; j < 4; j++)
104         {
105             /* ------------------------------------------------------------ */
106             /*  Skip empty event bindings.  These keys aren't bound.        */
107             /* ------------------------------------------------------------ */
108             if (!cfg->binding[i].event_action[j] ||
109                 !cfg->binding[i].event_action[j][0])
110                 continue;
111 
112             /* ------------------------------------------------------------ */
113             /*  Look up the event name, and skip if the name is invalid.    */
114             /* ------------------------------------------------------------ */
115             if ((action = cfg_get_evtact(cfg->binding[i].event_action[j])) < 0)
116             {
117                 fprintf(stderr, "cfg:  Invalid event action '%s'\n",
118                         cfg->binding[i].event_action[j]);
119                 continue;
120             }
121 
122             /* ------------------------------------------------------------ */
123             /*  Map the key to the event.                                   */
124             /* ------------------------------------------------------------ */
125             event_map(&cfg->event, cfg->binding[i].key, j,
126                       cfg_event_action[action].word,
127                       cfg_event_action[action].and_mask,
128                       cfg_event_action[action].or_mask);
129         }
130     }
131 
132     /* -------------------------------------------------------------------- */
133     /*  HACK: If the user specified a keyboard mapping file, read that in.  */
134     /* -------------------------------------------------------------------- */
135     if (!kbdhackfile)
136         return 0;
137 
138     if (!(f = lzoe_fopen(kbdhackfile, "r")))
139     {
140         fprintf(stderr, "Couldn't open keyboard map file '%s'\n", kbdhackfile);
141         exit(1);
142     }
143 
144     map = 0;
145     while (lzoe_fgets(buf, 256, f) != NULL)
146     {
147         char *s1, *s2;
148         char cmd[256], arg[256], arg2[256], arg3[256];
149         int bad, too_many;
150 
151         bad = too_many = 0;
152 
153         if ((s1 = strchr (buf, ';' ))) *s1 = 0;
154         if ((s1 = strrchr(buf, '\r'))) *s1 = 0;
155         if ((s1 = strrchr(buf, '\n'))) *s1 = 0;
156 
157         cmd[0] = 0;
158         arg[0] = 0;
159 
160 
161         s1 = buf;
162         while (*s1 && isspace(*s1)) s1++;
163 
164         s2 = cmd;
165         while (*s1 && !isspace(*s1) && s2 < &cmd[255]) *s2++ = *s1++;
166         if (s2 >= &cmd[255]) bad = 1;
167         *s2 = 0;
168 
169         while (*s1 && isspace(*s1)) s1++;
170 
171         s2 = arg;
172         while (*s1 && !isspace(*s1) && s2 < &arg[255]) *s2++ = *s1++;
173         if (s2 >= &arg[255]) bad = 2;
174         *s2 = 0;
175 
176         while (*s1 && isspace(*s1)) s1++;
177 
178         s2 = arg2;
179         while (*s1 && !isspace(*s1) && s2 < &arg2[255]) *s2++ = *s1++;
180         if (s2 >= &arg2[255]) bad = 3;
181         *s2 = 0;
182 
183         while (*s1 && isspace(*s1)) s1++;
184 
185         s2 = arg3;
186         while (*s1 && !isspace(*s1) && s2 < &arg3[255]) *s2++ = *s1++;
187         if (s2 >= &arg3[255]) bad = 4;
188         *s2 = 0;
189 
190         while (*s1 && isspace(*s1)) s1++;
191 
192         if (*s1) too_many = 1;
193 
194         if (bad)
195         {
196             fprintf(stderr, "cfg:  Fatal error (argument too long?) parsing "
197                             "kbdhackfile (%d)\n", bad);
198             goto fail;
199         }
200 
201         if (!too_many && !stricmp(cmd, "add_combo"))
202         {
203             j = atoi(arg);
204 
205             jzp_printf("cfg:  Combining %s and %s as COMBO%d\n", arg2, arg3, j);
206 
207             if (j > 63 || j < 0)
208             {
209                 fprintf(stderr, "cfg:  COMBO number out of range\n");
210                 goto fail;
211             }
212 
213             if (event_combine(&cfg->event, arg2, arg3, j))
214             {
215                 fprintf(stderr, "cfg:  Error registering combo\n");
216                 goto fail;
217             }
218 
219             continue;
220         }
221 
222         if (arg2[0] != 0 || arg3[0] != 0 || too_many)
223         {
224             fprintf(stderr, "cfg:  Too many arguments in kbdhackfile:\n> %s\n",
225                     buf);
226             fprintf(stderr, "cmd='%s' arg='%s' arg2='%s' arg3='%s' s1='%s'\n",
227                     cmd,arg,arg2,arg3,s1);
228             goto fail;
229         }
230 
231         if (!stricmp(cmd, "combo_delay"))
232         {
233             double ms = atof(arg);
234 
235             if (ms < 0. || ms > 100.)
236             {
237                 fprintf(stderr, "cfg:  COMBO_DELAY out of range.\n");
238                 goto fail;
239             }
240 
241             jzp_printf("cfg:  Setting combo event delay to %5.2fms\n", ms);
242 
243             event_set_combo_coalesce(&cfg->event, ms / 1000.);
244             continue;
245         }
246 
247         if (!stricmp(cmd, "map"))
248         {
249             map = atoi(arg);
250 
251             if (map < 0 || map > 3)
252             {
253                 fprintf(stderr, "cfg:  Map number out of range\n");
254                 goto fail;
255             }
256             continue;
257         }
258 
259         if (cmd[0] == 0 || arg[0] == 0)
260         {
261             if (cmd[0])
262             {
263                 fprintf(stderr, "cfg:  Unknown command '%s' in %s\n",
264                         cmd, kbdhackfile);
265                 goto fail;
266             }
267             continue;
268         }
269 
270         jzp_printf("cfg:  Binding %s to %s in map %d\n", cmd, arg, map);
271 
272         if ((action = cfg_get_evtact(arg)) < 0)
273         {
274             fprintf(stderr, "cfg: Invalid event action '%s'\n", arg);
275             goto fail;
276         }
277 
278         event_map(&cfg->event, cmd, map,
279                   cfg_event_action[action].word,
280                   cfg_event_action[action].and_mask,
281                   cfg_event_action[action].or_mask);
282     }
283 
284     lzoe_fclose(f);
285     return 0;
286 
287 fail:
288     if (f) lzoe_fclose(f);
289     return -1;
290 }
291 /* ======================================================================== */
292 /*  Built-in display resolutions.                                           */
293 /* ======================================================================== */
294 LOCAL const int res_x[] = { 320, 640, 320, 1024, 1680, 800, 1600, 3280 };
295 LOCAL const int res_y[] = { 200, 480, 240,  768, 1050, 400, 1200, 1200 };
296 LOCAL const int res_d[] = { 8,   8  , 16,     8,    8, 16 ,   32,   32 };
297 #define NUM_RES ((int)(sizeof(res_x) / sizeof(res_x[0])))
298 
299 /* ======================================================================== */
300 /*  CFG_PARSERES -- Parse a resolution string.  Return -1 if invalid.       */
301 /* ======================================================================== */
cfg_parseres(const char * const res,int * const rx,int * const ry,int * const rd)302 LOCAL const char *cfg_parseres(const char *const res,
303                                int *const rx, int *const ry, int *const rd)
304 {
305     int s;
306 
307     if (!rx || !ry || !rd)
308         return "cfg_parseres: internal error, invalid arguments";
309 
310     if (!res)
311     {
312         *rx = res_x[0];
313         *ry = res_y[0];
314         *rd = res_d[0];
315         return NULL;
316     }
317 
318     s = sscanf(res, "%d%*1c%d%*1c%d", rx, ry, rd);
319 
320     if (s < 1 || s > 3)
321         return "Bad resolution string.";
322 
323 
324     if (s == 1)
325     {
326         if (*rx >= 0 && *rx < NUM_RES)
327         {
328             int i = *rx;
329             *rx = res_x[i];
330             *ry = res_y[i];
331             *rd = res_d[i];
332             return NULL;
333         }
334 
335         if (*rx < 0)
336             return ""; /* not really an error, but force resolution listing */
337 
338         return "Resolution number out of range.";
339     }
340 
341     if (s == 2)
342         *rd = 8;
343 
344     if (!(*rd == 8 || *rd == 16 || *rd == 24 || *rd == 32))
345         return "Color depth must be 8, 16, 24 or 32";
346 
347     if (*rx < 320)
348         return "X resolution is too small.";
349 
350     if (*ry < 200)
351         return "Y resolution is too small.";
352 
353     return NULL;
354 }
355 
356 
357 /* ======================================================================== */
358 /*  CFG_LONGOPT  -- Long options for getopt_long                            */
359 /* ======================================================================== */
360 enum
361 {
362     FLAG_CGC0 = 2000,   FLAG_CGC1,         FLAG_KBDHACKFILE,  FLAG_GP2X_CLOCK,
363     FLAG_GFX_SWSURF,    FLAG_GFX_DBLBUF,   FLAG_GFX_ASYNCB,   FLAG_GFX_HWPAL,
364     FLAG_GFX_DIRTYRECT, FLAG_GFX_DR_MERGE, FLAG_GFX_VERBOSE,  FLAG_GFX_PALETTE,
365     FLAG_GFX_BORD_X,    FLAG_GFX_BORD_Y,   FLAG_GUI_MODE,     FLAG_RAND_MEM,
366     FLAG_START_DELAY,   FLAG_DBG_SCRIPT,   FLAG_DBG_SRCMAP,   FLAG_FILE_IO,
367     FLAG_ENABLE_MOUSE,  FLAG_PRESCALE,     FLAG_JLP_SAVEGAME, FLAG_AVI_RATE,
368     FLAG_LOCUTUS,       FLAG_ECS_TAPE,     FLAG_ECS_PRINTER,  FLAG_CHEAT
369 };
370 
371 struct option cfg_longopt[] =
372 {
373     {   "ecsimg",       1,      NULL,       'E'                 },
374     {   "execimg",      1,      NULL,       'e'                 },
375     {   "gromimg",      1,      NULL,       'g'                 },
376     {   "gramsize",     1,      NULL,       'G'                 },
377     {   "ecs",          2,      NULL,       's'                 },
378     {   "fullscreen",   2,      NULL,       'f'                 },
379     {   "audiofile",    1,      NULL,       'F'                 },
380     {   "debugger",     0,      NULL,       'd'                 },
381     {   "ratecontrol",  2,      NULL,       'r'                 },
382     {   "macho",        2,      NULL,       'r'                 },
383     {   "fullscreen",   2,      NULL,       'x'                 },
384     {   "displaysize",  1,      NULL,       'z'                 },
385     {   "resolution",   1,      NULL,       'z'                 },
386     {   "audio",        1,      NULL,       'a'                 },
387     {   "audiorate",    1,      NULL,       'a'                 },
388     {   "audiowindow",  1,      NULL,       'w'                 },
389     {   "audiobufsize", 1,      NULL,       'B'                 },
390     {   "audiobufcnt",  1,      NULL,       'C'                 },
391     {   "audiomintick", 1,      NULL,       'M'                 },
392     {   "voice",        2,      NULL,       'v'                 },
393     {   "voicewindow",  2,      NULL,       'W'                 },
394     {   "voicefiles",   2,      NULL,       'V'                 },
395     {   "i2pc0",        2,      NULL,       'i'                 },
396     {   "i2pc1",        2,      NULL,       'I'                 },
397     {   "intv2pc0",     2,      NULL,       'i'                 },
398     {   "intv2pc1",     2,      NULL,       'I'                 },
399 #ifdef CGC_DLL
400     {   "cgc0",         2,      NULL,       FLAG_CGC0           },
401     {   "cgc1",         2,      NULL,       FLAG_CGC1           },
402 #endif
403 #ifdef CGC_THREAD
404     {   "cgc0",         1,      NULL,       FLAG_CGC0           },
405     {   "cgc1",         1,      NULL,       FLAG_CGC1           },
406 #endif
407     {   "icartcache",   2,      NULL,       'c'                 },
408     {   "help",         0,      NULL,       'h'                 },
409     {   "license",      0,      NULL,       'l'                 },
410     {   "nobusywait",   0,      NULL,       '9'                 },
411     {   "kbdhackfile",  1,      NULL,       FLAG_KBDHACKFILE    },
412     {   "kbdmap",       1,      NULL,       'm'                 },
413     {   "demofile",     1,      NULL,       'D'                 },
414 
415     {   "js0",          2,      NULL,       1000                },
416     {   "js1",          2,      NULL,       1010                },
417     {   "js2",          2,      NULL,       1020                },
418     {   "js3",          2,      NULL,       1030                },
419 
420 #define JS_FLAG(j) \
421     {   "js" #j "a",    2,      NULL,     1000 + (j)*10                 }, \
422     {   "js" #j "b",    2,      NULL,     1001 + (j)*10                 }, \
423     {   "js" #j "c",    2,      NULL,     1002 + (j)*10                 }, \
424     {   "js" #j "d",    2,      NULL,     1003 + (j)*10                 }, \
425     {   "js" #j "e",    2,      NULL,     1004 + (j)*10                 }, \
426     {   "js" #j "f",    2,      NULL,     1005 + (j)*10                 }, \
427     {   "js" #j "g",    2,      NULL,     1006 + (j)*10                 }, \
428     {   "js" #j "h",    2,      NULL,     1007 + (j)*10                 }, \
429     {   "js" #j "i",    2,      NULL,     1008 + (j)*10                 }, \
430     {   "js" #j "j",    2,      NULL,     1009 + (j)*10     }
431 
432     JS_FLAG(0),
433     JS_FLAG(1),
434     JS_FLAG(2),
435     JS_FLAG(3),
436     JS_FLAG(4),
437     JS_FLAG(5),
438     JS_FLAG(6),
439     JS_FLAG(7),
440     JS_FLAG(8),
441     JS_FLAG(9),
442 
443 #ifdef GP2X
444     {   "gp2xclock",    1,      NULL,       FLAG_GP2X_CLOCK     },
445 #endif
446 
447     {   "gfx-swsurf",   2,      NULL,       FLAG_GFX_SWSURF     },
448     {   "gfx-dblbuf",   2,      NULL,       FLAG_GFX_DBLBUF     },
449     {   "gfx-asyncb",   2,      NULL,       FLAG_GFX_ASYNCB     },
450     {   "gfx-hwpal",    2,      NULL,       FLAG_GFX_HWPAL      },
451 
452     {   "gfx-verbose",  0,      NULL,       FLAG_GFX_VERBOSE    },
453 
454     {   "gfx-dirtyrect",2,      NULL,       FLAG_GFX_DIRTYRECT  },
455     {   "gfx-dr-clean-merge",2, NULL,       FLAG_GFX_DR_MERGE   },
456 
457     {   "gfx-palette",  1,      NULL,       FLAG_GFX_PALETTE    },
458 
459     {   "gfx-border-pct", 1,    NULL,       'b'                 },
460     {   "gfx-border-x", 1,      NULL,       FLAG_GFX_BORD_X     },
461     {   "gfx-border-y", 1,      NULL,       FLAG_GFX_BORD_Y     },
462 
463     {   "gui-mode",     0,      NULL,       FLAG_GUI_MODE       },
464 
465     {   "rom-path",     1,      NULL,       'p'                 },
466     {   "quiet",        0,      NULL,       'q'                 },
467     {   "start-delay",  2,      NULL,       FLAG_START_DELAY    },
468     {   "sym-file",     1,      NULL,       'S'                 },
469     {   "script",       1,      NULL,       FLAG_DBG_SCRIPT     },
470     {   "src-map",      1,      NULL,       FLAG_DBG_SRCMAP     },
471 
472     {   "rand-mem",     0,      NULL,       FLAG_RAND_MEM       },
473     {   "file-io",      1,      NULL,       FLAG_FILE_IO        },
474     {   "pal",          0,      NULL,       'P'                 },
475 
476     {   "enable-mouse", 0,      NULL,       FLAG_ENABLE_MOUSE   },
477     {   "prescale",     1,      NULL,       FLAG_PRESCALE       },
478 
479     {   "jlp",          0,      NULL,       'J'                 },
480     {   "jlp-savegame", 1,      NULL,       FLAG_JLP_SAVEGAME   },
481     {   "jlp-flash",    1,      NULL,       'j'                 },
482 
483     {   "avirate",      1,      NULL,       FLAG_AVI_RATE       },
484 
485     // --locutus for testing LUIGI files.
486     {   "locutus",      0,      NULL,       FLAG_LOCUTUS        },
487 
488     {   "ecs-tape",     1,      NULL,       FLAG_ECS_TAPE       },
489     {   "ecs-printer",  1,      NULL,       FLAG_ECS_PRINTER    },
490     {   "cheat",        1,      NULL,       FLAG_CHEAT          },
491 
492     {   NULL,           0,      NULL,       0                   }
493 };
494 
495 LOCAL const char *optchars= "b:E:e:G:g:s::f::F:?dhlqr:P::x::z:a:w:B:C:M:m:"
496                             "v::W::V::i::I::c:D:p:J:j::";
497 
498 /* ======================================================================== */
499 /*  Supported I/O addresses for INTV2PC.                                    */
500 /* ======================================================================== */
501 const uint32_t i2pc_ports[4] = { 0x0, 0x378, 0x278, 0x3BC };
502 
503 LOCAL char *joy_cfg[MAX_JOY][MAX_STICKS];
504 
505 /* ======================================================================== */
506 /*  CFG_INIT     -- Parse command line and get started                      */
507 /* ======================================================================== */
cfg_init(cfg_t * cfg,int argc,char * argv_orig[])508 void cfg_init(cfg_t *cfg, int argc, char * argv_orig[])
509 {
510     int c, option_idx = 0, rx, ry, rd, bx = -1, by = -1, bpct = -1;
511     int exec_type = 0, legacy_rom = 0;
512     int value = 1, busywaits = 1;
513     uint32_t cache_flags = IC_CACHE_DFLT;
514     char *audiofile = NULL, *tmp;
515     char *kbdhackfile = NULL;
516     char *demofile = NULL;
517     char *jlpsg = NULL;
518     char *elfi_prefix = NULL;
519     char *gfx_palette = NULL;
520     const char *fn_ecs_tape = NULL;
521     const char *fn_ecs_printer = NULL;
522     int jlp_accel = -1;
523     int jlp_flash = -1;
524     LZFILE *f;
525     int silent = 0;
526     char *debug_symtbl   = NULL;
527     char *debug_script   = NULL;
528     char *debug_srcmap   = NULL;
529     int snd_buf_size     = 0;
530     int snd_buf_cnt      = 0;
531     int gfx_verbose      = 0;
532     int rand_mem         = 0;
533     int enable_mouse     = 0;
534     int ecs_bin_fail_ok  = 0;
535     char       *disp_res = NULL;
536     const char *err_msg  = NULL;
537     int locutus          = 0;
538 #ifndef NO_SERIALIZER
539     ser_hier_t *ser_cfg;
540 #endif
541     game_metadata_t *meta = NULL;
542     int meta_needs_free = 0;
543     int initial_event_map = 0;
544     const bool batch_mode = plat_is_batch_mode();
545 
546     char **argv_copy = CALLOC(char *, argc);
547     char *argv_data;
548 
549     {
550         int i, sz = 0;
551         for (i = 0; i < argc; i++)
552             sz += strlen(argv_orig[i]) + 1;
553 
554         argv_data = CALLOC(char, sz);
555 
556         sz = 0;
557         for (i = 0; i < argc; i++)
558         {
559             strcpy(argv_data + sz, argv_orig[i]);
560             argv_copy[i] = argv_data + sz;
561             sz += strlen(argv_orig[i]) + 1;
562         }
563     }
564 
565     optind = 0;
566     optopt = 0;
567     opterr = 0;
568     optarg = NULL;
569 
570 #ifdef GP2X
571     int gp2xclock = 200;
572 #endif
573 
574 #ifdef WII
575     silent = 1;
576 #endif
577     /* -------------------------------------------------------------------- */
578     /*  Initialize random number generator.  Do this before peripherals,    */
579     /*  as some may use the random number generator.                        */
580     /* -------------------------------------------------------------------- */
581 #if !defined(__EMSCRIPTEN__)
582     srand_jz(time(0) + (uint32_t)(UINT32_MAX * fmod(get_time(), 0.999)));
583 #else
584     /* For some reason the line above triggered an overflow exception in */
585     /* Emscripten, so go with this simpler random seed init. */
586     /* TODO: Try it again now that I've added fmod. */
587     srand_jz(time(0) & 0xFFFFFFFFu);
588 #endif
589 
590     /* -------------------------------------------------------------------- */
591     /*  Set up the default state for everything.                            */
592     /* -------------------------------------------------------------------- */
593     memset((void *)cfg, 0, sizeof(cfg_t));
594 
595     cfg->pal_mode   = 0;            /* Default NTSC                         */
596     cfg->gram_size  = -1;           /* Automatic GRAM size                  */
597     cfg->audio_rate = DEFAULT_AUDIO_HZ;     /* see config.h                 */
598     cfg->psg_window = -1;           /* Automatic window setting.            */
599     cfg->ecs_enable = -1;           /* Automatic (dflt: ECS off)            */
600     cfg->ivc_enable = -1;           /* Automatic (dflt: Intellivoice off.   */
601     cfg->ivc_window = -1;           /* Automatic window setting.            */
602     cfg->gfx_flags  = 0             /* Windowed, single buf, hardware surf  */
603 #if 0
604                     | GFX_DRECTS    /* Dirty rectangle update               */
605                     | GFX_DRCMRG;   /* Allow merging cln rect btwn 2 dirty  */
606 #else
607                     /* dirty rectangles disabled for now. */
608                     ;
609 #endif
610     cfg->i2pc0_port     = 0;            /* No INTV2PC #0                    */
611     cfg->i2pc1_port     = 0;            /* No INTV2PC #1                    */
612     cfg->cgc0_num       = -1;           /* No CGC #0                        */
613     cfg->cgc1_num       = -1;           /* No CGC #1                        */
614     cfg->cgc0_dev       = NULL;         /* No CGC #0                        */
615     cfg->cgc1_dev       = NULL;         /* No CGC #1                        */
616     cfg->debugging      = 0;            /* No debugger.                     */
617     cfg->rate_ctl       = !batch_mode;  /* Enable rate ctl unless batch.    */
618     cfg->avi_time_scale = -1.0;         /* Default: unspecified.            */
619     cfg->accutick       = 1;            /* fully accurate audio.            */
620     cfg->binding        = cfg_key_bind; /* default key bindings.            */
621     cfg->start_dly      = -1;           /* No startup delay by default.     */
622 
623 #define STR_REPLACE(x,y) { CONDFREE(x); (x) = strdup(y); }
624 
625     STR_REPLACE(cfg->fn_exec, "exec.bin");   /* Default name to look for     */
626     STR_REPLACE(cfg->fn_grom, "grom.bin");   /* ...                          */
627     STR_REPLACE(cfg->fn_game, "game.rom");   /* ...                          */
628     STR_REPLACE(cfg->fn_ecs,  "ecs.bin");    /* ...                          */
629     STR_REPLACE(fn_ecs_tape,     "ecs_tape#.ecs");
630     STR_REPLACE(fn_ecs_printer,  "ecs_printer#.ecs");
631 
632     cheat_init(&cfg->cheat, &cfg->cp1600);
633 
634     /* -------------------------------------------------------------------- */
635     /*  Figure out out our executable's path.  If none, assume ".".         */
636     /* -------------------------------------------------------------------- */
637     if (!exe_path)
638     {
639         exe_path = get_exe_dir(argv_copy[0]);
640         if (!exe_path)
641             exe_path = strdup(".");
642     }
643 
644 #ifndef NO_SERIALIZER
645     /* -------------------------------------------------------------------- */
646     /*  Register our config variables for serialization.                    */
647     /* -------------------------------------------------------------------- */
648 #define SER_REG(x,t,l,f)\
649     ser_register(ser_cfg, #x, &cfg-> x, t, l, f)
650 
651     ser_cfg = ser_new_hierarchy(NULL, "cfg");
652     SER_REG(ecs_enable, ser_s32,    1,  SER_INIT|SER_MAND);
653     SER_REG(ivc_enable, ser_s32,    1,  SER_INIT|SER_MAND);
654     SER_REG(ivc_tname,  ser_string, 1,  SER_INIT|SER_MAND);
655 #endif
656 
657     /* -------------------------------------------------------------------- */
658     /*  Parse the commandline flags.                                        */
659     /* -------------------------------------------------------------------- */
660     while ((c = getopt_long(argc, argv_copy, optchars, cfg_longopt,
661                             &option_idx)) != EOF)
662     {
663         int noarg = 1;
664         double dvalue;
665 
666         value = 1;
667         dvalue = 1.0;
668         if (optarg)
669         {
670             noarg = 0;
671             value = atoi(optarg);
672             sscanf(optarg, "%lf", &dvalue);
673         }
674 
675         if (c >= 1000 && c <= 1099)     /* joystick flags */
676         {
677             int joy_num = (c - 1000) / 10, stick = (c - 1000) % 10;
678             STR_REPLACE(joy_cfg[joy_num][stick], (optarg ? optarg : ""));
679         } else switch (c)
680         {
681             case '?': case 'h': usage();                                break;
682             case 'l': license();                                        break;
683             case 'q': silent = 1;                                       break;
684             case 'B': snd_buf_size    = value;                          break;
685             case 'C': snd_buf_cnt     = value;                          break;
686             case 'M': cfg->accutick   = value;                          break;
687             case 'E': STR_REPLACE(cfg->fn_ecs     , optarg);            break;
688             case 'e': STR_REPLACE(cfg->fn_exec    , optarg);            break;
689             case 'g': STR_REPLACE(cfg->fn_grom    , optarg);            break;
690             case 'G': cfg->gram_size  = value;                          break;
691             case 'F': STR_REPLACE(audiofile       , optarg);            break;
692             case 's': cfg->ecs_enable = value;                          break;
693             case 'z': STR_REPLACE(disp_res        , optarg);            break;
694             case 'd': cfg->debugging  = 1;                              break;
695             case 'r': cfg->rate_ctl   = dvalue;                         break;
696             case 'a': cfg->audio_rate = value;                          break;
697             case 'w': cfg->psg_window = value;                          break;
698             case 'v': cfg->ivc_enable = value;                          break;
699             case 'W': cfg->ivc_window = value;                          break;
700             case 'V': STR_REPLACE(cfg->ivc_tname  , optarg);            break;
701             case 'i': cfg->i2pc0_port = value;                          break;
702             case 'I': cfg->i2pc1_port = value;                          break;
703             case 'S': STR_REPLACE(debug_symtbl    , optarg);            break;
704 
705             case FLAG_AVI_RATE:
706                 cfg->avi_time_scale = dvalue;
707                 break;
708 
709             case FLAG_DBG_SCRIPT:
710                 STR_REPLACE(debug_script, optarg);
711                 break;
712 
713             case FLAG_DBG_SRCMAP:
714                 STR_REPLACE(debug_srcmap, optarg);
715                 break;
716 
717             case FLAG_CGC0:
718                 cfg->cgc0_num   = noarg ? 0 : value;
719                 STR_REPLACE(cfg->cgc0_dev   , optarg);
720                 break;
721 
722             case FLAG_CGC1:
723                 cfg->cgc1_num   = noarg ? 0 : value;
724                 STR_REPLACE(cfg->cgc1_dev   , optarg);
725                 break;
726 
727             case FLAG_KBDHACKFILE:
728                 STR_REPLACE(kbdhackfile     , optarg);
729                 break;
730 
731             case FLAG_GP2X_CLOCK:
732 #ifdef GP2X
733                 gp2xclock = value;
734 #endif
735                 break;
736 
737 #define CHG_BIT(var, bit, to) (var) = ((var) & ~(bit)) | ((to) ? (bit) : 0)
738 
739             case 'f': case 'x':
740                 CHG_BIT(cfg->gfx_flags, GFX_FULLSC, value);
741                 break;
742 
743             case FLAG_GFX_SWSURF:
744                 CHG_BIT(cfg->gfx_flags, GFX_SWSURF, value);
745                 break;
746 
747             case FLAG_GFX_DBLBUF:
748                 CHG_BIT(cfg->gfx_flags, GFX_DBLBUF, value);
749                 if (value != 0)
750                     CHG_BIT(cfg->gfx_flags, GFX_DRECTS, 0);
751                 break;
752 
753             case FLAG_GFX_ASYNCB:
754                 CHG_BIT(cfg->gfx_flags, GFX_ASYNCB, value);
755                 break;
756 
757             case FLAG_GFX_HWPAL:
758                 CHG_BIT(cfg->gfx_flags, GFX_HWPAL,  value);
759                 break;
760 
761             case FLAG_GFX_DIRTYRECT:
762                 CHG_BIT(cfg->gfx_flags, GFX_DRECTS, value);
763                 if (value != 0)
764                     CHG_BIT(cfg->gfx_flags, GFX_DBLBUF, 0);
765                 break;
766 
767             case FLAG_GFX_DR_MERGE:
768                 CHG_BIT(cfg->gfx_flags, GFX_DRCMRG, value);
769                 break;
770 
771             case FLAG_GFX_VERBOSE:
772                 gfx_verbose = 1;
773                 break;
774 
775             case FLAG_GFX_PALETTE:
776                 STR_REPLACE(gfx_palette, optarg);
777                 break;
778 
779             case 'b':
780                 bpct = value;
781                 break;
782 
783             case FLAG_GFX_BORD_X:
784                 bx = value;
785                 break;
786 
787             case FLAG_GFX_BORD_Y:
788                 by = value;
789                 break;
790 
791             case FLAG_GUI_MODE:
792                 cfg->gui_mode = 1;
793                 break;
794 
795             case FLAG_RAND_MEM:
796                 rand_mem = 1;
797                 break;
798 
799             case 'P':
800                 cfg->pal_mode = 1;
801                 break;
802 
803             case FLAG_FILE_IO:
804                 STR_REPLACE(elfi_prefix, optarg);
805                 break;
806 
807             case 'D':
808                 STR_REPLACE(demofile, optarg);
809                 break;
810 
811             case '9':
812                 busywaits = 0;
813                 break;
814 
815             case FLAG_ENABLE_MOUSE:
816                 enable_mouse = 1;
817                 break;
818 
819             case FLAG_PRESCALE:
820                 cfg->prescale = value;
821                 break;
822 
823             case FLAG_JLP_SAVEGAME:
824                 STR_REPLACE(jlpsg, optarg);
825                 jlp_accel = 3;
826                 break;
827 
828             case 'J':
829                 jlp_accel = !noarg ? value : 3;
830                 break;
831 
832             case 'j':
833                 jlp_flash = value;
834                 break;
835 
836             case FLAG_LOCUTUS:
837                 locutus = 1;
838                 break;
839 
840             case FLAG_ECS_TAPE:
841                 STR_REPLACE(fn_ecs_tape, optarg);
842                 break;
843 
844             case FLAG_ECS_PRINTER:
845                 STR_REPLACE(fn_ecs_printer, optarg);
846                 break;
847 
848             case 'c':
849             {
850                 const char *name = "Default";
851                 switch (value)
852                 {
853                     default:
854                     case 0: cache_flags = IC_CACHE_CABS;
855                             name = "Cache bankswitched";            break;
856                     case 1: cache_flags = IC_CACHE_NOBS;
857                             name = "Don't cache bankswitched";      break;
858                     case 2: cache_flags = IC_CACHE_SAFE;
859                             name = "Cache read-only, no banksw";    break;
860                     case 3: cache_flags = IC_CACHE_NONE;
861                             name = "Cache nothing";                 break;
862                 }
863 
864                 UNUSED(name);
865                 break;
866             }
867 
868             case 'p':
869             {
870                 rom_path = parse_path_string(rom_path, optarg);
871                 break;
872             }
873 
874             case FLAG_START_DELAY:
875             {
876                 float ftmp = -1.f;
877 
878                 sscanf(optarg, "%f", &ftmp);
879 
880                 cfg->start_dly = 1000.f * ftmp;
881                 break;
882             }
883 
884             case 'm':
885             {
886                 if (value >= 0 && value < 4)
887                     initial_event_map = value;
888                 break;
889             }
890 
891             case FLAG_CHEAT:
892             {
893                 if (cheat_add(&cfg->cheat, optarg))
894                 {
895                     fprintf(stderr, "Unable to parse cheat arg.\n");
896                     exit(1);
897                 }
898                 break;
899             }
900 
901             default:
902             {
903                 fprintf(stderr, "Unrecognized option: '%s'\n"
904                         "Try jzintv --help for usage information.\n",
905                         argv_copy[optind - 1]);
906                 exit(1);
907             }
908         }
909     }
910 
911     if (optind < argc)
912         STR_REPLACE(cfg->fn_game, argv_copy[optind]);
913 
914     CONDFREE(argv_data);
915     CONDFREE(argv_copy);
916 
917     rom_path = parse_path_string(rom_path, getenv("JZINTV_ROM_PATH"));
918 
919     if (DEFAULT_ROM_PATH)
920         rom_path = parse_path_string(rom_path, DEFAULT_ROM_PATH);
921 
922     /* -------------------------------------------------------------------- */
923     /*  Set up jzp_printf.                                                  */
924     /* -------------------------------------------------------------------- */
925     if (cfg->gui_mode)
926     {
927         cfg->debugging = 0;
928         jzp_init(1, 0, NULL, NULL);
929         setvbuf(stdin, NULL, _IONBF, 0);
930 #ifndef NO_FCNTL
931         fcntl(STDIN_FILENO, F_SETFL, O_NDELAY);
932 #endif
933     } else
934         jzp_init(silent, stdout, NULL, NULL);
935 
936 #ifdef WII
937     /* -------------------------------------------------------------------- */
938     /*  On WII, just make sure we're full-screen.                           */
939     /* -------------------------------------------------------------------- */
940     cfg->gfx_flags |= GFX_FULLSC;
941 #endif
942 
943 #ifdef GP2X
944     /* -------------------------------------------------------------------- */
945     /*  On GP2X, simply force a few arguments to the only supported vals.   */
946     /*  Also, adjust the clock if the user requests it.                     */
947     /* -------------------------------------------------------------------- */
948     cfg->gfx_flags |=  GFX_FULLSC;
949     cfg->gfx_flags &= ~GFX_DBLBUF;
950     STR_REPLACE(disp_res, "2");
951 
952     if (gp2xclock > 0)
953     {
954         extern int gp2x_speed(int);
955 
956         if (gp2x_speed(gp2xclock))
957         {
958             jzp_printf("Clock rate %d unsupported.\n", gp2xclock);
959             exit(1);
960         }
961     }
962 #endif
963 
964     /* -------------------------------------------------------------------- */
965     /*  If the user specified a palette file, read it in.                   */
966     /* -------------------------------------------------------------------- */
967     if (gfx_palette)
968     {
969 
970         /* The internal names take precedence over external filenames. */
971         if (palette_get_by_name(gfx_palette, &cfg->palette) == 0)
972         {
973             /* continue */
974         } else
975         {
976             LZFILE *palette_file = path_fopen(rom_path, gfx_palette, "r");
977             if (!palette_file)
978             {
979                 jzp_printf("Unable to locate palette '%s'\n", gfx_palette);
980                 exit(1);
981             } else if (palette_load_file(palette_file, &cfg->palette))
982             {
983                 jzp_printf("Unable to parse palette '%s'\n", gfx_palette);
984                 exit(1);
985             }
986             lzoe_fclose(palette_file);
987         }
988     } else
989     {
990         int idx = cfg->pal_mode ? PALETTE_DEFAULT_PAL : PALETTE_DEFAULT_NTSC;
991         if (palette_get_by_idx(idx, &cfg->palette))
992         {
993             jzp_printf("Internal error configuring palette\n");
994             exit(1);
995         }
996     }
997 
998     /* -------------------------------------------------------------------- */
999     /*  Sanity-check some of the flags.  Most get checked by peripherals.   */
1000     /* -------------------------------------------------------------------- */
1001     if ( (err_msg = cfg_parseres( disp_res, &rx, &ry, &rd )) != NULL )
1002     {
1003         int i;
1004         fprintf(stderr,
1005 "%s\n"
1006 "Resolution string must be of the following forms:\n"
1007 "\n"
1008 "   N       where N is one of the built in resolutions\n"
1009 "   WxH     where W is display width and H is display height\n"
1010 "   WxH,D   where W is display width, H is display height, and D is color depth\n"
1011 "\n"
1012 "Width must be at least 320, and height must be at least 200.  Color depth\n"
1013 "defaults to 8bpp.  jzIntv supports 8bpp, 16bpp, 24bpp and 32bpp\n"
1014 "\n"
1015 "Valid built-in resolutions:\n\n",
1016             err_msg
1017         );
1018 
1019         for (i = 0; i < NUM_RES; i++)
1020         {
1021             fprintf(stderr, "    -z%d:  %dx%dx%d\n",
1022                     i, res_x[i], res_y[i], res_d[i]);
1023         }
1024         exit(1);
1025     }
1026     CONDFREE(disp_res);
1027 
1028     /* Establish border based on explicit values or "percentage" */
1029     if (bx < 0) bx = bpct >= 0 ? (bpct * rx + 1) / 100 : 0;
1030     if (by < 0) by = bpct >= 0 ? (bpct * ry + 1) / 100 : 0;
1031 
1032     bx = (bx + 7) & ~7;     /* Round horizontal border to multiple of 8 */
1033 
1034     if ( gfx_check(rx, ry, rd, cfg->prescale) != 0 )
1035     {
1036         exit(1);
1037     }
1038 
1039     /* -------------------------------------------------------------------- */
1040     /*  Delay starting emulation if full-screen is specified and no other   */
1041     /*  start delay is specified.                                           */
1042     /* -------------------------------------------------------------------- */
1043 #if FULLSC_START_DLY > 0
1044     if (cfg->start_dly < 0 && (cfg->gfx_flags & GFX_FULLSC) != 0)
1045         cfg->start_dly = FULLSC_START_DLY;
1046 #endif
1047 
1048 
1049     /* -------------------------------------------------------------------- */
1050     /*  He's a macho, macho duck.  He's a macho, macho duck!                */
1051     /* -------------------------------------------------------------------- */
1052     if (cfg->rate_ctl <= 0.01)
1053     {
1054         cfg->rate_ctl = 0;
1055         cfg->gfx_flags |= GFX_SKIP_EXTRA;
1056     }
1057     if (cfg->rate_ctl > 1.5)
1058         cfg->gfx_flags |= GFX_SKIP_EXTRA;
1059 
1060     /* -------------------------------------------------------------------- */
1061     /*  Default AVI rate to the same as rate_ctl unless explicitly given.   */
1062     /*  In batch mode, consider rate_ctl == 0 to mean "1.0."                */
1063     /* -------------------------------------------------------------------- */
1064     {
1065         if (cfg->avi_time_scale <= 0.01)
1066             cfg->avi_time_scale = cfg->rate_ctl > 0.0 ? cfg->rate_ctl
1067                                 : batch_mode          ? 1.0
1068                                 :                       10000.0;
1069 
1070         double audio_time_scale = cfg->rate_ctl >= 0.0 ? cfg->rate_ctl : 1.0;
1071 
1072         if (batch_mode && cfg->rate_ctl == 0.0)
1073             audio_time_scale = 1.0;
1074 
1075         avi_set_time_scale(cfg->avi_time_scale, audio_time_scale);
1076     }
1077 
1078 #ifdef DIRECT_INTV2PC
1079     /* -------------------------------------------------------------------- */
1080     /*  Look up INTV2PC port numbers, if any.                               */
1081     /* -------------------------------------------------------------------- */
1082     if (cfg->i2pc0_port > 3 || cfg->i2pc1_port > 3)
1083     {
1084         fprintf(stderr, "ERROR:  "
1085             "INTV2PC port number out of range.  Valid values are 1..3 for\n"
1086             "typical ports for LPT1: through LPT3:, and 0 to disable.\n"
1087             "\n"
1088             "The following port numbers are selected by 1 through 3:\n"
1089             "   1 selects 0x%.3X\n"
1090             "   2 selects 0x%.3X\n"
1091             "   3 selects 0x%.3X\n"
1092             "\n", i2pc_ports[1], i2pc_ports[2], i2pc_ports[3]);
1093         exit(1);
1094     }
1095     if (cfg->i2pc0_port && cfg->i2pc0_port == cfg->i2pc1_port)
1096     {
1097         fprintf(stderr, "ERROR:  Cannot enable two INTV2PCs on same port #\n");
1098         exit(1);
1099     }
1100     cfg->i2pc0_port = i2pc_ports[cfg->i2pc0_port];
1101     cfg->i2pc1_port = i2pc_ports[cfg->i2pc1_port];
1102 #endif
1103 
1104     /* -------------------------------------------------------------------- */
1105     /*  Create a new peripheral bus for the Intellivision main console.     */
1106     /* -------------------------------------------------------------------- */
1107     cfg->intv = periph_new(16, 16, 4);
1108     strncpy(cfg->intv->periph.name, "MasterComponent", 16);
1109 
1110     /* -------------------------------------------------------------------- */
1111     /*  Now, configure the Intellivision according to our flags.  Start     */
1112     /*  off by reading in the EXEC, GROM, and GAME images.                  */
1113     /* -------------------------------------------------------------------- */
1114     f = path_fopen(rom_path, cfg->fn_exec, "rb");
1115 
1116     exec_type = 0;
1117     if (!f || file_read_rom16(f, 4096, cfg->exec_img) != 4096)
1118     {
1119         if (errno) perror("file_read_rom16");
1120         fprintf(stderr, "ERROR:  Could not read EXEC image '%s'\n",
1121                 cfg->fn_exec);
1122         dump_search_path(rom_path);
1123         exit(1);
1124     }
1125     lzoe_fseek(f, 0, SEEK_END);
1126     if (lzoe_ftell(f) == 2 * (4096 + 256))
1127     {
1128         exec_type = 1;
1129         lzoe_fseek(f, 8192, SEEK_SET);
1130         if (file_read_rom16(f, 256, cfg->exec_img + 4096) != 256)
1131         {
1132             if (errno) perror("file_read_rom16");
1133             fprintf(stderr, "ERROR:  Could not read EXEC2 image '%s'\n",
1134                     cfg->fn_exec);
1135             exit(1);
1136         }
1137     } else if (lzoe_ftell(f) == 2 * 8192)
1138     {
1139         exec_type = 2;  /* INTV88 / TutorVision */
1140         lzoe_fseek(f, 8192, SEEK_SET);
1141         if (file_read_rom16(f, 4096, cfg->exec_img + 4096) != 4096)
1142         {
1143             if (errno) perror("file_read_rom16");
1144             fprintf(stderr, "ERROR:  Could not read WBEXEC image '%s'\n",
1145                     cfg->fn_exec);
1146             exit(1);
1147         }
1148     }
1149 
1150     lzoe_fclose(f);
1151 
1152     f = path_fopen(rom_path, cfg->fn_grom, "rb");
1153     if (!f || file_read_rom8 (f, 2048, cfg->grom_img) != 2048)
1154     {
1155         if (errno) perror("file_read_rom8");
1156         fprintf(stderr, "ERROR:  Could not read GROM image '%s'\n",
1157                 cfg->fn_grom);
1158         dump_search_path(rom_path);
1159         exit(1);
1160     }
1161     lzoe_fclose(f);
1162 
1163     /* -------------------------------------------------------------------- */
1164     /*  Once we know the EXEC type, adjust the GRAM size if necessary       */
1165     /* -------------------------------------------------------------------- */
1166     if (cfg->gram_size < 0)
1167         cfg->gram_size = exec_type == 2 ? 2 : 0;
1168 
1169     /* -------------------------------------------------------------------- */
1170     /*  XXX:  Hack:  If locutus == 1, then this is a LUIGI file.  Short     */
1171     /*  circuit everything and just read fn_game as a LUIGI file.           */
1172     /* -------------------------------------------------------------------- */
1173     if (locutus)
1174     {
1175         int locutus_ecs, locutus_voice;
1176         if ( make_locutus( &(cfg->locutus), cfg->fn_game, &cfg->cp1600, 0,
1177                            jlpsg ) )
1178         {
1179             fprintf(stderr, "ERROR:  make_locutus failed\n");
1180             exit(1);
1181         }
1182 
1183         // JLP emulation for Locutus is handled entirely inside Locutus, and
1184         // must be specified within the LUIGI flags.  The only thing the user
1185         // can provide is the name of the savegame file.
1186         jlp_accel = 0;
1187         jlp_flash = 0;
1188 
1189         // If the user didn't specify ECS and/or Intellivoice flags, pick them
1190         // up from the LUIGI file.  Only enable ECS/Intellivoice if the game
1191         // is at least "enhanced" by the peripheral.
1192         locutus_ecs   = get_locutus_compat_ecs  ( &(cfg->locutus) );
1193         locutus_voice = get_locutus_compat_voice( &(cfg->locutus) );
1194 
1195         if (cfg->ecs_enable == -1 && locutus_ecs >= CMP_ENHANCED)
1196             cfg->ecs_enable = 1;
1197         else if (cfg->ecs_enable == 0 && locutus_ecs == CMP_REQUIRES)
1198             jzp_printf("\nWARNING:  ECS explicitly disabled; "
1199                        "however the game says the ECS is required.\n\n");
1200 
1201         if (cfg->ivc_enable == -1 && locutus_voice >= CMP_ENHANCED)
1202             cfg->ivc_enable = 1;
1203         else if (cfg->ivc_enable == 0 && locutus_voice == CMP_REQUIRES)
1204             jzp_printf("\nWARNING:  Intellivoice explicitly disabled; "
1205                        "however the game says the \n"
1206                        "          Intellivoice is required.\n\n");
1207 
1208         meta = get_locutus_metadata(&(cfg->locutus));
1209         meta_needs_free = 1;
1210 
1211         goto locutus_loaded;
1212     }
1213 
1214     /* -------------------------------------------------------------------- */
1215     /*  First try to load it as a legacy ROM.  If the legacy code decides   */
1216     /*  it's not actually a BIN+CFG, it'll hand us back a .ROM filename.    */
1217     /* -------------------------------------------------------------------- */
1218     tmp = legacy_bincfg(&(cfg->legacy), rom_path, cfg->fn_game, &legacy_rom,
1219                         &(cfg->cp1600), jlp_accel, jlp_flash, rand_mem);
1220 
1221     if (legacy_rom && cfg->legacy.bc->metadata)
1222         meta = cfg->legacy.bc->metadata;
1223 
1224     if (legacy_rom && cfg->legacy.bc->diags)
1225     {
1226         jzp_printf("\n");
1227         bc_print_diag(jzp_printer(),
1228                       cfg->legacy.bc->cfgfile,
1229                       cfg->legacy.bc->diags, 0);
1230         jzp_printf("\n");
1231     }
1232 
1233     if (tmp == NULL)
1234     {
1235         fprintf(stderr, "ERROR:  Failed to initialize game\n");
1236         exit(1);
1237     }
1238     CONDFREE(cfg->fn_game);
1239     cfg->fn_game = tmp;
1240 
1241     /* -------------------------------------------------------------------- */
1242     /*  If it wasn't a legacy ROM, it must be an Intellicart ROM.           */
1243     /* -------------------------------------------------------------------- */
1244     if (!legacy_rom)
1245     {
1246         /* not path_fopen, because legacy_bincfg should do that for us. */
1247         if (!(f = lzoe_fopen(cfg->fn_game, "rb")))
1248         {
1249             perror("fopen()");
1250             fprintf(stderr, "ERROR:  Failed to open Intellicart ROM:\n  %s\n",
1251                     cfg->fn_game);
1252             exit(1);
1253         }
1254 
1255         /* ---------------------------------------------------------------- */
1256         /*  Process the Intellicart ROM itself.                             */
1257         /* ---------------------------------------------------------------- */
1258         if (icart_init(&cfg->icart, f, rand_mem))
1259         {
1260             fprintf(stderr, "ERROR:  Failed to register Intellicart\n");
1261             exit(1);
1262         }
1263 
1264         /* ---------------------------------------------------------------- */
1265         /*  Grab a look-see on any metadata that was in there.              */
1266         /* ---------------------------------------------------------------- */
1267         if (cfg->icart.rom.metadata)
1268             meta = cfg->icart.rom.metadata;
1269 
1270         lzoe_fclose(f);
1271     }
1272 
1273     /* -------------------------------------------------------------------- */
1274     /*  Now that we've established the ROM path exactly, go see if we       */
1275     /*  know anything about it, such as its name, what year it was made,    */
1276     /*  and if it prefers to have voice / ECS turned on.  If the user       */
1277     /*  didn't specify voice on/off or ECS on/off, we'll use this info.     */
1278     /* -------------------------------------------------------------------- */
1279     {
1280         uint32_t crc32;
1281         int tentative_metadata = 0;
1282         crc32 = file_crc32(cfg->fn_game);
1283 
1284         if (!meta)
1285         {
1286             meta = default_game_metadata();
1287             if (meta)
1288             {
1289                 game_metadata_set_compat_to_unspec(meta);
1290                 tentative_metadata = 1;
1291                 meta_needs_free = 1;
1292             }
1293         }
1294 
1295         if (!find_cart_metadata(crc32, meta) && tentative_metadata)
1296         {
1297             free_game_metadata( meta );
1298             meta = NULL;
1299             tentative_metadata = 0;
1300             meta_needs_free = 0;
1301         }
1302     }
1303 
1304 locutus_loaded:
1305     /* -------------------------------------------------------------------- */
1306     /*  Apply the game metadata to our defaults.                            */
1307     /* -------------------------------------------------------------------- */
1308     if (meta)
1309     {
1310         game_metadata_set_unspec_compat_to_defaults(meta);
1311 
1312         if (cfg->ecs_enable == -1 && meta->ecs_compat >= CMP_ENHANCED)
1313         {
1314             cfg->ecs_enable = 1;
1315             /* Fall back to "no ECS" if game is merely "enhanced" by ECS. */
1316             ecs_bin_fail_ok = meta->ecs_compat <= CMP_ENHANCED;
1317         } else if (cfg->ecs_enable == 0 && meta->ecs_compat == CMP_REQUIRES)
1318             jzp_printf("\nWARNING:  ECS explicitly disabled; "
1319                        "however the game says the ECS is required.\n\n");
1320 
1321         if (cfg->ivc_enable == -1 && meta->voice_compat >= CMP_ENHANCED)
1322             cfg->ivc_enable = 1;
1323         else if (cfg->ivc_enable == 0 && meta->voice_compat == CMP_REQUIRES)
1324             jzp_printf("\nWARNING:  Intellivoice explicitly disabled; "
1325                        "however the game says the \n"
1326                        "          Intellivoice is required.\n\n");
1327 
1328         if (jlp_accel == -1) jlp_accel = meta->jlp_accel;
1329         if (jlp_flash == -1) jlp_flash = meta->jlp_flash;
1330 
1331         print_metadata(meta);
1332 
1333         if (meta->name)
1334             cfg->cart_name = strdup(meta->name);
1335 
1336         /* If a build date is set, use its year as a default. */
1337         if (meta->build_dates && meta->build_dates[0].year)
1338             cfg->cart_year = meta->build_dates[0].year;
1339 
1340         /* If a release date is set, use its year, and let it override the */
1341         /* build date's year. */
1342         if (meta->release_dates && meta->release_dates[0].year)
1343             cfg->cart_year = meta->release_dates[0].year;
1344 
1345         /* Free this metadata if we own it. */
1346         if (meta_needs_free)
1347             free_game_metadata( meta );
1348         meta = NULL;
1349     }
1350 
1351     /* -------------------------------------------------------------------- */
1352     /*  Try to load the ECS ROM image early, in case we need to fall back   */
1353     /*  to ECS-disabled.  That way, subsequent code that tests ecs_enable   */
1354     /*  sees the correct state.                                             */
1355     /* -------------------------------------------------------------------- */
1356     if (cfg->ecs_enable > 0)
1357     {
1358         f = path_fopen(rom_path, cfg->fn_ecs, "rb");
1359         if (!f || file_read_rom16(f, 12*1024, cfg->ecs_img) != 12*1024)
1360         {
1361             if (errno) perror("\nECS ROM");
1362             if (ecs_bin_fail_ok)
1363             {
1364                 cfg->ecs_enable = 0;
1365                 jzp_printf(
1366                     "\n"
1367                   /* 0123456789012345678901234567890123456789 */
1368                     "NOTE: Game is 'enhanced by' the ECS, and"
1369                     " jzIntv tried to automatically enable\n"
1370                   /* 0123456789012345678901234567890123456789 */
1371                     "      ECS support.  However, jzIntv was "
1372                     "unable to load the ECS ROM.\n\n"
1373                   /* 0123456789012345678901234567890123456789 */
1374                     "      Disabling ECS support.\n\n");
1375                 goto skip_ecs;
1376             }
1377             fprintf(stderr, "ERROR:  Could not read ECS ROM image '%s'\n",
1378                     cfg->fn_ecs);
1379             dump_search_path(rom_path);
1380             exit(1);
1381         }
1382         lzoe_fclose(f);
1383     }
1384 skip_ecs:;
1385 
1386 #ifdef WII
1387     /* -------------------------------------------------------------------- */
1388     /*  On the Wii, default to the ECS keyboard bindings if ECS is enabled  */
1389     /*  since controller input will come from actual Wii controllers.       */
1390     /* -------------------------------------------------------------------- */
1391     if (cfg->ecs_enable > 0)
1392         initial_event_map = 2;
1393 #endif
1394 
1395     /* -------------------------------------------------------------------- */
1396     /*  Initialize the peripherals.                                         */
1397     /* -------------------------------------------------------------------- */
1398     jzp_printf("jzintv:  Initializing Master Component and peripherals...\n");
1399 
1400 #ifdef DIRECT_INTV2PC
1401     if (cfg->i2pc0_port > 0 &&
1402         pad_intv2pc_init(&cfg->i2pc0, 0x1F0, cfg->i2pc0_port))
1403     {
1404         fprintf(stderr, "ERROR:  Failed to initialize INTV2PC #0 at 0x%.3X\n",
1405                 cfg->i2pc0_port);
1406         exit(1);
1407     }
1408     if (cfg->ecs_enable > 0 &&
1409         cfg->i2pc1_port &&
1410         pad_intv2pc_init(&cfg->i2pc1, 0x0F0, cfg->i2pc1_port))
1411     {
1412         fprintf(stderr, "ERROR:  Failed to initialize INTV2PC #1 at 0x%.3X\n",
1413                 cfg->i2pc1_port);
1414         exit(1);
1415     }
1416 #endif
1417 
1418     if (cfg->cgc0_num >= 0 &&
1419         pad_cgc_init(&cfg->cgc0, 0x1F0, cfg->cgc0_num, cfg->cgc0_dev))
1420     {
1421         fprintf(stderr, "ERROR:  Failed to initialize CGC #%d as pad pair 0\n",
1422                 cfg->cgc0_num);
1423         exit(1);
1424     }
1425 
1426     if (cfg->ecs_enable > 0 &&
1427         cfg->cgc1_num >= 0 &&
1428         pad_cgc_init(&cfg->cgc1, 0x0F0, cfg->cgc1_num, cfg->cgc0_dev))
1429     {
1430         fprintf(stderr, "ERROR:  Failed to initialize CGC #%d as pad pair 1\n",
1431                 cfg->cgc1_num);
1432         exit(1);
1433     }
1434 
1435     if (emu_link_init())
1436     {
1437         fprintf(stderr, "ERROR:  Failed to initialize EMU_LINK\n");
1438         exit(1);
1439     }
1440 
1441     /* -------------------------------------------------------------------- */
1442     /*  Enable the Emu-Link File I/O if requested.                          */
1443     /* -------------------------------------------------------------------- */
1444     if (elfi_prefix)
1445         if (elfi_init(elfi_prefix))
1446         {
1447             fprintf(stderr, "ERROR:  Failed to initialize Emu-Link File I/O\n");
1448             exit(1);
1449         }
1450 
1451     if (demofile &&
1452         demo_init(&cfg->demo, demofile, &cfg->psg0,
1453                   cfg->ecs_enable > 0 ? &cfg->psg1 : 0))
1454     {
1455         fprintf(stderr, "ERROR:  Failed to initialize demo recorder\n");
1456         exit(1);
1457     }
1458 
1459     if (jlp_accel > 0 &&
1460         jlp_init(&cfg->jlp, jlpsg, &(cfg->cp1600.xr[0]), jlp_accel,
1461                  jlp_flash, rand_mem))
1462     {
1463         fprintf(stderr, "ERROR:  Failed to initialize JLP.\n"
1464                         "jlp_accel=%d  jlp_flash=%d  savegame='%s'\n",
1465                 jlp_accel, jlp_flash, jlpsg ? jlpsg : "(none)");
1466         exit(1);
1467     }
1468 
1469     if (gfx_init(&cfg->gfx, rx, ry, rd, cfg->gfx_flags, gfx_verbose,
1470                   cfg->prescale, bx, by, cfg->pal_mode, &cfg->avi,
1471                   cfg->audio_rate, &cfg->palette))
1472     {
1473         fprintf(stderr, "ERROR:  Failed to initialize graphics\n");
1474         exit(1);
1475     }
1476 
1477     if (cfg->audio_rate && snd_init(&cfg->snd, cfg->audio_rate, audiofile,
1478                                     snd_buf_size, snd_buf_cnt, &cfg->avi,
1479                                     cfg->pal_mode,
1480                                     cfg->rate_ctl))
1481     {
1482         fprintf(stderr, "WARNING:  Failed to initialize sound.  Disabled.\n");
1483         cfg->audio_rate = 0;
1484     }
1485 
1486     if (cp1600_init(&cfg->cp1600, 0x1000, 0x1004, rand_mem))
1487     {
1488         fprintf(stderr, "ERROR:  Failed to initialize CP-1610 CPU\n");
1489         exit(1);
1490     }
1491 
1492     if (mem_make_ram  (&cfg->scr_ram,  8, 0x0100, 8, rand_mem) ||
1493         mem_make_ram  (&cfg->sys_ram, 16, 0x0200, 9, rand_mem) /* ||
1494         mem_make_glitch_ram(&cfg->glt_ram, 0xD000, 12) ||
1495         mem_make_ram  (&cfg->gram,     8, 0x3800, 9)*/)
1496     {
1497         fprintf(stderr, "ERROR:  Failed to initialize RAMs\n");
1498         exit(1);
1499     }
1500     if (exec_type == 1 &&
1501         mem_make_9600a(&cfg->sys_ram2,    0x0300, 8))
1502     {
1503         fprintf(stderr, "ERROR:  Failed to initialize RAMs\n");
1504         exit(1);
1505     }
1506     if (exec_type == 2 &&
1507         mem_make_ram(&cfg->sys_ram2, 16, 0x0400, 8, rand_mem))
1508     {
1509         fprintf(stderr, "ERROR:  Failed to initialize RAMs\n");
1510         exit(1);
1511     }
1512 
1513     if (stic_init(&cfg->stic, cfg->grom_img, &cfg->cp1600.req_q, &cfg->gfx,
1514                   demofile ? &cfg->demo : NULL, rand_mem, cfg->pal_mode,
1515                   cfg->gram_size, exec_type == 2 ? STIC_STIC1A : STIC_8900))
1516     {
1517         fprintf(stderr, "ERROR:  Failed to initialize STIC\n");
1518         exit(1);
1519     }
1520 
1521     if (cfg->ecs_enable > 0 &&
1522         ecs_init(&cfg->ecs, cfg->ecs_img, &cfg->cp1600, rand_mem,
1523                  fn_ecs_tape, fn_ecs_printer))
1524     {
1525         fprintf(stderr, "ERROR:  Failed to initialize ECS\n");
1526         exit(1);
1527     }
1528     CONDFREE(fn_ecs_tape);
1529     CONDFREE(fn_ecs_printer);
1530 
1531     if (ay8910_init(&cfg->psg0, 0x1F0, &cfg->snd,
1532                     cfg->audio_rate, cfg->psg_window, cfg->accutick,
1533                     cfg->rate_ctl > 0.0 ? cfg->rate_ctl : 1.0, cfg->pal_mode,
1534                     &cfg->cp1600.periph.now))
1535     {
1536         fprintf(stderr, "ERROR:  Failed to initialize PSG#1 (AY8914)\n");
1537         exit(1);
1538     }
1539 
1540     if (cfg->ecs_enable > 0 &&
1541         ay8910_init(&cfg->psg1, 0x0F0, &cfg->snd,
1542                     cfg->audio_rate, cfg->psg_window, cfg->accutick,
1543                     cfg->rate_ctl > 0.0 ? cfg->rate_ctl : 1.0, cfg->pal_mode,
1544                     &cfg->cp1600.periph.now))
1545     {
1546         fprintf(stderr, "ERROR:  Failed to initialize PSG#2 (AY8914)\n");
1547         exit(1);
1548     }
1549 
1550     if (pad_init(&cfg->pad0, 0x1F0, PAD_INPUT_ONLY))
1551     {
1552         fprintf(stderr, "ERROR:  Failed to initialize game pads\n");
1553         exit(1);
1554     }
1555 
1556     if (cfg->ecs_enable > 0 &&
1557         pad_init(&cfg->pad1, 0x0F0, PAD_BIDIR))
1558     {
1559         fprintf(stderr, "ERROR:  Failed to ECS input device\n");
1560         exit(1);
1561     }
1562 
1563     if (cfg->rate_ctl > 0.0 &&
1564         speed_init(&cfg->speed, &cfg->gfx, &cfg->stic,
1565                    busywaits, cfg->rate_ctl, cfg->pal_mode))
1566     {
1567         fprintf(stderr, "ERROR:  Failed to initialize rate control.\n");
1568         exit(1);
1569     }
1570 
1571     if (cfg->debugging &&
1572         debug_init(&cfg->debug, &cfg->cp1600,
1573                    cfg->rate_ctl > 0.0 ? &cfg->speed : NULL, &cfg->gfx,
1574                    &cfg->stic, &cfg->event, debug_symtbl,
1575                    &cfg->stic.vid_enable, debug_script, &cfg->do_exit))
1576     {
1577         fprintf(stderr, "ERROR:  Failed to initialize debugger\n");
1578         exit(1);
1579     }
1580 
1581     if (joy_init(1, joy_cfg))
1582     {
1583         fprintf(stderr, "ERROR:  Failed to initialize joystick subsystem.\n");
1584         exit(1);
1585     }
1586 
1587     if (event_init(&cfg->event, enable_mouse, initial_event_map))
1588     {
1589         fprintf(stderr, "ERROR:  Failed to initialize event subsystem.\n");
1590         exit(1);
1591     }
1592 
1593     /* We must configure event bindings after initializing event subsystem. */
1594     if (cfg_setbind(cfg, kbdhackfile))
1595     {
1596         fprintf(stderr, "ERROR:  Failed to initialize key bindings\n");
1597         exit(1);
1598     }
1599 
1600     if (cfg->ivc_enable > 0 && cfg->audio_rate > 0 &&
1601         ivoice_init(&cfg->ivoice, 0x80, &cfg->snd,
1602                     cfg->audio_rate, cfg->ivc_window, cfg->ivc_tname,
1603                     cfg->pal_mode, cfg->rate_ctl > 0.0 ? cfg->rate_ctl : 1.0))
1604     {
1605         fprintf(stderr, "ERROR:  Failed to initialize Intellivoice\n");
1606         exit(1);
1607     }
1608 
1609     /* -------------------------------------------------------------------- */
1610     /*  Note:  We handle the EXEC ROM specially, since it's weird on        */
1611     /*  the Intellivision 2.                                                */
1612     /* -------------------------------------------------------------------- */
1613     if (exec_type == 0)
1614     {
1615         if (mem_make_rom(&cfg->exec,     16, 0x1000, 12, cfg->exec_img))
1616         {
1617             fprintf(stderr, "ERROR:  Failed to initialize EXEC ROM\n");
1618             exit(1);
1619         }
1620     } else if (exec_type == 1)
1621     {
1622         if (mem_make_rom(&cfg->exec,     16, 0x1000, 12, cfg->exec_img+256) ||
1623             mem_make_rom(&cfg->exec2,    16, 0x0400,  8, cfg->exec_img))
1624         {
1625             fprintf(stderr, "ERROR:  Failed to initialize EXEC2 ROM\n");
1626             exit(1);
1627         }
1628     } else if (exec_type == 2)
1629     {
1630         if (mem_make_rom(&cfg->exec,     16, 0x1000, 12, cfg->exec_img) ||
1631             mem_make_rom(&cfg->exec2,    16, 0x2000, 12, cfg->exec_img + 4096))
1632         {
1633             fprintf(stderr, "ERROR:  Failed to initialize WBEXEC ROM\n");
1634             exit(1);
1635         }
1636     }
1637 
1638     /* -------------------------------------------------------------------- */
1639     /*  Now register all the devices on the Intellivision's bus.            */
1640     /* -------------------------------------------------------------------- */
1641     #define P(x) cfg->intv, AS_PERIPH(&cfg->x)
1642 
1643     periph_register    (P(cp1600         ),  0x0000, 0x0000, "CP-1610"     );
1644 
1645     periph_register    (P(psg0           ),  0x01F0, 0x01FF, "PSG0 AY8914" );
1646     if (cfg->ecs_enable > 0)
1647         periph_register(P(psg1           ),  0x00F0, 0x00FF, "PSG1 AY8914" );
1648 
1649     if (cfg->ivc_enable > 0 && cfg->audio_rate)
1650         periph_register(P(ivoice         ),  0x0080, 0x0081, "Int. Voice"  );
1651 
1652     periph_register    (P(gfx            ),  0x0000, 0x0000, "[Graphics]"  );
1653     if (cfg->audio_rate)
1654         periph_register(P(snd            ),  0x0000, 0x0000, "[Sound]"     );
1655 
1656     periph_register    (P(scr_ram        ),  0x0100, 0x01EF, "Scratch RAM" );
1657 /*  periph_register    (P(glt_ram        ),  0xD000, 0xDFFF, "GLITCH RAM"  );*/
1658 
1659     switch (exec_type)
1660     {
1661         case 0:
1662         {
1663             periph_register(P(sys_ram    ),  0x0200, 0x035F, "System RAM"  );
1664             periph_register(P(exec       ),  0x1000, 0x1FFF, "EXEC ROM"    );
1665             break;
1666         }
1667         case 1:
1668         {
1669             periph_register(P(sys_ram    ),  0x0200, 0x035F, "System RAM"  );
1670             periph_register(P(sys_ram2   ),  0x0360, 0x03FF, "System RAM B");
1671             periph_register(P(exec       ),  0x1000, 0x1FFF, "EXEC2 main"  );
1672             periph_register(P(exec2      ),  0x0400, 0x04FF, "EXEC2 aux."  );
1673             break;
1674         }
1675         case 2:
1676         {
1677             periph_register(P(sys_ram    ),  0x0200, 0x03FF, "System RAM"  );
1678             periph_register(P(sys_ram2   ),  0x0400, 0x04FF, "System RAM B");
1679             periph_register(P(exec       ),  0x1000, 0x1FFF, "EXEC ROM"    );
1680             periph_register(P(exec2      ),  0x2000, 0x2FFF, "WBEXEC ROM"  );
1681             break;
1682         }
1683         default:
1684         {
1685             jzp_printf("Unknown EXEC type %d\n", exec_type);
1686             exit(1);
1687         }
1688     }
1689 
1690     if (cfg->ecs_enable > 0)
1691         ecs_register(&cfg->ecs, cfg->intv);
1692 
1693     periph_register    (P(pad0           ),  0x01F0, 0x01FF, "Pad Pair 0"  );
1694     if (cfg->ecs_enable > 0)
1695         periph_register(P(pad1           ),  0x00F0, 0x00FF, "Pad Pair 1"  );
1696     if (cfg->i2pc0_port)
1697         periph_register(P(i2pc0          ),  0x01F0, 0x01FF, "INTV2PC #0"  );
1698     if (cfg->i2pc1_port && cfg->ecs_enable > 0)
1699         periph_register(P(i2pc1          ),  0x00F0, 0x00FF, "INTV2PC #1"  );
1700     if (cfg->cgc0_num >= 0)
1701         periph_register(P(cgc0           ),  0x01F0, 0x01FF, "CGC #0"      );
1702     if (cfg->cgc1_num >= 0 && cfg->ecs_enable > 0)
1703         periph_register(P(cgc1           ),  0x00F0, 0x00FF, "CGC #1"      );
1704     periph_register    (P(stic.stic_cr   ),  0x0000, 0x007F, "STIC"        );
1705     if (exec_type != 2)
1706     {
1707         periph_register(P(stic.stic_cr   ),  0x4000, 0x403F, "STIC (alias)");
1708         periph_register(P(stic.stic_cr   ),  0x8000, 0x803F, "STIC (alias)");
1709         periph_register(P(stic.stic_cr   ),  0xC000, 0xC03F, "STIC (alias)");
1710     }
1711     periph_register    (P(stic.snoop_btab),  0x0200, 0x02EF, "STIC (BTAB)" );
1712     periph_register    (P(stic.snoop_gram),  0x3000, 0x3FFF, "GROM/GRAM" );
1713     if (exec_type != 2 && cfg->ecs_enable < 1)
1714     {
1715         periph_register(P(stic.alias_gram),  0x7800, 0x7FFF, "GRAM (alias)");
1716         periph_register(P(stic.alias_gram),  0xB800, 0xBFFF, "GRAM (alias)");
1717         periph_register(P(stic.alias_gram),  0xF800, 0xFFFF, "GRAM (alias)");
1718     }
1719 
1720     periph_register    (P(event          ),  0x0000, 0x0000, "[Event]"     );
1721 
1722     if (cfg->rate_ctl > 0.0)
1723         periph_register(P(speed          ),  0x0000, 0x0000, "[Rate Ctrl]" );
1724 
1725     /* -------------------------------------------------------------------- */
1726     /*  Register the game ROMs, or the Intellicart, as the case may be.     */
1727     /* -------------------------------------------------------------------- */
1728     if (locutus)
1729     {
1730         periph_register(P(locutus), 0x0000, 0xFFFF, "Locutus");
1731     } else if (legacy_rom)
1732     {
1733         legacy_register(&cfg->legacy, cfg->intv, &cfg->cp1600);
1734     } else
1735     {
1736         icart_register(&cfg->icart, cfg->intv, &cfg->cp1600, cache_flags);
1737     }
1738 
1739     /* -------------------------------------------------------------------- */
1740     /*  Mark the ROMs cacheable in the CPU.  Mark the 16-bit RAM as cache-  */
1741     /*  able, but in need of bus-snoop support.                             */
1742     /* -------------------------------------------------------------------- */
1743     cp1600_cacheable(&cfg->cp1600, 0x0200, 0x035F, 1);
1744     cp1600_cacheable(&cfg->cp1600, 0x1000, 0x1FFF, 0);
1745     cp1600_cacheable(&cfg->cp1600, 0x3000, 0x37FF, 0);
1746 
1747     /* -------------------------------------------------------------------- */
1748     /*  If JLP save-games are enabled, install the JLP neccessary portion   */
1749     /*  of the JLP RAM window at $9C80 to $9FFF.  JLP games that use the    */
1750     /*  SG support need to NOT declare RAM in this space!!!                 */
1751     /* -------------------------------------------------------------------- */
1752     if (jlp_accel > 0)
1753         periph_register(P(jlp            ),  0x8000, 0x9FFF, "JLP Support"   );
1754 
1755     /* -------------------------------------------------------------------- */
1756     /*  Register the debugger.  This _must_ be done last.                   */
1757     /* -------------------------------------------------------------------- */
1758     if (cfg->debugging)
1759         periph_register(P(debug          ),  0x0000, 0xFFFF, "[Debugger]"  );
1760 
1761 #if 0
1762     {
1763         f = fopen("ser.txt", "w");
1764         if (f)
1765             ser_print_hierarchy(f, NULL, 0, 0);
1766     }
1767 #endif
1768 
1769     /* -------------------------------------------------------------------- */
1770     /*  Load the source mapping if given one.                               */
1771     /* -------------------------------------------------------------------- */
1772     if (cfg->debugging && debug_srcmap)
1773         process_source_map(debug_srcmap);
1774 
1775     /* -------------------------------------------------------------------- */
1776     /*  Register the cheat engine if we have any cheats.                    */
1777     /* -------------------------------------------------------------------- */
1778     if (cheat_count(&cfg->cheat))
1779         periph_register(P(cheat),  0x0000, 0x0000, "[Cheat]");
1780 
1781     /* -------------------------------------------------------------------- */
1782     /*  Free up all of our temporary variables.                             */
1783     /* -------------------------------------------------------------------- */
1784     CONDFREE(audiofile);
1785     CONDFREE(kbdhackfile);
1786     CONDFREE(demofile);
1787     CONDFREE(jlpsg);
1788     CONDFREE(debug_symtbl);
1789     CONDFREE(debug_srcmap);
1790     CONDFREE(elfi_prefix);
1791     return;
1792 }
1793 
1794 /* ======================================================================== */
1795 /*  CFG_DTOR     -- Tear down a configured Intellivision.                   */
1796 /* ======================================================================== */
cfg_dtor(cfg_t * cfg)1797 void cfg_dtor(cfg_t *cfg)
1798 {
1799     periph_delete(cfg->intv);
1800     CONDFREE(cfg->ivc_tname);
1801     CONDFREE(cfg->cgc0_dev);
1802     CONDFREE(cfg->cgc1_dev);
1803     CONDFREE(cfg->fn_exec);
1804     CONDFREE(cfg->fn_game);
1805     CONDFREE(cfg->fn_grom);
1806     CONDFREE(cfg->fn_ecs);
1807     CONDFREE(cfg->cart_name);
1808 
1809     elfi_dtor();
1810     memset(cfg, 0, sizeof(cfg_t));
1811 }
1812 
1813 /* ======================================================================== */
1814 /*  This program is free software; you can redistribute it and/or modify    */
1815 /*  it under the terms of the GNU General Public License as published by    */
1816 /*  the Free Software Foundation; either version 2 of the License, or       */
1817 /*  (at your option) any later version.                                     */
1818 /*                                                                          */
1819 /*  This program is distributed in the hope that it will be useful,         */
1820 /*  but WITHOUT ANY WARRANTY; without even the implied warranty of          */
1821 /*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       */
1822 /*  General Public License for more details.                                */
1823 /*                                                                          */
1824 /*  You should have received a copy of the GNU General Public License along */
1825 /*  with this program; if not, write to the Free Software Foundation, Inc., */
1826 /*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.             */
1827 /* ======================================================================== */
1828 /*                 Copyright (c) 1998-2000, Joseph Zbiciak                  */
1829 /* ======================================================================== */
1830