1 // License:BSD-3-Clause
2 // copyright-holders:Sven Schnelle
3 /***************************************************************************
4 
5 HP98550 high-resolution color board
6 
7 1280x1024 @ 60Hz, 8 bpp
8 
9 ***************************************************************************/
10 
11 #include "emu.h"
12 #include "hp98550.h"
13 #include "screen.h"
14 #include "video/nereid.h"
15 #include "video/catseye.h"
16 #include "machine/ram.h"
17 
18 //#define VERBOSE 1
19 #include "logmacro.h"
20 
21 ROM_START(hp98550)
22 	ROM_REGION(0x8000, "hp98550a_rom", 0)
23 	ROM_LOAD("98550a.bin", 0x000000, 0x008000, CRC(9d639233) SHA1(d6b23a34850f24525ca5fb36de3deb91196d2dc5))
24 ROM_END
25 
26 DEFINE_DEVICE_TYPE_NS(HPDIO_98550, bus::hp_dio, dio32_98550_device, "dio98550", "HP98550A high-res color DIO video card")
27 
28 namespace bus { namespace hp_dio {
29 
device_add_mconfig(machine_config & config)30 void dio32_98550_device::device_add_mconfig(machine_config &config)
31 {
32 	screen_device &screen(SCREEN(config, "hp98550_screen", SCREEN_TYPE_RASTER));
33 	screen.set_screen_update(FUNC(dio32_98550_device::screen_update));
34 	screen.screen_vblank().set(FUNC(dio32_98550_device::vblank_w));
35 	screen.set_raw(XTAL(108'108'000), 1689, 0, m_h_pix, 1066, 0, m_v_pix);
36 
37 	for (int i = 0; i < CATSEYE_COUNT; i++) {
38 		CATSEYE(config, m_catseye[i], XTAL(108'108'000));
39 		m_catseye[i]->set_fb_width(m_fb_width);
40 		m_catseye[i]->set_fb_height(m_v_pix);
41 		m_catseye[i]->set_plane(i);
42 		m_catseye[i]->irq_out_cb().set(FUNC(dio32_98550_device::int_w));
43 	}
44 
45 	NEREID(config, m_nereid, 0);
46 }
47 
device_rom_region() const48 const tiny_rom_entry *dio32_98550_device::device_rom_region() const
49 {
50 	return ROM_NAME(hp98550);
51 }
52 
map(address_map & map)53 void dio32_98550_device::map(address_map& map)
54 {
55 	map(0, 0x3fffff).ram().share("vram_video");
56 	map(0x400000, 0x7fffff).ram().share("vram_overlay");
57 }
58 
memory_space_config() const59 device_memory_interface::space_config_vector dio32_98550_device::memory_space_config() const
60 {
61 		return space_config_vector {
62 				std::make_pair(0, &m_space_config)
63 		};
64 }
65 
dio32_98550_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)66 dio32_98550_device::dio32_98550_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
67 	dio32_98550_device(mconfig, HPDIO_98550, tag, owner, clock)
68 {
69 }
70 
dio32_98550_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)71 dio32_98550_device::dio32_98550_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
72 	device_t(mconfig, type, tag, owner, clock),
73 	device_dio16_card_interface(mconfig, *this),
74 	device_memory_interface(mconfig, *this),
75 	m_nereid(*this, "nereid"),
76 	m_catseye(*this, "catseye%d", 0),
77 	m_space_config("vram", ENDIANNESS_BIG, 8, 23, 0, address_map_constructor(FUNC(dio32_98550_device::map), this)),
78 	m_rom(*this, "hp98550a_rom"),
79 	m_vram(*this, { "vram_video", "vram_overlay"})
80 {
81 }
82 
device_start()83 void dio32_98550_device::device_start()
84 {
85 	save_item(NAME(m_intreg));
86 	save_item(NAME(m_ints));
87 
88 	dio().install_memory(
89 			0x200000, 0x3fffff,
90 			read16s_delegate(*this, FUNC(dio32_98550_device::vram_r)),
91 			write16s_delegate(*this, FUNC(dio32_98550_device::vram_w)));
92 
93 	dio().install_memory(
94 			0x560000, 0x56ffff,
95 			read16s_delegate(*this, FUNC(dio32_98550_device::rom_r)),
96 			write16s_delegate(*this, FUNC(dio32_98550_device::rom_w)));
97 
98 	dio().install_memory(
99 			0x564000, 0x5648ff,
100 			read16_delegate(*this, FUNC(dio32_98550_device::catseye_r)),
101 			write16_delegate(*this, FUNC(dio32_98550_device::catseye_w)));
102 
103 	dio().install_memory(
104 			0x566000, 0x5660ff,
105 			read16s_delegate(*m_nereid, FUNC(nereid_device::ctrl_r)),
106 			write16s_delegate(*m_nereid, FUNC(nereid_device::ctrl_w)));
107 }
108 
device_reset()109 void dio32_98550_device::device_reset()
110 {
111 	m_intreg = 0;
112 	m_ints = 0;
113 }
114 
rom_r(offs_t offset,uint16_t mem_mask)115 uint16_t dio32_98550_device::rom_r(offs_t offset, uint16_t mem_mask)
116 {
117 	LOG("%s: %04x\n", __func__, offset);
118 
119 	if (offset == 1)
120 		return m_intreg;
121 
122 	return 0xff00 | m_rom[offset];
123 }
124 
rom_w(offs_t offset,uint16_t data,uint16_t mem_mask)125 void dio32_98550_device::rom_w(offs_t offset, uint16_t data, uint16_t mem_mask)
126 {
127 	switch (offset) {
128 	case 0:
129 		reset();
130 		break;
131 
132 	case 1:
133 		m_intreg = data;
134 		break;
135 
136 	default:
137 		logerror("%s: %04x = %04x (mask %04x)\n", __func__, offset << 1, data, mem_mask);
138 		break;
139 	}
140 }
141 
catseye_r(address_space & space,offs_t offset,uint16_t mem_mask)142 uint16_t dio32_98550_device::catseye_r(address_space &space, offs_t offset, uint16_t mem_mask)
143 {
144 	uint16_t ret = 0;
145 
146 	for (auto &ce: m_catseye)
147 		ret |= ce->ctrl_r(space, offset, mem_mask);
148 	LOG("%s: %04X = %04X\n", __func__, offset << 1, ret);
149 	return ret;
150 }
151 
catseye_w(address_space & space,offs_t offset,uint16_t data,uint16_t mem_mask)152 void dio32_98550_device::catseye_w(address_space &space, offs_t offset, uint16_t data, uint16_t mem_mask)
153 {
154 	LOG("%s: %04X = %04X\n", __func__, offset << 1, data);
155 	for (auto &ce: m_catseye)
156 		ce->ctrl_w(offset, data, mem_mask);
157 }
158 
vram_r(offs_t offset,uint16_t mem_mask)159 uint16_t dio32_98550_device::vram_r(offs_t offset, uint16_t mem_mask)
160 {
161 	uint16_t ret = 0;
162 
163 	for (auto &ce: m_catseye)
164 		ret |= ce->vram_r(offset, mem_mask);
165 
166 	return ret;
167 }
168 
vram_w(offs_t offset,uint16_t data,uint16_t mem_mask)169 void dio32_98550_device::vram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
170 {
171 	for (auto &ce: m_catseye)
172 		ce->vram_w(offset, data, mem_mask);
173 }
174 
WRITE_LINE_MEMBER(dio32_98550_device::vblank_w)175 WRITE_LINE_MEMBER(dio32_98550_device::vblank_w)
176 {
177 	for (auto &ce: m_catseye)
178 		ce->vblank_w(state);
179 }
180 
int_w(offs_t offset,uint8_t data)181 void dio32_98550_device::int_w(offs_t offset, uint8_t data)
182 {
183 	LOG("%s: plane%d = %s\n", __func__, offset, data ? "assert" : "deassert");
184 	m_ints &= ~(1 << offset);
185 	m_ints |= data;
186 	update_int();
187 }
188 
update_int()189 void dio32_98550_device::update_int()
190 {
191 	bool state = m_ints;
192 	int line = (m_intreg >> 3) & 7;
193 
194 	if (!(m_intreg & 0x80))
195 		state = false;
196 
197 	irq1_out(line == 1 && state);
198 	irq2_out(line == 2 && state);
199 	irq3_out(line == 3 && state);
200 	irq4_out(line == 4 && state);
201 	irq5_out(line == 5 && state);
202 	irq6_out(line == 6 && state);
203 	irq7_out(line == 7 && state);
204 }
205 
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)206 uint32_t dio32_98550_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
207 {
208 	bool changed = false;
209 	uint8_t mask = 0;
210 
211 	for (auto &ce: m_catseye)
212 		changed |= ce->has_changed();
213 
214 	if (!changed)
215 		return UPDATE_HAS_NOT_CHANGED;
216 
217 	for (auto &ce: m_catseye)
218 		mask |= ce->plane_enabled();
219 
220 	for (int y = 0; y < m_v_pix; y++) {
221 		uint32_t *scanline = &bitmap.pix(y);
222 
223 		for (int x = 0; x < m_h_pix; x++) {
224 			const int offset = y * m_fb_width +x;
225 			uint8_t tmp = m_vram[0][offset] & mask;
226 			uint8_t ovl = m_vram[1][offset] & mask;
227 			*scanline++ = m_nereid->map_color(tmp, ovl);
228 		}
229 	}
230 	return 0;
231 }
232 
233 } // namespace bus::hp_dio
234 } // namespace bus
235