/*************************************************************************** watchdog.c Watchdog handling Copyright Nicola Salmoria and the MAME Team. Visit http://mamedev.org for licensing and usage restrictions. ***************************************************************************/ #include "driver.h" /*************************************************************************** GLOBAL VARIABLES ***************************************************************************/ static UINT8 watchdog_enabled; static INT32 watchdog_counter; static emu_timer *watchdog_timer; /*************************************************************************** FUNCTION PROTOTYPES ***************************************************************************/ static void watchdog_internal_reset(running_machine *machine); static TIMER_CALLBACK( watchdog_callback ); /*------------------------------------------------- watchdog_init - one time initialization -------------------------------------------------*/ void watchdog_init(running_machine *machine) { /* allocate a timer for the watchdog */ watchdog_timer = timer_alloc(machine, watchdog_callback, NULL); add_reset_callback(machine, watchdog_internal_reset); /* save some stuff in the default tag */ state_save_register_item(machine, "watchdog", NULL, 0, watchdog_enabled); state_save_register_item(machine, "watchdog", NULL, 0, watchdog_counter); } /*------------------------------------------------- watchdog_internal_reset - reset the watchdog system -------------------------------------------------*/ static void watchdog_internal_reset(running_machine *machine) { /* set up the watchdog timer; only start off enabled if explicitly configured */ watchdog_enabled = (machine->config->watchdog_vblank_count != 0 || attotime_compare(machine->config->watchdog_time, attotime_zero) != 0); watchdog_reset(machine); watchdog_enabled = TRUE; } /*------------------------------------------------- watchdog_callback - watchdog timer callback -------------------------------------------------*/ static TIMER_CALLBACK( watchdog_callback ) { logerror("Reset caused by the watchdog!!!\n"); #ifdef MAME_DEBUG popmessage("Reset caused by the watchdog!!!\n"); #endif mame_schedule_soft_reset(machine); } /*------------------------------------------------- on_vblank - updates VBLANK based watchdog timers -------------------------------------------------*/ static void on_vblank(const device_config *screen, void *param, int vblank_state) { /* VBLANK starting */ if (vblank_state && watchdog_enabled) { /* check the watchdog */ if (screen->machine->config->watchdog_vblank_count != 0) { watchdog_counter = watchdog_counter - 1; if (watchdog_counter == 0) watchdog_callback(screen->machine, NULL, 0); } } } /*------------------------------------------------- watchdog_reset - reset the watchdog timer -------------------------------------------------*/ void watchdog_reset(running_machine *machine) { /* if we're not enabled, skip it */ if (!watchdog_enabled) timer_adjust_oneshot(watchdog_timer, attotime_never, 0); /* VBLANK-based watchdog? */ else if (machine->config->watchdog_vblank_count != 0) { watchdog_counter = machine->config->watchdog_vblank_count; /* register a VBLANK callback for the primary screen */ if (machine->primary_screen != NULL) video_screen_register_vblank_callback(machine->primary_screen, on_vblank, NULL); } /* timer-based watchdog? */ else if (attotime_compare(machine->config->watchdog_time, attotime_zero) != 0) timer_adjust_oneshot(watchdog_timer, machine->config->watchdog_time, 0); /* default to an obscene amount of time (3 seconds) */ else timer_adjust_oneshot(watchdog_timer, ATTOTIME_IN_SEC(3), 0); } /*------------------------------------------------- watchdog_enable - reset the watchdog timer -------------------------------------------------*/ void watchdog_enable(running_machine *machine, int enable) { /* when re-enabled, we reset our state */ if (watchdog_enabled != enable) { watchdog_enabled = enable; watchdog_reset(machine); } }