Split the screen device into a separate module.

Converted global video routines into a video_manager.
Moved video manager initialization earlier in startup.
This commit is contained in:
Aaron Giles 2010-12-02 17:26:38 +00:00
parent 3c55c67436
commit 57ef3a5ed6
38 changed files with 2523 additions and 2706 deletions

2
.gitattributes vendored
View File

@ -845,6 +845,8 @@ src/emu/romload.c svneol=native#text/plain
src/emu/romload.h svneol=native#text/plain src/emu/romload.h svneol=native#text/plain
src/emu/schedule.c svneol=native#text/plain src/emu/schedule.c svneol=native#text/plain
src/emu/schedule.h svneol=native#text/plain src/emu/schedule.h svneol=native#text/plain
src/emu/screen.c svneol=native#text/plain
src/emu/screen.h svneol=native#text/plain
src/emu/softlist.c svneol=native#text/plain src/emu/softlist.c svneol=native#text/plain
src/emu/softlist.h svneol=native#text/plain src/emu/softlist.h svneol=native#text/plain
src/emu/sound.c svneol=native#text/plain src/emu/sound.c svneol=native#text/plain

View File

@ -2418,7 +2418,7 @@ static void execute_snap(running_machine *machine, int ref, int params, const ch
/* if no params, use the default behavior */ /* if no params, use the default behavior */
if (params == 0) if (params == 0)
{ {
video_save_active_screen_snapshots(machine); machine->video().save_active_screen_snapshots();
debug_console_printf(machine, "Saved snapshot\n"); debug_console_printf(machine, "Saved snapshot\n");
} }
@ -2449,7 +2449,7 @@ static void execute_snap(running_machine *machine, int ref, int params, const ch
return; return;
} }
screen_save_snapshot(screen->machine, screen, fp); screen->machine->video().save_snapshot(screen, *fp);
mame_fclose(fp); mame_fclose(fp);
debug_console_printf(machine, "Saved screen #%d snapshot as '%s'\n", scrnum, filename); debug_console_printf(machine, "Saved screen #%d snapshot as '%s'\n", scrnum, filename);
} }

View File

