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