summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/video/crtc_ega.h
blob: 3a25b6e10952c6b92537783a46f04902ada5dc21 (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
/**********************************************************************

    IBM EGA CRT Controller emulation

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

#ifndef __CRTC_EGA__
#define __CRTC_EGA__

#include "emu.h"
#include "machine/devhelpr.h"

#define CRTC_EGA_INTERFACE(name) \
	const crtc_ega_interface (name) =

#define MCFG_CRTC_EGA_ADD(_tag, _clock, _intrf) \
	MCFG_DEVICE_ADD(_tag, CRTC_EGA, _clock) \
	MCFG_DEVICE_CONFIG(_intrf)


class crtc_ega_device;

/* callback definitions */
typedef void * (*crtc_ega_begin_update_func)(crtc_ega_device *device, bitmap_ind16 &bitmap, const rectangle &cliprect);
#define CRTC_EGA_BEGIN_UPDATE(name)	void *name(crtc_ega_device *device, bitmap_ind16 &bitmap, const rectangle &cliprect)

typedef void (*crtc_ega_update_row_func)(crtc_ega_device *device, bitmap_ind16 &bitmap,
									   const rectangle &cliprect, UINT16 ma, UINT8 ra,
									   UINT16 y, UINT8 x_count, INT8 cursor_x, void *param);
#define CRTC_EGA_UPDATE_ROW(name)		void name(crtc_ega_device *device, bitmap_ind16 &bitmap,	\
											  const rectangle &cliprect, UINT16 ma, UINT8 ra,					\
											  UINT16 y, UINT8 x_count, INT8 cursor_x, void *param)

typedef void (*crtc_ega_end_update_func)(crtc_ega_device *device, bitmap_ind16 &bitmap, const rectangle &cliprect, void *param);
#define CRTC_EGA_END_UPDATE(name)		void name(crtc_ega_device *device, bitmap_ind16 &bitmap, const rectangle &cliprect, void *param)


/* interface */
typedef struct _crtc_ega_interface crtc_ega_interface;
struct _crtc_ega_interface
{
	const char *m_screen_tag;		/* screen we are acting on */
	int m_hpixels_per_column;		/* number of pixels per video memory address */

	/* if specified, this gets called before any pixel update,
       optionally return a pointer that will be passed to the
       update and tear down callbacks */
	crtc_ega_begin_update_func		m_begin_update;

	/* this gets called for every row, the driver must output
       x_count * hpixels_per_column pixels.
       cursor_x indicates the character position where the cursor is, or -1
       if there is no cursor on this row */
	crtc_ega_update_row_func		m_update_row;

	/* if specified, this gets called after all row updating is complete */
	crtc_ega_end_update_func			m_end_update;

	/* if specified, this gets called for every change of the disply enable signal */
	devcb_write_line	m_out_de_func;

	/* if specified, this gets called for every change of the HSYNC signal */
	devcb_write_line	m_out_hsync_func;

	/* if specified, this gets called for every change of the VSYNC signal */
	devcb_write_line	m_out_vsync_func;

	devcb_write_line	m_out_vblank_func;
};


class crtc_ega_device :	public device_t,
						public crtc_ega_interface
{
public:
	crtc_ega_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);

	/* select one of the registers for reading or writing */
	DECLARE_WRITE8_MEMBER( address_w );

	/* read from the currently selected register */
	DECLARE_READ8_MEMBER( register_r );

	/* write to the currently selected register */
	DECLARE_WRITE8_MEMBER( register_w );

	/* return the current value on the MA0-MA15 pins */
	UINT16 get_ma();

	/* return the current value on the RA0-RA4 pins */
	UINT8 get_ra();

	/* simulates the LO->HI clocking of the light pen pin */
	void assert_light_pen_input();

	/* set the clock of the chip */
	void set_clock(int clock);

	/* set number of pixels per video memory address */
	void set_hpixels_per_column(int hpixels_per_column);

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

protected:
	// device-level overrides
	virtual void device_config_complete();
	virtual void device_start();
	virtual void device_reset();
	virtual void device_post_load();
	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);

