1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /**********************************************************************
4 
5     RCA CDP1869/1870/1876 Video Interface System (VIS) emulation
6 
7 **********************************************************************
8                             _____   _____
9                    TPA   1 |*    \_/     | 40  Vdd
10                    TPB   2 |             | 39  PMSEL
11                   _MRD   3 |             | 38  _PMWR
12                   _MWR   4 |             | 37  CMSEL
13                  MA0/8   5 |             | 36  _CMWR
14                  MA1/9   6 |             | 35  PMA0
15                 MA2/10   7 |             | 34  PMA1
16                 MA3/11   8 |             | 33  PMA2
17                 MA4/12   9 |             | 32  PMA3
18                 MA5/13  10 |             | 31  PMA4
19                 MA6/14  11 |   CDP1869   | 30  PMA5
20                 MA7/15  12 |             | 29  PMA6
21                     N0  13 |             | 28  PMA7
22                     N1  14 |             | 27  PMA8
23                     N2  15 |             | 26  PMA9
24                _H SYNC  16 |             | 25  CMA3/PMA10
25               _DISPLAY  17 |             | 24  CMA2
26               _ADDRSTB  18 |             | 23  CMA1
27                  SOUND  19 |             | 22  CMA0
28                    Vss  20 |_____________| 21  _N=3
29 
30                             _____   _____
31            _PREDISPLAY   1 |*    \_/     | 40  Vdd
32               _DISPLAY   2 |             | 39  PAL/_NTSC
33                    PCB   3 |             | 38  CPUCLK
34                   CCB1   4 |             | 37  XTAL (DOT)
35                   BUS7   5 |             | 36  _XTAL (DOT)
36                   CCB0   6 |             | 35  _ADDRSTB
37                   BUS6   7 |             | 34  _MRD
38                   CDB5   8 |             | 33  TPB
39                   BUS5   9 |             | 32  CMSEL
40                   CDB4  10 |             | 31  BURST
41                   BUS4  11 |   CDP1870   | 30  _H SYNC
42                   CDB3  12 |             | 29  _COMPSYNC
43                   BUS3  13 |             | 28  LUM
44                   CDB2  14 |             | 27  PAL CHROM
45                   BUS2  15 |             | 26  NTSC CHROM
46                   CDB1  16 |             | 25  _XTAL (CHROM)
47                   BUS1  17 |             | 24  XTAL (CHROM)
48                   CDB0  18 |             | 23  _EMS
49                   BUS0  19 |             | 22  _EVS
50                    Vss  20 |_____________| 21  _N=3
51 
52                             _____   _____
53            _PREDISPLAY   1 |*    \_/     | 40  Vdd
54               _DISPLAY   2 |             | 39  PAL/_NTSC
55                    PCB   3 |             | 38  CPUCLK
56                   CCB1   4 |             | 37  XTAL (DOT)
57                   BUS7   5 |             | 36  _XTAL (DOT)
58                   CCB0   6 |             | 35  _ADDRSTB
59                   BUS6   7 |             | 34  _MRD
60                   CDB5   8 |             | 33  TPB
61                   BUS5   9 |             | 32  CMSEL
62                   CDB4  10 |             | 31  BURST
63                   BUS4  11 |   CDP1876   | 30  _H SYNC
64                   CDB3  12 |             | 29  _COMPSYNC
65                   BUS3  13 |             | 28  RED
66                   CDB2  14 |             | 27  BLUE
67                   BUS2  15 |             | 26  GREEN
68                   CDB1  16 |             | 25  _XTAL (CHROM)
69                   BUS1  17 |             | 24  XTAL (CHROM)
70                   CDB0  18 |             | 23  _EMS
71                   BUS0  19 |             | 22  _EVS
72                    Vss  20 |_____________| 21  _N=3
73 
74 **********************************************************************/
75 
76 #ifndef MAME_SOUND_CDP1869_H
77 #define MAME_SOUND_CDP1869_H
78 
79 #pragma once
80 
81 #include "emupal.h"
82 #include "screen.h"
83 
84 //**************************************************************************
85 //  TYPE DEFINITIONS
86 //**************************************************************************
87 
88 #define CDP1869_CHAR_RAM_READ_MEMBER(name) uint8_t name(uint16_t pma, uint8_t cma, uint8_t pmd)
89 #define CDP1869_CHAR_RAM_WRITE_MEMBER(name) void name(uint16_t pma, uint8_t cma, uint8_t pmd, uint8_t data)
90 #define CDP1869_PCB_READ_MEMBER(name) int name(uint16_t pma, uint8_t cma, uint8_t pmd)
91 
92 // ======================> cdp1869_device
93 
94 class cdp1869_device :  public device_t,
95 						public device_sound_interface,
96 						public device_video_interface,
97 						public device_memory_interface
98 {
99 public:
100 	static constexpr auto DOT_CLK_PAL         = XTAL(5'626'000);
101 	static constexpr auto DOT_CLK_NTSC        = XTAL(5'670'000);
102 	static constexpr auto COLOR_CLK_PAL       = XTAL(8'867'236);
103 	static constexpr auto COLOR_CLK_NTSC      = XTAL(7'159'090);
104 
105 	static constexpr auto CPU_CLK_PAL         = DOT_CLK_PAL / 2;
106 	static constexpr auto CPU_CLK_NTSC        = DOT_CLK_NTSC / 2;
107 
108 	static constexpr unsigned CH_WIDTH            = 6;
109 
110 	static constexpr unsigned HSYNC_START         = 56 * CH_WIDTH;
111 	static constexpr unsigned HSYNC_END           = 60 * CH_WIDTH;
112 	static constexpr unsigned HBLANK_START        = 54 * CH_WIDTH;
113 	static constexpr unsigned HBLANK_END          =  5 * CH_WIDTH;
114 	static constexpr unsigned SCREEN_START_PAL    =  9 * CH_WIDTH;
115 	static constexpr unsigned SCREEN_START_NTSC   = 10 * CH_WIDTH;
116 	static constexpr unsigned SCREEN_START        = 10 * CH_WIDTH;
117 	static constexpr unsigned SCREEN_END          = 50 * CH_WIDTH;
118 	static constexpr unsigned SCREEN_WIDTH        = 60 * CH_WIDTH;
119 
120 	static constexpr unsigned TOTAL_SCANLINES_PAL             = 312;
121 	static constexpr unsigned SCANLINE_VBLANK_START_PAL       = 304;
122 	static constexpr unsigned SCANLINE_VBLANK_END_PAL         = 10;
123 	static constexpr unsigned SCANLINE_VSYNC_START_PAL        = 308;
124 	static constexpr unsigned SCANLINE_VSYNC_END_PAL          = 312;
125 	static constexpr unsigned SCANLINE_DISPLAY_START_PAL      = 44;
126 	static constexpr unsigned SCANLINE_DISPLAY_END_PAL        = 260;
127 	static constexpr unsigned SCANLINE_PREDISPLAY_START_PAL   = 43;
128 	static constexpr unsigned SCANLINE_PREDISPLAY_END_PAL     = 260;
129 	static constexpr unsigned VISIBLE_SCANLINES_PAL           = SCANLINE_DISPLAY_END_PAL - SCANLINE_DISPLAY_START_PAL;
130 
131 	static constexpr unsigned TOTAL_SCANLINES_NTSC            = 262;
132 	static constexpr unsigned SCANLINE_VBLANK_START_NTSC      = 252;
133 	static constexpr unsigned SCANLINE_VBLANK_END_NTSC        = 10;
134 	static constexpr unsigned SCANLINE_VSYNC_START_NTSC       = 258;
135 	static constexpr unsigned SCANLINE_VSYNC_END_NTSC         = 262;
136 	static constexpr unsigned SCANLINE_DISPLAY_START_NTSC     = 36;
137 	static constexpr unsigned SCANLINE_DISPLAY_END_NTSC       = 228;
138 	static constexpr unsigned SCANLINE_PREDISPLAY_START_NTSC  = 35;
139 	static constexpr unsigned SCANLINE_PREDISPLAY_END_NTSC    = 228;
140 	static constexpr unsigned VISIBLE_SCANLINES_NTSC          = SCANLINE_DISPLAY_END_NTSC - SCANLINE_DISPLAY_START_NTSC;
141 
142 	static constexpr unsigned PALETTE_LENGTH  = 8+64;
143 
144 	typedef device_delegate<uint8_t (uint16_t pma, uint8_t cma, uint8_t pmd)> char_ram_read_delegate;
145 	typedef device_delegate<void (uint16_t pma, uint8_t cma, uint8_t pmd, uint8_t data)> char_ram_write_delegate;
146 	typedef device_delegate<int (uint16_t pma, uint8_t cma, uint8_t pmd)> pcb_read_delegate;
147 
148 	// construction/destruction
149 	template <typename T>
cdp1869_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock,T && addrmap)150 	cdp1869_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&addrmap)
151 		: cdp1869_device(mconfig, tag, owner, clock)
152 	{
153 		set_addrmap(0, std::forward<T>(addrmap));
154 	}
155 	cdp1869_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
156 
pal_ntsc_callback()157 	auto pal_ntsc_callback() { return m_read_pal_ntsc.bind(); }
prd_callback()158 	auto prd_callback() { return m_write_prd.bind(); }
set_color_clock(int color_clock)159 	void set_color_clock(int color_clock) { m_color_clock = color_clock; }
set_color_clock(const XTAL & xtal)160 	void set_color_clock(const XTAL &xtal) { xtal.validate("selecting cdp1869 clock"); set_color_clock(xtal.value()); }
161 
162 	// delegate setters
set_char_ram_read_callback(T &&...args)163 	template <typename... T> void set_char_ram_read_callback(T &&... args) { m_in_char_ram_func.set(std::forward<T>(args)...); }
set_char_ram_write_callback(T &&...args)164 	template <typename... T> void set_char_ram_write_callback(T &&... args) { m_out_char_ram_func.set(std::forward<T>(args)...); }
set_pcb_read_callback(T &&...args)165 	template <typename... T> void set_pcb_read_callback(T &&... args) { m_in_pcb_func.set(std::forward<T>(args)...); }
166 
167 	// helper functions
add_pal_screen(machine_config & config,T && screen_tag,U && clock)168 	template <typename T, typename U> screen_device& add_pal_screen(machine_config &config, T &&screen_tag, U &&clock)
169 	{
170 		screen_device &screen(SCREEN(config, std::forward<T>(screen_tag), SCREEN_TYPE_RASTER));
171 		screen.set_screen_update(tag(), FUNC(cdp1869_device::screen_update));
172 		screen.set_raw(std::forward<U>(clock), cdp1869_device::SCREEN_WIDTH, cdp1869_device::HBLANK_END, cdp1869_device::HBLANK_START,
173 			cdp1869_device::TOTAL_SCANLINES_PAL, cdp1869_device::SCANLINE_VBLANK_END_PAL, cdp1869_device::SCANLINE_VBLANK_START_PAL);
174 		return screen;
175 	}
176 
add_ntsc_screen(machine_config & config,T && screen_tag,U && clock)177 	template <typename T, typename U> screen_device& add_ntsc_screen(machine_config &config, T &&screen_tag, U &&clock)
178 	{
179 		screen_device &screen(SCREEN(config, std::forward<T>(screen_tag), SCREEN_TYPE_RASTER));
180 		screen.set_screen_update(tag(), FUNC(cdp1869_device::screen_update));
181 		screen.set_raw(std::forward<U>(clock), cdp1869_device::SCREEN_WIDTH, cdp1869_device::HBLANK_END, cdp1869_device::HBLANK_START,
182 			cdp1869_device::TOTAL_SCANLINES_NTSC, cdp1869_device::SCANLINE_VBLANK_END_NTSC, cdp1869_device::SCANLINE_VBLANK_START_NTSC);
183 		return screen;
184 	}
185 
186 	virtual void io_map(address_map &map);
187 	virtual void char_map(address_map &map);
188 	virtual void page_map(address_map &map);
189 
190 	void out3_w(uint8_t data);
191 	void out4_w(offs_t offset);
192 	void out5_w(offs_t offset);
193 	void out6_w(offs_t offset);
194 	void out7_w(offs_t offset);
195 
196 	uint8_t char_ram_r(offs_t offset);
197 	void char_ram_w(offs_t offset, uint8_t data);
198 
199 	uint8_t page_ram_r(offs_t offset);
200 	void page_ram_w(offs_t offset, uint8_t data);
201 
202 	int predisplay_r();
203 	int pal_ntsc_r();
204 
205 	uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
206 
207 	void cdp1869(address_map &map);
208 protected:
209 	// device-level overrides
210 	virtual void device_add_mconfig(machine_config &config) override;
211 	virtual void device_start() override;
212 	virtual void device_post_load() override;
213 	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
214 
215 	// device_memory_interface overrides
216 	virtual space_config_vector memory_space_config() const override;
217 
218 	// device_sound_interface callbacks
219 	virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
220 
221 	inline bool is_ntsc();
222 	inline uint8_t read_page_ram_byte(offs_t address);
223 	inline void write_page_ram_byte(offs_t address, uint8_t data);
224 	inline uint8_t read_char_ram_byte(offs_t pma, offs_t cma, uint8_t pmd);
225 	inline void write_char_ram_byte(offs_t pma, offs_t cma, uint8_t pmd, uint8_t data);
226 	inline int read_pcb(offs_t pma, offs_t cma, uint8_t pmd);
227 	inline void update_prd_changed_timer();
228 	static rgb_t get_rgb(int i, int c, int l);
229 	inline int get_lines();
230 	inline uint16_t get_pmemsize(int cols, int rows);
231 	inline uint16_t get_pma();
232 	inline int get_pen(int ccb0, int ccb1, int pcb);
233 
234 	void draw_line(bitmap_rgb32 &bitmap, const rectangle &rect, int x, int y, uint8_t data, int color);
235 	void draw_char(bitmap_rgb32 &bitmap, const rectangle &rect, int x, int y, uint16_t pma);
236 
237 private:
238 	devcb_read_line        m_read_pal_ntsc;
239 	devcb_write_line       m_write_prd;
240 	pcb_read_delegate           m_in_pcb_func;
241 	char_ram_read_delegate      m_in_char_ram_func;
242 	char_ram_write_delegate     m_out_char_ram_func;
243 	int m_color_clock;
244 
245 	//address_space *m_page_ram;
246 	emu_timer *m_prd_timer;
247 	sound_stream *m_stream;
248 	required_device<palette_device> m_palette;
249 	const address_space_config      m_space_config;
250 
251 	// video state
252 	int m_prd;                      // predisplay
253 	int m_dispoff;                  // display off
254 	int m_fresvert;                 // full resolution vertical
255 	int m_freshorz;                 // full resolution horizontal
256 	int m_cmem;                     // character memory access mode
257 	int m_dblpage;                  // double page mode
258 	int m_line16;                   // 16-line hi-res mode
259 	int m_line9;                    // 9 line mode
260 	int m_cfc;                      // color format control
261 	uint8_t m_col;                    // character color control
262 	uint8_t m_bkg;                    // background color
263 	uint16_t m_pma;                   // page memory address
264 	uint16_t m_hma;                   // home memory address
265 
266 	// sound state
267 	stream_buffer::sample_t m_signal; // current signal
268 	int m_incr;                     // initial wave state
269 	int m_toneoff;                  // tone off
270 	int m_wnoff;                    // white noise off
271 	uint8_t m_tonediv;                // tone divisor
272 	uint8_t m_tonefreq;               // tone range select
273 	uint8_t m_toneamp;                // tone output amplitude
274 	uint8_t m_wnfreq;                 // white noise range select
275 	uint8_t m_wnamp;                  // white noise output amplitude
276 
277 	void cdp1869_palette(palette_device &palette) const;
278 };
279 
280 
281 // device type definition
282 DECLARE_DEVICE_TYPE(CDP1869, cdp1869_device)
283 
284 #endif // MAME_SOUND_CDP1869_H
285