summaryrefslogblamecommitdiffstatshomepage
path: root/src/emu/video.h
blob: 5ccfe2b99b065af1687bd088aec0abb14953d954 (plain) (tree)
1
2
3
4
5
6
7
8

                                





                                                                            



                                                                            



                                                              



                        
 
 


                                                                            
 
                                              

                                                   
 
 


                                                                            
 
                                        
 
                   

                                   
 
       





                               

                                   
                                                
 
                  
                                                              


                                                                                   
                                                      
                                                               
                                                          
                                  

                  
                                          
                                                                              
                                                                                        
                                                                        
                                                              
 

                               



                                                                                             

                                                            
 
                         
                                                      
 
                                
                                 
                                                                
                                        
 
                    
                                                                  
                                            
                                   
 
                 
                                                                    

                                                                                          
                                                

                                               
                                                                      
                                                                                          
 








                                                                             
 
        
                           
                    
                                                              
                        
 
                                  
                                             
                                        
 






                                                                   
                                                      

                                 
                                                           
                            

                         
                                                                                   
 
                             

                                                                                        

                                  


                                                                                                  
                                                                                                      

                                    


                                                                                                      

                                    
                                                                                                   

                                                                                                    
                                                                                                   

                        
                                                                                                  
                                                                                     
                                                                                                        
                                                                                                   
                                                                                                          
                                                                                
                                                                                                         

                        



                                                                                                          
                                                                                                          
                                                                                                     

                         


                                                                                                  

                                                                                          
 
                                












                                                                                                   
                                       
 
                                













                                                                                                 
                                       
 
                                                                            
 
                                                                                             
                                                  
 




                                                                                                                         

  
                          
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    video.h

    Core MAME video routines.

***************************************************************************/

#pragma once

#ifndef __EMU_H__
#error Dont include this file directly; include emu.h instead.
#endif

#ifndef MAME_EMU_VIDEO_H
#define MAME_EMU_VIDEO_H

#include "aviio.h"


//**************************************************************************
//  CONSTANTS
//**************************************************************************

// number of levels of frameskipping supported
constexpr int FRAMESKIP_LEVELS = 12;
constexpr int MAX_FRAMESKIP = FRAMESKIP_LEVELS - 2;


//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************

// ======================> video_manager

class video_manager
{
	friend class screen_device;

public:
	// movie format options
	enum movie_format
	{
		MF_MNG,
		MF_AVI
	};

	// construction/destruction
	video_manager(running_machine &machine);

	// getters
	running_machine &machine() const { return m_machine; }
	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_throttled; }
	float throttle_rate() const { return m_throttle_rate; }
	bool fastforward() const { return m_fastforward; }
	bool is_recording() const;

	// setters
	void set_frameskip(int frameskip);
	void set_throttled(bool throttled = true) { m_throttled = throttled; }
	void set_throttle_rate(float throttle_rate) { m_throttle_rate = throttle_rate; }
	void set_fastforward(bool ffwd = true) { m_fastforward = ffwd; }
	void set_output_changed() { m_output_changed = true; }

	// misc
	void toggle_throttle();
	void toggle_record_movie(movie_format format);
	void toggle_record_mng() { toggle_record_movie(MF_MNG); }
	void toggle_record_avi() { toggle_record_movie(MF_AVI); }
	osd_file::error open_next(emu_file &file, const char *extension, uint32_t index = 0);
	void compute_snapshot_size(s32 &width, s32 &height);
	void pixels(u32 *buffer);

	// render a frame
	void frame_update(bool from_debugger = false);

	// current speed helpers
	std::string speed_text();
	double speed_percent() const { return m_speed_percent; }
	int effective_frameskip() const;

	// snapshots
	void save_snapshot(screen_device *screen, emu_file &file);
	void save_active_screen_snapshots();
	void save_input_timecode();

	// movies
	void begin_recording(const char *name, movie_format format);
	void begin_recording_mng(const char *name, uint32_t index, screen_device *screen);
	void begin_recording_avi(const char *name, uint32_t index, screen_device *screen);
	void end_recording(movie_format format);
	void end_recording_mng(uint32_t index);
	void end_recording_avi(uint32_t index);
	void add_sound_to_recording(const s16 *sound, int numsamples);
	void add_sound_to_avi_recording(const s16 *sound, int numsamples, uint32_t index);

	void set_timecode_enabled(bool value) { m_timecode_enabled = value; }
	bool get_timecode_enabled() { return m_timecode_enabled; }
	bool get_timecode_write() { return m_timecode_write; }
	void set_timecode_write(bool value) { m_timecode_write = value; }
	void set_timecode_text(std::string &str) { m_timecode_text = str; }
	void set_timecode_start(attotime time) { m_timecode_start = time; }
	void add_to_total_time(attotime time) { m_timecode_total += time; }
	std::string &timecode_text(std::string &str);
	std::string &timecode_total_text(std::string &str);

