summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/315_5124.h
blob: f5bb3cc02f5a8d4dfe84e7caea2d451351bdf38b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
// license:BSD-3-Clause
// copyright-holders:Wilbert Pol, Enik Land
/*************************************************************************

    sega315_5124.h

    Implementation of Sega VDP chips used in System E, Master System and Game Gear

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

#ifndef MAME_VIDEO_315_5124_H
#define MAME_VIDEO_315_5124_H

#pragma once

#include "sound/sn76496.h"
#include "emupal.h"
#include "screen.h"


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

DECLARE_DEVICE_TYPE(SEGA315_5124, sega315_5124_device)      /* aka SMS1 vdp */
DECLARE_DEVICE_TYPE(SEGA315_5246, sega315_5246_device)      /* aka SMS2 vdp */
DECLARE_DEVICE_TYPE(SEGA315_5377, sega315_5377_device)      /* aka Gamegear (2 ASIC version) vdp */


class sega315_5124_device : public device_t,
							public device_memory_interface,
							public device_video_interface,
							public device_mixer_interface
{
public:
	static constexpr unsigned WIDTH                      = 342;    /* 342 pixels */
	static constexpr unsigned HEIGHT_NTSC                = 262;    /* 262 lines */
	static constexpr unsigned HEIGHT_PAL                 = 313;    /* 313 lines */
	static constexpr unsigned LBORDER_START              = 26 + 2 + 14 + 8;
	static constexpr unsigned LBORDER_WIDTH              = 13;     /* 13 pixels */
	static constexpr unsigned RBORDER_WIDTH              = 15;     /* 15 pixels */
	static constexpr unsigned TBORDER_START              = 3 + 13;
	static constexpr unsigned NTSC_192_TBORDER_HEIGHT    = 0x1b;   /* 27 lines */
	//static constexpr unsigned NTSC_192_BBORDER_HEIGHT  = 0x18;   /* 24 lines */
	static constexpr unsigned NTSC_224_TBORDER_HEIGHT    = 0x0b;   /* 11 lines */
	//static constexpr unsigned NTSC_224_BBORDER_HEIGHT  = 0x08;   /* 8 lines */
	//static constexpr unsigned PAL_192_TBORDER_HEIGHT   = 0x36;   /* 54 lines */
	//static constexpr unsigned PAL_192_BBORDER_HEIGHT   = 0x30;   /* 48 lines */
	//static constexpr unsigned PAL_224_TBORDER_HEIGHT   = 0x26;   /* 38 lines */
	//static constexpr unsigned PAL_224_BBORDER_HEIGHT   = 0x20;   /* 32 lines */
	static constexpr unsigned PAL_240_TBORDER_HEIGHT     = 0x1e;   /* 30 lines */
	//static constexpr unsigned PAL_240_BBORDER_HEIGHT   = 0x18;   /* 24 lines */


	// construction/destruction
	sega315_5124_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);

	void set_is_pal(bool is_pal) { m_is_pal = is_pal; }

	auto vblank() { return m_vblank_cb.bind(); }
	auto n_csync() { return m_n_csync_cb.bind(); }
	auto n_int() { return m_n_int_cb.bind(); }
	auto n_nmi() { return m_n_nmi_cb.bind(); }

	void psg_w(u8 data) { m_snsnd->write(data); }
	void psg_stereo_w(u8 data) { m_snsnd->stereo_w(data); }
	void n_nmi_in_write(int state) { m_n_nmi_in_state = state; } /* /NMI-IN line input, controls the /NMI state */
	u8 data_read();
	void data_write(u8 data);
	u8 control_read();
	void control_write(u8 data);
	u8 vcount_read();
	u8 hcount_read();

	void hcount_latch();
	bool hcount_latched() { return m_hcounter_latched; }

	bitmap_rgb32 &get_bitmap() { return m_tmpbitmap; };
	bitmap_ind8 &get_y1_bitmap() { return m_y1_bitmap; };

	/* update the screen */
	u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);

	virtual void set_sega315_5124_compatibility_mode(bool sega315_5124_compatibility_mode) { }

