summaryrefslogblamecommitdiffstatshomepage
path: root/src/devices/video/mc6847.h
blob: b82c014e5b06801ce069424ee389ecb459911703 (plain) (tree)
1
2
3
4
5
6
7
8
9

                                 






                                                                            

                           


            
                   
              




                                                                            
                                                                              
 
 
                                         







                                                                            
                                                                
                                                                           

       











                                                                                      
                  

                                                       
 

                                                                 
 
                                                                                                                    
 
          
                                                                                                                               

                                                                                                                                  
 
                

                                                   


                                                          
                                       

                            
                                 


                                                                
                                         

         
                                                                









                                                                                      
                                                                         


                                                                            
                                                                                                                                                             



                                                        
                                                            

                                                                                  
                                                                                         

                                                                          
                                                                                                                       

                                                               
                                                                                      

                                                     

                                                                                                                                    











                                                                                                                                       
                 



                            







                                                  





                                                                                 


                                                                  
                                          

                                                             
                                                                                                             




                                                                          
                                     






                                                    
                                   


                                                                                                      


                                          

                                                                                                                                     




                                                                                           

                                                                                     















                                                                                                                                  

                                    
                                                                                                               













                                                                                                                   
                                                                                                      




                                                                                                           














                                                                                         
                                      





                                                 
                                                    
                                                                                
 
                                                           
                                                                                

          
                    

                                         
 

                                                                                    
                                           
 



                                      
                                 
                                             

                                                 

                             
                                 
                                                               
                                                   
                                           
                                                                        
                                                                                                          
                                                                                                                                                     

                        
                           
                                             
 
                          
                                                   
         
                                                                                
                                                                          


                               
                                                                                                              











                                                                               
                                                 
                                                  





















                                                                  
         


                                                        
                                                                                                                                                             






                                                                      
                                                                                                                                                  





                                                                                                             

                                                
                                                                                                                                                             






                                                                      
                                                                                        





                                                                                                             

                                                 
                                                                                                                                              
                                                                                
         
                                






























                                                                                                                                
                                                                            


                                              
                                                                                                           



                                                        
                                                                                                               
                                                                                                                         











                                                                                                       







                                            


                 



                                     



                            
                      
                            
                                                     

                             

                                        
                                  
                                                     
 






                                             
                      


                                         

                               
                                           

                    

                                                              

                                       
                                         

                    
                                                                   




                                                            





                                                      
                                                           
 

                                                                      
 
                                                               
                                                                
                                                
                                                                                                       

                                   







                                                                       
 


                                                                                                          
          
                                                                                                                                                                              
 
                                 
                                                       


                                                                       

                          
                                                            
                                                                                                       
                                                                                                                                                          
 

                                                                                                                                               
         
                                                                                                       
         








                                                                                                                                           
 


                             


                                       



                                             
                                                        
 
                                                                                                                         
                               


                                              

                      

                                  



                                             

                                 
                     
                                   
 
                                                 
         
                                                                              

                                                        
                                     
                                 
                          
                                                 
                    





                                                    
                                      

                                     





                                               


                          
                                
 
                        

                                                                         









                                                                            
                                                                                                            




                                                   
                                                                                                           




                                                     
                                                                                                             




                                                    
                                                                                                            




                                                      
                                                                                                              




                                                                                                                                                                                

  
                                                       

       
                                                                                                             

  


                                               
                                                                                                       
 






                                                                                                                                                    

        
                                                   

  

                                                  
       
                                                                                                          

  
 

                                                      
                                                       




                                                        
 
                             
// license:BSD-3-Clause
// copyright-holders:Nathan Woods
/*********************************************************************

    mc6847.h

    Implementation of Motorola 6847 video hardware chip

***************************************************************************/
#ifndef MAME_VIDEO_MC6847_H
#define MAME_VIDEO_MC6847_H

#pragma once

#include "screen.h"
#include <map>

