Seperates out the notion of screen specific vs. "global" VBLANK callbacks

"Global" VBLANK callbacks, of course, make no conceptual sense -- it should probably fire every once in a while even if there is no screen
This commit is contained in:
Zsolt Vasvari 2008-03-07 08:18:28 +00:00
parent 5f53680e03
commit 9ad9532722
6 changed files with 97 additions and 77 deletions

View File

@ -968,27 +968,26 @@ static void cpu_inittimers(running_machine *machine)
/* VBLANK interrupts */ /* VBLANK interrupts */
if (config->vblank_interrupts_per_frame > 0) if (config->vblank_interrupts_per_frame > 0)
{ {
const char *screen_tag; const device_config *screen;
screen_state *screen;
/* get the screen that will trigger the VBLANK */ /* get the screen that will trigger the VBLANK */
/* new style - use screen tag directly */ /* new style - use screen tag directly */
if (config->vblank_interrupts_per_frame == 1) 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 */ /* old style 'hack' setup - use screen #0 */
else else
{ {
const device_config *config = device_list_first(machine->config->devicelist, VIDEO_SCREEN); screen = device_list_first(machine->config->devicelist, VIDEO_SCREEN);
screen_tag = config->tag;
/* allocate timer that will trigger the partial frame updates */ /* allocate timer that will trigger the partial frame updates */
cpu[cpunum].partial_frame_timer = timer_alloc(trigger_partial_frame_interrupt, 0); cpu[cpunum].partial_frame_timer = timer_alloc(trigger_partial_frame_interrupt, 0);
} }
screen = devtag_get_token(machine, VIDEO_SCREEN, screen_tag); assert(screen != NULL);
video_screen_register_vbl_cb(machine, screen, on_vblank);
video_screen_register_vbl_cb(screen, on_vblank);
} }
/* periodic interrupts */ /* periodic interrupts */

View File

@ -144,7 +144,7 @@ int mame_debug_is_active(void)
on_vblank - called when a VBLANK hits 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 we're configured to stop on VBLANK, break */
if (vblank_state && break_on_vblank) if (vblank_state && break_on_vblank)
@ -296,7 +296,7 @@ void debug_cpu_init(running_machine *machine)
} }
/* add callback for breaking on VBLANK */ /* 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); add_exit_callback(machine, debug_cpu_exit);
} }

View File

@ -1032,7 +1032,7 @@ static int default_ports_lookup[__ipt_max][MAX_PLAYERS];
FUNCTION PROTOTYPES 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_playback(running_machine *machine);
static void setup_record(running_machine *machine); static void setup_record(running_machine *machine);
static void input_port_exit(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) void input_port_post_init(running_machine *machine)
{ {
/* set up callback for updating the ports */ /* 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 */ /* VBLANK starting - read keyboard & update the status of the input ports */
if (vblank_state) if (vblank_state)
input_port_vblank_start(device->machine); input_port_vblank_start(machine);
/* VBLANK ending - update IPT_VBLANK input ports */ /* VBLANK ending - update IPT_VBLANK input ports */
else else

View File

