mirror of
https://github.com/holub/mame
synced 2025-07-03 09:06:08 +03:00
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:
parent
5f53680e03
commit
9ad9532722
@ -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 */
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
126
src/emu/video.c
126
src/emu/video.c
@ -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++;
|
||||||
|
@ -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 ----- */
|
||||||
|
@ -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? */
|
||||||
|
Loading…
Reference in New Issue
Block a user