diff --git a/src/emu/cpuexec.c b/src/emu/cpuexec.c index bf23131c209..391cce2eaad 100644 --- a/src/emu/cpuexec.c +++ b/src/emu/cpuexec.c @@ -968,27 +968,26 @@ static void cpu_inittimers(running_machine *machine) /* VBLANK interrupts */ if (config->vblank_interrupts_per_frame > 0) { - const char *screen_tag; - screen_state *screen; + const device_config *screen; /* get the screen that will trigger the VBLANK */ /* new style - use screen tag directly */ if (config->vblank_interrupts_per_frame == 1) - screen_tag = config->vblank_interrupt_screen; + screen = device_list_find_by_tag(machine->config->devicelist, VIDEO_SCREEN, config->vblank_interrupt_screen); /* old style 'hack' setup - use screen #0 */ else { - const device_config *config = device_list_first(machine->config->devicelist, VIDEO_SCREEN); - screen_tag = config->tag; + screen = device_list_first(machine->config->devicelist, VIDEO_SCREEN); /* allocate timer that will trigger the partial frame updates */ cpu[cpunum].partial_frame_timer = timer_alloc(trigger_partial_frame_interrupt, 0); } - screen = devtag_get_token(machine, VIDEO_SCREEN, screen_tag); - video_screen_register_vbl_cb(machine, screen, on_vblank); + assert(screen != NULL); + + video_screen_register_vbl_cb(screen, on_vblank); } /* periodic interrupts */ diff --git a/src/emu/debug/debugcpu.c b/src/emu/debug/debugcpu.c index 64b483f21a2..1d175f5f8d1 100644 --- a/src/emu/debug/debugcpu.c +++ b/src/emu/debug/debugcpu.c @@ -144,7 +144,7 @@ int mame_debug_is_active(void) on_vblank - called when a VBLANK hits -------------------------------------------------*/ -static void on_vblank(const device_config *device, int vblank_state) +static void on_vblank(running_machine *machine, int vblank_state) { /* if we're configured to stop on VBLANK, break */ if (vblank_state && break_on_vblank) @@ -296,7 +296,7 @@ void debug_cpu_init(running_machine *machine) } /* add callback for breaking on VBLANK */ - video_screen_register_vbl_cb(machine, NULL, on_vblank); + video_screen_register_global_vbl_cb(on_vblank); add_exit_callback(machine, debug_cpu_exit); } diff --git a/src/emu/inptport.c b/src/emu/inptport.c index 2aa3fdf2ec0..7f368fb4ab0 100644 --- a/src/emu/inptport.c +++ b/src/emu/inptport.c @@ -1032,7 +1032,7 @@ static int default_ports_lookup[__ipt_max][MAX_PLAYERS]; FUNCTION PROTOTYPES ***************************************************************************/ -static void on_vblank(const device_config *device, int vblank_state); +static void on_vblank(running_machine *machine, int vblank_state); static void setup_playback(running_machine *machine); static void setup_record(running_machine *machine); static void input_port_exit(running_machine *machine); @@ -1142,7 +1142,7 @@ void input_port_init(running_machine *machine, const input_port_token *ipt) void input_port_post_init(running_machine *machine) { /* set up callback for updating the ports */ - video_screen_register_vbl_cb(machine, NULL, on_vblank); + video_screen_register_global_vbl_cb(on_vblank); } @@ -1153,11 +1153,11 @@ void input_port_post_init(running_machine *machine) * *************************************/ -static void on_vblank(const device_config *device, int vblank_state) +static void on_vblank(running_machine *machine, int vblank_state) { /* VBLANK starting - read keyboard & update the status of the input ports */ if (vblank_state) - input_port_vblank_start(device->machine); + input_port_vblank_start(machine); /* VBLANK ending - update IPT_VBLANK input ports */ else diff --git a/src/emu/video.c b/src/emu/video.c index 4d30386afcc..b600f08e4a1 100644 --- a/src/emu/video.c +++ b/src/emu/video.c @@ -73,7 +73,6 @@ struct _internal_screen_state UINT64 frame_number; /* the current frame number */ /* screen specific VBLANK callbacks */ - int vbl_cb_count; vblank_state_changed_func vbl_cbs[MAX_VBL_CB]; /* the array of callbacks */ /* movie recording */ @@ -132,6 +131,9 @@ struct _video_global UINT8 crosshair_animate; /* animation frame index */ UINT8 crosshair_visible; /* crosshair visible mask */ UINT8 crosshair_needed; /* crosshair needed mask */ + + /* global VBLANK callbacks */ + vblank_state_changed_global_func vbl_cbs[MAX_VBL_CB]; /* the array of callbacks */ }; @@ -218,7 +220,7 @@ INLINE screen_state *get_safe_token(const device_config *device) { assert(device != NULL); assert(device->token != NULL); - assert(device->type == DEVICE_GET_INFO_NAME(video_screen)); + assert(device->type == VIDEO_SCREEN); return (screen_state *)device->token; } @@ -1103,53 +1105,64 @@ UINT64 video_screen_get_frame_number(int scrnum) VBLANK callback for a specific screen -------------------------------------------------*/ -void video_screen_register_vbl_cb(running_machine *machine, void *screen, vblank_state_changed_func vbl_cb) +void video_screen_register_vbl_cb(const device_config *screen, vblank_state_changed_func vbl_cb) { int i, found; - internal_screen_state *internal_state = NULL; + screen_state *state = get_safe_token(screen); + internal_screen_state *internal_state = (internal_screen_state *)state->private_data; /* validate arguments */ - assert(machine != NULL); - assert(machine->config != NULL); - assert(machine->config->devicelist != NULL); assert(vbl_cb != NULL); - /* if the screen is NULL, grab the first screen -- we are installing a "global" handler */ - if (screen == NULL) - { - if (video_screen_count(machine->config) > 0) - { - const char *screen_tag = video_screen_first(machine->config)->tag; - screen = devtag_get_token(machine, VIDEO_SCREEN, screen_tag); - } - else - { - /* we need to do something for screenless games */ - assert(screen != NULL); - } - } - - /* find the screen info structure for the given token - there should only be one */ - for (i = 0; i < MAX_SCREENS; i++) - if (machine->screen[i].private_data == ((screen_state *)screen)->private_data) - internal_state = get_internal_state(machine, i); - - /* make sure we still have room for the callback */ - assert(internal_state != NULL); - assert(internal_state->vbl_cb_count != MAX_VBL_CB); - /* check if we already have this callback registered */ found = FALSE; - for (i = 0; i < internal_state->vbl_cb_count; i++) + for (i = 0; i < MAX_VBL_CB; i++) + { + if (internal_state->vbl_cbs[i] == NULL) + break; + if (internal_state->vbl_cbs[i] == vbl_cb) found = TRUE; + } + + /* check that there is room */ + assert(i != MAX_VBL_CB); /* if not found, register and increment count */ if (!found) + internal_state->vbl_cbs[i] = vbl_cb; +} + + +/*------------------------------------------------- + video_screen_register_global_vbl_cb - registers a + VBLANK callback for a specific screen +-------------------------------------------------*/ + +void video_screen_register_global_vbl_cb(vblank_state_changed_global_func vbl_cb) +{ + int i, found; + + /* validate arguments */ + assert(vbl_cb != NULL); + + /* check if we already have this callback registered */ + found = FALSE; + for (i = 0; i < MAX_VBL_CB; i++) { - internal_state->vbl_cbs[internal_state->vbl_cb_count] = vbl_cb; - internal_state->vbl_cb_count++; + if (global.vbl_cbs[i] == NULL) + break; + + if (global.vbl_cbs[i] == vbl_cb) + found = TRUE; } + + /* check that there is room */ + assert(i != MAX_VBL_CB); + + /* if not found, register and increment count */ + if (!found) + global.vbl_cbs[i] = vbl_cb; } @@ -1218,23 +1231,6 @@ DEVICE_GET_INFO( video_screen ) GLOBAL RENDERING ***************************************************************************/ -/*------------------------------------------------- - call_vb_callbacks - call any external VBLANK - callsbacks with the given state --------------------------------------------------*/ - -static void call_vb_callbacks(internal_screen_state *scrinfo, int vblank_state) -{ - int i; - - /* set it in the state structure */ - scrinfo->vblank_state = vblank_state; - - for (i = 0; scrinfo->vbl_cbs[i] != NULL; i++) - scrinfo->vbl_cbs[i](scrinfo->device, vblank_state); -} - - /*------------------------------------------------- vblank_begin_callback - call any external callbacks to signal the VBLANK period has begun @@ -1242,6 +1238,7 @@ static void call_vb_callbacks(internal_screen_state *scrinfo, int vblank_state) static TIMER_CALLBACK( vblank_begin_callback ) { + int i; attoseconds_t vblank_period; screen_state *state = ptr; internal_screen_state *internal_state = (internal_screen_state *)state->private_data; @@ -1249,8 +1246,17 @@ static TIMER_CALLBACK( vblank_begin_callback ) /* reset the starting VBLANK time */ internal_state->vblank_time = timer_get_time(); - /* call the external callbacks */ - call_vb_callbacks(internal_state, TRUE); + /* mark as being in VBLANK */ + internal_state->vblank_state = TRUE; + + /* call the screen specific callbacks */ + for (i = 0; internal_state->vbl_cbs[i] != NULL; i++) + internal_state->vbl_cbs[i](internal_state->device, TRUE); + + /* for the first screen, call the global callbacks */ + if (internal_state->scrnum == 0) + for (i = 0; global.vbl_cbs[i] != NULL; i++) + global.vbl_cbs[i](machine, TRUE); /* do we update the screen now? - only do it for the first screen */ if (!(machine->config->video_attributes & VIDEO_UPDATE_AFTER_VBLANK) && (internal_state->scrnum == 0)) @@ -1276,14 +1282,24 @@ static TIMER_CALLBACK( vblank_begin_callback ) static TIMER_CALLBACK( vblank_end_callback ) { + int i; internal_screen_state *internal_state = ptr; /* update the first screen if we didn't before */ if ((machine->config->video_attributes & VIDEO_UPDATE_AFTER_VBLANK) && (internal_state->scrnum == 0)) video_frame_update(machine, FALSE); - /* let any external parties know that the VBLANK is over */ - call_vb_callbacks(internal_state, FALSE); + /* mark as not being in VBLANK */ + internal_state->vblank_state = FALSE; + + /* call the screen specific callbacks */ + for (i = 0; internal_state->vbl_cbs[i] != NULL; i++) + internal_state->vbl_cbs[i](internal_state->device, FALSE); + + /* for the first screen, call the global callbacks */ + if (internal_state->scrnum == 0) + for (i = 0; global.vbl_cbs[i] != NULL; i++) + global.vbl_cbs[i](machine, FALSE); /* increment the frame number counter */ internal_state->frame_number++; diff --git a/src/emu/video.h b/src/emu/video.h index 490b2d06f0d..a578b52bb72 100644 --- a/src/emu/video.h +++ b/src/emu/video.h @@ -90,12 +90,14 @@ struct _screen_config /*------------------------------------------------- - vblank_state_changed_func - callback that a - screen calls to notify of a change of - the VBLANK state + vblank_state_changed_func + vblank_state_changed_global_func - + callback that is called to notify of a change + in the VBLANK state -------------------------------------------------*/ typedef void (*vblank_state_changed_func)(const device_config *device, int vblank_state); +typedef void (*vblank_state_changed_global_func)(running_machine *machine, int vblank_state); @@ -155,8 +157,11 @@ UINT64 video_screen_get_frame_number(int scrnum); /* returns whether a given screen exists */ int video_screen_exists(int scrnum); -/* registers a VBLANK callback for the given screen*/ -void video_screen_register_vbl_cb(running_machine *machine, void *screen, vblank_state_changed_func vbl_cb); +/* registers a VBLANK callback for the given screen */ +void video_screen_register_vbl_cb(const device_config *screen, vblank_state_changed_func vbl_cb); + +/* registers a VBLANK callback independent of a screen */ +void video_screen_register_global_vbl_cb(vblank_state_changed_global_func vbl_cb); /* ----- video screen device interface ----- */ diff --git a/src/emu/watchdog.c b/src/emu/watchdog.c index 63a3b6f252a..7cf41f5ade3 100644 --- a/src/emu/watchdog.c +++ b/src/emu/watchdog.c @@ -83,18 +83,18 @@ static TIMER_CALLBACK( watchdog_callback ) timers -------------------------------------------------*/ -static void on_vblank(const device_config *device, int vblank_state) +static void on_vblank(running_machine *machine, int vblank_state) { /* VBLANK starting */ if (vblank_state && watchdog_enabled) { /* check the watchdog */ - if (device->machine->config->watchdog_vblank_count != 0) + if (machine->config->watchdog_vblank_count != 0) { watchdog_counter = watchdog_counter - 1; if (watchdog_counter == 0) - watchdog_callback(device->machine, NULL, 0); + watchdog_callback(machine, NULL, 0); } } } @@ -116,7 +116,7 @@ void watchdog_reset(running_machine *machine) watchdog_counter = machine->config->watchdog_vblank_count; /* register a global VBLANK callback */ - video_screen_register_vbl_cb(machine, NULL, on_vblank); + video_screen_register_global_vbl_cb(on_vblank); } /* timer-based watchdog? */