//**************************************************************************
//  MC6847 CONFIGURATION / INTERFACE
//**************************************************************************

#define MC6847_GET_CHARROM_MEMBER(_name)   uint8_t _name(uint8_t ch, int line)


#define ARTIFACTING_TAG     "artifacting"

INPUT_PORTS_EXTERN(mc6847_artifacting);


//**************************************************************************
//  MC6847 CORE
//**************************************************************************

// base class so that the GIME emulation can access mc6847 stuff
class mc6847_friend_device : public device_t, public device_video_interface
{
public:
	// video mode constants
	static constexpr uint8_t MODE_AG      = 0x80;
	static constexpr uint8_t MODE_GM2     = 0x40;
	static constexpr uint8_t MODE_GM1     = 0x20;
	static constexpr uint8_t MODE_GM0     = 0x10;
	static constexpr uint8_t MODE_CSS     = 0x08;
	static constexpr uint8_t MODE_AS      = 0x04;
	static constexpr uint8_t MODE_INTEXT  = 0x02;
	static constexpr uint8_t MODE_INV     = 0x01;

	typedef device_delegate<uint8_t (uint8_t ch, int line)> get_char_rom_delegate;

	// inlines
	bool hs_r() const { return m_horizontal_sync; }
	bool fs_r() const { return m_field_sync; }

	auto hsync_wr_callback() { return m_write_hsync.bind(); }
	auto fsync_wr_callback() { return m_write_fsync.bind(); }

