1 /***************************************************************************
2
3 mame.c
4
5 Controls execution of the core MAME system.
6
7 ****************************************************************************
8
9 libretro manages:
10 - platform-specific init
11 - calls init_game() from retro_load_game()
12 - calls run_game() from retro_load_game
13
14 mame.c manages:
15 init_game()
16 - constructs the machine driver
17 - calls init_game_options()
18
19 init_game_options()
20 - determines color depth from the options
21 - computes orientation from the options
22
23 - initializes the savegame system
24 - calls init_machine()
25
26 init_machine()
27 - initializes the localized strings
28 - initializes the input system
29 - parses and allocates the game's input ports
30 - initializes the hard disk system
31 - loads the game's ROMs
32 - resets the timer system
33 - starts the refresh timer
34 - initializes the CPUs
35 - loads the configuration file
36 - initializes the memory system for the game
37 - calls the driver's DRIVER_INIT callback
38
39 - calls run_machine()
40
41 run_machine()
42 - calls vh_open()
43
44 vh_open()
45 - allocates the palette
46 - decodes the graphics
47 - computes vector game resolution
48 - sets up the artwork
49 - calls osd_create_display() to init the display
50 - allocates the scrbitmap
51 - sets the initial visible_area
52 - sets up buffered spriteram
53 - creates the user interface font
54 - creates the debugger bitmap and font
55 - finishes palette initialization
56
57 - initializes the tilemap system
58 - calls the driver's VIDEO_START callback
59 - starts the audio system
60 - disposes of regions marked as disposable
61 - calls ui_copyright_and_warnings()
62
63 pause_action_start_emulator()
64 - initializes the user interface
65 - initializes the cheat system
66 - calls the driver's NVRAM_HANDLER
67
68 --------------( at this point, we're up and running )---------------------------
69
70 - calls the driver's NVRAM_HANDLER
71 - tears down the cheat system
72 - saves the game's configuration
73
74 - stops the audio system
75 - calls the driver's VIDEO_STOP callback
76 - tears down the tilemap system
77 - calls vh_close()
78
79 vh_close()
80 - frees the decoded graphics
81 - frees the fonts
82 - calls osd_close_display() to shut down the display
83 - tears down the artwork
84 - tears down the palette system
85
86 - calls shutdown_machine()
87
88 shutdown_machine()
89 - tears down the memory system
90 - frees all the memory regions
91 - tears down the hard disks
92 - tears down the CPU system
93 - releases the input ports
94 - tears down the input system
95 - tears down the localized strings
96 - resets the saved state system
97
98 - calls osd_exit() to do platform-specific cleanup
99
100 - exits the program
101
102 ***************************************************************************/
103
104 #include <ctype.h>
105 #include <stdarg.h>
106 #include <file/file_path.h>
107 #include "ui_text.h"
108 #include "mamedbg.h"
109 #include "artwork.h"
110 #include "state.h"
111 #include "vidhrdw/generic.h"
112 #include "vidhrdw/vector.h"
113 #include "palette.h"
114 #include "harddisk.h"
115 #include "driver.h"
116 #include "mame.h"
117 #include "bootstrap.h"
118
119 /***************************************************************************
120
121 Constants
122
123 ***************************************************************************/
124
125 #define FRAMES_PER_FPS_UPDATE 12
126
127
128
129 /***************************************************************************
130
131 Global variables
132
133 ***************************************************************************/
134
135 /* handy globals for other parts of the system */
136 int framerate_test = 0;
137 void *record; /* for -record */
138 void *playback; /* for -playback */
139 int mame_debug; /* !0 when -debug option is specified */
140 int bailing; /* set to 1 if the startup is aborted to prevent multiple error messages */
141
142 extern int16_t XsoundBuffer[2048];
143 extern void (*pause_action)(void);
144
145 /* the active machine */
146 static struct RunningMachine active_machine;
147 struct RunningMachine *Machine = &active_machine;
148
149 /* the active game driver */
150 static const struct GameDriver *gamedrv;
151 static struct InternalMachineDriver internal_drv;
152
153 /* various game options filled in by the OSD */
154 struct GameOptions options;
155
156 /* the active video display */
157 static struct mame_display current_display;
158 static UINT8 visible_area_changed;
159
160 /* video updating */
161 static UINT8 full_refresh_pending;
162 static int last_partial_scanline;
163
164 /* speed computation */
165 static struct performance_info performance;
166
167 /* misc other statics */
168 static int settingsloaded;
169 static int leds_status;
170
171 /* artwork callbacks */
172 static struct artwork_callbacks mame_artwork_callbacks =
173 {
174 NULL,
175 artwork_load_artwork_file
176 };
177
178 static int game_loaded;
179
180
181
182 /***************************************************************************
183
184 Hard disk interface prototype
185
186 ***************************************************************************/
187
188 static struct chd_interface_file *mame_chd_open(const char *filename, const char *mode);
189 static void mame_chd_close(struct chd_interface_file *file);
190 static UINT32 mame_chd_read(struct chd_interface_file *file, UINT64 offset, UINT32 count, void *buffer);
191 static UINT32 mame_chd_write(struct chd_interface_file *file, UINT64 offset, UINT32 count, const void *buffer);
192 static UINT64 mame_chd_length(struct chd_interface_file *file);
193
194 static struct chd_interface mame_chd_interface =
195 {
196 mame_chd_open,
197 mame_chd_close,
198 mame_chd_read,
199 mame_chd_write,
200 mame_chd_length
201 };
202
203
204
205 /***************************************************************************
206
207 Other function prototypes
208
209 ***************************************************************************/
210
211 static int init_machine(void);
212 static void shutdown_machine(void);
213 static int run_machine(void);
214 void pause_action_start_emulator(void);
215
216 #ifdef MAME_DEBUG
217 static int validitychecks(void);
218 #endif
219
220 static int vh_open(void);
221 static void vh_close(void);
222 static void init_game_options(void);
223 static int decode_graphics(const struct GfxDecodeInfo *gfxdecodeinfo);
224 static void compute_aspect_ratio(const struct InternalMachineDriver *drv, int *aspect_x, int *aspect_y);
225 static void scale_vectorgames(int gfx_width, int gfx_height, int *width, int *height);
226 static int init_buffered_spriteram(void);
227
228 /***************************************************************************
229
230 Inline functions
231
232 ***************************************************************************/
233
234 /*-------------------------------------------------
235 bail_and_print - set the bailing flag and
236 print a message if one hasn't already been
237 printed
238 -------------------------------------------------*/
239
bail_and_print(const char * message)240 static INLINE void bail_and_print(const char *message)
241 {
242 if (!bailing)
243 {
244 bailing = 1;
245 log_cb(RETRO_LOG_ERROR, LOGPRE "%s\n", message);
246 }
247 }
248
249
250
251
252 /***************************************************************************
253
254 Core system management
255
256 ***************************************************************************/
257
init_game(int game)258 bool init_game(int game)
259 {
260 begin_resource_tracking();
261
262 #ifdef MAME_DEBUG
263 /* validity checks -- debug build only */
264 if (validitychecks())
265 return false;
266 #endif
267
268 /* first give the machine a good cleaning */
269 memset(Machine, 0, sizeof(*Machine));
270
271 /* initialize the driver-related variables in the Machine */
272 Machine->gamedrv = gamedrv = drivers[game];
273 expand_machine_driver(gamedrv->drv, &internal_drv);
274 Machine->drv = &internal_drv;
275 return true;
276 }
277
278
279 /*-------------------------------------------------
280 run_game - run the given game in a session
281 -------------------------------------------------*/
282
run_game(int game)283 bool run_game(int game)
284 {
285 init_game_options();
286
287 /* here's the meat of it all */
288 bailing = 0;
289
290 begin_resource_tracking();
291
292 /* finish setting up our local machine */
293 if (init_machine())
294 bail_and_print("Unable to initialize machine emulation");
295 else
296 {
297 /* then run it */
298 if (run_machine())
299 bail_and_print("Unable to start machine emulation");
300 else
301 {
302 game_loaded = 1;
303 return 0;
304 }
305
306 /* shutdown the local machine */
307 shutdown_machine();
308 }
309 /* stop tracking resources and exit the OSD layer */
310 end_resource_tracking();
311
312 return 1;
313 }
314
run_game_done(void)315 void run_game_done(void)
316 {
317 shutdown_machine();
318 end_resource_tracking();
319 }
320
321 /*-------------------------------------------------
322 init_machine - initialize the emulated machine
323 -------------------------------------------------*/
324
init_machine(void)325 static int init_machine(void)
326 {
327
328 /* load the localization file */
329 if (uistring_init(options.language_file) != 0)
330 {
331 log_cb(RETRO_LOG_ERROR, LOGPRE "uistring_init failed\n");
332 goto cant_load_language_file;
333 }
334
335 /* initialize the input system */
336 if (code_init() != 0)
337 {
338 log_cb(RETRO_LOG_ERROR, LOGPRE "code_init failed\n");
339 goto cant_init_input;
340 }
341
342 /* if we have inputs, process them now */
343 if (gamedrv->input_ports)
344 {
345 /* allocate input ports */
346 Machine->input_ports = input_port_allocate(gamedrv->input_ports);
347 if (!Machine->input_ports)
348 {
349 log_cb(RETRO_LOG_ERROR, LOGPRE "could not allocate Machine->input_ports\n");
350 goto cant_allocate_input_ports;
351 }
352
353 /* allocate default input ports */
354 Machine->input_ports_default = input_port_allocate(gamedrv->input_ports);
355 if (!Machine->input_ports_default)
356 {
357 log_cb(RETRO_LOG_ERROR, LOGPRE "could not allocate Machine->input_ports_default\n");
358 goto cant_allocate_input_ports_default;
359 }
360 }
361
362 /* init the hard drive interface now, before attempting to load */
363 chd_set_interface(&mame_chd_interface);
364
365 /* load the ROMs if we have some */
366 if (gamedrv->rom && rom_load(gamedrv->rom) != 0)
367 {
368 log_cb(RETRO_LOG_ERROR, LOGPRE "readroms failed\n");
369 goto cant_load_roms;
370 }
371
372 /* first init the timers; some CPUs have built-in timers and will need */
373 /* to allocate them up front */
374 timer_init();
375 cpu_init_refresh_timer();
376
377 /* now set up all the CPUs */
378 cpu_init();
379
380 /* load input ports settings (keys, dip switches, and so on) */
381 settingsloaded = load_input_port_settings();
382
383 /* multi-session safety - set spriteram size to zero before memory map is set up */
384 spriteram_size = spriteram_2_size = 0;
385
386 /* initialize the memory system for this game */
387 if (!memory_init())
388 {
389 log_cb(RETRO_LOG_ERROR, LOGPRE "memory_init failed\n");
390 goto cant_init_memory;
391 }
392
393 /* call the game driver's init function */
394 if (gamedrv->driver_init)
395 (*gamedrv->driver_init)();
396
397 return 0;
398
399 cant_init_memory:
400 cant_load_roms:
401 input_port_free(Machine->input_ports_default);
402 Machine->input_ports_default = 0;
403 cant_allocate_input_ports_default:
404 input_port_free(Machine->input_ports);
405 Machine->input_ports = 0;
406 cant_allocate_input_ports:
407 code_close();
408 cant_init_input:
409 cant_load_language_file:
410 return 1;
411 }
412
413
414
415 /*-------------------------------------------------
416 run_machine - start the various subsystems
417 and the CPU emulation; returns non zero in
418 case of error
419 -------------------------------------------------*/
420
run_machine(void)421 static int run_machine(void)
422 {
423 int res = 1;
424
425 /* start the video hardware */
426 if (vh_open())
427 bail_and_print("Unable to start video emulation");
428 else
429 {
430 /* initialize tilemaps */
431 tilemap_init();
432
433 /* start up the driver's video */
434 if (Machine->drv->video_start && (*Machine->drv->video_start)())
435 bail_and_print("Unable to start video emulation");
436 else
437 {
438 /* start the audio system */
439 if (sound_start())
440 bail_and_print("Unable to start audio emulation");
441 else
442 {
443 int region;
444
445 /* free memory regions allocated with REGIONFLAG_DISPOSE (typically gfx roms) */
446 for (region = 0; region < MAX_MEMORY_REGIONS; region++)
447 if (Machine->memory_region[region].flags & ROMREGION_DISPOSE)
448 {
449 int i;
450
451 /* invalidate contents to avoid subtle bugs */
452 for (i = 0; i < memory_region_length(region); i++)
453 memory_region(region)[i] = rand();
454 free(Machine->memory_region[region].base);
455 Machine->memory_region[region].base = 0;
456 }
457
458 ui_copyright_and_warnings();
459 pause_action = pause_action_start_emulator;
460 return 0;
461 }
462
463 /* shut down the driver's video and kill and artwork */
464 if (Machine->drv->video_stop)
465 (*Machine->drv->video_stop)();
466 }
467
468 /* close down the tilemap and video systems */
469 tilemap_close();
470 vh_close();
471 }
472
473 return res;
474 }
475
run_machine_done(void)476 void run_machine_done(void)
477 {
478 sound_stop();
479
480 /* shut down the driver's video and kill and artwork */
481 if (Machine->drv->video_stop)
482 (*Machine->drv->video_stop)();
483
484 /* close down the tilemap and video systems */
485 tilemap_close();
486 vh_close();
487 }
488
pause_action_start_emulator(void)489 void pause_action_start_emulator(void)
490 {
491 init_user_interface();
492 artwork_enable(1);
493 InitCheat();
494
495 /* load the NVRAM now */
496 if (Machine->drv->nvram_handler)
497 {
498 mame_file *nvram_file = mame_fopen(Machine->gamedrv->name, 0, FILETYPE_NVRAM, 0);
499
500 if(!nvram_file)
501 log_cb(RETRO_LOG_INFO, LOGPRE "First run: NVRAM handler found for %s but no existing NVRAM file found.\n", Machine->gamedrv->name);
502
503 log_cb(RETRO_LOG_INFO, LOGPRE "options.nvram_bootstrap: %i \n", options.nvram_bootstrap);
504 if(!nvram_file && (Machine->gamedrv->bootstrap != NULL))
505 {
506 if(options.nvram_bootstrap)
507 {
508 log_cb(RETRO_LOG_INFO, LOGPRE "Spwaning NVRAM bootstrap as the initial NVRAM image.\n");
509 nvram_file = spawn_bootstrap_nvram(Machine->gamedrv->bootstrap->data, Machine->gamedrv->bootstrap->length);
510 }
511 else
512 log_cb(RETRO_LOG_INFO, LOGPRE "NVRAM bootstrap available, but disabled via core option.\n");
513 }
514 else
515 log_cb(RETRO_LOG_INFO, LOGPRE "Delegating population of initial NVRAM to emulated system.\n");
516
517 (*Machine->drv->nvram_handler)(nvram_file, 0);
518 if (nvram_file)
519 mame_fclose(nvram_file);
520 }
521
522 /* run the emulation! */
523 cpu_run();
524
525 /* Unpause */
526 pause_action = 0;
527 }
528
run_machine_core_done(void)529 void run_machine_core_done(void)
530 {
531 /* save the NVRAM */
532 if (Machine->drv->nvram_handler)
533 {
534 mame_file *nvram_file = mame_fopen(Machine->gamedrv->name, 0, FILETYPE_NVRAM, 1);
535 if (nvram_file != NULL)
536 {
537 (*Machine->drv->nvram_handler)(nvram_file, 1);
538 mame_fclose(nvram_file);
539 }
540 }
541
542 StopCheat();
543
544 /* save input ports settings */
545 save_input_port_settings();
546 }
547
548 /*-------------------------------------------------
549 shutdown_machine - tear down the emulated
550 machine
551 -------------------------------------------------*/
552
shutdown_machine(void)553 static void shutdown_machine(void)
554 {
555 int i;
556
557 /* release any allocated memory */
558 memory_shutdown();
559
560 /* free the memory allocated for various regions */
561 for (i = 0; i < MAX_MEMORY_REGIONS; i++)
562 free_memory_region(i);
563
564 /* close all hard drives */
565 chd_close_all();
566
567 /* reset the CPU system */
568 cpu_exit();
569
570 /* free the memory allocated for input ports definition */
571 input_port_free(Machine->input_ports);
572 input_port_free(Machine->input_ports_default);
573
574 /* close down the input system */
575 code_close();
576
577 /* reset the saved states */
578 state_save_reset();
579 }
580
581 /*-------------------------------------------------
582 expand_machine_driver - construct a machine
583 driver from the macroized state
584 -------------------------------------------------*/
585
expand_machine_driver(void (* constructor)(struct InternalMachineDriver *),struct InternalMachineDriver * output)586 void expand_machine_driver(void (*constructor)(struct InternalMachineDriver *), struct InternalMachineDriver *output)
587 {
588 /* keeping this function allows us to pre-init the driver before constructing it */
589 memset(output, 0, sizeof(*output));
590 (*constructor)(output);
591 }
592
593
594
595 /*-------------------------------------------------
596 vh_open - start up the video system
597 -------------------------------------------------*/
598
vh_open(void)599 static int vh_open(void)
600 {
601 struct osd_create_params params;
602 struct artwork_callbacks *artcallbacks;
603 int bmwidth = Machine->drv->screen_width;
604 int bmheight = Machine->drv->screen_height;
605
606 /* first allocate the necessary palette structures */
607 if (palette_start())
608 goto cant_start_palette;
609
610 /* convert the gfx ROMs into character sets. This is done BEFORE calling the driver's */
611 /* palette_init() routine because it might need to check the Machine->gfx[] data */
612 if (Machine->drv->gfxdecodeinfo)
613 if (decode_graphics(Machine->drv->gfxdecodeinfo))
614 goto cant_decode_graphics;
615
616 /* if we're a vector game, override the screen width and height */
617 if (Machine->drv->video_attributes & VIDEO_TYPE_VECTOR)
618 {
619 scale_vectorgames(options.vector_width, options.vector_height, &bmwidth, &bmheight);
620 }
621 /* compute the visible area for raster games */
622 if (!(Machine->drv->video_attributes & VIDEO_TYPE_VECTOR))
623 {
624 params.width = Machine->drv->default_visible_area.max_x - Machine->drv->default_visible_area.min_x + 1;
625 params.height = Machine->drv->default_visible_area.max_y - Machine->drv->default_visible_area.min_y + 1;
626 }
627 else
628 {
629 params.width = bmwidth;
630 params.height = bmheight;
631 }
632
633 /* fill in the rest of the display parameters */
634 compute_aspect_ratio(Machine->drv, ¶ms.aspect_x, ¶ms.aspect_y);
635 params.depth = Machine->color_depth;
636 params.colors = palette_get_total_colors_with_ui();
637 params.fps = Machine->drv->frames_per_second;
638 params.video_attributes = Machine->drv->video_attributes;
639 params.orientation = Machine->orientation;
640 artcallbacks = &mame_artwork_callbacks;
641
642 /* initialize the display through the artwork (and eventually the OSD) layer */
643 if (artwork_create_display(¶ms, direct_rgb_components, artcallbacks))
644 goto cant_create_display;
645
646 /* the create display process may update the vector width/height, so recompute */
647 if (Machine->drv->video_attributes & VIDEO_TYPE_VECTOR)
648 {
649 scale_vectorgames(options.vector_width, options.vector_height, &bmwidth, &bmheight);
650 }
651
652
653 /* now allocate the screen bitmap */
654 Machine->scrbitmap = auto_bitmap_alloc_depth(bmwidth, bmheight, Machine->color_depth);
655 if (!Machine->scrbitmap)
656 goto cant_create_scrbitmap;
657
658 /* set the default visible area */
659 set_visible_area(0,1,0,1); /* make sure everything is recalculated on multiple runs */
660 set_visible_area(
661 Machine->drv->default_visible_area.min_x,
662 Machine->drv->default_visible_area.max_x,
663 Machine->drv->default_visible_area.min_y,
664 Machine->drv->default_visible_area.max_y);
665
666 /* create spriteram buffers if necessary */
667 if (Machine->drv->video_attributes & VIDEO_BUFFERS_SPRITERAM)
668 if (init_buffered_spriteram())
669 goto cant_init_buffered_spriteram;
670
671 /* build our private user interface font */
672 /* This must be done AFTER osd_create_display() so the function knows the */
673 /* resolution we are running at and can pick a different font depending on it. */
674 /* It must be done BEFORE palette_init() because that will also initialize */
675 /* (through osd_allocate_colors()) the uifont colortable. */
676 Machine->uifont = builduifont();
677 if (Machine->uifont == NULL)
678 goto cant_build_uifont;
679
680 #ifdef MAME_DEBUG
681 /* if the debugger is enabled, initialize its bitmap and font */
682 if (mame_debug)
683 {
684 int depth = options.debug_depth ? options.debug_depth : Machine->color_depth;
685
686 /* first allocate the debugger bitmap */
687 Machine->debug_bitmap = auto_bitmap_alloc_depth(options.debug_width, options.debug_height, depth);
688 if (!Machine->debug_bitmap)
689 goto cant_create_debug_bitmap;
690
691 /* then create the debugger font */
692 Machine->debugger_font = build_debugger_font();
693 if (Machine->debugger_font == NULL)
694 goto cant_build_debugger_font;
695 }
696 #endif
697
698 /* initialize the palette - must be done after osd_create_display() */
699 if (palette_init())
700 goto cant_init_palette;
701
702 /* force the first update to be full */
703 set_vh_global_attribute(NULL, 0);
704
705 /* reset video statics and get out of here */
706 pdrawgfx_shadow_lowpri = 0;
707 leds_status = 0;
708
709 return 0;
710
711 cant_init_palette:
712
713 #ifdef MAME_DEBUG
714 cant_build_debugger_font:
715 cant_create_debug_bitmap:
716 #endif
717
718 cant_build_uifont:
719 cant_init_buffered_spriteram:
720 cant_create_scrbitmap:
721 cant_create_display:
722 cant_decode_graphics:
723 cant_start_palette:
724 vh_close();
725 return 1;
726 }
727
728
729
730 /*-------------------------------------------------
731 vh_close - close down the video system
732 -------------------------------------------------*/
733
vh_close(void)734 static void vh_close(void)
735 {
736 int i;
737
738 /* free all the graphics elements */
739 for (i = 0; i < MAX_GFX_ELEMENTS; i++)
740 {
741 freegfx(Machine->gfx[i]);
742 Machine->gfx[i] = 0;
743 }
744
745 /* free the font elements */
746 if (Machine->uifont)
747 {
748 freegfx(Machine->uifont);
749 Machine->uifont = NULL;
750 }
751 if (Machine->debugger_font)
752 {
753 freegfx(Machine->debugger_font);
754 Machine->debugger_font = NULL;
755 }
756
757 /* close down the OSD layer's display */
758 osd_close_display();
759 }
760
761
762
763 /*-------------------------------------------------
764 compute_aspect_ratio - determine the aspect
765 ratio encoded in the video attributes
766 -------------------------------------------------*/
767
compute_aspect_ratio(const struct InternalMachineDriver * drv,int * aspect_x,int * aspect_y)768 static void compute_aspect_ratio(const struct InternalMachineDriver *drv, int *aspect_x, int *aspect_y)
769 {
770 /* if it's explicitly specified, use it */
771 if (drv->aspect_x && drv->aspect_y)
772 {
773 *aspect_x = drv->aspect_x;
774 *aspect_y = drv->aspect_y;
775 }
776
777 /* otherwise, attempt to deduce the result */
778 else if (!(drv->video_attributes & VIDEO_DUAL_MONITOR))
779 {
780 *aspect_x = 4;
781 *aspect_y = (drv->video_attributes & VIDEO_DUAL_MONITOR) ? 6 : 3;
782 }
783 }
784
785
786
787 /*-------------------------------------------------
788 init_game_options - initialize the various
789 game options
790 -------------------------------------------------*/
791
init_game_options(void)792 static void init_game_options(void)
793 {
794 /* copy some settings into easier-to-handle variables */
795 record = options.record;
796 playback = options.playback;
797 mame_debug = options.mame_debug;
798
799 /* determine the color depth */
800 Machine->color_depth = 16;
801 alpha_active = 0;
802 if (Machine->drv->video_attributes & VIDEO_RGB_DIRECT)
803 {
804 /* first pick a default */
805 if (Machine->drv->video_attributes & VIDEO_NEEDS_6BITS_PER_GUN)
806 Machine->color_depth = 32;
807 else
808 Machine->color_depth = 15;
809
810 /* use 32-bit color output as default to skip color conversions */
811 if (Machine->drv->video_attributes & VIDEO_TYPE_VECTOR) Machine->color_depth = 32;
812
813 /* now allow overrides */
814 if (options.color_depth == 15 || options.color_depth == 32)
815 Machine->color_depth = options.color_depth;
816
817 /* enable alpha for direct video modes */
818 alpha_active = 1;
819 alpha_init();
820 }
821
822 /* update the vector width/height with libretro settings or use the default */
823 if (options.vector_width == 0) options.vector_width = Machine->drv->screen_width;
824 if (options.vector_height == 0) options.vector_height = Machine->drv->screen_height;
825
826
827
828 /* get orientation right */
829 Machine->orientation = ROT0;
830 Machine->ui_orientation = options.ui_orientation;
831
832
833 // set sample rate here as osd_start_audio_stream the logic must be the same in both some soundcores require setting here as well
834 // ie ymf271 will segfault without this.
835 if (options.machine_timing)
836 {
837 if ( ( Machine->drv->frames_per_second * 1000 < options.samplerate) || (Machine->drv->frames_per_second < 60) )
838 Machine->sample_rate = Machine->drv->frames_per_second * 1000;
839
840 else Machine->sample_rate = options.samplerate;
841 }
842
843 else
844 {
845 if ( Machine->drv->frames_per_second * 1000 < options.samplerate)
846 Machine->sample_rate=22050;
847
848 else
849 Machine->sample_rate = options.samplerate;
850 }
851
852 }
853
854
855
856 /*-------------------------------------------------
857 decode_graphics - decode the graphics
858 -------------------------------------------------*/
859
decode_graphics(const struct GfxDecodeInfo * gfxdecodeinfo)860 static int decode_graphics(const struct GfxDecodeInfo *gfxdecodeinfo)
861 {
862 int i;
863
864 /* loop over all elements */
865 for (i = 0; i < MAX_GFX_ELEMENTS && gfxdecodeinfo[i].memory_region != -1; i++)
866 {
867 int region_length = 8 * memory_region_length(gfxdecodeinfo[i].memory_region);
868 UINT8 *region_base = memory_region(gfxdecodeinfo[i].memory_region);
869 struct GfxLayout glcopy;
870 int j;
871
872 /* make a copy of the layout */
873 glcopy = *gfxdecodeinfo[i].gfxlayout;
874
875 /* if the character count is a region fraction, compute the effective total */
876 if (IS_FRAC(glcopy.total))
877 glcopy.total = region_length / glcopy.charincrement * FRAC_NUM(glcopy.total) / FRAC_DEN(glcopy.total);
878
879 /* loop over all the planes, converting fractions */
880 for (j = 0; j < MAX_GFX_PLANES; j++)
881 {
882 int value = glcopy.planeoffset[j];
883 if (IS_FRAC(value))
884 glcopy.planeoffset[j] = FRAC_OFFSET(value) + region_length * FRAC_NUM(value) / FRAC_DEN(value);
885 }
886
887 /* loop over all the X/Y offsets, converting fractions */
888 for (j = 0; j < MAX_GFX_SIZE; j++)
889 {
890 int value = glcopy.xoffset[j];
891 if (IS_FRAC(value))
892 glcopy.xoffset[j] = FRAC_OFFSET(value) + region_length * FRAC_NUM(value) / FRAC_DEN(value);
893
894 value = glcopy.yoffset[j];
895 if (IS_FRAC(value))
896 glcopy.yoffset[j] = FRAC_OFFSET(value) + region_length * FRAC_NUM(value) / FRAC_DEN(value);
897 }
898
899 /* some games increment on partial tile boundaries; to handle this without reading */
900 /* past the end of the region, we may need to truncate the count */
901 /* an example is the games in metro.c */
902 if (glcopy.planeoffset[0] == GFX_RAW)
903 {
904 int base = gfxdecodeinfo[i].start;
905 int end = region_length/8;
906 while (glcopy.total > 0)
907 {
908 int elementbase = base + (glcopy.total - 1) * glcopy.charincrement / 8;
909 int lastpixelbase = elementbase + glcopy.height * glcopy.yoffset[0] / 8 - 1;
910 if (lastpixelbase < end)
911 break;
912 glcopy.total--;
913 }
914 }
915
916 /* now decode the actual graphics */
917 if ((Machine->gfx[i] = decodegfx(region_base + gfxdecodeinfo[i].start, &glcopy)) == 0)
918 {
919 bailing = 1;
920 log_cb(RETRO_LOG_ERROR, LOGPRE "Out of memory decoding gfx\n");
921 return 1;
922 }
923
924 /* if we have a remapped colortable, point our local colortable to it */
925 if (Machine->remapped_colortable)
926 Machine->gfx[i]->colortable = &Machine->remapped_colortable[gfxdecodeinfo[i].color_codes_start];
927 Machine->gfx[i]->total_colors = gfxdecodeinfo[i].total_color_codes;
928 }
929 return 0;
930 }
931
932
933
934 /*-------------------------------------------------
935 scale_vectorgames - scale the vector games
936 to a given resolution
937 -------------------------------------------------*/
938
scale_vectorgames(int gfx_width,int gfx_height,int * width,int * height)939 static void scale_vectorgames(int gfx_width, int gfx_height, int *width, int *height)
940 {
941 double x_scale, y_scale, scale;
942
943 /* compute the scale values */
944 x_scale = (double)gfx_width / (double)(*width);
945 y_scale = (double)gfx_height / (double)(*height);
946
947 /* pick the smaller scale factor */
948 scale = (x_scale < y_scale) ? x_scale : y_scale;
949
950 /* compute the new size */
951 *width = (int)((double)*width * scale);
952 *height = (int)((double)*height * scale);
953
954 /* round to the nearest 4 pixel value */
955
956 }
957
958
959
960 /*-------------------------------------------------
961 init_buffered_spriteram - initialize the
962 double-buffered spriteram
963 -------------------------------------------------*/
964
init_buffered_spriteram(void)965 static int init_buffered_spriteram(void)
966 {
967 /* make sure we have a valid size */
968 if (spriteram_size == 0)
969 {
970 log_cb(RETRO_LOG_ERROR, LOGPRE "vh_open(): Video buffers spriteram but spriteram_size is 0\n");
971 return 0;
972 }
973
974 /* allocate memory for the back buffer */
975 buffered_spriteram = auto_malloc(spriteram_size);
976 if (!buffered_spriteram)
977 return 1;
978
979 /* register for saving it */
980 state_save_register_UINT8("generic_video", 0, "buffered_spriteram", buffered_spriteram, spriteram_size);
981
982 /* do the same for the secon back buffer, if present */
983 if (spriteram_2_size)
984 {
985 /* allocate memory */
986 buffered_spriteram_2 = auto_malloc(spriteram_2_size);
987 if (!buffered_spriteram_2)
988 return 1;
989
990 /* register for saving it */
991 state_save_register_UINT8("generic_video", 0, "buffered_spriteram_2", buffered_spriteram_2, spriteram_2_size);
992 }
993
994 /* make 16-bit and 32-bit pointer variants */
995 buffered_spriteram16 = (data16_t *)buffered_spriteram;
996 buffered_spriteram32 = (data32_t *)buffered_spriteram;
997 buffered_spriteram16_2 = (data16_t *)buffered_spriteram_2;
998 buffered_spriteram32_2 = (data32_t *)buffered_spriteram_2;
999 return 0;
1000 }
1001
1002
1003
1004 /***************************************************************************
1005
1006 Screen rendering and management.
1007
1008 ***************************************************************************/
1009
1010 /*-------------------------------------------------
1011 set_visible_area - adjusts the visible portion
1012 of the bitmap area dynamically
1013 -------------------------------------------------*/
1014
set_visible_area(int min_x,int max_x,int min_y,int max_y)1015 void set_visible_area(int min_x, int max_x, int min_y, int max_y)
1016 {
1017 if ( Machine->visible_area.min_x == min_x
1018 && Machine->visible_area.max_x == max_x
1019 && Machine->visible_area.min_y == min_y
1020 && Machine->visible_area.max_y == max_y)
1021 return;
1022
1023 /* "dirty" the area for the next display update */
1024 visible_area_changed = 1;
1025
1026 /* set the new values in the Machine struct */
1027 Machine->visible_area.min_x = min_x;
1028 Machine->visible_area.max_x = max_x;
1029 Machine->visible_area.min_y = min_y;
1030 Machine->visible_area.max_y = max_y;
1031
1032 /* vector games always use the whole bitmap */
1033 if (Machine->drv->video_attributes & VIDEO_TYPE_VECTOR)
1034 {
1035 Machine->absolute_visible_area.min_x = 0;
1036 Machine->absolute_visible_area.max_x = Machine->scrbitmap->width - 1;
1037 Machine->absolute_visible_area.min_y = 0;
1038 Machine->absolute_visible_area.max_y = Machine->scrbitmap->height - 1;
1039 }
1040
1041 /* raster games need to use the visible area */
1042 else
1043 Machine->absolute_visible_area = Machine->visible_area;
1044
1045 /* recompute scanline timing */
1046 cpu_compute_scanline_timing();
1047 }
1048
1049
1050
1051 /*-------------------------------------------------
1052 schedule_full_refresh - force a full erase
1053 and refresh the next frame
1054 -------------------------------------------------*/
1055
schedule_full_refresh(void)1056 void schedule_full_refresh(void)
1057 {
1058 full_refresh_pending = 1;
1059 }
1060
1061
1062
1063 /*-------------------------------------------------
1064 reset_partial_updates - reset the partial
1065 updating mechanism for a new frame
1066 -------------------------------------------------*/
1067
reset_partial_updates(void)1068 void reset_partial_updates(void)
1069 {
1070 last_partial_scanline = 0;
1071 performance.partial_updates_this_frame = 0;
1072 }
1073
1074
1075
1076 /*-------------------------------------------------
1077 force_partial_update - perform a partial
1078 update from the last scanline up to and
1079 including the specified scanline
1080 -------------------------------------------------*/
1081
force_partial_update(int scanline)1082 void force_partial_update(int scanline)
1083 {
1084 struct rectangle clip = Machine->visible_area;
1085
1086 /* if skipping this frame, bail */
1087 if (osd_skip_this_frame())
1088 return;
1089
1090 /* skip if less than the lowest so far */
1091 if (scanline < last_partial_scanline)
1092 return;
1093
1094 /* if there's a dirty bitmap and we didn't do any partial updates yet, handle it now */
1095 if (full_refresh_pending && last_partial_scanline == 0)
1096 {
1097 fillbitmap(Machine->scrbitmap, get_black_pen(), NULL);
1098 full_refresh_pending = 0;
1099 }
1100
1101 /* set the start/end scanlines */
1102 if (last_partial_scanline > clip.min_y)
1103 clip.min_y = last_partial_scanline;
1104 if (scanline < clip.max_y)
1105 clip.max_y = scanline;
1106
1107 /* render if necessary */
1108 if (clip.min_y <= clip.max_y)
1109 {
1110 profiler_mark(PROFILER_VIDEO);
1111 (*Machine->drv->video_update)(Machine->scrbitmap, &clip);
1112 performance.partial_updates_this_frame++;
1113 profiler_mark(PROFILER_END);
1114 }
1115
1116 /* remember where we left off */
1117 last_partial_scanline = scanline + 1;
1118 }
1119
1120
1121
1122 /*-------------------------------------------------
1123 draw_screen - render the final screen bitmap
1124 and update any artwork
1125 -------------------------------------------------*/
1126 int gbPriorityBitmapIsDirty;
1127
draw_screen(void)1128 void draw_screen(void)
1129 {
1130 /* finish updating the screen */
1131 force_partial_update(Machine->visible_area.max_y);
1132 if( gbPriorityBitmapIsDirty )
1133 {
1134 fillbitmap( priority_bitmap, 0x00, NULL );
1135 gbPriorityBitmapIsDirty = 0;
1136 }
1137 }
1138
1139
1140 /*-------------------------------------------------
1141 update_video_and_audio - actually call the
1142 OSD layer to perform an update
1143 -------------------------------------------------*/
1144
update_video_and_audio(void)1145 void update_video_and_audio(void)
1146 {
1147 int skipped_it = osd_skip_this_frame();
1148
1149 #ifdef MAME_DEBUG
1150 debug_trace_delay = 0;
1151 #endif
1152
1153 /* fill in our portion of the display */
1154 current_display.changed_flags = 0;
1155
1156 /* set the main game bitmap */
1157 current_display.game_bitmap = Machine->scrbitmap;
1158 current_display.game_bitmap_update = Machine->absolute_visible_area;
1159 if (!skipped_it)
1160 current_display.changed_flags |= GAME_BITMAP_CHANGED;
1161
1162 /* set the visible area */
1163 current_display.game_visible_area = Machine->absolute_visible_area;
1164 if (visible_area_changed)
1165 current_display.changed_flags |= GAME_VISIBLE_AREA_CHANGED;
1166
1167 /* set the vector dirty list */
1168 if (Machine->drv->video_attributes & VIDEO_TYPE_VECTOR)
1169 if (!full_refresh_pending && !ui_dirty && !skipped_it)
1170 {
1171 current_display.vector_dirty_pixels = vector_dirty_list;
1172 current_display.changed_flags |= VECTOR_PIXELS_CHANGED;
1173 }
1174
1175 #ifdef MAME_DEBUG
1176 /* set the debugger bitmap */
1177 current_display.debug_bitmap = Machine->debug_bitmap;
1178 if (debugger_bitmap_changed)
1179 current_display.changed_flags |= DEBUG_BITMAP_CHANGED;
1180 debugger_bitmap_changed = 0;
1181
1182 /* adjust the debugger focus */
1183 if (debugger_focus != current_display.debug_focus)
1184 {
1185 current_display.debug_focus = debugger_focus;
1186 current_display.changed_flags |= DEBUG_FOCUS_CHANGED;
1187 }
1188 #endif
1189
1190 /* set the LED status */
1191 if (leds_status != current_display.led_state)
1192 {
1193 current_display.led_state = leds_status;
1194 current_display.changed_flags |= LED_STATE_CHANGED;
1195 }
1196
1197 /* update with data from other parts of the system */
1198 palette_update_display(¤t_display);
1199
1200 /* render */
1201 artwork_update_video_and_audio(¤t_display);
1202
1203 /* reset dirty flags */
1204 visible_area_changed = 0;
1205 if (ui_dirty) ui_dirty--;
1206 }
1207
1208
1209
1210 /*-------------------------------------------------
1211 updatescreen - handle frameskipping and UI,
1212 plus updating the screen during normal
1213 operations
1214 -------------------------------------------------*/
1215
updatescreen(void)1216 int updatescreen(void)
1217 {
1218 /* update sound */
1219 sound_update();
1220
1221 /* if we're not skipping this frame, draw the screen */
1222 if (osd_skip_this_frame() == 0)
1223 {
1224 profiler_mark(PROFILER_VIDEO);
1225 draw_screen();
1226 profiler_mark(PROFILER_END);
1227 }
1228
1229 /* the user interface must be called between vh_update() and osd_update_video_and_audio(), */
1230 /* to allow it to overlay things on the game display. We must call it even */
1231 /* if the frame is skipped, to keep a consistent timing. */
1232 if (handle_user_interface(artwork_get_ui_bitmap()))
1233 /* quit if the user asked to */
1234 return 1;
1235
1236 /* blit to the screen */
1237 update_video_and_audio();
1238
1239 /* call the end-of-frame callback */
1240 if (Machine->drv->video_eof)
1241 {
1242 profiler_mark(PROFILER_VIDEO);
1243 (*Machine->drv->video_eof)();
1244 profiler_mark(PROFILER_END);
1245 }
1246
1247 return 0;
1248 }
1249
1250
1251
1252 /*-------------------------------------------------
1253 set_led_status - set the state of a given LED
1254 -------------------------------------------------*/
1255
set_led_status(int num,int on)1256 void set_led_status(int num, int on)
1257 {
1258 if (on)
1259 leds_status |= (1 << num);
1260 else
1261 leds_status &= ~(1 << num);
1262 }
1263
1264
1265
1266 /*-------------------------------------------------
1267 mame_get_performance_info - return performance
1268 info
1269 -------------------------------------------------*/
1270
mame_get_performance_info(void)1271 const struct performance_info *mame_get_performance_info(void)
1272 {
1273 return &performance;
1274 }
1275
1276
1277
1278 /*-------------------------------------------------
1279 mame_find_cpu_index - return the index of the
1280 given CPU, or -1 if not found
1281 -------------------------------------------------*/
1282
mame_find_cpu_index(const char * tag)1283 int mame_find_cpu_index(const char *tag)
1284 {
1285 int cpunum;
1286
1287 for (cpunum = 0; cpunum < MAX_CPU; cpunum++)
1288 if (Machine->drv->cpu[cpunum].tag && strcmp(Machine->drv->cpu[cpunum].tag, tag) == 0)
1289 return cpunum;
1290
1291 return -1;
1292 }
1293
1294
1295
1296 /*-------------------------------------------------
1297 machine_add_cpu - add a CPU during machine
1298 driver expansion
1299 -------------------------------------------------*/
1300
machine_add_cpu(struct InternalMachineDriver * machine,const char * tag,int type,int cpuclock)1301 struct MachineCPU *machine_add_cpu(struct InternalMachineDriver *machine, const char *tag, int type, int cpuclock)
1302 {
1303 int cpunum;
1304
1305 for (cpunum = 0; cpunum < MAX_CPU; cpunum++)
1306 if (machine->cpu[cpunum].cpu_type == 0)
1307 {
1308 machine->cpu[cpunum].tag = tag;
1309 machine->cpu[cpunum].cpu_type = type;
1310 machine->cpu[cpunum].cpu_clock = cpuclock;
1311 return &machine->cpu[cpunum];
1312 }
1313
1314 log_cb(RETRO_LOG_ERROR, LOGPRE "Out of CPU's!\n");
1315 return NULL;
1316 }
1317
1318
1319
1320 /*-------------------------------------------------
1321 machine_find_cpu - find a tagged CPU during
1322 machine driver expansion
1323 -------------------------------------------------*/
1324
machine_find_cpu(struct InternalMachineDriver * machine,const char * tag)1325 struct MachineCPU *machine_find_cpu(struct InternalMachineDriver *machine, const char *tag)
1326 {
1327 int cpunum;
1328
1329 for (cpunum = 0; cpunum < MAX_CPU; cpunum++)
1330 if (machine->cpu[cpunum].tag && strcmp(machine->cpu[cpunum].tag, tag) == 0)
1331 return &machine->cpu[cpunum];
1332
1333 log_cb(RETRO_LOG_ERROR, LOGPRE "Can't find CPU '%s'!\n", tag);
1334 return NULL;
1335 }
1336
1337
1338
1339 /*-------------------------------------------------
1340 machine_remove_cpu - remove a tagged CPU
1341 during machine driver expansion
1342 -------------------------------------------------*/
1343
machine_remove_cpu(struct InternalMachineDriver * machine,const char * tag)1344 void machine_remove_cpu(struct InternalMachineDriver *machine, const char *tag)
1345 {
1346 int cpunum;
1347
1348 for (cpunum = 0; cpunum < MAX_CPU; cpunum++)
1349 if (machine->cpu[cpunum].tag && strcmp(machine->cpu[cpunum].tag, tag) == 0)
1350 {
1351 memmove(&machine->cpu[cpunum], &machine->cpu[cpunum + 1], sizeof(machine->cpu[0]) * (MAX_CPU - cpunum - 1));
1352 memset(&machine->cpu[MAX_CPU - 1], 0, sizeof(machine->cpu[0]));
1353 return;
1354 }
1355
1356 log_cb(RETRO_LOG_ERROR, LOGPRE "Can't find CPU '%s'!\n", tag);
1357 }
1358
1359
1360
1361 /*-------------------------------------------------
1362 machine_add_sound - add a sound system during
1363 machine driver expansion
1364 -------------------------------------------------*/
1365
machine_add_sound(struct InternalMachineDriver * machine,const char * tag,int type,void * sndintf)1366 struct MachineSound *machine_add_sound(struct InternalMachineDriver *machine, const char *tag, int type, void *sndintf)
1367 {
1368 int soundnum;
1369
1370 for (soundnum = 0; soundnum < MAX_SOUND; soundnum++)
1371 if (machine->sound[soundnum].sound_type == 0)
1372 {
1373 machine->sound[soundnum].tag = tag;
1374 machine->sound[soundnum].sound_type = type;
1375 machine->sound[soundnum].sound_interface = sndintf;
1376 return &machine->sound[soundnum];
1377 }
1378
1379 log_cb(RETRO_LOG_ERROR, LOGPRE "Out of sounds!\n");
1380 return NULL;
1381
1382 }
1383
1384
1385
1386 /*-------------------------------------------------
1387 machine_find_sound - find a tagged sound
1388 system during machine driver expansion
1389 -------------------------------------------------*/
1390
machine_find_sound(struct InternalMachineDriver * machine,const char * tag)1391 struct MachineSound *machine_find_sound(struct InternalMachineDriver *machine, const char *tag)
1392 {
1393 int soundnum;
1394
1395 for (soundnum = 0; soundnum < MAX_SOUND; soundnum++)
1396 if (machine->sound[soundnum].tag && strcmp(machine->sound[soundnum].tag, tag) == 0)
1397 return &machine->sound[soundnum];
1398
1399 log_cb(RETRO_LOG_ERROR, LOGPRE "Can't find sound '%s'!\n", tag);
1400 return NULL;
1401 }
1402
1403
1404
1405 /*-------------------------------------------------
1406 machine_remove_sound - remove a tagged sound
1407 system during machine driver expansion
1408 -------------------------------------------------*/
1409
machine_remove_sound(struct InternalMachineDriver * machine,const char * tag)1410 void machine_remove_sound(struct InternalMachineDriver *machine, const char *tag)
1411 {
1412 int soundnum;
1413
1414 for (soundnum = 0; soundnum < MAX_SOUND; soundnum++)
1415 if (machine->sound[soundnum].tag && strcmp(machine->sound[soundnum].tag, tag) == 0)
1416 {
1417 memmove(&machine->sound[soundnum], &machine->sound[soundnum + 1], sizeof(machine->sound[0]) * (MAX_SOUND - soundnum - 1));
1418 memset(&machine->sound[MAX_SOUND - 1], 0, sizeof(machine->sound[0]));
1419 return;
1420 }
1421
1422 log_cb(RETRO_LOG_ERROR, LOGPRE "Can't find sound '%s'!\n", tag);
1423 }
1424
1425
1426
1427 /*-------------------------------------------------
1428 mame_chd_open - interface for opening
1429 a hard disk image
1430 -------------------------------------------------*/
1431
mame_chd_open(const char * filename,const char * mode)1432 struct chd_interface_file *mame_chd_open(const char *filename, const char *mode)
1433 {
1434 /* look for read-only drives first in the ROM path */
1435 if (mode[0] == 'r' && !strchr(mode, '+'))
1436 {
1437 const struct GameDriver *drv;
1438
1439 /* attempt reading up the chain through the parents */
1440 for (drv = Machine->gamedrv; drv != NULL; drv = drv->clone_of)
1441 {
1442 void* file = mame_fopen(drv->name, filename, FILETYPE_IMAGE, 0);
1443
1444 if (file != NULL)
1445 return file;
1446 }
1447
1448 return NULL;
1449 }
1450
1451 /* look for read/write drives in the diff area */
1452 return (struct chd_interface_file *)mame_fopen(NULL, filename, FILETYPE_IMAGE_DIFF, 1);
1453 }
1454
1455
1456
1457 /*-------------------------------------------------
1458 mame_chd_close - interface for closing
1459 a hard disk image
1460 -------------------------------------------------*/
1461
mame_chd_close(struct chd_interface_file * file)1462 void mame_chd_close(struct chd_interface_file *file)
1463 {
1464 mame_fclose((mame_file *)file);
1465 }
1466
1467
1468
1469 /*-------------------------------------------------
1470 mame_chd_read - interface for reading
1471 from a hard disk image
1472 -------------------------------------------------*/
1473
mame_chd_read(struct chd_interface_file * file,UINT64 offset,UINT32 count,void * buffer)1474 UINT32 mame_chd_read(struct chd_interface_file *file, UINT64 offset, UINT32 count, void *buffer)
1475 {
1476 mame_fseek((mame_file *)file, offset, SEEK_SET);
1477 return mame_fread((mame_file *)file, buffer, count);
1478 }
1479
1480
1481
1482 /*-------------------------------------------------
1483 mame_chd_write - interface for writing
1484 to a hard disk image
1485 -------------------------------------------------*/
1486
mame_chd_write(struct chd_interface_file * file,UINT64 offset,UINT32 count,const void * buffer)1487 UINT32 mame_chd_write(struct chd_interface_file *file, UINT64 offset, UINT32 count, const void *buffer)
1488 {
1489 mame_fseek((mame_file *)file, offset, SEEK_SET);
1490 return mame_fwrite((mame_file *)file, buffer, count);
1491 }
1492
1493
1494 /*-------------------------------------------------
1495 mame_chd_length - interface for getting
1496 the length a hard disk image
1497 -------------------------------------------------*/
1498
mame_chd_length(struct chd_interface_file * file)1499 UINT64 mame_chd_length(struct chd_interface_file *file)
1500 {
1501 return mame_fsize((mame_file *)file);
1502 }
1503
1504
1505
1506 /***************************************************************************
1507
1508 Huge bunch of validity checks for the debug build
1509
1510 ***************************************************************************/
1511
1512 #ifdef MAME_DEBUG
1513
validitychecks(void)1514 static int validitychecks(void)
1515 {
1516 int i,j,cpu;
1517 UINT8 a,b;
1518 int error = 0;
1519
1520
1521 a = 0xff;
1522 b = a + 1;
1523 if (b > a) { log_cb(RETRO_LOG_ERROR, LOGPRE "UINT8 must be 8 bits\n"); error = 1; }
1524
1525 if (sizeof(INT8) != 1) { log_cb(RETRO_LOG_ERROR, LOGPRE "INT8 must be 8 bits\n"); error = 1; }
1526 if (sizeof(UINT8) != 1) { log_cb(RETRO_LOG_ERROR, LOGPRE "UINT8 must be 8 bits\n"); error = 1; }
1527 if (sizeof(INT16) != 2) { log_cb(RETRO_LOG_ERROR, LOGPRE "INT16 must be 16 bits\n"); error = 1; }
1528 if (sizeof(UINT16) != 2) { log_cb(RETRO_LOG_ERROR, LOGPRE "UINT16 must be 16 bits\n"); error = 1; }
1529 if (sizeof(INT32) != 4) { log_cb(RETRO_LOG_ERROR, LOGPRE "INT32 must be 32 bits\n"); error = 1; }
1530 if (sizeof(UINT32) != 4) { log_cb(RETRO_LOG_ERROR, LOGPRE "UINT32 must be 32 bits\n"); error = 1; }
1531 if (sizeof(INT64) != 8) { log_cb(RETRO_LOG_ERROR, LOGPRE "INT64 must be 64 bits\n"); error = 1; }
1532 if (sizeof(UINT64) != 8) { log_cb(RETRO_LOG_ERROR, LOGPRE "UINT64 must be 64 bits\n"); error = 1; }
1533
1534 for (i = 0;drivers[i];i++)
1535 {
1536 struct InternalMachineDriver drv;
1537 const struct RomModule *romp;
1538 const struct InputPortTiny *inp;
1539
1540 expand_machine_driver(drivers[i]->drv, &drv);
1541
1542 if (drivers[i]->clone_of == drivers[i])
1543 {
1544 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s is set as a clone of itself\n",drivers[i]->source_file,drivers[i]->name);
1545 error = 1;
1546 }
1547
1548 if (drivers[i]->clone_of && drivers[i]->clone_of->clone_of)
1549 {
1550 if ((drivers[i]->clone_of->clone_of->flags & NOT_A_DRIVER) == 0)
1551 {
1552 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s is a clone of a clone\n",drivers[i]->source_file,drivers[i]->name);
1553 error = 1;
1554 }
1555 }
1556
1557 #if 0
1558 /* if (drivers[i]->drv->color_table_len == drivers[i]->drv->total_colors && */
1559 if (drivers[i]->drv->color_table_len && drivers[i]->drv->total_colors &&
1560 drivers[i]->drv->vh_init_palette == 0)
1561 {
1562 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s could use color_table_len = 0\n",drivers[i]->source_file,drivers[i]->name);
1563 error = 1;
1564 }
1565 #endif
1566
1567 for (j = i+1;drivers[j];j++)
1568 {
1569 if (!strcmp(drivers[i]->name,drivers[j]->name))
1570 {
1571 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s is a duplicate name (%s, %s)\n",drivers[i]->source_file,drivers[i]->name,drivers[i]->source_file,drivers[j]->source_file);
1572 error = 1;
1573 }
1574 if (!strcmp(drivers[i]->description,drivers[j]->description))
1575 {
1576 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s is a duplicate description (%s, %s)\n",drivers[i]->description,drivers[i]->source_file,drivers[i]->name,drivers[j]->name);
1577 error = 1;
1578 }
1579 if (drivers[i]->rom && drivers[i]->rom == drivers[j]->rom
1580 && (drivers[i]->flags & NOT_A_DRIVER) == 0
1581 && (drivers[j]->flags & NOT_A_DRIVER) == 0)
1582 {
1583 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s and %s use the same ROM set\n",drivers[i]->source_file,drivers[i]->name,drivers[j]->name);
1584 error = 1;
1585 }
1586 }
1587
1588 if ((drivers[i]->flags & NOT_A_DRIVER) == 0)
1589 {
1590 if (drv.sound[0].sound_type == 0 && (drivers[i]->flags & GAME_NO_SOUND) == 0 &&
1591 strcmp(drivers[i]->name,"minivadr"))
1592 {
1593 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s missing GAME_NO_SOUND flag\n",drivers[i]->source_file,drivers[i]->name);
1594 error = 1;
1595 }
1596 }
1597
1598 romp = drivers[i]->rom;
1599
1600 if (romp)
1601 {
1602 int region_type_used[REGION_MAX];
1603 int region_length[REGION_MAX];
1604 const char *last_name = 0;
1605 int count = -1;
1606
1607 for (j = 0;j < REGION_MAX;j++)
1608 {
1609 region_type_used[j] = 0;
1610 region_length[j] = 0;
1611 }
1612
1613 while (!ROMENTRY_ISEND(romp))
1614 {
1615 const char *c;
1616
1617 if (ROMENTRY_ISREGION(romp))
1618 {
1619 int type = ROMREGION_GETTYPE(romp);
1620
1621 count++;
1622 if (type && (type >= REGION_MAX || type <= REGION_INVALID))
1623 {
1624 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s has invalid ROM_REGION type %x\n",drivers[i]->source_file,drivers[i]->name,type);
1625 error = 1;
1626 }
1627
1628 region_type_used[type]++;
1629 region_length[type] = region_length[count] = ROMREGION_GETLENGTH(romp);
1630 }
1631 if (ROMENTRY_ISFILE(romp))
1632 {
1633 const char *hash;
1634
1635 last_name = c = ROM_GETNAME(romp);
1636 while (*c)
1637 {
1638 if (tolower(*c) != *c)
1639 {
1640 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s has upper case ROM name %s\n",drivers[i]->source_file,drivers[i]->name,ROM_GETNAME(romp));
1641 error = 1;
1642 }
1643 c++;
1644 }
1645
1646 hash = ROM_GETHASHDATA(romp);
1647 if (!hash_verify_string(hash))
1648 {
1649 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: rom '%s' has an invalid hash string '%s'\n", drivers[i]->name, ROM_GETNAME(romp), hash);
1650 error = 1;
1651 }
1652 }
1653 if (!ROMENTRY_ISREGIONEND(romp)) /* ROM_LOAD_XXX() */
1654 {
1655 if (ROM_GETOFFSET(romp) + ROM_GETLENGTH(romp) > region_length[count])
1656 {
1657 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s has ROM %s extending past the defined memory region\n",drivers[i]->source_file,drivers[i]->name,last_name);
1658 error = 1;
1659 }
1660 }
1661 romp++;
1662 }
1663
1664 for (j = 1;j < REGION_MAX;j++)
1665 {
1666 if (region_type_used[j] > 1)
1667 {
1668 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s has duplicated ROM_REGION type %x\n",drivers[i]->source_file,drivers[i]->name,j);
1669 error = 1;
1670 }
1671 }
1672
1673
1674 for (cpu = 0;cpu < MAX_CPU;cpu++)
1675 {
1676 if (drv.cpu[cpu].cpu_type)
1677 {
1678 int alignunit,databus_width;
1679
1680
1681 alignunit = cputype_align_unit(drv.cpu[cpu].cpu_type);
1682 databus_width = cputype_databus_width(drv.cpu[cpu].cpu_type);
1683
1684 if (drv.cpu[cpu].memory_read)
1685 {
1686 const struct Memory_ReadAddress *mra = drv.cpu[cpu].memory_read;
1687
1688 if (!IS_MEMPORT_MARKER(mra) || (mra->end & MEMPORT_DIRECTION_MASK) != MEMPORT_DIRECTION_READ)
1689 {
1690 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s wrong MEMPORT_READ_START\n",drivers[i]->source_file,drivers[i]->name);
1691 error = 1;
1692 }
1693
1694 switch (databus_width)
1695 {
1696 case 8:
1697 if ((mra->end & MEMPORT_WIDTH_MASK) != MEMPORT_WIDTH_8)
1698 {
1699 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s cpu #%d uses wrong data width memory handlers! (width = %d, memory = %08x)\n",drivers[i]->source_file,drivers[i]->name,cpu,databus_width,mra->end);
1700 error = 1;
1701 }
1702 break;
1703 case 16:
1704 if ((mra->end & MEMPORT_WIDTH_MASK) != MEMPORT_WIDTH_16)
1705 {
1706 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s cpu #%d uses wrong data width memory handlers! (width = %d, memory = %08x)\n",drivers[i]->source_file,drivers[i]->name,cpu,databus_width,mra->end);
1707 error = 1;
1708 }
1709 break;
1710 case 32:
1711 if ((mra->end & MEMPORT_WIDTH_MASK) != MEMPORT_WIDTH_32)
1712 {
1713 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s cpu #%d uses wrong data width memory handlers! (width = %d, memory = %08x)\n",drivers[i]->source_file,drivers[i]->name,cpu,databus_width,mra->end);
1714 error = 1;
1715 }
1716 break;
1717 }
1718
1719 while (!IS_MEMPORT_END(mra))
1720 {
1721 if (!IS_MEMPORT_MARKER(mra))
1722 {
1723 if (mra->end < mra->start)
1724 {
1725 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s wrong memory read handler start = %08x > end = %08x\n",drivers[i]->source_file,drivers[i]->name,mra->start,mra->end);
1726 error = 1;
1727 }
1728 if ((mra->start & (alignunit-1)) != 0 || (mra->end & (alignunit-1)) != (alignunit-1))
1729 {
1730 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s wrong memory read handler start = %08x, end = %08x ALIGN = %d\n",drivers[i]->source_file,drivers[i]->name,mra->start,mra->end,alignunit);
1731 error = 1;
1732 }
1733 }
1734 mra++;
1735 }
1736 }
1737 if (drv.cpu[cpu].memory_write)
1738 {
1739 const struct Memory_WriteAddress *mwa = drv.cpu[cpu].memory_write;
1740
1741 if (mwa->start != MEMPORT_MARKER ||
1742 (mwa->end & MEMPORT_DIRECTION_MASK) != MEMPORT_DIRECTION_WRITE)
1743 {
1744 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s wrong MEMPORT_WRITE_START\n",drivers[i]->source_file,drivers[i]->name);
1745 error = 1;
1746 }
1747
1748 switch (databus_width)
1749 {
1750 case 8:
1751 if ((mwa->end & MEMPORT_WIDTH_MASK) != MEMPORT_WIDTH_8)
1752 {
1753 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s cpu #%d uses wrong data width memory handlers! (width = %d, memory = %08x)\n",drivers[i]->source_file,drivers[i]->name,cpu,databus_width,mwa->end);
1754 error = 1;
1755 }
1756 break;
1757 case 16:
1758 if ((mwa->end & MEMPORT_WIDTH_MASK) != MEMPORT_WIDTH_16)
1759 {
1760 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s cpu #%d uses wrong data width memory handlers! (width = %d, memory = %08x)\n",drivers[i]->source_file,drivers[i]->name,cpu,databus_width,mwa->end);
1761 error = 1;
1762 }
1763 break;
1764 case 32:
1765 if ((mwa->end & MEMPORT_WIDTH_MASK) != MEMPORT_WIDTH_32)
1766 {
1767 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s cpu #%d uses wrong data width memory handlers! (width = %d, memory = %08x)\n",drivers[i]->source_file,drivers[i]->name,cpu,databus_width,mwa->end);
1768 error = 1;
1769 }
1770 break;
1771 }
1772
1773 while (!IS_MEMPORT_END(mwa))
1774 {
1775 if (!IS_MEMPORT_MARKER(mwa))
1776 {
1777 if (mwa->end < mwa->start)
1778 {
1779 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s wrong memory write handler start = %08x > end = %08x\n",drivers[i]->source_file,drivers[i]->name,mwa->start,mwa->end);
1780 error = 1;
1781 }
1782 if ((mwa->start & (alignunit-1)) != 0 || (mwa->end & (alignunit-1)) != (alignunit-1))
1783 {
1784 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s wrong memory write handler start = %08x, end = %08x ALIGN = %d\n",drivers[i]->source_file,drivers[i]->name,mwa->start,mwa->end,alignunit);
1785 error = 1;
1786 }
1787 }
1788 mwa++;
1789 }
1790 }
1791
1792 if (drv.cpu[cpu].port_read)
1793 {
1794 const struct IO_ReadPort *pra = drv.cpu[cpu].port_read;
1795
1796 if (!IS_MEMPORT_MARKER(pra) || (pra->end & MEMPORT_DIRECTION_MASK) != MEMPORT_DIRECTION_READ)
1797 {
1798 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s wrong PORT_READ_START\n",drivers[i]->source_file,drivers[i]->name);
1799 error = 1;
1800 }
1801
1802 switch (databus_width)
1803 {
1804 case 8:
1805 if ((pra->end & MEMPORT_WIDTH_MASK) != MEMPORT_WIDTH_8)
1806 {
1807 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s cpu #%d uses wrong data width port handlers! (width = %d, port = %08x)\n",drivers[i]->source_file,drivers[i]->name,cpu,databus_width,pra->end);
1808 error = 1;
1809 }
1810 break;
1811 case 16:
1812 if ((pra->end & MEMPORT_WIDTH_MASK) != MEMPORT_WIDTH_16)
1813 {
1814 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s cpu #%d uses wrong data width port handlers! (width = %d, port = %08x)\n",drivers[i]->source_file,drivers[i]->name,cpu,databus_width,pra->end);
1815 error = 1;
1816 }
1817 break;
1818 case 32:
1819 if ((pra->end & MEMPORT_WIDTH_MASK) != MEMPORT_WIDTH_32)
1820 {
1821 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s cpu #%d uses wrong data width port handlers! (width = %d, port = %08x)\n",drivers[i]->source_file,drivers[i]->name,cpu,databus_width,pra->end);
1822 error = 1;
1823 }
1824 break;
1825 }
1826
1827 while (!IS_MEMPORT_END(pra))
1828 {
1829 if (!IS_MEMPORT_MARKER(pra))
1830 {
1831 if (pra->end < pra->start)
1832 {
1833 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s wrong port read handler start = %08x > end = %08x\n",drivers[i]->source_file,drivers[i]->name,pra->start,pra->end);
1834 error = 1;
1835 }
1836 if ((pra->start & (alignunit-1)) != 0 || (pra->end & (alignunit-1)) != (alignunit-1))
1837 {
1838 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s wrong port read handler start = %08x, end = %08x ALIGN = %d\n",drivers[i]->source_file,drivers[i]->name,pra->start,pra->end,alignunit);
1839 error = 1;
1840 }
1841
1842 }
1843 pra++;
1844 }
1845 }
1846
1847 if (drv.cpu[cpu].port_write)
1848 {
1849 const struct IO_WritePort *pwa = drv.cpu[cpu].port_write;
1850
1851 if (pwa->start != MEMPORT_MARKER ||
1852 (pwa->end & MEMPORT_DIRECTION_MASK) != MEMPORT_DIRECTION_WRITE)
1853 {
1854 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s wrong PORT_WRITE_START\n",drivers[i]->source_file,drivers[i]->name);
1855 error = 1;
1856 }
1857
1858 switch (databus_width)
1859 {
1860 case 8:
1861 if ((pwa->end & MEMPORT_WIDTH_MASK) != MEMPORT_WIDTH_8)
1862 {
1863 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s cpu #%d uses wrong data width port handlers! (width = %d, port = %08x)\n",drivers[i]->source_file,drivers[i]->name,cpu,databus_width,pwa->end);
1864 error = 1;
1865 }
1866 break;
1867 case 16:
1868 if ((pwa->end & MEMPORT_WIDTH_MASK) != MEMPORT_WIDTH_16)
1869 {
1870 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s cpu #%d uses wrong data width port handlers! (width = %d, port = %08x)\n",drivers[i]->source_file,drivers[i]->name,cpu,databus_width,pwa->end);
1871 error = 1;
1872 }
1873 break;
1874 case 32:
1875 if ((pwa->end & MEMPORT_WIDTH_MASK) != MEMPORT_WIDTH_32)
1876 {
1877 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s cpu #%d uses wrong data width port handlers! (width = %d, port = %08x)\n",drivers[i]->source_file,drivers[i]->name,cpu,databus_width,pwa->end);
1878 error = 1;
1879 }
1880 break;
1881 }
1882
1883 while (!IS_MEMPORT_END(pwa))
1884 {
1885 if (!IS_MEMPORT_MARKER(pwa))
1886 {
1887 if (pwa->end < pwa->start)
1888 {
1889 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s wrong port write handler start = %08x > end = %08x\n",drivers[i]->source_file,drivers[i]->name,pwa->start,pwa->end);
1890 error = 1;
1891 }
1892 if ((pwa->start & (alignunit-1)) != 0 || (pwa->end & (alignunit-1)) != (alignunit-1))
1893 {
1894 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s wrong port write handler start = %08x, end = %08x ALIGN = %d\n",drivers[i]->source_file,drivers[i]->name,pwa->start,pwa->end,alignunit);
1895 error = 1;
1896 }
1897
1898 }
1899 pwa++;
1900 }
1901 }
1902
1903 }
1904 }
1905
1906
1907 if (drv.gfxdecodeinfo)
1908 {
1909 for (j = 0;j < MAX_GFX_ELEMENTS && drv.gfxdecodeinfo[j].memory_region != -1;j++)
1910 {
1911 int len,avail,k,start;
1912 int type = drv.gfxdecodeinfo[j].memory_region;
1913
1914
1915 /*
1916 if (type && (type >= REGION_MAX || type <= REGION_INVALID))
1917 {
1918 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s has invalid memory region for gfx[%d]\n",drivers[i]->source_file,drivers[i]->name,j);
1919 error = 1;
1920 }
1921 */
1922
1923 if (!IS_FRAC(drv.gfxdecodeinfo[j].gfxlayout->total))
1924 {
1925 start = 0;
1926 for (k = 0;k < MAX_GFX_PLANES;k++)
1927 {
1928 if (drv.gfxdecodeinfo[j].gfxlayout->planeoffset[k] > start)
1929 start = drv.gfxdecodeinfo[j].gfxlayout->planeoffset[k];
1930 }
1931 start &= ~(drv.gfxdecodeinfo[j].gfxlayout->charincrement-1);
1932 len = drv.gfxdecodeinfo[j].gfxlayout->total *
1933 drv.gfxdecodeinfo[j].gfxlayout->charincrement;
1934 avail = region_length[type]
1935 - (drv.gfxdecodeinfo[j].start & ~(drv.gfxdecodeinfo[j].gfxlayout->charincrement/8-1));
1936 if ((start + len) / 8 > avail)
1937 {
1938 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s has gfx[%d] extending past allocated memory\n",drivers[i]->source_file,drivers[i]->name,j);
1939 error = 1;
1940 }
1941 }
1942 }
1943 }
1944 }
1945
1946
1947 inp = drivers[i]->input_ports;
1948
1949 if (inp)
1950 {
1951 while (inp->type != IPT_END)
1952 {
1953 if (inp->name && inp->name != IP_NAME_DEFAULT)
1954 {
1955 j = 0;
1956
1957 for (j = 0;j < STR_TOTAL;j++)
1958 {
1959 if (inp->name == ipdn_defaultstrings[j]) break;
1960 else if (!strcasecmp(inp->name,ipdn_defaultstrings[j]))
1961 {
1962 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s must use DEF_STR( %s )\n",drivers[i]->source_file,drivers[i]->name,inp->name);
1963 error = 1;
1964 }
1965 }
1966
1967 if (inp->name == DEF_STR( On ) && (inp+1)->name == DEF_STR( Off ))
1968 {
1969 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s has inverted Off/On dipswitch order\n",drivers[i]->source_file,drivers[i]->name);
1970 error = 1;
1971 }
1972
1973 if (inp->name == DEF_STR( Yes ) && (inp+1)->name == DEF_STR( No ))
1974 {
1975 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s has inverted No/Yes dipswitch order\n",drivers[i]->source_file,drivers[i]->name);
1976 error = 1;
1977 }
1978
1979 if (!strcasecmp(inp->name,"table"))
1980 {
1981 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s must use DEF_STR( Cocktail ), not %s\n",drivers[i]->source_file,drivers[i]->name,inp->name);
1982 error = 1;
1983 }
1984
1985 if (inp->name == DEF_STR( Cabinet ) && (inp+1)->name == DEF_STR( Upright )
1986 && inp->default_value != (inp+1)->default_value)
1987 {
1988 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s Cabinet must default to Upright\n",drivers[i]->source_file,drivers[i]->name);
1989 error = 1;
1990 }
1991
1992 if (inp->name == DEF_STR( Cocktail ) && (inp+1)->name == DEF_STR( Upright ))
1993 {
1994 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s has inverted Upright/Cocktail dipswitch order\n",drivers[i]->source_file,drivers[i]->name);
1995 error = 1;
1996 }
1997
1998 if (inp->name >= DEF_STR( 9C_1C ) && inp->name <= DEF_STR( Free_Play )
1999 && (inp+1)->name >= DEF_STR( 9C_1C ) && (inp+1)->name <= DEF_STR( Free_Play )
2000 && inp->name >= (inp+1)->name)
2001 {
2002 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s has unsorted coinage %s > %s\n",drivers[i]->source_file,drivers[i]->name,inp->name,(inp+1)->name);
2003 error = 1;
2004 }
2005
2006 if (inp->name == DEF_STR( Flip_Screen ) && (inp+1)->name != DEF_STR( Off ))
2007 {
2008 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s has wrong Flip Screen option %s\n",drivers[i]->source_file,drivers[i]->name,(inp+1)->name);
2009 error = 1;
2010 }
2011
2012 if (inp->name == DEF_STR( Demo_Sounds ) && (inp+2)->name == DEF_STR( On )
2013 && inp->default_value != (inp+2)->default_value)
2014 {
2015 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s Demo Sounds must default to On\n",drivers[i]->source_file,drivers[i]->name);
2016 error = 1;
2017 }
2018
2019 if (inp->name == DEF_STR( Demo_Sounds ) && (inp+1)->name == DEF_STR( No ))
2020 {
2021 log_cb(RETRO_LOG_ERROR, LOGPRE "%s: %s has wrong Demo Sounds option No instead of Off\n",drivers[i]->source_file,drivers[i]->name);
2022 error = 1;
2023 }
2024 }
2025
2026 inp++;
2027 }
2028 }
2029 }
2030
2031 return error;
2032 }
2033 #endif
2034
2035 void cpu_run_done(void);
mame_done(void)2036 void mame_done(void)
2037 {
2038 if(game_loaded)
2039 {
2040 cpu_run_done();
2041 run_machine_core_done();
2042 run_machine_done();
2043 run_game_done();
2044 }
2045
2046 game_loaded = 0;
2047 }
2048