mirror of
https://github.com/holub/mame
synced 2025-06-01 02:21:48 +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 */
|
||||
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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
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 */
|
||||
|
||||
/* 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++;
|
||||
|
@ -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 ----- */
|
||||
|
@ -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? */
|
||||
|
Loading…
Reference in New Issue
Block a user