	template <typename... T> void set_get_char_rom(T &&... args) { m_charrom_cb.set(std::forward<T>(args)...); }

protected:
	mc6847_friend_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock,
			const uint8_t *fontdata, bool is_mc6847t1, double tpfs, int field_sync_falling_edge_scanline, int divider,
			bool supports_partial_body_scanlines, bool pal);

	// fonts
	static const uint8_t vdg_t1_fontdata8x12[];
	static const uint8_t vdg_fontdata8x12[];
	static const uint8_t semigraphics4_fontdata8x12[];
	static const uint8_t semigraphics6_fontdata8x12[];
	static const uint8_t s68047_fontdata8x12[];
	static const uint8_t stripes[];

	// pixel definitions
	typedef uint32_t pixel_t;

	pixel_t *bitmap_addr(bitmap_rgb32 &bitmap, int y, int x)
	{
		return &bitmap.pix(y, x);
	}

	static uint8_t simplify_mode(uint8_t data, uint8_t mode)
	{
		// simplifies MC6847 modes to drop mode flags that are not significant
		return mode & ~((mode & MODE_AG) ? (MODE_AS | MODE_INV) : 0);
	}

	// internal class that represents a MC6847 character map
	class character_map
	{
	public:
		// constructor that sets up the font data
		character_map(const uint8_t *fontdata, bool is_mc6847t1);

		// optimized template function that emits a single character
		template<int xscale>
		ATTR_FORCE_INLINE void emit_character(uint8_t mode, const uint8_t *data, int length, pixel_t *RESTRICT pixels, int y, const pixel_t *palette)
		{
			for (int i = 0; i < length; i++)
			{
				// get the character
				uint8_t character = data[i];

				// based on the mode, determine which entry to use
				const entry *e = &m_entries[mode % std::size(m_entries)];

				// identify the character in the font data
				const uint8_t *font_character = e->m_fontdata + (character & e->m_character_mask) * 12;

				// get the particular slice out
				uint8_t font_character_slice = font_character[y % 12];

				// get the two colors
				uint16_t color_base_0 = e->m_color_base_0 + ((character >> e->m_color_shift_0) & e->m_color_mask_0);
				uint16_t color_base_1 = e->m_color_base_1 + ((character >> e->m_color_shift_1) & e->m_color_mask_1);
				pixel_t color_0 = palette[color_base_0];
				pixel_t color_1 = palette[color_base_1];

				// emit the bits
				for (int j = 0; j < 8; j++)
				{
					for (int k = 0; k < xscale; k++)
					{
						pixels[(i * 8 + j) * xscale + k] = bit_test(font_character_slice, j, color_0, color_1);
					}
				}
			}
		}

	private:
		struct entry
		{
			const uint8_t *m_fontdata;
			uint8_t m_character_mask;
			uint8_t m_color_shift_0;
			uint8_t m_color_shift_1;
			uint8_t m_color_mask_0;
			uint8_t m_color_mask_1;
			uint16_t m_color_base_0;
			uint16_t m_color_base_1;
		};

		// lookup table for MC6847 modes to determine font data and color
		entry m_entries[128];

		// text font data calculated on startup
		uint8_t m_text_fontdata_inverse[64*12];
		uint8_t m_text_fontdata_lower_case[64*12];
		uint8_t m_text_fontdata_lower_case_inverse[64*12];
		uint8_t m_stripes[128*12];

		// optimized function that tests a single bit
		ATTR_FORCE_INLINE pixel_t bit_test(uint8_t data, int shift, pixel_t color_0, pixel_t color_1)
		{
			return data & (0x80 >> shift) ? color_1 : color_0;
		}
	};

	// artificater internal class
	class artifacter
	{
	public:
		artifacter();

		// artifacting config
		void setup_config(device_t *device);
		bool poll_config();
		void set_pal_artifacting( bool palartifacting ) { m_palartifacting = palartifacting; }
		bool get_pal_artifacting() { return m_palartifacting; }
		void create_color_blend_table( const pixel_t *palette );

		// artifacting application
		template<int xscale>
		void process_artifacts_pal(bitmap_rgb32 &bitmap, int y, int base_x, int base_y, uint8_t mode, const pixel_t *palette)
		{
			if( !m_artifacting || !m_palartifacting )
				return;

			if( (mode & MODE_AS) || ((mode & (MODE_AG|MODE_GM0) ) == MODE_AG) )
			{
				pixel_t *line1 = &bitmap.pix(y + base_y, base_x);
				pixel_t *line2 = &bitmap.pix(y + base_y + 1, base_x);
				std::map<std::pair<pixel_t,pixel_t>,pixel_t>::const_iterator newColor;

				for( int pixel = 0; pixel < bitmap.width() - (base_x * 2); ++pixel )
				{
					if( line1[pixel] == line2[pixel] )
						continue;

					newColor = m_palcolorblendmap.find(std::pair<pixel_t,pixel_t>(line1[pixel],line2[pixel]));
					if( newColor != m_palcolorblendmap.end() )
					{
						line1[pixel] = newColor->second;
						line2[pixel] = newColor->second;
					}
				}
			}
		}

		template<int xscale>
		ATTR_FORCE_INLINE void process_artifacts(pixel_t *pixels, uint8_t mode, const pixel_t *palette)
		{
			if (((mode & (MODE_AG|MODE_GM2|MODE_GM1|MODE_GM0)) == (MODE_AG|MODE_GM2|MODE_GM1|MODE_GM0))
				&& (m_artifacting != 0))
			{
				// identify the new colors and update
				pixel_t c0 = palette[(mode & MODE_CSS) ? 10 : 8];
				pixel_t c1 = palette[(mode & MODE_CSS) ? 11 : 9];
				update_colors(c0, c1);

				// generate the new line
				pixel_t new_line[256];
				int x, i;
				for (x = 0; x < 256; x += 2)
				{
					uint8_t val = ((pixels[(x - 2) * xscale] == c1) ? 0x20 : 0x00)
							| ((pixels[(x - 1) * xscale] == c1) ? 0x10 : 0x00)
							| ((pixels[(x + 0) * xscale] == c1) ? 0x08 : 0x00)
							| ((pixels[(x + 1) * xscale] == c1) ? 0x04 : 0x00)
							| ((pixels[(x + 2) * xscale] == c1) ? 0x02 : 0x00)
							| ((pixels[(x + 3) * xscale] == c1) ? 0x01 : 0x00);

					new_line[x + 0] = m_expanded_colors[val * 2 + 0];
					new_line[x + 1] = m_expanded_colors[val * 2 + 1];
				}

				// and copy it in
				for (x = 0; x < 256; x++)
				{
					for (i = 0; i < xscale; i++)
						pixels[x * xscale + i] = new_line[x];
				}
			}
		}

	private:
		bool m_palartifacting;
		ioport_port *m_config;
		ioport_value m_artifacting;
		ioport_value m_saved_artifacting;
		pixel_t m_saved_c0, m_saved_c1;
		pixel_t m_expanded_colors[128];

		// PAL color blend emulation values.
		std::map<std::pair<pixel_t,pixel_t>,pixel_t> m_palcolorblendmap;

		void update_colors(pixel_t c0, pixel_t c1);
		static pixel_t mix_color(double factor, uint8_t c0, uint8_t c1);
	};

	// callbacks
	devcb_write_line   m_write_hsync;
	devcb_write_line   m_write_fsync;

	/* if specified, this reads the external char rom off of the driver state */
	// moved here from mc6847_base_device so to be useable in GIME
	get_char_rom_delegate m_charrom_cb;

	// incidentals
	character_map m_character_map;
	artifacter m_artifacter;

	// device-level overrides
	virtual void device_start() override;
	virtual void device_reset() override;
	virtual void device_post_load() override;

	// other overridables
	virtual void new_frame();
	virtual TIMER_CALLBACK_MEMBER(horizontal_sync_changed);
	virtual void field_sync_changed(bool line);
	virtual void enter_bottom_border();
	virtual void record_border_scanline(uint16_t physical_scanline);
	virtual void record_full_body_scanline(uint16_t physical_scanline, uint16_t logical_scanline) = 0;
	virtual void record_partial_body_scanline(uint16_t physical_scanline, uint16_t logical_scanline, int32_t start_clock, int32_t end_clock) = 0;

	// miscellaneous
	void video_flush();
	std::string describe_context() const;

	// converts to B&W
	static pixel_t black_and_white(rgb_t color)
	{
		uint8_t average_color = (color.r() + color.g() + color.b()) / 3;
		return rgb_t(average_color, average_color, average_color);
	}

	// changes the geometry
	ATTR_FORCE_INLINE void set_geometry(uint16_t top_border_scanlines, uint16_t body_scanlines, bool wide)
	{
		if (UNEXPECTED((m_top_border_scanlines != top_border_scanlines)
			|| (m_body_scanlines != body_scanlines)
			|| (m_wide != wide)))
		{
			m_top_border_scanlines = top_border_scanlines;
			m_body_scanlines = body_scanlines;
			m_wide = wide;
			update_field_sync_timer();
		}
	}

	// checks to see if the video has changed
	ATTR_FORCE_INLINE bool has_video_changed()
	{
		/* poll the artifacting config */
		m_artifacter.poll_config();

		/* if the video didn't change, indicate as much */
		bool video_changed = m_video_changed;
		m_video_changed = false;
		return video_changed;
	}

	// updates a byte in the video state
	template<class T>
	ATTR_FORCE_INLINE bool update_value(T *ptr, T byte)
	{
		bool result = false;
		if (*ptr != byte)
		{
			*ptr = byte;
			m_video_changed = true;
			result = true;
		}
		return result;
	}

	// template function for emitting graphics bytes
	template<int bits_per_pixel, int xscale>
	ATTR_FORCE_INLINE void emit_graphics(const uint8_t *data, int length, pixel_t *RESTRICT pixels, uint16_t color_base, const pixel_t *RESTRICT palette)
	{
		for (int i = 0; i < length; i++)
		{
			for (int j = 0; j < (8 / bits_per_pixel); j++)
			{
				for (int k = 0; k < xscale; k++)
				{
					uint16_t color = color_base + ((data[i] >> (8 - (j + 1) * bits_per_pixel)) & ((1 << bits_per_pixel) - 1));
					pixels[(i * (8 / bits_per_pixel) + j) * xscale + k] = palette[color];
				}
			}
		}
	}

	// template function for external bytes
	template<int bits_per_pixel, int xscale>
	ATTR_FORCE_INLINE void emit_extbytes(const uint8_t *data, int length, pixel_t *RESTRICT pixels, uint16_t color_base, const pixel_t *RESTRICT palette)
	{
		for (int i = 0; i < length; i++)
		{
			for (int j = 0; j < (8 / bits_per_pixel); j++)
			{
				for (int k = 0; k < xscale; k++)
				{
					uint16_t color = color_base + BIT(data[i], 7-j);
					pixels[(i * (8 / bits_per_pixel) + j) * xscale + k] = palette[color];
				}
			}
		}
	}

	// template function for emitting samples
	template<int xscale>
	uint32_t emit_mc6847_samples(uint8_t mode, const uint8_t *data, int length, pixel_t *RESTRICT pixels, const pixel_t *RESTRICT palette,
			get_char_rom_delegate const &get_char_rom, int x, int y)
	{
		uint32_t result;
		if (mode & MODE_AG)
		{
			/* graphics */
			switch(mode & (MODE_GM2|MODE_GM1|MODE_GM0))
			{
				case 0:
					emit_graphics<2, xscale * 4>(data, length, pixels, (mode & MODE_CSS) ? 4 : 0, palette);
					result = length * 8 * xscale * 2;
					break;

				case MODE_GM0:
				case MODE_GM1|MODE_GM0:
				case MODE_GM2|MODE_GM0:
					emit_graphics<1, xscale * 2>(data, length, pixels, (mode & MODE_CSS) ? 10 : 8, palette);
					result = length * 8 * xscale * 2;
					break;

				case MODE_GM1:
				case MODE_GM2:
				case MODE_GM2|MODE_GM1:
					emit_graphics<2, xscale * 2>(data, length, pixels, (mode & MODE_CSS) ? 4 : 0, palette);
					result = length * 8 * xscale;
					break;

				case MODE_GM2|MODE_GM1|MODE_GM0:
					emit_graphics<1, xscale * 1>(data, length, pixels, (mode & MODE_CSS) ? 10 : 8, palette);
					result = length * 8 * xscale;
					break;

				default:
					/* should not get here */
					fatalerror("Should not get here\n");
					break;
			}
		}
		else if (!m_charrom_cb.isnull() && ((mode & (MODE_AG|MODE_AS|MODE_INTEXT)) == MODE_INTEXT))
		{
			/* external ROM */
			for (int i = 0; i < length; i++)
			{
				uint8_t byte = m_charrom_cb(data[i], y % 12) ^ (mode & MODE_INV ? 0xFF : 0x00);
				emit_extbytes<1, xscale>(&byte, 1, &pixels[i * 8], (mode & MODE_CSS) ? 14 : 12, palette);
			}
			result = length * 8 * xscale;
		}
		else
		{
			/* text/semigraphics */
			m_character_map.emit_character<xscale>(mode, data, length, pixels, y, palette);
			result = length * 8 * xscale;
		}
		return result;
	}

