summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/video/v1050.c
blob: b1b8f9d1208334cc3ba121f66fd554c68f789815 (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
#include "includes/v1050.h"

/*

    TODO:

    - bright in reverse video

*/

#define V1050_ATTR_BRIGHT	0x01
#define V1050_ATTR_BLINKING	0x02
#define V1050_ATTR_ATTEN	0x04
#define V1050_ATTR_REVERSE	0x10
#define V1050_ATTR_BLANK	0x20
#define V1050_ATTR_BOLD		0x40
#define V1050_ATTR_BLINK	0x80

/* Video RAM Access */

READ8_MEMBER( v1050_state::attr_r )
{
	return m_attr;
}

WRITE8_MEMBER( v1050_state::attr_w )
{
	m_attr = data;
}

READ8_MEMBER( v1050_state::videoram_r )
{
	if (offset >= 0x2000)
	{
		m_attr = (m_attr & 0xfc) | (m_attr_ram[offset] & 0x03);
	}

	return m_video_ram[offset];
}

WRITE8_MEMBER( v1050_state::videoram_w )
{
	m_video_ram[offset] = data;

	if (offset >= 0x2000 && BIT(m_attr, 2))
	{
		m_attr_ram[offset] = m_attr & 0x03;
	}
}

/* MC6845 Interface */

static MC6845_UPDATE_ROW( v1050_update_row )
{
	v1050_state *state = device->machine().driver_data<v1050_state>();
	const rgb_t *palette = palette_entry_list_raw(bitmap.palette());

	int column, bit;

	for (column = 0; column < x_count; column++)
	{
		UINT16 address = (((ra & 0x03) + 1) << 13) | ((ma & 0x1fff) + column);
		UINT8 data = state->m_video_ram[address & V1050_VIDEORAM_MASK];
		UINT8 attr = (state->m_attr & 0xfc) | (state->m_attr_ram[address] & 0x03);

		for (bit = 0; bit < 8; bit++)
		{
			int x = (column * 8) + bit;
			int color = BIT(data, 7);

			/* blinking */
			if ((attr & V1050_ATTR_BLINKING) && !(attr & V1050_ATTR_BLINK)) color = 0;

			/* reverse video */
			color ^= BIT(attr, 4);

			/* bright */
			if (color && (!(attr & V1050_ATTR_BOLD) ^ (attr & V1050_ATTR_BRIGHT))) color = 2;

			/* display blank */
			if (attr & V1050_ATTR_BLANK) color = 0;

			bitmap.pix32(y, x) = palette[color];

			data <<= 1;
		}
	}
}

WRITE_LINE_MEMBER( v1050_state::crtc_vs_w )
{
	m_subcpu->set_input_line(INPUT_LINE_IRQ0, state ? ASSERT_LINE : CLEAR_LINE);

	set_interrupt(INT_VSYNC, state);
}

static const mc6845_interface crtc_intf =
{
	SCREEN_TAG,
	8,
	NULL,
	v1050_update_row,
	NULL,
	DEVCB_NULL,
	DEVCB_NULL,
	DEVCB_NULL,
	DEVCB_DRIVER_LINE_MEMBER(v1050_state, crtc_vs_w),
	NULL
};

/* Palette */

static PALETTE_INIT( v1050 )
{
	palette_set_color(machine, 0, RGB_BLACK); /* black */
	palette_set_color_rgb(machine, 1, 0x00, 0xc0, 0x00); /* green */
	palette_set_color_rgb(machine, 2, 0x00, 0xff, 0x00); /* bright green */
}

/* Video Start */

void v1050_state::video_start()
{
	/* allocate memory */
	m_attr_ram = auto_alloc_array(machine(), UINT8, V1050_VIDEORAM_SIZE);

	/* register for state saving */
	save_item(NAME(m_attr));
	save_pointer(NAME(m_attr_ram), V1050_VIDEORAM_SIZE);
}

/* Machine Drivers */

MACHINE_CONFIG_FRAGMENT( v1050_video )
	MCFG_MC6845_ADD(H46505_TAG, H46505, XTAL_15_36MHz/8, crtc_intf)

	MCFG_SCREEN_ADD(SCREEN_TAG, RASTER)
	MCFG_SCREEN_UPDATE_DEVICE(H46505_TAG, h46505_device, screen_update)

	MCFG_SCREEN_REFRESH_RATE(60)
	MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500))
	MCFG_SCREEN_SIZE(640, 400)
	MCFG_SCREEN_VISIBLE_AREA(0,640-1, 0, 400-1)

	MCFG_PALETTE_LENGTH(3)
    MCFG_PALETTE_INIT(v1050)
MACHINE_CONFIG_END