1 // license:BSD-3-Clause
2 // copyright-holders:Wilbert Pol, Enik Land
3 /*************************************************************************
4 
5     sega315_5124.h
6 
7     Implementation of Sega VDP chips used in System E, Master System and Game Gear
8 
9 **************************************************************************/
10 
11 #ifndef MAME_VIDEO_315_5124_H
12 #define MAME_VIDEO_315_5124_H
13 
14 #pragma once
15 
16 #include "sound/sn76496.h"
17 #include "emupal.h"
18 #include "screen.h"
19 
20 
21 /***************************************************************************
22     TYPE DEFINITIONS
23 ***************************************************************************/
24 
DECLARE_DEVICE_TYPE(SEGA315_5124,sega315_5124_device)25 DECLARE_DEVICE_TYPE(SEGA315_5124, sega315_5124_device)      /* aka SMS1 vdp */
26 DECLARE_DEVICE_TYPE(SEGA315_5246, sega315_5246_device)      /* aka SMS2 vdp */
27 DECLARE_DEVICE_TYPE(SEGA315_5377, sega315_5377_device)      /* aka Gamegear (2 ASIC version) vdp */
28 
29 
30 class sega315_5124_device : public device_t,
31 							public device_memory_interface,
32 							public device_video_interface,
33 							public device_mixer_interface
34 {
35 public:
36 	static constexpr unsigned WIDTH                      = 342;    /* 342 pixels */
37 	static constexpr unsigned HEIGHT_NTSC                = 262;    /* 262 lines */
38 	static constexpr unsigned HEIGHT_PAL                 = 313;    /* 313 lines */
39 	static constexpr unsigned LBORDER_START              = 26 + 2 + 14 + 8;
40 	static constexpr unsigned LBORDER_WIDTH              = 13;     /* 13 pixels */
41 	static constexpr unsigned RBORDER_WIDTH              = 15;     /* 15 pixels */
42 	static constexpr unsigned TBORDER_START              = 3 + 13;
43 	static constexpr unsigned NTSC_192_TBORDER_HEIGHT    = 0x1b;   /* 27 lines */
44 	//static constexpr unsigned NTSC_192_BBORDER_HEIGHT  = 0x18;   /* 24 lines */
45 	static constexpr unsigned NTSC_224_TBORDER_HEIGHT    = 0x0b;   /* 11 lines */
46 	//static constexpr unsigned NTSC_224_BBORDER_HEIGHT  = 0x08;   /* 8 lines */
47 	//static constexpr unsigned PAL_192_TBORDER_HEIGHT   = 0x36;   /* 54 lines */
48 	//static constexpr unsigned PAL_192_BBORDER_HEIGHT   = 0x30;   /* 48 lines */
49 	//static constexpr unsigned PAL_224_TBORDER_HEIGHT   = 0x26;   /* 38 lines */
50 	//static constexpr unsigned PAL_224_BBORDER_HEIGHT   = 0x20;   /* 32 lines */
51 	static constexpr unsigned PAL_240_TBORDER_HEIGHT     = 0x1e;   /* 30 lines */
52 	//static constexpr unsigned PAL_240_BBORDER_HEIGHT   = 0x18;   /* 24 lines */
53 
54 
55 	// construction/destruction
56 	sega315_5124_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
57 
58 	void set_hcounter_divide(unsigned divide) { m_hcounter_divide = divide; }
59 	void set_is_pal(bool is_pal) { m_is_pal = is_pal; }
60 
61 	auto vblank() { return m_vblank_cb.bind(); }
62 	auto n_csync() { return m_n_csync_cb.bind(); }
63 	auto n_int() { return m_n_int_cb.bind(); }
64 	auto n_nmi() { return m_n_nmi_cb.bind(); }
65 
66 	void psg_w(u8 data) { m_snsnd->write(data); }
67 	void psg_stereo_w(u8 data) { m_snsnd->stereo_w(data); }
68 	void n_nmi_in_write(int state) { m_n_nmi_in_state = state; } /* /NMI-IN line input, controls the /NMI state */
69 	u8 data_read();
70 	void data_write(u8 data);
71 	u8 control_read();
72 	void control_write(u8 data);
73 	u8 vcount_read();
74 	u8 hcount_read();
75 
76 	void hcount_latch();
77 	bool hcount_latched() { return m_hcounter_latched; }
78 
79 	bitmap_rgb32 &get_bitmap() { return m_tmpbitmap; };
80 	bitmap_ind8 &get_y1_bitmap() { return m_y1_bitmap; };
81 
82 	/* update the screen */
83 	u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
84 
85 	virtual void set_sega315_5124_compatibility_mode(bool sega315_5124_compatibility_mode) { }
86 
87 protected:
88 	static constexpr unsigned SEGA315_5377_CRAM_SIZE        = 0x40; /* 32 colors x 2 bytes per color = 64 bytes */
89 	static constexpr unsigned SEGA315_5124_CRAM_SIZE        = 0x20; /* 32 colors x 1 bytes per color = 32 bytes */
90 
91 	sega315_5124_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 cram_size, u8 palette_offset, u8 reg_num_mask, int max_sprite_zoom_hcount, int max_sprite_zoom_vcount, const u8 *line_timing);
92 
93 	// device-level overrides
94 	virtual void device_post_load() override;
95 	virtual void device_start() override;
96 	virtual void device_reset() override;
97 	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
98 	virtual void device_add_mconfig(machine_config &config) override;
99 
100 	virtual space_config_vector memory_space_config() const override;
101 
102 	void sega315_5124_palette(palette_device &palette) const;
103 
104 	void sega315_5124(address_map &map);
105 
106 	virtual int screen_hpos() { return screen().hpos() / ((m_hcounter_divide == 0) ? 1 : m_hcounter_divide); }
107 	void set_display_settings();
108 	void set_frame_timing();
109 	virtual void vblank_end(int vpos);
110 	virtual void update_palette();
111 	virtual void write_memory(u8 data);
112 	virtual void cram_write(u8 data);
113 	virtual void load_vram_addr(u8 data);
114 	virtual void select_display_mode();
115 	virtual void select_extended_res_mode4(bool M1, bool M2, bool M3);
116 	virtual void select_sprites(int line);
117 	virtual void sprite_collision(int line, int sprite_col_x);
118 	virtual void sprite_count_overflow(int line, int sprite_index);
119 	virtual void draw_scanline(int pixel_offset_x, int pixel_plot_y, int line);
120 	virtual void blit_scanline(int *line_buffer, int *priority_selected, int pixel_offset_x, int pixel_plot_y, int line);
121 	virtual void draw_leftmost_pixels_mode4(int *line_buffer, int *priority_selected, int fine_x_scroll, int palette_selected, int tile_line);
122 	virtual u16 name_row_mode4(u16 row);
123 	virtual u16 tile1_select_mode4(u16 tile_number);
124 	virtual u16 tile2_select_mode4(u16 tile_number);
125 	virtual u8 sprite_attribute_extra_offset_mode4(u8 offset);
126 	virtual u8 sprite_tile_select_mode4(u8 tile_number);
127 	void process_line_timer();
128 	void draw_scanline_mode4(int *line_buffer, int *priority_selected, int line);
129 	void draw_sprites_mode4(int *line_buffer, int *priority_selected, int line);
130 	void draw_sprites_tms9918_mode(int *line_buffer, int line);
131 	void draw_scanline_mode3(int *line_buffer, int line);
132 	void draw_scanline_mode2(int *line_buffer, int line);
133 	void draw_scanline_mode1(int *line_buffer, int line);
134 	void draw_scanline_mode0(int *line_buffer, int line);
135 	void check_pending_flags();
136 	u8 vcount();
137 	u8 hcount();
138 
139 	unsigned         m_hcounter_divide;
140 	u8               m_reg[16];                  /* All the registers */
141 	u8               m_status;                   /* Status register */
142 	u8               m_pending_status;           /* Pending status flags */
143 	u8               m_reg8copy;                 /* Internal copy of register 8 (X-Scroll) */
144 	u8               m_reg9copy;                 /* Internal copy of register 9 (Y-Scroll) */
145 	u8               m_addrmode;                 /* Type of VDP action */
146 	u16              m_addr;                     /* Contents of internal VDP address register */
147 	const u8         m_cram_size;                /* CRAM size */
148 	u8               m_cram_mask;                /* Mask to switch between SMS and GG CRAM sizes */
149 	bool             m_cram_dirty;               /* Have there been any changes to the CRAM area */
150 	bool             m_hcounter_latched;
151 	bool             m_hint_occurred;
152 	bool             m_pending_hint;
153 	bool             m_pending_control_write;
154 	int              m_pending_sprcol_x;
155 	u8               m_buffer;
156 	u8               m_control_write_data_latch;
157 	bool             m_sega315_5124_compatibility_mode;    /* when true, GG VDP behaves as SMS VDP */
158 	int              m_n_int_state;                /* The status of the /INT line of the VDP */
159 	int              m_n_nmi_state;                /* The status of the /NMI line of the VDP */
160 	int              m_n_nmi_in_state;             /* The status of the /NMI-IN line of the VDP */
161 	int              m_vdp_mode;                 /* Current mode of the VDP: 0,1,2,3,4 */
162 	int              m_y_pixels;                 /* 192, 224, 240 */
163 	int              m_draw_time;
164 	u8               m_line_counter;
165 	u8               m_hcounter;
166 	u8               m_CRAM[SEGA315_5377_CRAM_SIZE];  /* CRAM */
167 	const u8         *m_frame_timing;
168 	const u8         *m_line_timing;
169 	bitmap_rgb32     m_tmpbitmap;
170 	bitmap_ind8      m_y1_bitmap;
171 	const u8         m_palette_offset;
172 	const u8         m_reg_num_mask;
173 	bool             m_display_disabled;
174 	u16              m_sprite_attribute_base;
175 	u16              m_sprite_pattern_line[8];
176 	int              m_sprite_tile_selected[8];
177 	int              m_sprite_x[8];
178 	u8               m_sprite_flags[8];
179 	int              m_sprite_count;
180 	int              m_sprite_height;
181 	int              m_sprite_zoom_scale;
182 	int              m_max_sprite_zoom_hcount;
183 	int              m_max_sprite_zoom_vcount;
184 	int              m_current_palette[32];
185 	bool             m_is_pal;             /* false = NTSC, true = PAL */
186 	devcb_write_line m_vblank_cb;      /* VBlank line callback function */
187 	devcb_write_line m_n_csync_cb;     /* /C-SYNC line callback function */
188 	devcb_write_line m_n_int_cb;       /* /INT (Interrupt) line callback function */
189 	devcb_write_line m_n_nmi_cb;       /* /NMI (Non-Maskable Interrupt) line callback function */
190 	emu_timer        *m_display_timer;
191 	emu_timer        *m_hint_timer;
192 	emu_timer        *m_vint_timer;
193 	emu_timer        *m_nmi_timer;
194 	emu_timer        *m_draw_timer;
195 	emu_timer        *m_lborder_timer;
196 	emu_timer        *m_rborder_timer;
197 	emu_timer        *m_pending_flags_timer;
198 
199 	const address_space_config  m_space_config;
200 
201 	/* Timers */
202 	static constexpr device_timer_id TIMER_LINE = 0;
203 	static constexpr device_timer_id TIMER_DRAW = 1;
204 	static constexpr device_timer_id TIMER_LBORDER = 2;
205 	static constexpr device_timer_id TIMER_RBORDER = 3;
206 	static constexpr device_timer_id TIMER_HINT = 4;
207 	static constexpr device_timer_id TIMER_VINT = 5;
208 	static constexpr device_timer_id TIMER_NMI = 6;
209 	static constexpr device_timer_id TIMER_FLAGS = 7;
210 
211 	required_device<palette_device> m_palette_lut;
212 	required_device<sn76496_base_device> m_snsnd;
213 };
214 
215 
216 class sega315_5246_device : public sega315_5124_device
217 {
218 public:
219 	sega315_5246_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
220 
221 protected:
222 	sega315_5246_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 cram_size, u8 palette_offset, u8 reg_num_mask, int max_sprite_zoom_hcount, int max_sprite_zoom_vcount, const u8 *line_timing);
223 
224 	virtual void device_add_mconfig(machine_config &config) override;
225 
226 	virtual u16 name_row_mode4(u16 row) override;
227 	virtual u16 tile1_select_mode4(u16 tile_number) override;
228 	virtual u16 tile2_select_mode4(u16 tile_number) override;
229 	virtual u8 sprite_attribute_extra_offset_mode4(u8 offset) override;
230 	virtual u8 sprite_tile_select_mode4(u8 tile_number) override;
231 	virtual void select_extended_res_mode4(bool M1, bool M2, bool M3) override;
232 
233 private:
234 	void sega315_5246_palette(palette_device &palette) const;
235 };
236 
237 
238 class sega315_5377_device : public sega315_5246_device
239 {
240 public:
241 	sega315_5377_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
242 
243 	virtual void set_sega315_5124_compatibility_mode(bool sega315_5124_compatibility_mode) override;
244 
245 protected:
246 	sega315_5377_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 cram_size, u8 palette_offset, u8 reg_num_mask, int max_sprite_zoom_hcount, int max_sprite_zoom_vcount, const u8 *line_timing);
247 
248 	virtual void device_reset() override;
249 	virtual void device_add_mconfig(machine_config &config) override;
250 
251 	virtual void vblank_end(int vpos) override;
252 	virtual void update_palette() override;
253 	virtual void cram_write(u8 data) override;
254 	virtual void blit_scanline(int *line_buffer, int *priority_selected, int pixel_offset_x, int pixel_plot_y, int line) override;
255 
256 private:
257 	void sega315_5377_palette(palette_device &palette) const;
258 };
259 
260 
261 // Embedded mode 4 support of the 315-5313 (Mega Drive) VDP
262 class sega315_5313_mode4_device : public sega315_5246_device
263 {
264 public:
265 	void stop_timers();
266 
267 protected:
268 	sega315_5313_mode4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 cram_size, u8 palette_offset, u8 reg_num_mask, int max_sprite_zoom_hcount, int max_sprite_zoom_vcount, const u8 *line_timing);
269 
270 	virtual void device_add_mconfig(machine_config &config) override;
271 
272 	virtual void update_palette() override;
273 	virtual void write_memory(u8 data) override;
274 	virtual void load_vram_addr(u8 data) override;
275 	virtual void select_sprites(int line) override;
276 	virtual void sprite_collision(int line, int sprite_col_x) override;
277 	virtual void sprite_count_overflow(int line, int sprite_index) override;
278 	virtual void select_display_mode() override;
279 	virtual void select_extended_res_mode4(bool M1, bool M2, bool M3) override;
280 	virtual void draw_leftmost_pixels_mode4(int *line_buffer, int *priority_selected, int fine_x_scroll, int palette_selected, int tile_line) override;
281 
282 private:
283 	void sega315_5313_palette(palette_device &palette) const;
284 };
285 
286 #endif // MAME_VIDEO_315_5124_H
287