private:
	enum scanline_zone
	{
		SCANLINE_ZONE_TOP_BORDER,
		SCANLINE_ZONE_BODY,
		SCANLINE_ZONE_BOTTOM_BORDER,
		SCANLINE_ZONE_RETRACE,
		SCANLINE_ZONE_VBLANK,
	};

	// timers
	emu_timer *m_hsync_on_timer;
	emu_timer *m_hsync_off_timer;
	emu_timer *m_fsync_timer;

protected:
	const double m_tpfs;

private:
	// incidentals
	const int m_divider;
	const int m_field_sync_falling_edge_scanline;
	bool m_wide;
	bool m_video_changed;
	uint16_t m_top_border_scanlines;
	uint16_t m_body_scanlines;
	bool m_recording_scanline;
	const bool m_supports_partial_body_scanlines;

protected:
	const bool m_pal;
	const uint16_t m_lines_top_border;
	const uint16_t m_lines_until_vblank;
	const uint16_t m_lines_until_retrace;

private:
	// video state
	uint16_t m_physical_scanline;
	uint16_t m_logical_scanline;
	uint16_t m_logical_scanline_zone;
	bool m_horizontal_sync;
	bool m_field_sync;
	uint32_t m_partial_scanline_clocks;

	// functions
	virtual TIMER_CALLBACK_MEMBER(change_horizontal_sync);
	TIMER_CALLBACK_MEMBER(change_field_sync);
	void update_field_sync_timer();
	void next_scanline();
	int32_t get_clocks_since_hsync();

	// debugging
	std::string scanline_zone_string(scanline_zone zone) const;