private:
	// internal helpers
	void exit();
	void screenless_update_callback(void *ptr, int param);
	void postload();

	// effective value helpers
	bool effective_autoframeskip() 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(const attotime &emutime);

	// snapshot/movie helpers
	void create_snapshot_bitmap(screen_device *screen);
	void record_frame();

	// internal state
	running_machine &   m_machine;                  // reference to our machine

	// screenless systems
	emu_timer *         m_screenless_frame_timer;   // timer to signal VBLANK start
	bool                m_output_changed;           // did an output element change?

	// throttling calculations
	osd_ticks_t         m_throttle_last_ticks;      // osd_ticks the last call to throttle
	attotime            m_throttle_realtime;        // real time the last call to throttle
	attotime            m_throttle_emutime;         // emulated time the last call to throttle
	u32                 m_throttle_history;         // history of frames where we were fast enough

	// dynamic speed computation
	osd_ticks_t         m_speed_last_realtime;      // real time at the last speed calculation
	attotime            m_speed_last_emutime;       // emulated time at the last speed calculation
	double              m_speed_percent;            // most recent speed percentage

	// overall speed computation
	u32                 m_overall_real_seconds;     // accumulated real seconds at normal speed
	osd_ticks_t         m_overall_real_ticks;       // accumulated real ticks at normal speed
	attotime            m_overall_emutime;          // accumulated emulated time at normal speed
	u32                 m_overall_valid_counter;    // number of consecutive valid time periods

	// configuration
	bool                m_throttled;                // flag: true if we're currently throttled
	float               m_throttle_rate;            // target rate for throttling
	bool                m_fastforward;              // flag: true if we're currently fast-forwarding
	u32                 m_seconds_to_run;           // number of seconds to run before quitting
	bool                m_auto_frameskip;           // flag: true if we're automatically frameskipping
	u32                 m_speed;                    // overall speed (*1000)
	bool                m_low_latency;              // flag: true if we are throttling after blitting

	// frameskipping
	u8                  m_empty_skip_count;         // number of empty frames we have skipped
	u8                  m_frameskip_level;          // current frameskip level
	u8                  m_frameskip_counter;        // counter that counts through the frameskip steps
	s8                  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_rgb32        m_snap_bitmap;              // screen snapshot bitmap
	bool                m_snap_native;              // are we using native per-screen layouts?
	s32                 m_snap_width;               // width of snapshots (0 == auto)
	s32                 m_snap_height;              // height of snapshots (0 == auto)

	// movie recording - MNG
	class mng_info_t
	{
	public:
		mng_info_t()
			: m_mng_frame_period(attotime::zero)
			, m_mng_next_frame_time(attotime::zero)
			, m_mng_frame(0) { }

		std::unique_ptr<emu_file> m_mng_file;              // handle to the open movie file
		attotime            m_mng_frame_period;         // period of a single movie frame
		attotime            m_mng_next_frame_time;      // time of next frame
		u32                 m_mng_frame;                // current movie frame number
	};
	std::vector<mng_info_t> m_mngs;

	// movie recording - AVI
	class avi_info_t
	{
	public:
		avi_info_t()
			: m_avi_file(nullptr)
			, m_avi_frame_period(attotime::zero)
			, m_avi_next_frame_time(attotime::zero)
			, m_avi_frame(0) { }

		avi_file::ptr       m_avi_file;                 // handle to the open movie file
		attotime            m_avi_frame_period;         // period of a single movie frame
		attotime            m_avi_next_frame_time;      // time of next frame
		u32                 m_avi_frame;                // current movie frame number
	};
	std::vector<avi_info_t> m_avis;

	static const bool   s_skiptable[FRAMESKIP_LEVELS][FRAMESKIP_LEVELS];

	static const attoseconds_t ATTOSECONDS_PER_SPEED_UPDATE = ATTOSECONDS_PER_SECOND / 4;
	static const int PAUSED_REFRESH_RATE = 30;

	bool                m_timecode_enabled;     // inp.timecode record enabled
	bool                m_timecode_write;       // Show/hide timer at right (partial time)
	std::string         m_timecode_text;        // Message for that video part (intro, gameplay, extra)
	attotime            m_timecode_start;       // Starting timer for that video part (intro, gameplay, extra)
	attotime            m_timecode_total;       // Show/hide timer at left (total elapsed on resulting video preview)
};

#endif // MAME_EMU_VIDEO_H