protected:
	static constexpr unsigned SEGA315_5377_CRAM_SIZE        = 0x40; /* 32 colors x 2 bytes per color = 64 bytes */
	static constexpr unsigned SEGA315_5124_CRAM_SIZE        = 0x20; /* 32 colors x 1 bytes per color = 32 bytes */

	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);

	// device-level overrides
	virtual void device_post_load() override;
	virtual void device_start() override;
	virtual void device_reset() override;
	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
	virtual void device_add_mconfig(machine_config &config) override;

	virtual space_config_vector memory_space_config() const override;

	void sega315_5124_palette(palette_device &palette) const;

	void sega315_5124(address_map &map);

	void set_display_settings();
	void set_frame_timing();
	virtual void vblank_end(int vpos);
	virtual void update_palette();
	virtual void write_memory(u8 data);
	virtual void cram_write(u8 data);
	virtual void load_vram_addr(u8 data);
	virtual void select_display_mode();
	virtual void select_extended_res_mode4(bool M1, bool M2, bool M3);
	virtual void select_sprites(int line);
	virtual void sprite_collision(int line, int sprite_col_x);
	virtual void sprite_count_overflow(int line, int sprite_index);
	virtual void draw_scanline(int pixel_offset_x, int pixel_plot_y, int line);
	virtual void blit_scanline(int *line_buffer, int *priority_selected, int pixel_offset_x, int pixel_plot_y, int line);
	virtual void draw_leftmost_pixels_mode4(int *line_buffer, int *priority_selected, int fine_x_scroll, int palette_selected, int tile_line);
	virtual u16 name_table_row_mode4(int row);
	virtual u16 sprite_attributes_addr_mode4(u16 base);
	virtual u8 sprite_tile_mask_mode4(u8 tile_number);
	void process_line_timer();
	void draw_scanline_mode4(int *line_buffer, int *priority_selected, int line);
	void draw_sprites_mode4(int *line_buffer, int *priority_selected, int line);
	void draw_sprites_tms9918_mode(int *line_buffer, int line);
	void draw_scanline_mode3(int *line_buffer, int line);
	void draw_scanline_mode2(int *line_buffer, int line);
	void draw_scanline_mode1(int *line_buffer, int line);
	void draw_scanline_mode0(int *line_buffer, int line);
	void check_pending_flags();

	u8               m_reg[16];                  /* All the registers */
	u8               m_status;                   /* Status register */
	u8               m_pending_status;           /* Pending status flags */
	u8               m_reg8copy;                 /* Internal copy of register 8 (X-Scroll) */
	u8               m_reg9copy;                 /* Internal copy of register 9 (Y-Scroll) */
	u8               m_addrmode;                 /* Type of VDP action */
	u16              m_addr;                     /* Contents of internal VDP address register */
	const u8         m_cram_size;                /* CRAM size */
	u8               m_cram_mask;                /* Mask to switch between SMS and GG CRAM sizes */
	bool             m_cram_dirty;               /* Have there been any changes to the CRAM area */
	bool             m_hcounter_latched;
	bool             m_hint_occurred;
	bool             m_pending_hint;
	bool             m_pending_control_write;
	int              m_pending_sprcol_x;
	u8               m_buffer;
	u8               m_control_write_data_latch;
	bool             m_sega315_5124_compatibility_mode;    /* when true, GG VDP behaves as SMS VDP */
	int              m_n_int_state;                /* The status of the /INT line of the VDP */
	int              m_n_nmi_state;                /* The status of the /NMI line of the VDP */
	int              m_n_nmi_in_state;             /* The status of the /NMI-IN line of the VDP */
	int              m_vdp_mode;                 /* Current mode of the VDP: 0,1,2,3,4 */
	int              m_y_pixels;                 /* 192, 224, 240 */
	int              m_draw_time;
	u8               m_line_counter;
	u8               m_hcounter;
	u8               m_CRAM[SEGA315_5377_CRAM_SIZE];  /* CRAM */
	const u8         *m_frame_timing;
	const u8         *m_line_timing;
	bitmap_rgb32     m_tmpbitmap;
	bitmap_ind8      m_y1_bitmap;
	const u8         m_palette_offset;
	const u8         m_reg_num_mask;
	bool             m_display_disabled;
	u16              m_sprite_base;
	u16              m_sprite_pattern_line[8];
	int              m_sprite_tile_selected[8];
	int              m_sprite_x[8];
	u8               m_sprite_flags[8];
	int              m_sprite_count;
	int              m_sprite_height;
	int              m_sprite_zoom_scale;
	int              m_max_sprite_zoom_hcount;
	int              m_max_sprite_zoom_vcount;
	int              m_current_palette[32];
	bool             m_is_pal;             /* false = NTSC, true = PAL */
	devcb_write_line m_vblank_cb;      /* VBlank line callback function */
	devcb_write_line m_n_csync_cb;     /* /C-SYNC line callback function */
	devcb_write_line m_n_int_cb;       /* /INT (Interrupt) line callback function */
	devcb_write_line m_n_nmi_cb;       /* /NMI (Non-Maskable Interrupt) line callback function */
	emu_timer        *m_display_timer;
	emu_timer        *m_hint_timer;
	emu_timer        *m_vint_timer;
	emu_timer        *m_nmi_timer;
	emu_timer        *m_draw_timer;
	emu_timer        *m_lborder_timer;
	emu_timer        *m_rborder_timer;
	emu_timer        *m_pending_flags_timer;

	const address_space_config  m_space_config;

	/* Timers */
	static constexpr device_timer_id TIMER_LINE = 0;
	static constexpr device_timer_id TIMER_DRAW = 1;
	static constexpr device_timer_id TIMER_LBORDER = 2;
	static constexpr device_timer_id TIMER_RBORDER = 3;
	static constexpr device_timer_id TIMER_HINT = 4;
	static constexpr device_timer_id TIMER_VINT = 5;
	static constexpr device_timer_id TIMER_NMI = 6;
	static constexpr device_timer_id TIMER_FLAGS = 7;

	required_device<palette_device> m_palette_lut;
	required_device<sn76496_base_device> m_snsnd;
};