protected:
	bool is_top_pal_padding_line(int scanline) const;
	bool is_bottom_pal_padding_line(int scanline) const;
	bool is_pal_padding_line(int scanline) const;
};

// actual base class for MC6847 family of devices
class mc6847_base_device : public mc6847_friend_device
{
public:
	auto input_callback() { return m_input_cb.bind(); }

	void set_get_fixed_mode(uint8_t mode) { m_fixed_mode = mode; }
	void set_black_and_white(bool bw) { m_black_and_white = bw; }

	/* updates the screen -- this will call begin_update(),
	   followed by update_row() repeatedly and after all row
	   updating is complete, end_update() */
	uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);

	// mode changing operations
	void ag_w(int state)       { change_mode(MODE_AG, state); }
	void gm2_w(int state)      { change_mode(MODE_GM2, state); }
	void gm1_w(int state)      { change_mode(MODE_GM1, state); }
	void gm0_w(int state)      { change_mode(MODE_GM0, state); }
	void as_w(int state)       { change_mode(MODE_AS, state); }
	void css_w(int state)      { change_mode(MODE_CSS, state); }
	void intext_w(int state)   { change_mode(MODE_INTEXT, state); }
	void inv_w(int state)      { change_mode(MODE_INV, state); }

	// palette
	void set_palette(const uint32_t *palette) { m_palette = (palette) ? palette : default_palette(); }