@ -142,7 +142,7 @@ static UINT64 get_frame(symbol_table &table, void *ref);
void debug_cpu_init(running_machine *machine) void debug_cpu_init(running_machine *machine)
{ {
screen_device *first_screen = screen_first(*machine); screen_device *first_screen = machine->first_screen();
debugcpu_private *global; debugcpu_private *global;
int regnum; int regnum;

View File

@ -104,7 +104,7 @@ void debugger_init(running_machine *machine)
void debugger_refresh_display(running_machine *machine) void debugger_refresh_display(running_machine *machine)
{ {
video_frame_update(machine, TRUE); machine->video().frame_update(true);
} }

View File

@ -219,7 +219,7 @@ bool device_config_execute_interface::interface_validity_check(const game_driver
/* validate the interrupts */ /* validate the interrupts */
if (m_vblank_interrupt != NULL) if (m_vblank_interrupt != NULL)
{ {
if (screen_count(m_machine_config) == 0) if (m_machine_config.m_devicelist.count(SCREEN) == 0)
{ {
mame_printf_error("%s: %s device '%s' has a VBLANK interrupt, but the driver is screenless!\n", driver.source_file, driver.name, devconfig->tag()); mame_printf_error("%s: %s device '%s' has a VBLANK interrupt, but the driver is screenless!\n", driver.source_file, driver.name, devconfig->tag());
error = true; error = true;
@ -629,7 +629,7 @@ void device_execute_interface::interface_post_reset()
// old style 'hack' setup - use screen #0 // old style 'hack' setup - use screen #0
else else
screen = screen_first(m_machine); screen = m_machine.first_screen();
assert(screen != NULL); assert(screen != NULL);
screen->register_vblank_callback(static_on_vblank, NULL); screen->register_vblank_callback(static_on_vblank, NULL);

View File

@ -121,6 +121,7 @@ typedef device_config * (*machine_config_constructor)(machine_config &config, de
#include "drawgfx.h" #include "drawgfx.h"
#include "tilemap.h" #include "tilemap.h"
#include "emupal.h" #include "emupal.h"
#include "screen.h"
#include "video.h" #include "video.h"
// sound-related // sound-related

View File

@ -89,6 +89,7 @@ EMUOBJS = \
$(EMUOBJ)/rendutil.o \ $(EMUOBJ)/rendutil.o \
$(EMUOBJ)/romload.o \ $(EMUOBJ)/romload.o \
$(EMUOBJ)/schedule.o \ $(EMUOBJ)/schedule.o \
$(EMUOBJ)/screen.o \
$(EMUOBJ)/softlist.o \ $(EMUOBJ)/softlist.o \
$(EMUOBJ)/sound.o \ $(EMUOBJ)/sound.o \
$(EMUOBJ)/state.o \ $(EMUOBJ)/state.o \

View File

@ -97,7 +97,7 @@ static void configure_rgb_shadows(running_machine *machine, int mode, float fact
void palette_init(running_machine *machine) void palette_init(running_machine *machine)
{ {
palette_private *palette = auto_alloc_clear(machine, palette_private); palette_private *palette = auto_alloc_clear(machine, palette_private);
screen_device *device = screen_first(*machine); screen_device *device = machine->first_screen();
/* get the format from the first screen, or use BITMAP_FORMAT_INVALID, if screenless */ /* get the format from the first screen, or use BITMAP_FORMAT_INVALID, if screenless */
bitmap_format format = (device != NULL) ? device->format() : BITMAP_FORMAT_INVALID; bitmap_format format = (device != NULL) ? device->format() : BITMAP_FORMAT_INVALID;

View File

@ -726,7 +726,7 @@ static void print_game_display(FILE *out, const game_driver *game, const machine
const screen_device_config *devconfig; const screen_device_config *devconfig;
/* iterate over screens */ /* iterate over screens */
for (devconfig = screen_first(config); devconfig != NULL; devconfig = screen_next(devconfig)) for (devconfig = config.first_screen(); devconfig != NULL; devconfig = devconfig->next_screen())
{ {
fprintf(out, "\t\t<display"); fprintf(out, "\t\t<display");

View File

@ -4667,7 +4667,7 @@ static void record_frame(running_machine *machine, attotime curtime)
record_write_uint64(machine, curtime.attoseconds); record_write_uint64(machine, curtime.attoseconds);
/* then the current speed */ /* then the current speed */
record_write_uint32(machine, video_get_speed_percent(machine) * (double)(1 << 20)); record_write_uint32(machine, machine->video().speed_percent() * (double)(1 << 20));
} }
} }

View File

@ -192,6 +192,7 @@ running_machine::running_machine(const machine_config &_config, osd_interface &o
m_driver_device(NULL), m_driver_device(NULL),
m_cheat(NULL), m_cheat(NULL),
m_render(NULL), m_render(NULL),
m_video(NULL),
m_debug_view(NULL) m_debug_view(NULL)
{ {
memset(gfx, 0, sizeof(gfx)); memset(gfx, 0, sizeof(gfx));
@ -210,7 +211,7 @@ running_machine::running_machine(const machine_config &_config, osd_interface &o
assert(m_driver_device != NULL); assert(m_driver_device != NULL);
// find devices // find devices
primary_screen = screen_first(*this); primary_screen = downcast<screen_device *>(m_devicelist.first(SCREEN));
for (device_t *device = m_devicelist.first(); device != NULL; device = device->next()) for (device_t *device = m_devicelist.first(); device != NULL; device = device->next())
if (dynamic_cast<cpu_device *>(device) != NULL) if (dynamic_cast<cpu_device *>(device) != NULL)
{ {
@ -230,7 +231,7 @@ running_machine::running_machine(const machine_config &_config, osd_interface &o
running_machine::~running_machine() running_machine::~running_machine()
{ {
/* clear flag for added devices */ // clear flag for added devices
options_set_bool(&m_options, OPTION_ADDED_DEVICE_OPTIONS, FALSE, OPTION_PRIORITY_CMDLINE); options_set_bool(&m_options, OPTION_ADDED_DEVICE_OPTIONS, FALSE, OPTION_PRIORITY_CMDLINE);
} }
@ -285,6 +286,9 @@ void running_machine::start()
// init the osd layer // init the osd layer
m_osd.init(*this); m_osd.init(*this);
// create the video manager
m_video = auto_alloc(this, video_manager(*this));
ui_init(this); ui_init(this);
// initialize the base time (needed for doing record/playback) // initialize the base time (needed for doing record/playback)
@ -320,7 +324,6 @@ void running_machine::start()
tilemap_init(this); tilemap_init(this);
crosshair_init(this); crosshair_init(this);
sound_init(this); sound_init(this);
video_init(this);
// initialize the debugger // initialize the debugger
if ((debug_flags & DEBUG_FLAG_ENABLED) != 0) if ((debug_flags & DEBUG_FLAG_ENABLED) != 0)
@ -399,7 +402,7 @@ int running_machine::run(bool firstrun)
// otherwise, just pump video updates through // otherwise, just pump video updates through
else else
video_frame_update(this, false); m_video->frame_update();
// handle save/load // handle save/load
if (m_saveload_schedule != SLS_NONE) if (m_saveload_schedule != SLS_NONE)

View File

@ -182,6 +182,7 @@ class gfx_element;
class colortable_t; class colortable_t;
class cheat_manager; class cheat_manager;
class render_manager; class render_manager;
class video_manager;
class debug_view_manager; class debug_view_manager;
class osd_interface; class osd_interface;
@ -362,6 +363,7 @@ public:
const char *new_driver_name() const { return m_new_driver_pending->name; } const char *new_driver_name() const { return m_new_driver_pending->name; }
device_scheduler &scheduler() { return m_scheduler; } device_scheduler &scheduler() { return m_scheduler; }
osd_interface &osd() const { return m_osd; } osd_interface &osd() const { return m_osd; }
screen_device *first_screen() const { return primary_screen; }
// immediate operations // immediate operations
int run(bool firstrun); int run(bool firstrun);
@ -390,6 +392,7 @@ public:
// managers // managers
cheat_manager &cheat() const { assert(m_cheat != NULL); return *m_cheat; } cheat_manager &cheat() const { assert(m_cheat != NULL); return *m_cheat; }
render_manager &render() const { assert(m_render != NULL); return *m_render; } render_manager &render() const { assert(m_render != NULL); return *m_render; }
video_manager &video() const { assert(m_video != NULL); return *m_video; }
debug_view_manager &debug_view() const { assert(m_debug_view != NULL); return *m_debug_view; } debug_view_manager &debug_view() const { assert(m_debug_view != NULL); return *m_debug_view; }
// misc // misc
@ -530,6 +533,7 @@ private:
driver_device * m_driver_device; driver_device * m_driver_device;
cheat_manager * m_cheat; // internal data from cheat.c cheat_manager * m_cheat; // internal data from cheat.c
render_manager * m_render; // internal data from render.c render_manager * m_render; // internal data from render.c
video_manager * m_video; // internal data from video.c
debug_view_manager * m_debug_view; // internal data from debugvw.c debug_view_manager * m_debug_view; // internal data from debugvw.c
}; };

View File

@ -529,7 +529,7 @@ void mame_parse_ini_files(core_options *options, const game_driver *driver)
/* parse "vector.ini" for vector games */ /* parse "vector.ini" for vector games */
{ {
machine_config config(*driver); machine_config config(*driver);
for (const screen_device_config *devconfig = screen_first(config); devconfig != NULL; devconfig = screen_next(devconfig)) for (const screen_device_config *devconfig = config.first_screen(); devconfig != NULL; devconfig = devconfig->next_screen())
if (devconfig->screen_type() == SCREEN_TYPE_VECTOR) if (devconfig->screen_type() == SCREEN_TYPE_VECTOR)
{ {
parse_ini_file(options, "vector", OPTION_PRIORITY_VECTOR_INI); parse_ini_file(options, "vector", OPTION_PRIORITY_VECTOR_INI);

View File

@ -100,6 +100,17 @@ machine_config::~machine_config()
} }
//-------------------------------------------------
// first_screen - return a pointer to the first
// screen device
//-------------------------------------------------
screen_device_config *machine_config::first_screen() const
{
return downcast<screen_device_config *>(m_devicelist.first(SCREEN));
}
//------------------------------------------------- //-------------------------------------------------
// device_add - configuration helper to add a // device_add - configuration helper to add a
// new device // new device

View File

@ -105,6 +105,7 @@
// forward references // forward references
struct gfx_decode_entry; struct gfx_decode_entry;
class driver_device; class driver_device;
class screen_device_config;
@ -124,11 +125,15 @@ class machine_config
friend class running_machine; friend class running_machine;
public: public:
// construction/destruction
machine_config(const game_driver &gamedrv); machine_config(const game_driver &gamedrv);
~machine_config(); ~machine_config();
// getters
const game_driver &gamedrv() const { return m_gamedrv; } const game_driver &gamedrv() const { return m_gamedrv; }
screen_device_config *first_screen() const;
// public state
attotime m_minimum_quantum; // minimum scheduling quantum attotime m_minimum_quantum; // minimum scheduling quantum
const char * m_perfect_cpu_quantum; // tag of CPU to use for "perfect" scheduling const char * m_perfect_cpu_quantum; // tag of CPU to use for "perfect" scheduling
INT32 m_watchdog_vblank_count; // number of VBLANKs until the watchdog kills us INT32 m_watchdog_vblank_count; // number of VBLANKs until the watchdog kills us

View File

@ -1151,6 +1151,78 @@ void render_target::set_max_texture_size(int maxwidth, int maxheight)
} }
//-------------------------------------------------
// configured_view - select a view for this
// target based on the configuration parameters
//-------------------------------------------------
int render_target::configured_view(const char *viewname, int targetindex, int numtargets)
{
layout_view *view = NULL;
int viewindex;
// auto view just selects the nth view
if (strcmp(viewname, "auto") != 0)
{
// scan for a matching view name
for (view = view_by_index(viewindex = 0); view != NULL; view = view_by_index(++viewindex))
if (mame_strnicmp(view->name(), viewname, strlen(viewname)) == 0)
break;
}
// if we don't have a match, default to the nth view
int scrcount = m_manager.machine().m_devicelist.count(SCREEN);
if (view == NULL && scrcount > 0)
{
// if we have enough targets to be one per screen, assign in order
if (numtargets >= scrcount)
{
int ourindex = index() % scrcount;
screen_device *screen;
for (screen = m_manager.machine().first_screen(); screen != NULL; screen = screen->next_screen())
if (ourindex-- == 0)
break;
// find the first view with this screen and this screen only
for (view = view_by_index(viewindex = 0); view != NULL; view = view_by_index(++viewindex))
{
const render_screen_list &viewscreens = view->screens();
if (viewscreens.count() == 1 && viewscreens.contains(*screen))
break;
if (viewscreens.count() == 0)
{
view = NULL;
break;
}
}
}
// otherwise, find the first view that has all the screens
if (view == NULL)
{
for (view = view_by_index(viewindex = 0); view != NULL; view = view_by_index(++viewindex))
{
const render_screen_list &viewscreens = view->screens();
if (viewscreens.count() == 0)
break;
if (viewscreens.count() >= scrcount)
{
screen_device *screen;
for (screen = m_manager.machine().first_screen(); screen != NULL; screen = screen->next_screen())
if (!viewscreens.contains(*screen))
break;
if (screen == NULL)
break;
}
}
}
}
// make sure it's a valid view
return (view != NULL) ? view_index(*view) : 0;
}
//------------------------------------------------- //-------------------------------------------------
// view_name - return the name of the given view // view_name - return the name of the given view
//------------------------------------------------- //-------------------------------------------------
@ -1548,7 +1620,7 @@ void render_target::load_layout_files(const char *layoutfile, bool singlefile)
load_layout_file(cloneof->name, "default"); load_layout_file(cloneof->name, "default");
// now do the built-in layouts for single-screen games // now do the built-in layouts for single-screen games
if (screen_count(m_manager.machine().m_config) == 1) if (m_manager.machine().m_devicelist.count(SCREEN) == 1)
{ {
if (gamedrv->flags & ORIENTATION_SWAP_XY) if (gamedrv->flags & ORIENTATION_SWAP_XY)
load_layout_file(NULL, layout_vertical); load_layout_file(NULL, layout_vertical);
@ -2366,7 +2438,7 @@ render_manager::render_manager(running_machine &machine)
config_register(&machine, "video", config_load_static, config_save_static); config_register(&machine, "video", config_load_static, config_save_static);
// create one container per screen // create one container per screen
for (screen_device *screen = screen_first(machine); screen != NULL; screen = screen_next(screen)) for (screen_device *screen = machine.first_screen(); screen != NULL; screen = screen->next_screen())
screen->set_container(*container_alloc(screen)); screen->set_container(*container_alloc(screen));
} }

View File

@ -627,6 +627,9 @@ public:
void set_screen_overlay_enabled(bool enable) { m_layerconfig.set_screen_overlay_enabled(enable); update_layer_config(); } void set_screen_overlay_enabled(bool enable) { m_layerconfig.set_screen_overlay_enabled(enable); update_layer_config(); }
void set_zoom_to_screen(bool zoom) { m_layerconfig.set_zoom_to_screen(zoom); update_layer_config(); } void set_zoom_to_screen(bool zoom) { m_layerconfig.set_zoom_to_screen(zoom); update_layer_config(); }
// view configuration helper
int configured_view(const char *viewname, int targetindex, int numtargets);
// view information // view information
const char *view_name(int viewindex); const char *view_name(int viewindex);
const render_screen_list &view_screens(int viewindex); const render_screen_list &view_screens(int viewindex);

View File

@ -193,7 +193,7 @@ static int get_variable_value(running_machine &machine, const char *string, char
char temp[100]; char temp[100];
// screen 0 parameters // screen 0 parameters
for (const screen_device_config *devconfig = screen_first(machine.m_config); devconfig != NULL; devconfig = screen_next(devconfig)) for (const screen_device_config *devconfig = machine.m_config.first_screen(); devconfig != NULL; devconfig = devconfig->next_screen())
{ {
int scrnum = machine.m_config.m_devicelist.index(SCREEN, devconfig->tag()); int scrnum = machine.m_config.m_devicelist.index(SCREEN, devconfig->tag());

1076
src/emu/screen.c Normal file

File diff suppressed because it is too large Load Diff

305
src/emu/screen.h Normal file
View File

@ -0,0 +1,305 @@
/***************************************************************************
screen.h
Core MAME screen device.
****************************************************************************
Copyright Aaron Giles
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name 'MAME' nor the names of its contributors may be
used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
***************************************************************************/
#pragma once
#ifndef __EMU_H__
#error Dont include this file directly; include emu.h instead.
#endif
#ifndef __SCREEN_H__
#define __SCREEN_H__
//**************************************************************************
// CONSTANTS
//**************************************************************************
// screen types
enum screen_type_enum
{
SCREEN_TYPE_INVALID = 0,
SCREEN_TYPE_RASTER,
SCREEN_TYPE_VECTOR,
SCREEN_TYPE_LCD
};
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// forward references
class render_texture;
class screen_device;
// device type definition
extern const device_type SCREEN;
// callback that is called to notify of a change in the VBLANK state
typedef void (*vblank_state_changed_func)(screen_device &device, void *param, bool vblank_state);
// ======================> screen_device_config
class screen_device_config : public device_config
{
friend class screen_device;
// construction/destruction
screen_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
public:
// allocators
static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
virtual device_t *alloc_device(running_machine &machine) const;
// configuration readers
screen_device_config *next_screen() const { return downcast<screen_device_config *>(typenext()); }
screen_type_enum screen_type() const { return m_type; }
int width() const { return m_width; }
int height() const { return m_height; }
const rectangle &visible_area() const { return m_visarea; }
bool oldstyle_vblank_supplied() const { return m_oldstyle_vblank_supplied; }
attoseconds_t refresh() const { return m_refresh; }
attoseconds_t vblank() const { return m_vblank; }
bitmap_format format() const { return m_format; }
float xoffset() const { return m_xoffset; }
float yoffset() const { return m_yoffset; }
float xscale() const { return m_xscale; }
float yscale() const { return m_yscale; }
// inline configuration helpers
static void static_set_format(device_config *device, bitmap_format format);
static void static_set_type(device_config *device, screen_type_enum type);
static void static_set_raw(device_config *device, UINT32 pixclock, UINT16 htotal, UINT16 hbend, UINT16 hbstart, UINT16 vtotal, UINT16 vbend, UINT16 vbstart);
static void static_set_refresh(device_config *device, attoseconds_t rate);
static void static_set_vblank_time(device_config *device, attoseconds_t time);
static void static_set_size(device_config *device, UINT16 width, UINT16 height);
static void static_set_visarea(device_config *device, INT16 minx, INT16 maxx, INT16 miny, INT16 maxy);
static void static_set_default_position(device_config *device, double xscale, double xoffs, double yscale, double yoffs);
private:
// device_config overrides
virtual bool device_validity_check(const game_driver &driver) const;
// inline configuration data
screen_type_enum m_type; // type of screen
int m_width, m_height; // default total width/height (HTOTAL, VTOTAL)
rectangle m_visarea; // default visible area (HBLANK end/start, VBLANK end/start)
bool m_oldstyle_vblank_supplied; // MDRV_SCREEN_VBLANK_TIME macro used
attoseconds_t m_refresh; // default refresh period
attoseconds_t m_vblank; // duration of a VBLANK
bitmap_format m_format; // bitmap format
float m_xoffset, m_yoffset; // default X/Y offsets
float m_xscale, m_yscale; // default X/Y scale factor
};
// ======================> screen_device
class screen_device : public device_t
{
friend class screen_device_config;
friend class render_manager;
friend resource_pool_object<screen_device>::~resource_pool_object();
// construction/destruction
screen_device(running_machine &_machine, const screen_device_config &config);
virtual ~screen_device();
public:
// information getters
const screen_device_config &config() const { return m_config; }
screen_device *next_screen() const { return downcast<screen_device *>(typenext()); }
screen_type_enum screen_type() const { return m_config.m_type; }
int width() const { return m_width; }
int height() const { return m_height; }
const rectangle &visible_area() const { return m_visarea; }
bitmap_format format() const { return m_config.m_format; }
render_container &container() const { assert(m_container != NULL); return *m_container; }
// dynamic configuration
void configure(int width, int height, const rectangle &visarea, attoseconds_t frame_period);
void reset_origin(int beamy = 0, int beamx = 0);
void set_visible_area(int min_x, int max_x, int min_y, int max_y);
// beam positioning and state
int vpos() const;
int hpos() const;
bool vblank() const { return attotime_compare(timer_get_time(machine), m_vblank_end_time) < 0; }
bool hblank() const { int curpos = hpos(); return (curpos < m_visarea.min_x || curpos > m_visarea.max_x); }
// timing
attotime time_until_pos(int vpos, int hpos = 0) const;
attotime time_until_vblank_start() const { return time_until_pos(m_visarea.max_y + 1); }
attotime time_until_vblank_end() const;
attotime time_until_update() const { return (machine->config->m_video_attributes & VIDEO_UPDATE_AFTER_VBLANK) ? time_until_vblank_end() : time_until_vblank_start(); }
attotime scan_period() const { return attotime_make(0, m_scantime); }
attotime frame_period() const { return (this == NULL || !started()) ? DEFAULT_FRAME_PERIOD : attotime_make(0, m_frame_period); };
UINT64 frame_number() const { return m_frame_number; }
int partial_updates() const { return m_partial_updates_this_frame; }
// updating
bool update_partial(int scanline);
void update_now();
// additional helpers
void register_vblank_callback(vblank_state_changed_func vblank_callback, void *param);
bitmap_t *alloc_compatible_bitmap(int width = 0, int height = 0) { return auto_bitmap_alloc(machine, (width == 0) ? m_width : width, (height == 0) ? m_height : height, m_config.m_format); }
// internal to the video system
bool update_quads();
void update_burnin();
// globally accessible constants
static const int DEFAULT_FRAME_RATE = 60;
static const attotime DEFAULT_FRAME_PERIOD;
private:
// device-level overrides
virtual void device_start();
virtual void device_post_load();
// internal helpers
void set_container(render_container &container) { m_container = &container; }
void realloc_screen_bitmaps();
static TIMER_CALLBACK( static_vblank_begin_callback ) { reinterpret_cast<screen_device *>(ptr)->vblank_begin_callback(); }
void vblank_begin_callback();
static TIMER_CALLBACK( static_vblank_end_callback ) { reinterpret_cast<screen_device *>(ptr)->vblank_end_callback(); }
void vblank_end_callback();
static TIMER_CALLBACK( static_scanline0_callback ) { reinterpret_cast<screen_device *>(ptr)->scanline0_callback(); }
public: // temporary
void scanline0_callback();
private:
static TIMER_CALLBACK( static_scanline_update_callback ) { reinterpret_cast<screen_device *>(ptr)->scanline_update_callback(param); }
void scanline_update_callback(int scanline);
void finalize_burnin();
void load_effect_overlay(const char *filename);
// internal state
const screen_device_config &m_config;
render_container * m_container; // pointer to our container
// dimensions
int m_width; // current width (HTOTAL)
int m_height; // current height (VTOTAL)
rectangle m_visarea; // current visible area (HBLANK end/start, VBLANK end/start)
// textures and bitmaps
render_texture * m_texture[2]; // 2x textures for the screen bitmap
bitmap_t * m_bitmap[2]; // 2x bitmaps for rendering
bitmap_t * m_burnin; // burn-in bitmap
UINT8 m_curbitmap; // current bitmap index
UINT8 m_curtexture; // current texture index
INT32 m_texture_format; // texture format of bitmap for this screen
bool m_changed; // has this bitmap changed?
INT32 m_last_partial_scan; // scanline of last partial update
bitmap_t * m_screen_overlay_bitmap;// screen overlay bitmap
// screen timing
attoseconds_t m_frame_period; // attoseconds per frame
attoseconds_t m_scantime; // attoseconds per scanline
attoseconds_t m_pixeltime; // attoseconds per pixel
attoseconds_t m_vblank_period; // attoseconds per VBLANK period
attotime m_vblank_start_time; // time of last VBLANK start
attotime m_vblank_end_time; // time of last VBLANK end
emu_timer * m_vblank_begin_timer; // timer to signal VBLANK start
emu_timer * m_vblank_end_timer; // timer to signal VBLANK end
emu_timer * m_scanline0_timer; // scanline 0 timer
emu_timer * m_scanline_timer; // scanline timer
UINT64 m_frame_number; // the current frame number
UINT32 m_partial_updates_this_frame;// partial update counter this frame
struct callback_item
{
callback_item * m_next;
vblank_state_changed_func m_callback;
void * m_param;
};
callback_item * m_callback_list; // list of VBLANK callbacks
};
//**************************************************************************
// SCREEN DEVICE CONFIGURATION MACROS
//**************************************************************************
#define MDRV_SCREEN_ADD(_tag, _type) \
MDRV_DEVICE_ADD(_tag, SCREEN, 0) \
MDRV_SCREEN_TYPE(_type) \
#define MDRV_SCREEN_MODIFY(_tag) \
MDRV_DEVICE_MODIFY(_tag)
#define MDRV_SCREEN_FORMAT(_format) \
screen_device_config::static_set_format(device, _format); \
#define MDRV_SCREEN_TYPE(_type) \
screen_device_config::static_set_type(device, SCREEN_TYPE_##_type); \
#define MDRV_SCREEN_RAW_PARAMS(_pixclock, _htotal, _hbend, _hbstart, _vtotal, _vbend, _vbstart) \
screen_device_config::static_set_raw(device, _pixclock, _htotal, _hbend, _hbstart, _vtotal, _vbend, _vbstart);
#define MDRV_SCREEN_REFRESH_RATE(_rate) \
screen_device_config::static_set_refresh(device, HZ_TO_ATTOSECONDS(_rate)); \
#define MDRV_SCREEN_VBLANK_TIME(_time) \
screen_device_config::static_set_vblank_time(device, _time); \
#define MDRV_SCREEN_SIZE(_width, _height) \
screen_device_config::static_set_size(device, _width, _height); \
#define MDRV_SCREEN_VISIBLE_AREA(_minx, _maxx, _miny, _maxy) \
screen_device_config::static_set_visarea(device, _minx, _maxx, _miny, _maxy); \
#define MDRV_SCREEN_DEFAULT_POSITION(_xscale, _xoffs, _yscale, _yoffs) \
screen_device_config::static_set_default_position(device, _xscale, _xoffs, _yscale, _yoffs); \
#endif /* __SCREEN_H__ */

View File

@ -379,7 +379,7 @@ static TIMER_CALLBACK( sound_update )
speaker->mix(leftmix, rightmix, samples_this_update, !global->enabled); speaker->mix(leftmix, rightmix, samples_this_update, !global->enabled);
/* now downmix the final result */ /* now downmix the final result */
finalmix_step = video_get_speed_factor(); finalmix_step = machine->video().speed_factor();
finalmix_offset = 0; finalmix_offset = 0;
for (sample = global->finalmix_leftover; sample < samples_this_update * 100; sample += finalmix_step) for (sample = global->finalmix_leftover; sample < samples_this_update * 100; sample += finalmix_step)
{ {
@ -409,7 +409,7 @@ static TIMER_CALLBACK( sound_update )
{ {
if (!global->nosound_mode) if (!global->nosound_mode)
machine->osd().update_audio_stream(finalmix, finalmix_offset / 2); machine->osd().update_audio_stream(finalmix, finalmix_offset / 2);
video_avi_add_sound(machine, finalmix, finalmix_offset / 2); machine->video().add_sound_to_recording(finalmix, finalmix_offset / 2);
if (global->wavfile != NULL) if (global->wavfile != NULL)
wav_add_data_16(global->wavfile, finalmix, finalmix_offset); wav_add_data_16(global->wavfile, finalmix, finalmix_offset);
} }

View File

@ -56,6 +56,21 @@ typedef enum _state_save_error state_save_error;
#define STATE_POSTLOAD(name) void name(running_machine *machine, void *param) #define STATE_POSTLOAD(name) void name(running_machine *machine, void *param)
template<class T, void (T::*func)()>
void state_presave_stub(running_machine *machine, void *param)
{
T *target = reinterpret_cast<T *>(param);
(target->*func)();
}
template<class T, void (T::*func)()>
void state_postload_stub(running_machine *machine, void *param)
{
T *target = reinterpret_cast<T *>(param);
(target->*func)();
}
#ifdef __GNUC__ #ifdef __GNUC__
#define IS_VALID_SAVE_TYPE(_var) \ #define IS_VALID_SAVE_TYPE(_var) \
(std::tr1::is_arithmetic<typeof(_var)>::value || std::tr1::is_enum<typeof(_var)>::value || \ (std::tr1::is_arithmetic<typeof(_var)>::value || std::tr1::is_enum<typeof(_var)>::value || \

View File

@ -324,11 +324,11 @@ int ui_display_startup_screens(running_machine *machine, int first_time, int sho
/* loop while we have a handler */ /* loop while we have a handler */
while (ui_handler_callback != handler_ingame && !machine->scheduled_event_pending() && !ui_menu_is_force_game_select()) while (ui_handler_callback != handler_ingame && !machine->scheduled_event_pending() && !ui_menu_is_force_game_select())
video_frame_update(machine, FALSE); machine->video().frame_update();
/* clear the handler and force an update */ /* clear the handler and force an update */
ui_set_handler(handler_ingame, 0); ui_set_handler(handler_ingame, 0);
video_frame_update(machine, FALSE); machine->video().frame_update();
} }
/* if we're the empty driver, force the menus on */ /* if we're the empty driver, force the menus on */
@ -357,7 +357,7 @@ void ui_set_startup_text(running_machine *machine, const char *text, int force)
if (force || (curtime - lastupdatetime) > osd_ticks_per_second() / 4) if (force || (curtime - lastupdatetime) > osd_ticks_per_second() / 4)
{ {
lastupdatetime = curtime; lastupdatetime = curtime;
video_frame_update(machine, FALSE); machine->video().frame_update();
} }
} }
@ -1000,7 +1000,7 @@ static astring &warnings_string(running_machine *machine, astring &string)
astring &game_info_astring(running_machine *machine, astring &string) astring &game_info_astring(running_machine *machine, astring &string)
{ {
int scrcount = screen_count(*machine->config); int scrcount = machine->m_devicelist.count(SCREEN);
int found_sound = FALSE; int found_sound = FALSE;
/* print description, manufacturer, and CPU: */ /* print description, manufacturer, and CPU: */
@ -1077,7 +1077,7 @@ astring &game_info_astring(running_machine *machine, astring &string)
string.cat("None\n"); string.cat("None\n");
else else
{ {
for (screen_device *screen = screen_first(*machine); screen != NULL; screen = screen_next(screen)) for (screen_device *screen = machine->first_screen(); screen != NULL; screen = screen->next_screen())
{ {
if (scrcount > 1) if (scrcount > 1)
{ {
@ -1295,7 +1295,8 @@ static UINT32 handler_ingame(running_machine *machine, render_container *contain
/* first draw the FPS counter */ /* first draw the FPS counter */
if (showfps || osd_ticks() < showfps_end) if (showfps || osd_ticks() < showfps_end)
{ {
ui_draw_text_full(container, video_get_speed_text(machine), 0.0f, 0.0f, 1.0f, astring tempstring;
ui_draw_text_full(container, machine->video().speed_text(tempstring), 0.0f, 0.0f, 1.0f,
JUSTIFY_RIGHT, WRAP_WORD, DRAW_OPAQUE, ARGB_WHITE, ARGB_BLACK, NULL, NULL); JUSTIFY_RIGHT, WRAP_WORD, DRAW_OPAQUE, ARGB_WHITE, ARGB_BLACK, NULL, NULL);
} }
else else
@ -1409,7 +1410,7 @@ static UINT32 handler_ingame(running_machine *machine, render_container *contain
/* handle a save snapshot request */ /* handle a save snapshot request */
if (ui_input_pressed(machine, IPT_UI_SNAPSHOT)) if (ui_input_pressed(machine, IPT_UI_SNAPSHOT))
video_save_active_screen_snapshots(machine); machine->video().save_active_screen_snapshots();
/* toggle pause */ /* toggle pause */
if (ui_input_pressed(machine, IPT_UI_PAUSE)) if (ui_input_pressed(machine, IPT_UI_PAUSE))
@ -1433,14 +1434,14 @@ static UINT32 handler_ingame(running_machine *machine, render_container *contain
/* toggle movie recording */ /* toggle movie recording */
if (ui_input_pressed(machine, IPT_UI_RECORD_MOVIE)) if (ui_input_pressed(machine, IPT_UI_RECORD_MOVIE))
{ {
if (!video_mng_is_movie_active(machine)) if (!machine->video().is_recording())
{ {
video_mng_begin_recording(machine, NULL); machine->video().begin_recording(NULL, video_manager::MF_MNG);
popmessage("REC START"); popmessage("REC START");
} }
else else
{ {
video_mng_end_recording(machine); machine->video().end_recording();
popmessage("REC STOP"); popmessage("REC STOP");
} }
} }
@ -1457,10 +1458,10 @@ static UINT32 handler_ingame(running_machine *machine, render_container *contain
if (ui_input_pressed(machine, IPT_UI_FRAMESKIP_INC)) if (ui_input_pressed(machine, IPT_UI_FRAMESKIP_INC))
{ {
/* get the current value and increment it */ /* get the current value and increment it */
int newframeskip = video_get_frameskip() + 1; int newframeskip = machine->video().frameskip() + 1;
if (newframeskip > MAX_FRAMESKIP) if (newframeskip > MAX_FRAMESKIP)
newframeskip = -1; newframeskip = -1;
video_set_frameskip(newframeskip); machine->video().set_frameskip(newframeskip);
/* display the FPS counter for 2 seconds */ /* display the FPS counter for 2 seconds */
ui_show_fps_temp(2.0); ui_show_fps_temp(2.0);
@ -1470,10 +1471,10 @@ static UINT32 handler_ingame(running_machine *machine, render_container *contain
if (ui_input_pressed(machine, IPT_UI_FRAMESKIP_DEC)) if (ui_input_pressed(machine, IPT_UI_FRAMESKIP_DEC))
{ {
/* get the current value and decrement it */ /* get the current value and decrement it */
int newframeskip = video_get_frameskip() - 1; int newframeskip = machine->video().frameskip() - 1;
if (newframeskip < -1) if (newframeskip < -1)
newframeskip = MAX_FRAMESKIP; newframeskip = MAX_FRAMESKIP;
video_set_frameskip(newframeskip); machine->video().set_frameskip(newframeskip);
/* display the FPS counter for 2 seconds */ /* display the FPS counter for 2 seconds */
ui_show_fps_temp(2.0); ui_show_fps_temp(2.0);
@ -1481,16 +1482,16 @@ static UINT32 handler_ingame(running_machine *machine, render_container *contain
/* toggle throttle? */ /* toggle throttle? */
if (ui_input_pressed(machine, IPT_UI_THROTTLE)) if (ui_input_pressed(machine, IPT_UI_THROTTLE))
video_set_throttle(!video_get_throttle()); machine->video().set_throttled(!machine->video().throttled());
/* check for fast forward */ /* check for fast forward */
if (input_type_pressed(machine, IPT_UI_FAST_FORWARD, 0)) if (input_type_pressed(machine, IPT_UI_FAST_FORWARD, 0))
{ {
video_set_fastforward(TRUE); machine->video().set_fastforward(true);
ui_show_fps_temp(0.5); ui_show_fps_temp(0.5);
} }
else else
video_set_fastforward(FALSE); machine->video().set_fastforward(false);
return 0; return 0;
} }
@ -1659,7 +1660,7 @@ static slider_state *slider_init(running_machine *machine)
} }
/* add screen parameters */ /* add screen parameters */
for (screen_device *screen = screen_first(*machine); screen != NULL; screen = screen_next(screen)) for (screen_device *screen = machine->first_screen(); screen != NULL; screen = screen->next_screen())
{ {
int defxscale = floor(screen->config().xscale() * 1000.0f + 0.5f); int defxscale = floor(screen->config().xscale() * 1000.0f + 0.5f);
int defyscale = floor(screen->config().yscale() * 1000.0f + 0.5f); int defyscale = floor(screen->config().yscale() * 1000.0f + 0.5f);
@ -1728,7 +1729,7 @@ static slider_state *slider_init(running_machine *machine)
} }
} }
for (screen_device *screen = screen_first(*machine); screen != NULL; screen = screen_next(screen)) for (screen_device *screen = machine->first_screen(); screen != NULL; screen = screen->next_screen())
if (screen->screen_type() == SCREEN_TYPE_VECTOR) if (screen->screen_type() == SCREEN_TYPE_VECTOR)
{ {
/* add flicker control */ /* add flicker control */
@ -2129,7 +2130,7 @@ static INT32 slider_beam(running_machine *machine, void *arg, astring *string, I
static char *slider_get_screen_desc(screen_device &screen) static char *slider_get_screen_desc(screen_device &screen)
{ {
int scrcount = screen_count(*screen.machine->config); int scrcount = screen.machine->m_devicelist.count(SCREEN);
static char descbuf[256]; static char descbuf[256];
if (scrcount > 1) if (scrcount > 1)

View File

@ -586,7 +586,7 @@ static bool validate_display(const machine_config &config)
bool palette_modes = false; bool palette_modes = false;
bool error = false; bool error = false;
for (const screen_device_config *scrconfig = screen_first(config); scrconfig != NULL; scrconfig = screen_next(scrconfig)) for (const screen_device_config *scrconfig = config.first_screen(); scrconfig != NULL; scrconfig = scrconfig->next_screen())
if (scrconfig->format() == BITMAP_FORMAT_INDEXED16) if (scrconfig->format() == BITMAP_FORMAT_INDEXED16)
palette_modes = true; palette_modes = true;

File diff suppressed because it is too large Load Diff

View File

@ -55,15 +55,6 @@
const int FRAMESKIP_LEVELS = 12; const int FRAMESKIP_LEVELS = 12;
const int MAX_FRAMESKIP = FRAMESKIP_LEVELS - 2; const int MAX_FRAMESKIP = FRAMESKIP_LEVELS - 2;
// screen types
enum screen_type_enum
{
SCREEN_TYPE_INVALID = 0,
SCREEN_TYPE_RASTER,
SCREEN_TYPE_VECTOR,
SCREEN_TYPE_LCD
};
//************************************************************************** //**************************************************************************
@ -72,385 +63,149 @@ enum screen_type_enum
// forward references // forward references
class render_target; class render_target;
class render_texture;
class screen_device; class screen_device;
typedef struct _avi_file avi_file;
// callback that is called to notify of a change in the VBLANK state
typedef void (*vblank_state_changed_func)(screen_device &device, void *param, bool vblank_state);
// ======================> video_manager
// ======================> screen_device_config class video_manager
class screen_device_config : public device_config
{ {
friend class screen_device; friend class screen_device;
public:
// movie format options
enum movie_format
{
MF_MNG,
MF_AVI
};
// construction/destruction // construction/destruction
screen_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock); video_manager(running_machine &machine);
// getters
bool skip_this_frame() const { return m_skipping_this_frame; }
int speed_factor() const { return m_speed; }
int frameskip() const { return m_auto_frameskip ? -1 : m_frameskip_level; }
bool throttled() const { return m_throttle; }
bool fastforward() const { return m_fastforward; }
bool is_recording() const { return (m_mngfile != NULL || m_avifile != NULL); }
public: // setters
// allocators void set_speed_factor(int speed) { m_speed = speed; }
static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock); void set_frameskip(int frameskip);
virtual device_t *alloc_device(running_machine &machine) const; void set_throttled(bool throttled = true) { m_throttle = throttled; }
void set_fastforward(bool ffwd = true) { m_fastforward = ffwd; }
// configuration readers // render a frame
screen_type_enum screen_type() const { return m_type; } void frame_update(bool debug = false);
int width() const { return m_width; }
int height() const { return m_height; } // current speed helpers
const rectangle &visible_area() const { return m_visarea; } astring &speed_text(astring &string);
bool oldstyle_vblank_supplied() const { return m_oldstyle_vblank_supplied; } double speed_percent() const { return m_speed_percent; }
attoseconds_t refresh() const { return m_refresh; }
attoseconds_t vblank() const { return m_vblank; }
bitmap_format format() const { return m_format; }
float xoffset() const { return m_xoffset; }
float yoffset() const { return m_yoffset; }
float xscale() const { return m_xscale; }
float yscale() const { return m_yscale; }
// inline configuration helpers // snapshots
static void static_set_format(device_config *device, bitmap_format format); void save_snapshot(screen_device *screen, mame_file &file);
static void static_set_type(device_config *device, screen_type_enum type); void save_active_screen_snapshots();
static void static_set_raw(device_config *device, UINT32 pixclock, UINT16 htotal, UINT16 hbend, UINT16 hbstart, UINT16 vtotal, UINT16 vbend, UINT16 vbstart);
static void static_set_refresh(device_config *device, attoseconds_t rate); // movies
static void static_set_vblank_time(device_config *device, attoseconds_t time); void begin_recording(const char *name, movie_format format = MF_AVI);
static void static_set_size(device_config *device, UINT16 width, UINT16 height); void end_recording();
static void static_set_visarea(device_config *device, INT16 minx, INT16 maxx, INT16 miny, INT16 maxy); void add_sound_to_recording(const INT16 *sound, int numsamples);
static void static_set_default_position(device_config *device, double xscale, double xoffs, double yscale, double yoffs);
private: private:
// device_config overrides
virtual bool device_validity_check(const game_driver &driver) const;
// inline configuration data
screen_type_enum m_type; // type of screen
int m_width, m_height; // default total width/height (HTOTAL, VTOTAL)
rectangle m_visarea; // default visible area (HBLANK end/start, VBLANK end/start)
bool m_oldstyle_vblank_supplied; // MDRV_SCREEN_VBLANK_TIME macro used
attoseconds_t m_refresh; // default refresh period
attoseconds_t m_vblank; // duration of a VBLANK
bitmap_format m_format; // bitmap format
float m_xoffset, m_yoffset; // default X/Y offsets
float m_xscale, m_yscale; // default X/Y scale factor
};
// ======================> screen_device
class screen_device : public device_t
{
friend class screen_device_config;
friend class render_manager;
friend resource_pool_object<screen_device>::~resource_pool_object();
// construction/destruction
screen_device(running_machine &_machine, const screen_device_config &config);
virtual ~screen_device();
public:
// information getters
const screen_device_config &config() const { return m_config; }
screen_type_enum screen_type() const { return m_config.m_type; }
int width() const { return m_width; }
int height() const { return m_height; }
const rectangle &visible_area() const { return m_visarea; }
bitmap_format format() const { return m_config.m_format; }
render_container &container() const { assert(m_container != NULL); return *m_container; }
// dynamic configuration
void configure(int width, int height, const rectangle &visarea, attoseconds_t frame_period);
void reset_origin(int beamy = 0, int beamx = 0);
void set_visible_area(int min_x, int max_x, int min_y, int max_y);
// beam positioning and state
int vpos() const;
int hpos() const;
bool vblank() const { return attotime_compare(timer_get_time(machine), m_vblank_end_time) < 0; }
bool hblank() const { int curpos = hpos(); return (curpos < m_visarea.min_x || curpos > m_visarea.max_x); }
// timing
attotime time_until_pos(int vpos, int hpos = 0) const;
attotime time_until_vblank_start() const { return time_until_pos(m_visarea.max_y + 1); }
attotime time_until_vblank_end() const;
attotime time_until_update() const { return (machine->config->m_video_attributes & VIDEO_UPDATE_AFTER_VBLANK) ? time_until_vblank_end() : time_until_vblank_start(); }
attotime scan_period() const { return attotime_make(0, m_scantime); }
attotime frame_period() const { return (this == NULL || !started()) ? k_default_frame_period : attotime_make(0, m_frame_period); };
UINT64 frame_number() const { return m_frame_number; }
// updating
bool update_partial(int scanline);
void update_now();
// additional helpers
void save_snapshot(mame_file *fp);
void register_vblank_callback(vblank_state_changed_func vblank_callback, void *param);
bitmap_t *alloc_compatible_bitmap(int width = 0, int height = 0) { return auto_bitmap_alloc(machine, (width == 0) ? m_width : width, (height == 0) ? m_height : height, m_config.m_format); }
// internal to the video system
bool update_quads();
void update_burnin();
// globally accessible constants
static const int k_default_frame_rate = 60;
static const attotime k_default_frame_period;
private:
// device-level overrides
virtual void device_start();
virtual void device_post_load();
// internal helpers // internal helpers
void set_container(render_container &container) { m_container = &container; } void init_buffered_spriteram();
void realloc_screen_bitmaps(); static void exit_static(running_machine &machine);
void exit();
static TIMER_CALLBACK( screenless_update_callback );
void postload();
// effective value helpers
int effective_autoframeskip() const;
int effective_frameskip() const;
bool effective_throttle() const;
// speed and throttling helpers
int original_speed_setting() const;
bool finish_screen_updates();
void update_throttle(attotime emutime);
osd_ticks_t throttle_until_ticks(osd_ticks_t target_ticks);
void update_frameskip();
void update_refresh_speed();
void recompute_speed(attotime emutime);
static TIMER_CALLBACK( static_vblank_begin_callback ) { reinterpret_cast<screen_device *>(ptr)->vblank_begin_callback(); } // snapshot/movie helpers
void vblank_begin_callback(); void create_snapshot_bitmap(device_t *screen);
file_error mame_fopen_next(const char *pathoption, const char *extension, mame_file *&file);
static TIMER_CALLBACK( static_vblank_end_callback ) { reinterpret_cast<screen_device *>(ptr)->vblank_end_callback(); } void record_frame();
void vblank_end_callback();
static TIMER_CALLBACK( static_scanline0_callback ) { reinterpret_cast<screen_device *>(ptr)->scanline0_callback(); }
public: // temporary
void scanline0_callback();
private:
static TIMER_CALLBACK( static_scanline_update_callback ) { reinterpret_cast<screen_device *>(ptr)->scanline_update_callback(param); }
void scanline_update_callback(int scanline);
void finalize_burnin();
void load_effect_overlay(const char *filename);
// internal state // internal state
const screen_device_config &m_config; running_machine & m_machine; // reference to our machine
render_container * m_container; // pointer to our container
// screenless systems
emu_timer * m_screenless_frame_timer; // timer to signal VBLANK start
// dimensions // throttling calculations
int m_width; // current width (HTOTAL) osd_ticks_t m_throttle_last_ticks; // osd_ticks the last call to throttle
int m_height; // current height (VTOTAL) attotime m_throttle_realtime; // real time the last call to throttle
rectangle m_visarea; // current visible area (HBLANK end/start, VBLANK end/start) attotime m_throttle_emutime; // emulated time the last call to throttle
UINT32 m_throttle_history; // history of frames where we were fast enough
// textures and bitmaps // dynamic speed computation
render_texture * m_texture[2]; // 2x textures for the screen bitmap osd_ticks_t m_speed_last_realtime; // real time at the last speed calculation
bitmap_t * m_bitmap[2]; // 2x bitmaps for rendering attotime m_speed_last_emutime; // emulated time at the last speed calculation
bitmap_t * m_burnin; // burn-in bitmap double m_speed_percent; // most recent speed percentage
UINT8 m_curbitmap; // current bitmap index
UINT8 m_curtexture; // current texture index
INT32 m_texture_format; // texture format of bitmap for this screen
bool m_changed; // has this bitmap changed?
INT32 m_last_partial_scan; // scanline of last partial update
bitmap_t * m_screen_overlay_bitmap;// screen overlay bitmap
// screen timing // overall speed computation
attoseconds_t m_frame_period; // attoseconds per frame UINT32 m_overall_real_seconds; // accumulated real seconds at normal speed
attoseconds_t m_scantime; // attoseconds per scanline osd_ticks_t m_overall_real_ticks; // accumulated real ticks at normal speed
attoseconds_t m_pixeltime; // attoseconds per pixel attotime m_overall_emutime; // accumulated emulated time at normal speed
attoseconds_t m_vblank_period; // attoseconds per VBLANK period UINT32 m_overall_valid_counter; // number of consecutive valid time periods
attotime m_vblank_start_time; // time of last VBLANK start
attotime m_vblank_end_time; // time of last VBLANK end
emu_timer * m_vblank_begin_timer; // timer to signal VBLANK start
emu_timer * m_vblank_end_timer; // timer to signal VBLANK end
emu_timer * m_scanline0_timer; // scanline 0 timer
emu_timer * m_scanline_timer; // scanline timer
UINT64 m_frame_number; // the current frame number
struct callback_item // configuration
{ bool m_throttle; // flag: TRUE if we're currently throttled
callback_item * m_next; bool m_fastforward; // flag: TRUE if we're currently fast-forwarding
vblank_state_changed_func m_callback; UINT32 m_seconds_to_run; // number of seconds to run before quitting
void * m_param; bool m_auto_frameskip; // flag: TRUE if we're automatically frameskipping
}; UINT32 m_speed; // overall speed (*100)
callback_item * m_callback_list; // list of VBLANK callbacks
// frameskipping
UINT8 m_empty_skip_count; // number of empty frames we have skipped
UINT8 m_frameskip_level; // current frameskip level
UINT8 m_frameskip_counter; // counter that counts through the frameskip steps
INT8 m_frameskip_adjust;
bool m_skipping_this_frame; // flag: TRUE if we are skipping the current frame
osd_ticks_t m_average_oversleep; // average number of ticks the OSD oversleeps
// snapshot stuff
render_target * m_snap_target; // screen shapshot target
bitmap_t * m_snap_bitmap; // screen snapshot bitmap
bool m_snap_native; // are we using native per-screen layouts?
INT32 m_snap_width; // width of snapshots (0 == auto)
INT32 m_snap_height; // height of snapshots (0 == auto)
// movie recording
mame_file * m_mngfile; // handle to the open movie file
avi_file * m_avifile; // handle to the open movie file
attotime m_movie_frame_period; // period of a single movie frame
attotime m_movie_next_frame_time; // time of next frame
UINT32 m_movie_frame; // current movie frame number
static const UINT8 s_skiptable[FRAMESKIP_LEVELS][FRAMESKIP_LEVELS];
static const attoseconds_t SUBSECONDS_PER_SPEED_UPDATE = ATTOSECONDS_PER_SECOND / 4;
static const int PAUSED_REFRESH_RATE = 30;
}; };
// device type definition
extern const device_type SCREEN;
// ----- debugging helpers -----
// assert if any pixels in the given bitmap contain an invalid palette index
//**************************************************************************
// SCREEN DEVICE CONFIGURATION MACROS
//**************************************************************************
#define MDRV_SCREEN_ADD(_tag, _type) \
MDRV_DEVICE_ADD(_tag, SCREEN, 0) \
MDRV_SCREEN_TYPE(_type) \
#define MDRV_SCREEN_MODIFY(_tag) \
MDRV_DEVICE_MODIFY(_tag)
#define MDRV_SCREEN_FORMAT(_format) \
screen_device_config::static_set_format(device, _format); \
#define MDRV_SCREEN_TYPE(_type) \
screen_device_config::static_set_type(device, SCREEN_TYPE_##_type); \
#define MDRV_SCREEN_RAW_PARAMS(_pixclock, _htotal, _hbend, _hbstart, _vtotal, _vbend, _vbstart) \
screen_device_config::static_set_raw(device, _pixclock, _htotal, _hbend, _hbstart, _vtotal, _vbend, _vbstart);
#define MDRV_SCREEN_REFRESH_RATE(_rate) \
screen_device_config::static_set_refresh(device, HZ_TO_ATTOSECONDS(_rate)); \
#define MDRV_SCREEN_VBLANK_TIME(_time) \
screen_device_config::static_set_vblank_time(device, _time); \
#define MDRV_SCREEN_SIZE(_width, _height) \
screen_device_config::static_set_size(device, _width, _height); \
#define MDRV_SCREEN_VISIBLE_AREA(_minx, _maxx, _miny, _maxy) \
screen_device_config::static_set_visarea(device, _minx, _maxx, _miny, _maxy); \
#define MDRV_SCREEN_DEFAULT_POSITION(_xscale, _xoffs, _yscale, _yoffs) \
screen_device_config::static_set_default_position(device, _xscale, _xoffs, _yscale, _yoffs); \
//**************************************************************************
// FUNCTION PROTOTYPES
//**************************************************************************
/* ----- core implementation ----- */
/* core initialization */
void video_init(running_machine *machine);
/* ----- global rendering ----- */
/* update the screen, handling frame skipping and rendering */
void video_frame_update(running_machine *machine, int debug);
/* ----- throttling/frameskipping/performance ----- */
/* are we skipping the current frame? */
int video_skip_this_frame(void);
/* get/set the speed factor as an integer * 100 */
int video_get_speed_factor(void);
void video_set_speed_factor(int speed);
/* return text to display about the current speed */
const char *video_get_speed_text(running_machine *machine);
/* return the current effective speed percentage */
double video_get_speed_percent(running_machine *machine);
/* get/set the current frameskip (-1 means auto) */
int video_get_frameskip(void);
void video_set_frameskip(int frameskip);
/* get/set the current throttle */
int video_get_throttle(void);
void video_set_throttle(int throttle);
/* get/set the current fastforward state */
int video_get_fastforward(void);
void video_set_fastforward(int fastforward);
/* ----- snapshots ----- */
/* save a snapshot of a given screen */
void screen_save_snapshot(running_machine *machine, device_t *screen, mame_file *fp);
/* save a snapshot of all the active screens */
void video_save_active_screen_snapshots(running_machine *machine);
/* ----- movie recording ----- */
int video_mng_is_movie_active(running_machine *machine);
void video_mng_begin_recording(running_machine *machine, const char *name);
void video_mng_end_recording(running_machine *machine);
void video_avi_begin_recording(running_machine *machine, const char *name);
void video_avi_end_recording(running_machine *machine);
void video_avi_add_sound(running_machine *machine, const INT16 *sound, int numsamples);
/* ----- configuration helpers ----- */
/* select a view for a given target */
int video_get_view_for_target(running_machine *machine, render_target *target, const char *viewname, int targetindex, int numtargets);
/* ----- debugging helpers ----- */
/* assert if any pixels in the given bitmap contain an invalid palette index */
void video_assert_out_of_range_pixels(running_machine *machine, bitmap_t *bitmap); void video_assert_out_of_range_pixels(running_machine *machine, bitmap_t *bitmap);
//**************************************************************************
// INLINE HELPERS
//**************************************************************************
//-------------------------------------------------
// screen_count - return the number of
// video screen devices in a machine_config
//-------------------------------------------------
inline int screen_count(const machine_config &config)
{
return config.m_devicelist.count(SCREEN);
}
//-------------------------------------------------
// screen_first - return the first
// video screen device config in a machine_config
//-------------------------------------------------
inline const screen_device_config *screen_first(const machine_config &config)
{
return downcast<screen_device_config *>(config.m_devicelist.first(SCREEN));
}
//-------------------------------------------------
// screen_next - return the next
// video screen device config in a machine_config
//-------------------------------------------------
inline const screen_device_config *screen_next(const screen_device_config *previous)
{
return downcast<screen_device_config *>(previous->typenext());
}
//-------------------------------------------------
// screen_count - return the number of
// video screen devices in a machine
//-------------------------------------------------
inline int screen_count(running_machine &machine)
{
return machine.m_devicelist.count(SCREEN);
}
//-------------------------------------------------
// screen_first - return the first
// video screen device in a machine
//-------------------------------------------------
inline screen_device *screen_first(running_machine &machine)
{
return downcast<screen_device *>(machine.m_devicelist.first(SCREEN));
}
//-------------------------------------------------
// screen_next - return the next
// video screen device in a machine
//-------------------------------------------------
inline screen_device *screen_next(screen_device *previous)
{
return downcast<screen_device *>(previous->typenext());
}
#endif /* __VIDEO_H__ */ #endif /* __VIDEO_H__ */

View File

@ -435,7 +435,7 @@ int TMS9928A_interrupt(running_machine *machine) {
int b; int b;
/* when skipping frames, calculate sprite collision */ /* when skipping frames, calculate sprite collision */
if (video_skip_this_frame() ) { if (machine->video().skip_this_frame()) {
if (TMS_SPRITES_ENABLED) { if (TMS_SPRITES_ENABLED) {
draw_sprites (machine->primary_screen, NULL, NULL); draw_sprites (machine->primary_screen, NULL, NULL);
} }

View File

@ -115,8 +115,8 @@ void atarigen_init(running_machine *machine)
int i; int i;
/* allocate timers for all screens */ /* allocate timers for all screens */
assert(screen_count(*machine) <= ARRAY_LENGTH(state->screen_timer)); assert(machine->m_devicelist.count(SCREEN) <= ARRAY_LENGTH(state->screen_timer));
for (i = 0, screen = screen_first(*machine); screen != NULL; i++, screen = screen_next(screen)) for (i = 0, screen = machine->first_screen(); screen != NULL; i++, screen = screen->next_screen())
{ {
state->screen_timer[i].screen = screen; state->screen_timer[i].screen = screen;
state->screen_timer[i].scanline_interrupt_timer = timer_alloc(machine, scanline_interrupt_callback, (void *)screen); state->screen_timer[i].scanline_interrupt_timer = timer_alloc(machine, scanline_interrupt_callback, (void *)screen);

View File

@ -1743,7 +1743,7 @@ void cave_get_sprite_info( running_machine *machine )
cave_state *state = machine->driver_data<cave_state>(); cave_state *state = machine->driver_data<cave_state>();
if (state->kludge == 3) /* mazinger metmqstr */ if (state->kludge == 3) /* mazinger metmqstr */
{ {
if (video_skip_this_frame() == 0) if (machine->video().skip_this_frame() == 0)
{ {
state->spriteram_bank = state->spriteram_bank_delay; state->spriteram_bank = state->spriteram_bank_delay;
(*state->get_sprite_info)(machine); (*state->get_sprite_info)(machine);
@ -1752,7 +1752,7 @@ void cave_get_sprite_info( running_machine *machine )
} }
else else
{ {
if (video_skip_this_frame() == 0) if (machine->video().skip_this_frame() == 0)
{ {
state->spriteram_bank = state->videoregs[4] & 1; state->spriteram_bank = state->videoregs[4] & 1;
(*state->get_sprite_info)(machine); (*state->get_sprite_info)(machine);

View File

@ -268,7 +268,7 @@ void cyberbal_scanline_update(screen_device &screen, int scanline)
screen_device *update_screen; screen_device *update_screen;
/* loop over screens */ /* loop over screens */
for (i = 0, update_screen = screen_first(*screen.machine); update_screen != NULL; i++, update_screen = screen_next(update_screen)) for (i = 0, update_screen = screen.machine->first_screen(); update_screen != NULL; i++, update_screen = update_screen->next_screen())
{ {
UINT16 *vram = i ? state->alpha2 : state->alpha; UINT16 *vram = i ? state->alpha2 : state->alpha;
UINT16 *base = &vram[((scanline - 8) / 8) * 64 + 47]; UINT16 *base = &vram[((scanline - 8) / 8) * 64 + 47];

View File

@ -404,7 +404,7 @@ WRITE32_HANDLER( gaelco3d_render_w )
fatalerror("Out of polygon buffer space!"); fatalerror("Out of polygon buffer space!");
/* if we've accumulated a completed poly set of data, queue it */ /* if we've accumulated a completed poly set of data, queue it */
if (!video_skip_this_frame()) if (!space->machine->video().skip_this_frame())
{ {
if (polydata_count >= 18 && (polydata_count % 2) == 1 && IS_POLYEND(polydata_buffer[polydata_count - 2])) if (polydata_count >= 18 && (polydata_count % 2) == 1 && IS_POLYEND(polydata_buffer[polydata_count - 2]))
{ {

View File

@ -581,7 +581,7 @@ VIDEO_EOF( f3 )
{ {
if (sprite_lag==2) if (sprite_lag==2)
{ {
if (video_skip_this_frame() == 0) if (machine->video().skip_this_frame() == 0)
{ {
get_sprite_info(machine, spriteram32_buffered); get_sprite_info(machine, spriteram32_buffered);
} }
@ -589,7 +589,7 @@ VIDEO_EOF( f3 )
} }
else if (sprite_lag==1) else if (sprite_lag==1)
{ {
if (video_skip_this_frame() == 0) if (machine->video().skip_this_frame() == 0)
{ {
get_sprite_info(machine, machine->generic.spriteram.u32); get_sprite_info(machine, machine->generic.spriteram.u32);
} }

View File

@ -1207,7 +1207,7 @@ static int drawogl_window_draw(sdl_window_info *window, UINT32 dc, int update)
// figure out if we're vector // figure out if we're vector
scrnum = is_vector = 0; scrnum = is_vector = 0;
for (screen = screen_first(*window->machine->config); screen != NULL; screen = screen_next(screen)) for (screen = window->machine->config->first_screen(); screen != NULL; screen = screen->next_screen())
{ {
if (scrnum == window->index) if (scrnum == window->index)
{ {
@ -2944,7 +2944,7 @@ static void texture_shader_update(sdl_window_info *window, texture_info *texture
scrnum = 0; scrnum = 0;
container = (render_container *)NULL; container = (render_container *)NULL;
for (screen_device *screen = screen_first(*window->machine); screen != NULL; screen = screen_next(screen)) for (screen_device *screen = window->machine->first_screen(); screen != NULL; screen = screen->next_screen())
{ {
if (scrnum == window->start_viewscreen) if (scrnum == window->start_viewscreen)
{ {

View File

@ -130,13 +130,13 @@ static void sdl_cleanup_audio(running_machine &machine)
//============================================================ //============================================================
// lock_buffer // lock_buffer
//============================================================ //============================================================
static int lock_buffer(long offset, long size, void **buffer1, long *length1, void **buffer2, long *length2) static int lock_buffer(running_machine &machine, long offset, long size, void **buffer1, long *length1, void **buffer2, long *length2)
{ {
volatile long pstart, pend, lstart, lend; volatile long pstart, pend, lstart, lend;
if (!buf_locked) if (!buf_locked)
{ {
if (video_get_throttle()) if (machine.video().throttled())
{ {
pstart = stream_playpos; pstart = stream_playpos;
pend = (pstart + sdl_xfer_samples); pend = (pstart + sdl_xfer_samples);
@ -213,14 +213,14 @@ static void att_memcpy(void *dest, const INT16 *data, int bytes_to_copy)
// copy_sample_data // copy_sample_data
//============================================================ //============================================================
static void copy_sample_data(const INT16 *data, int bytes_to_copy) static void copy_sample_data(running_machine &machine, const INT16 *data, int bytes_to_copy)
{ {
void *buffer1, *buffer2 = (void *)NULL; void *buffer1, *buffer2 = (void *)NULL;
long length1, length2; long length1, length2;
int cur_bytes; int cur_bytes;
// attempt to lock the stream buffer // attempt to lock the stream buffer
if (lock_buffer(stream_buffer_in, bytes_to_copy, &buffer1, &length1, &buffer2, &length2) < 0) if (lock_buffer(machine, stream_buffer_in, bytes_to_copy, &buffer1, &length1, &buffer2, &length2) < 0)
{ {
buffer_underflows++; buffer_underflows++;
return; return;
@ -333,7 +333,7 @@ void sdl_osd_interface::update_audio_stream(const INT16 *buffer, int samples_thi
// now we know where to copy; let's do it // now we know where to copy; let's do it
stream_buffer_in = stream_in; stream_buffer_in = stream_in;
copy_sample_data(buffer, bytes_this_frame); copy_sample_data(machine(), buffer, bytes_this_frame);
} }
} }

View File

@ -1017,7 +1017,7 @@ static void set_starting_view(running_machine *machine, int index, sdl_window_in
view = defview; view = defview;
// query the video system to help us pick a view // query the video system to help us pick a view
viewindex = video_get_view_for_target(machine, window->target, view, index, video_config.numscreens); viewindex = window->target->configured_view(view, index, video_config.numscreens);
// set the view // set the view
window->target->set_view(viewindex); window->target->set_view(viewindex);

View File

@ -1283,7 +1283,7 @@ static void pick_best_mode(win_window_info *window)
int modenum; int modenum;
// determine the refresh rate of the primary screen // determine the refresh rate of the primary screen
const screen_device_config *primary_screen = screen_first(*window->machine->config); const screen_device_config *primary_screen = window->machine->config->first_screen();
if (primary_screen != NULL) if (primary_screen != NULL)
target_refresh = ATTOSECONDS_TO_HZ(primary_screen->refresh()); target_refresh = ATTOSECONDS_TO_HZ(primary_screen->refresh());

View File

@ -457,7 +457,7 @@ static int drawdd_window_draw(win_window_info *window, HDC dc, int update)
if (result != DD_OK) mame_printf_verbose("DirectDraw: Error %08X unlocking blit surface\n", (int)result); if (result != DD_OK) mame_printf_verbose("DirectDraw: Error %08X unlocking blit surface\n", (int)result);
// sync to VBLANK // sync to VBLANK
if ((video_config.waitvsync || video_config.syncrefresh) && video_get_throttle() && (!window->fullscreen || dd->back == NULL)) if ((video_config.waitvsync || video_config.syncrefresh) && window->machine->video().throttled() && (!window->fullscreen || dd->back == NULL))
{ {
result = IDirectDraw7_WaitForVerticalBlank(dd->ddraw, DDWAITVB_BLOCKBEGIN, NULL); result = IDirectDraw7_WaitForVerticalBlank(dd->ddraw, DDWAITVB_BLOCKBEGIN, NULL);
if (result != DD_OK) mame_printf_verbose("DirectDraw: Error %08X waiting for VBLANK\n", (int)result); if (result != DD_OK) mame_printf_verbose("DirectDraw: Error %08X waiting for VBLANK\n", (int)result);
@ -1333,7 +1333,7 @@ static void pick_best_mode(win_window_info *window)
// determine the refresh rate of the primary screen // determine the refresh rate of the primary screen
einfo.target_refresh = 60.0; einfo.target_refresh = 60.0;
const screen_device_config *primary_screen = screen_first(*window->machine->config); const screen_device_config *primary_screen = window->machine->config->first_screen();
if (primary_screen != NULL) if (primary_screen != NULL)
einfo.target_refresh = ATTOSECONDS_TO_HZ(primary_screen->refresh()); einfo.target_refresh = ATTOSECONDS_TO_HZ(primary_screen->refresh());
printf("Target refresh = %f\n", einfo.target_refresh); printf("Target refresh = %f\n", einfo.target_refresh);

View File

@ -753,7 +753,7 @@ void winwindow_video_window_update(win_window_info *window)
mtlog_add("winwindow_video_window_update: try lock"); mtlog_add("winwindow_video_window_update: try lock");
// only block if we're throttled // only block if we're throttled
if (video_get_throttle() || timeGetTime() - last_update_time > 250) if (window->machine->video().throttled() || timeGetTime() - last_update_time > 250)
osd_lock_acquire(window->render_lock); osd_lock_acquire(window->render_lock);
else else
got_lock = osd_lock_try(window->render_lock); got_lock = osd_lock_try(window->render_lock);
@ -868,7 +868,7 @@ static void set_starting_view(int index, win_window_info *window, const char *vi
view = defview; view = defview;
// query the video system to help us pick a view // query the video system to help us pick a view
viewindex = video_get_view_for_target(window->machine, window->target, view, index, video_config.numscreens); viewindex = window->target->configured_view(view, index, video_config.numscreens);
// set the view // set the view
window->target->set_view(viewindex); window->target->set_view(viewindex);