class sega315_5246_device : public sega315_5124_device
{
public:
	sega315_5246_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);

protected:
	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);

	virtual u16 name_table_row_mode4(int row) override;
	virtual u16 sprite_attributes_addr_mode4(u16 base) override;
	virtual u8 sprite_tile_mask_mode4(u8 tile_number) override;
	virtual void select_extended_res_mode4(bool M1, bool M2, bool M3) override;
};


class sega315_5377_device : public sega315_5246_device
{
public:
	sega315_5377_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);

	virtual void set_sega315_5124_compatibility_mode(bool sega315_5124_compatibility_mode) override;

protected:
	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);

	virtual void device_reset() override;
	virtual void device_add_mconfig(machine_config &config) override;

	virtual void vblank_end(int vpos) override;
	virtual void update_palette() override;
	virtual void cram_write(u8 data) override;
	virtual void blit_scanline(int *line_buffer, int *priority_selected, int pixel_offset_x, int pixel_plot_y, int line) override;

private:
	void sega315_5377_palette(palette_device &palette) const;
};


// Embedded mode 4 support of the 315-5313 (Mega Drive) VDP
class sega315_5313_mode4_device : public sega315_5246_device
{
public:
	void stop_timers();

protected:
	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);

	virtual void device_add_mconfig(machine_config &config) override;

	virtual void update_palette() override;
	virtual void write_memory(u8 data) override;
	virtual void load_vram_addr(u8 data) override;
	virtual void select_sprites(int line) override;
	virtual void sprite_collision(int line, int sprite_col_x) override;
	virtual void sprite_count_overflow(int line, int sprite_index) override;
	virtual void select_display_mode() override;
	virtual void select_extended_res_mode4(bool M1, bool M2, bool M3) override;
	virtual void draw_leftmost_pixels_mode4(int *line_buffer, int *priority_selected, int fine_x_scroll, int palette_selected, int tile_line) override;

private:
	void sega315_5313_palette(palette_device &palette) const;
};

#endif // MAME_VIDEO_315_5124_H