protected:
	mc6847_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const uint8_t *fontdata, double tpfs, bool pal);

	// device-level overrides
	virtual void device_config_complete() override;
	virtual void device_start() override;
	virtual void device_reset() override;
	virtual ioport_constructor device_input_ports() const override;

	// other overrides
	virtual void field_sync_changed(bool line) override;
	virtual void record_full_body_scanline(uint16_t physical_scanline, uint16_t scanline) override;
	virtual void record_partial_body_scanline(uint16_t physical_scanline, uint16_t logical_scanline, int32_t start_clock, int32_t end_clock) override;

	virtual uint32_t emit_samples(uint8_t mode, const uint8_t *data, int length, pixel_t *RESTRICT pixels, const pixel_t *RESTRICT palette,
			get_char_rom_delegate const &get_char_rom, int x, int y)
	{
		return emit_mc6847_samples<1>(mode, data, length, pixels, palette, get_char_rom, x, y);
	}
	virtual const uint32_t* default_palette() { return s_palette; }

	// runtime functions
	virtual void record_body_scanline(uint8_t mode, uint16_t physical_scanline, uint16_t scanline, int32_t start_pos, int32_t end_pos);
	virtual uint8_t border_value(uint8_t mode);

	// template function for doing video update collection
	template<int sample_count, int yres>
	void record_scanline_res(int scanline, int32_t start_pos, int32_t end_pos);