@ -73,7 +73,6 @@ struct _internal_screen_state
UINT64 frame_number; /* the current frame number */ UINT64 frame_number; /* the current frame number */
/* screen specific VBLANK callbacks */ /* screen specific VBLANK callbacks */
int vbl_cb_count;
vblank_state_changed_func vbl_cbs[MAX_VBL_CB]; /* the array of callbacks */ vblank_state_changed_func vbl_cbs[MAX_VBL_CB]; /* the array of callbacks */
/* movie recording */ /* movie recording */
@ -132,6 +131,9 @@ struct _video_global
UINT8 crosshair_animate; /* animation frame index */ UINT8 crosshair_animate; /* animation frame index */
UINT8 crosshair_visible; /* crosshair visible mask */ UINT8 crosshair_visible; /* crosshair visible mask */
UINT8 crosshair_needed; /* crosshair needed 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 != NULL);
assert(device->token != NULL); assert(device->token != NULL);
assert(device->type == DEVICE_GET_INFO_NAME(video_screen)); assert(device->type == VIDEO_SCREEN);
return (screen_state *)device->token; return (screen_state *)device->token;
} }
@ -1103,53 +1105,64 @@ UINT64 video_screen_get_frame_number(int scrnum)
VBLANK callback for a specific screen 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; 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 */ /* validate arguments */
assert(machine != NULL);
assert(machine->config != NULL);
assert(machine->config->devicelist != NULL);
assert(vbl_cb != 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 */ /* check if we already have this callback registered */
found = FALSE; 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) if (internal_state->vbl_cbs[i] == vbl_cb)
found = TRUE; found = TRUE;
}
/* check that there is room */
assert(i != MAX_VBL_CB);
/* if not found, register and increment count */ /* if not found, register and increment count */
if (!found) 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; if (global.vbl_cbs[i] == NULL)
internal_state->vbl_cb_count++; 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 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 vblank_begin_callback - call any external
callbacks to signal the VBLANK period has begun 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 ) static TIMER_CALLBACK( vblank_begin_callback )
{ {
int i;
attoseconds_t vblank_period; attoseconds_t vblank_period;
screen_state *state = ptr; screen_state *state = ptr;
internal_screen_state *internal_state = (internal_screen_state *)state->private_data; 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 */ /* reset the starting VBLANK time */
internal_state->vblank_time = timer_get_time(); internal_state->vblank_time = timer_get_time();
/* call the external callbacks */ /* mark as being in VBLANK */
call_vb_callbacks(internal_state, TRUE); 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 */ /* 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)) 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 ) static TIMER_CALLBACK( vblank_end_callback )
{ {
int i;
internal_screen_state *internal_state = ptr; internal_screen_state *internal_state = ptr;
/* update the first screen if we didn't before */ /* update the first screen if we didn't before */
if ((machine->config->video_attributes & VIDEO_UPDATE_AFTER_VBLANK) && (internal_state->scrnum == 0)) if ((machine->config->video_attributes & VIDEO_UPDATE_AFTER_VBLANK) && (internal_state->scrnum == 0))
video_frame_update(machine, FALSE); video_frame_update(machine, FALSE);
/* let any external parties know that the VBLANK is over */ /* mark as not being in VBLANK */
call_vb_callbacks(internal_state, FALSE); 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 */ /* increment the frame number counter */
internal_state->frame_number++; internal_state->frame_number++;

View File

@ -90,12 +90,14 @@ struct _screen_config
/*------------------------------------------------- /*-------------------------------------------------
vblank_state_changed_func - callback that a vblank_state_changed_func
screen calls to notify of a change of vblank_state_changed_global_func -
the VBLANK state 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_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 */ /* returns whether a given screen exists */
int video_screen_exists(int scrnum); int video_screen_exists(int scrnum);
/* registers a VBLANK callback for the given screen*/ /* 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); 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 ----- */ /* ----- video screen device interface ----- */

View File

@ -83,18 +83,18 @@ static TIMER_CALLBACK( watchdog_callback )
timers timers
-------------------------------------------------*/ -------------------------------------------------*/
static void on_vblank(const device_config *device, int vblank_state) static void on_vblank(running_machine *machine, int vblank_state)
{ {
/* VBLANK starting */ /* VBLANK starting */
if (vblank_state && watchdog_enabled) if (vblank_state && watchdog_enabled)
{ {
/* check the watchdog */ /* check the watchdog */
if (device->machine->config->watchdog_vblank_count != 0) if (machine->config->watchdog_vblank_count != 0)
{ {
watchdog_counter = watchdog_counter - 1; watchdog_counter = watchdog_counter - 1;
if (watchdog_counter == 0) 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; watchdog_counter = machine->config->watchdog_vblank_count;
/* register a global VBLANK callback */ /* 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? */ /* timer-based watchdog? */