private:
	screen_device *m_screen;

	devcb_resolved_write_line	m_res_out_de_func;
	devcb_resolved_write_line	m_res_out_cur_func;
	devcb_resolved_write_line	m_res_out_hsync_func;
	devcb_resolved_write_line	m_res_out_vsync_func;
	devcb_resolved_write_line	m_res_out_vblank_func;

	/* ega/vga register file */
	UINT8	m_horiz_char_total;	/* 0x00 */
	UINT8	m_horiz_disp;			/* 0x01 */
	UINT8	m_horiz_blank_start;	/* 0x02 */
	UINT8	m_horiz_blank_end;	/* 0x03/0x05 */
	UINT8	m_ena_vert_access;	/* 0x03 */
	UINT8	m_de_skew;			/* 0x03 */
	UINT8	m_horiz_retr_start;	/* 0x04 */
	UINT8	m_horiz_retr_end;		/* 0x05 */
	UINT8	m_horiz_retr_skew;	/* 0x05 */
	UINT16	m_vert_total;			/* 0x06/0x07 */
	UINT8	m_preset_row_scan;	/* 0x08 */
	UINT8	m_byte_panning;		/* 0x08 */
	UINT8	m_max_ras_addr;		/* 0x09 */
	UINT8	m_scan_doubling;		/* 0x09 */
	UINT8	m_cursor_start_ras;	/* 0x0a */
	UINT8	m_cursor_disable;		/* 0x0a */
	UINT8	m_cursor_end_ras;		/* 0x0b */
	UINT8	m_cursor_skew;		/* 0x0b */
	UINT16	m_disp_start_addr;	/* 0x0c/0x0d */
	UINT16	m_cursor_addr;		/* 0x0e/0x0f */
	UINT16	m_light_pen_addr;		/* 0x10/0x11 */
	UINT16	m_vert_retr_start;	/* 0x10/0x07 */
	UINT8	m_vert_retr_end;		/* 0x11 */
	UINT8	m_protect;			/* 0x11 */
	UINT8	m_bandwidth;			/* 0x11 */
	UINT16	m_vert_disp_end;		/* 0x12/0x07 */
	UINT8	m_offset;				/* 0x13 */
	UINT8	m_underline_loc;		/* 0x14 */
	UINT16	m_vert_blank_start;	/* 0x15/0x07/0x09 */
	UINT8	m_vert_blank_end;		/* 0x16 */
	UINT8	m_mode_control;		/* 0x17 */
	UINT16	m_line_compare;		/* 0x18/0x07/0x09 */

	/* other internal state */
	UINT8	m_register_address_latch;
	UINT8	m_hpixels_per_column;
	bool	m_cursor_state;	/* 0 = off, 1 = on */
	UINT8	m_cursor_blink_count;

	/* output signals */
	int		m_cur;
	int		m_hsync;
	int		m_vsync;
	int		m_vblank;
	int		m_de;

	/* internal counters */
	UINT8	m_character_counter;
	UINT8	m_hsync_width_counter;
	UINT16	m_line_counter;
	UINT8	m_raster_counter;
	UINT8	m_vsync_width_counter;
	bool	m_line_enable_ff;		/* Internal flip flop which is set when the line_counter is reset and reset when vert_disp is reached */
	UINT8	m_vsync_ff;
	UINT8	m_adjust_active;
	UINT16	m_line_address;
	INT16	m_cursor_x;

	/* timers */
	static const device_timer_id TIMER_LINE = 0;
	static const device_timer_id TIMER_DE_OFF = 1;
	static const device_timer_id TIMER_CUR_ON = 2;
	static const device_timer_id TIMER_CUR_OFF = 3;
	static const device_timer_id TIMER_HSYNC_ON = 4;
	static const device_timer_id TIMER_HSYNC_OFF = 5;
	static const device_timer_id TIMER_LIGHT_PEN_LATCH = 6;

	emu_timer *m_line_timer;
	emu_timer *m_de_off_timer;
	emu_timer *m_cur_on_timer;
	emu_timer *m_cur_off_timer;
	emu_timer *m_hsync_on_timer;
	emu_timer *m_hsync_off_timer;
	emu_timer *m_light_pen_latch_timer;

	/* computed values - do NOT state save these! */
	UINT16	m_horiz_pix_total;
	UINT16	m_vert_pix_total;
	UINT16	m_max_visible_x;
	UINT16	m_max_visible_y;
	UINT16	m_hsync_on_pos;
	UINT16	m_hsync_off_pos;
	UINT16	m_vsync_on_pos;
	UINT16	m_vsync_off_pos;
	UINT16  m_current_disp_addr;	/* the display address currently drawn */
	UINT8	m_light_pen_latched;
	bool	m_has_valid_parameters;

	void recompute_parameters(bool postload);
	void update_counters();
	void set_de(int state);
	void set_hsync(int state);
	void set_vsync(int state);
	void set_vblank(int state);
	void set_cur(int state);
	void handle_line_timer();
	void update_cursor_state();
};

extern const device_type CRTC_EGA;

#endif