private:
	struct video_scanline
	{
		uint8_t m_sample_count;
		uint8_t m_mode[32];
		uint8_t m_data[32];
	};

	// palette
	static const int PALETTE_LENGTH = 16;
	static const uint32_t s_palette[PALETTE_LENGTH];

	/* if specified, this gets called whenever reading a byte (offs_t ~0 specifies DA* entering the tristate mode) */
	devcb_read8 m_input_cb;

	/* if true, this is black and white */
	bool m_black_and_white;

	// incidentals
	uint8_t m_fixed_mode;
	uint8_t m_fixed_mode_mask;
	const pixel_t *m_palette;
	pixel_t m_bw_palette[PALETTE_LENGTH];

	// state
	uint8_t m_mode;
	uint16_t m_video_address;
	bool m_dirty;
	video_scanline m_data[192];

	void change_mode(uint8_t mode, int state)
	{
		// sanity check, to ensure that we're not changing fixed modes
		assert((mode & m_fixed_mode_mask) == 0);

		// calculate new mode
		uint8_t new_mode;
		if (state)
			new_mode = m_mode | mode;
		else
			new_mode = m_mode & ~mode;

		// has the mode changed?
		if (new_mode != m_mode)
		{
			// it has!  check dirty flag
			video_flush();
			if (!m_dirty)
			{
				m_dirty = true;
			}

			// and set the new mode
			m_mode = new_mode;
		}
	}

	// setup functions
	void setup_fixed_mode();

	// miscellaneous
	uint8_t input(uint16_t address);
	int32_t scanline_position_from_clock(int32_t clocks_since_hsync);
};


//**************************************************************************
//  VARIATIONS
//**************************************************************************

class mc6847_ntsc_device : public mc6847_base_device
{
public:
	mc6847_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

class mc6847_pal_device : public mc6847_base_device
{
public:
	mc6847_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

class mc6847y_ntsc_device : public mc6847_base_device
{
public:
	mc6847y_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

class mc6847y_pal_device : public mc6847_base_device
{
public:
	mc6847y_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

class mc6847t1_ntsc_device : public mc6847_base_device
{
public:
	mc6847t1_ntsc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

protected:
	mc6847t1_ntsc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const uint8_t *fontdata, double tpfs, bool pal);

	virtual uint8_t border_value(uint8_t mode) override;
};

class mc6847t1_pal_device : public mc6847t1_ntsc_device
{
public:
	mc6847t1_pal_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

class s68047_device : public mc6847_base_device
{
public:
	s68047_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

protected:
	virtual uint32_t emit_samples(uint8_t mode, const uint8_t *data, int length, pixel_t *RESTRICT pixels, const pixel_t *RESTRICT palette,
			get_char_rom_delegate const &get_char_rom, int x, int y) override;
	virtual const uint32_t* default_palette() override { return s_s68047_palette; }

	virtual void record_body_scanline(uint8_t mode, uint16_t physical_scanline, uint16_t scanline, int32_t start_pos, int32_t end_pos) override;
	virtual uint8_t border_value(uint8_t mode) override;

private:
	static const uint32_t s_s68047_palette[16];
};

class m5c6847p1_device : public mc6847_base_device
{
public:
	m5c6847p1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};


DECLARE_DEVICE_TYPE(MC6847_NTSC,   mc6847_ntsc_device)
DECLARE_DEVICE_TYPE(MC6847_PAL,    mc6847_pal_device)
DECLARE_DEVICE_TYPE(MC6847Y_NTSC,  mc6847y_ntsc_device)
DECLARE_DEVICE_TYPE(MC6847Y_PAL,   mc6847y_pal_device)
DECLARE_DEVICE_TYPE(MC6847T1_NTSC, mc6847t1_ntsc_device)
DECLARE_DEVICE_TYPE(MC6847T1_PAL,  mc6847t1_pal_device)
DECLARE_DEVICE_TYPE(S68047,        s68047_device)
DECLARE_DEVICE_TYPE(M5C6847P1,     m5c6847p1_device)

#endif // MAME_VIDEO_MC6847_H