1 // license:GPL-2.0+
2 // copyright-holders:Peter Trauner
3 /******************************************************************************
4  watara supervision handheld
5 
6  PeT mess@utanet.at in december 2000
7 ******************************************************************************/
8 
9 #include "emu.h"
10 #include "includes/svision.h"
11 #include "screen.h"
12 #include "softlist.h"
13 #include "speaker.h"
14 
15 #include "svision.lh"
16 
17 
18 #define MAKE8_RGB32(red3, green3, blue2) ( ( (red3)<<(16+5)) | ( (green3)<<(8+5)) | ( (blue2)<<(0+6)) )
19 #define MAKE9_RGB32(red3, green3, blue3) ( ( (red3)<<(16+5)) | ( (green3)<<(8+5)) | ( (blue3)<<(0+5)) )
20 #define MAKE12_RGB32(red4, green4, blue4) ( ( (red4)<<(16+4)) | ((green4)<<(8+4)) | ((blue4)<<(0+4)) )
21 #define MAKE24_RGB32(red8, green8, blue8) ( (((red8)&0xf8)<<16) | (((green8)&0xf8)<<8) | (((blue8)&0xf8)) )
22 
23 
TIMER_CALLBACK_MEMBER(svision_state::svision_pet_timer)24 TIMER_CALLBACK_MEMBER(svision_state::svision_pet_timer)
25 {
26 	switch (m_pet.state)
27 	{
28 		case 0x00:
29 			if (m_joy2.found())
30 			{
31 				m_pet.input = m_joy2->read();
32 			}
33 			/* fall through */
34 
35 		case 0x02: case 0x04: case 0x06: case 0x08:
36 		case 0x0a: case 0x0c: case 0x0e:
37 			m_pet.clock = m_pet.state & 2;
38 			m_pet.data = m_pet.input & 1;
39 			m_pet.input >>= 1;
40 			m_pet.state++;
41 			break;
42 
43 		case 0x1f:
44 			m_pet.state = 0;
45 			break;
46 
47 		default:
48 			m_pet.state++;
49 			break;
50 	}
51 }
52 
TIMER_DEVICE_CALLBACK_MEMBER(svision_state::svision_pet_timer_dev)53 TIMER_DEVICE_CALLBACK_MEMBER(svision_state::svision_pet_timer_dev)
54 {
55 	svision_pet_timer(ptr,param);
56 }
57 
WRITE_LINE_MEMBER(svision_state::sound_irq_w)58 WRITE_LINE_MEMBER(svision_state::sound_irq_w)
59 {
60 	m_dma_finished = true;
61 	check_irq();
62 }
63 
check_irq()64 void svision_state::check_irq()
65 {
66 	bool irq = m_svision.timer_shot && BIT(m_reg[BANK], 1);
67 	irq = irq || (m_dma_finished && BIT(m_reg[BANK], 2));
68 
69 	m_maincpu->set_input_line(M65C02_IRQ_LINE, irq ? ASSERT_LINE : CLEAR_LINE);
70 }
71 
TIMER_CALLBACK_MEMBER(svision_state::svision_timer)72 TIMER_CALLBACK_MEMBER(svision_state::svision_timer)
73 {
74 	m_svision.timer_shot = true;
75 	m_svision.timer1->enable(false);
76 	check_irq();
77 }
78 
svision_r(offs_t offset)79 uint8_t svision_state::svision_r(offs_t offset)
80 {
81 	int data = m_reg[offset];
82 	switch (offset)
83 	{
84 		case 0x20:
85 			return m_joy->read();
86 
87 		case 0x21:
88 			data &= ~0xf;
89 			data |= m_reg[0x22] & 0xf;
90 			if (m_pet.on)
91 			{
92 				if (!m_pet.clock)
93 				{
94 					data &= ~4;
95 				}
96 				if (!m_pet.data)
97 				{
98 					data &= ~8;
99 				}
100 			}
101 			break;
102 
103 		case 0x27:
104 			data &= ~3;
105 			if (m_svision.timer_shot)
106 			{
107 				data |= 1;
108 			}
109 			if (m_dma_finished)
110 			{
111 				data |= 2;
112 			}
113 			break;
114 
115 		case 0x24:
116 			m_svision.timer_shot = false;
117 			check_irq();
118 			break;
119 
120 		case 0x25:
121 			m_dma_finished = false;
122 			check_irq();
123 			break;
124 
125 		default:
126 			logerror("%.6f svision read %04x %02x\n", machine().time().as_double(),offset,data);
127 			break;
128 	}
129 
130 	return data;
131 }
132 
svision_w(offs_t offset,uint8_t data)133 void svision_state::svision_w(offs_t offset, uint8_t data)
134 {
135 	m_reg[offset] = data;
136 
137 	switch (offset)
138 	{
139 		case 0x02:
140 		case 0x03:
141 			break;
142 
143 		case 0x26: /* bits 5,6 memory management for a000? */
144 		{
145 			logerror("%.6f svision write %04x %02x\n", machine().time().as_double(), offset, data);
146 			int bank = ((m_reg[0x26] & 0xe0) >> 5) % (m_cart_rom->bytes() / 0x4000);
147 			m_bank1->set_base(m_cart_rom->base() + (bank * 0x4000));
148 			check_irq();
149 			break;
150 		}
151 
152 		case 0x23: /* delta hero irq routine write */
153 		{
154 			int delay = (data == 0) ? 0x100 : data;
155 			delay *= (BIT(m_reg[BANK], 4)) ? 0x4000 : 0x100;
156 			m_svision.timer1->enable(true);
157 			m_svision.timer1->reset(m_maincpu->cycles_to_attotime(delay));
158 			break;
159 		}
160 
161 		case 0x10: case 0x11: case 0x12: case 0x13:
162 			m_sound->soundport_w(0, offset & 3, data);
163 			break;
164 
165 		case 0x14: case 0x15: case 0x16: case 0x17:
166 			m_sound->soundport_w(1, offset & 3, data);
167 			break;
168 
169 		case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c:
170 			m_sound->sounddma_w(offset - 0x18, data);
171 			break;
172 
173 		case 0x28: case 0x29: case 0x2a:
174 			m_sound->noise_w(offset - 0x28, data);
175 			break;
176 
177 		default:
178 			logerror("%.6f svision write %04x %02x\n", machine().time().as_double(), offset, data);
179 			break;
180 	}
181 }
182 
tvlink_r(offs_t offset)183 uint8_t svision_state::tvlink_r(offs_t offset)
184 {
185 	switch(offset)
186 	{
187 		default:
188 			if (offset >= 0x800 && offset < 0x840)
189 			{
190 				/* strange effects when modifying palette */
191 				return svision_r(offset);
192 			}
193 			else
194 			{
195 				return svision_r(offset);
196 			}
197 	}
198 }
199 
tvlink_w(offs_t offset,uint8_t data)200 void svision_state::tvlink_w(offs_t offset, uint8_t data)
201 {
202 	switch (offset)
203 	{
204 		case 0x0e:
205 			m_reg[offset] = data;
206 			m_tvlink.palette_on = data & 1;
207 			if (m_tvlink.palette_on)
208 			{
209 				// hack, normally initialising with palette from ram
210 				m_tvlink.palette[0] = MAKE12_RGB32(163/16,172/16,115/16); // these are the tron colors messured from screenshot
211 				m_tvlink.palette[1] = MAKE12_RGB32(163/16,155/16,153/16);
212 				m_tvlink.palette[2] = MAKE12_RGB32(77/16,125/16,73/16);
213 				m_tvlink.palette[3] = MAKE12_RGB32(59/16,24/16,20/16);
214 			}
215 			else
216 			{
217 				// cleaner to use colors from compile time palette, or compose from "fixed" palette values
218 				m_tvlink.palette[0]=MAKE12_RGB32(0,0,0);
219 				m_tvlink.palette[1]=MAKE12_RGB32(5*16/256,18*16/256,9*16/256);
220 				m_tvlink.palette[2]=MAKE12_RGB32(48*16/256,76*16/256,100*16/256);
221 				m_tvlink.palette[3]=MAKE12_RGB32(190*16/256,190*16/256,190*16/256);
222 			}
223 			break;
224 		default:
225 			svision_w(offset,data);
226 			if (offset >= 0x800 && offset < 0x840)
227 			{
228 				if (offset == 0x803 && data == 0x07)
229 				{
230 					/* tron hack */
231 					m_reg[0x0804] = 0x00;
232 					m_reg[0x0805] = 0x01;
233 					m_reg[0x0806] = 0x00;
234 					m_reg[0x0807] = 0x00;
235 				}
236 				uint16_t c = m_reg[0x800] | (m_reg[0x804] << 8);
237 				m_tvlink.palette[0] = MAKE9_RGB32( (c>>0)&7, (c>>3)&7, (c>>6)&7);
238 				c = m_reg[0x801] | (m_reg[0x805] << 8);
239 				m_tvlink.palette[1] = MAKE9_RGB32( (c>>0)&7, (c>>3)&7, (c>>6)&7);
240 				c = m_reg[0x802] | (m_reg[0x806]<<8);
241 				m_tvlink.palette[2]=MAKE9_RGB32( (c>>0)&7, (c>>3)&7, (c>>6)&7);
242 				c = m_reg[0x803] | (m_reg[0x807]<<8);
243 				m_tvlink.palette[3]=MAKE9_RGB32( (c>>0)&7, (c>>3)&7, (c>>6)&7);
244 				/* writes to palette effect video color immediately */
245 				/* some writes modify other registers, */
246 				/* encoding therefor not known (rgb8 or rgb9) */
247 			}
248 	}
249 }
250 
svision_mem(address_map & map)251 void svision_state::svision_mem(address_map &map)
252 {
253 	map(0x0000, 0x1fff).ram();
254 	map(0x2000, 0x3fff).rw(FUNC(svision_state::svision_r), FUNC(svision_state::svision_w)).share(m_reg);
255 	map(0x4000, 0x5fff).ram().share(m_videoram);
256 	map(0x6000, 0x7fff).noprw();
257 	map(0x8000, 0xbfff).bankr(m_bank1);
258 	map(0xc000, 0xffff).bankr(m_bank2);
259 }
260 
tvlink_mem(address_map & map)261 void svision_state::tvlink_mem(address_map &map)
262 {
263 	map(0x0000, 0x1fff).ram();
264 	map(0x2000, 0x3fff).rw(FUNC(svision_state::tvlink_r), FUNC(svision_state::tvlink_w)).share(m_reg);
265 	map(0x4000, 0x5fff).ram().share(m_videoram);
266 	map(0x6000, 0x7fff).noprw();
267 	map(0x8000, 0xbfff).bankr(m_bank1);
268 	map(0xc000, 0xffff).bankr(m_bank2);
269 }
270 
271 static INPUT_PORTS_START( svision )
272 	PORT_START("JOY")
273 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT)
274 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT )
275 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN )
276 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP   )
277 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("B")
278 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("A")
279 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SELECT) PORT_NAME("Select")
280 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START) PORT_NAME("Start/Pause")
281 INPUT_PORTS_END
282 
283 static INPUT_PORTS_START( svisions )
284 	PORT_START("JOY")
285 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_PLAYER(1)
286 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
287 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
288 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP   ) PORT_PLAYER(1)
289 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("B") PORT_PLAYER(1)
290 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("A") PORT_PLAYER(1)
291 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SELECT) PORT_NAME("Select") PORT_PLAYER(1)
292 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START) PORT_NAME("Start/Pause") PORT_PLAYER(1)
293 	PORT_START("JOY2")
294 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_PLAYER(2)
295 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
296 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
297 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP   ) PORT_PLAYER(2)
298 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("2nd B") PORT_PLAYER(2)
299 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("2nd A") PORT_PLAYER(2)
300 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SELECT) PORT_NAME("2nd Select") PORT_PLAYER(2)
301 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START) PORT_NAME("2nd Start/Pause") PORT_PLAYER(2)
302 INPUT_PORTS_END
303 
304 // most games contain their graphics in roms, and have hardware to draw complete rectangular objects
305 
306 // palette in red, green, blue triples
307 static constexpr rgb_t svision_pens[] =
308 {
309 #if 0
310 	// greens grabbed from a scan of a handheld in its best adjustment for contrast
311 	{ 86, 121,  86 },
312 	{ 81, 115,  90 },
313 	{ 74, 107, 101 },
314 	{ 54,  78,  85 }
315 #else
316 	// grabbed from chris covell's black white pics
317 	{ 0xe0, 0xe0, 0xe0 },
318 	{ 0xb9, 0xb9, 0xb9 },
319 	{ 0x54, 0x54, 0x54 },
320 	{ 0x12, 0x12, 0x12 }
321 #endif
322 };
323 
324 // palette in RGB triplets
325 static constexpr rgb_t svisionp_pens[] =
326 {
327 	// pal
328 	{   1,   1,   3 },
329 	{   5,  18,   9 },
330 	{  48,  76, 100 },
331 	{ 190, 190, 190 }
332 };
333 
334 // palette in RGB triplets
335 static constexpr rgb_t svisionn_pens[] =
336 {
337 	{   0,   0,   0 },
338 	{ 188, 242, 244 }, // darker
339 	{ 129, 204, 255 },
340 	{ 245, 249, 248 }
341 };
342 
svision_palette(palette_device & palette) const343 void svision_state::svision_palette(palette_device &palette) const
344 {
345 	palette.set_pen_colors(0, svision_pens);
346 }
svisionn_palette(palette_device & palette) const347 void svision_state::svisionn_palette(palette_device &palette) const
348 {
349 	palette.set_pen_colors(0, svisionn_pens);
350 }
svisionp_palette(palette_device & palette) const351 void svision_state::svisionp_palette(palette_device &palette) const
352 {
353 	palette.set_pen_colors(0, svisionp_pens);
354 }
355 
screen_update_svision(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)356 uint32_t svision_state::screen_update_svision(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
357 {
358 	if (BIT(m_reg[BANK], 3))
359 	{
360 		int j = m_reg[XPOS] / 4 + m_reg[YPOS] * 0x30;
361 		for (int y = 0; y < 160; y++)
362 		{
363 			const int start_x = 3 - (m_reg[XPOS] & 3);
364 			const int end_x = std::min(163, m_reg[XSIZE] | 3);
365 			uint16_t *line = &bitmap.pix(y, start_x);
366 			for (int x = start_x, i = 0; x < end_x; x+=4, i++)
367 			{
368 				uint8_t b = m_videoram[j+i];
369 				for (int pix = 0; pix < 4; pix++)
370 				{
371 					*line = b & 3;
372 					b >>= 2;
373 					line++;
374 				}
375 			}
376 			j += 0x30;
377 			if (j >= 0x1fe0)
378 				j = 0; //sssnake
379 		}
380 	}
381 	else
382 	{
383 		bitmap.plot_box(3, 0, 162, 159, 0);
384 	}
385 	return 0;
386 }
387 
screen_update_tvlink(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)388 uint32_t svision_state::screen_update_tvlink(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
389 {
390 	if (BIT(m_reg[BANK], 3))
391 	{
392 		int j = m_reg[XPOS] / 4 + m_reg[YPOS] * 0x30;
393 		for (int y = 0; y < 160; y++)
394 		{
395 			const int start_x = 3 - (m_reg[XPOS] & 3);
396 			const int end_x = std::min(163, m_reg[XSIZE] | 3);
397 			uint32_t *line = &bitmap.pix(y, start_x);
398 			for (int x = start_x, i = 0; x < end_x; x += 4, i++)
399 			{
400 				uint8_t b = m_videoram[j + i];
401 				for (int pix = 0; pix < 4; pix++)
402 				{
403 					*line = m_tvlink.palette[b & 3];
404 					b >>= 2;
405 					line++;
406 				}
407 			}
408 			j += 0x30;
409 			if (j >= 0x1fe0)
410 				j = 0; //sssnake
411 		}
412 	}
413 	else
414 	{
415 		bitmap.plot_box(3, 0, 162, 159, m_palette->pen(0));
416 	}
417 	return 0;
418 }
419 
WRITE_LINE_MEMBER(svision_state::frame_int_w)420 WRITE_LINE_MEMBER(svision_state::frame_int_w)
421 {
422 	if (!state)
423 		return;
424 
425 	if (BIT(m_reg[BANK], 0))
426 		m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
427 
428 	m_sound->sound_decrement();
429 }
430 
init_svision()431 void svision_state::init_svision()
432 {
433 	m_svision.timer1 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(svision_state::svision_timer),this));
434 	m_dma_finished = false;
435 	m_pet.on = false;
436 }
437 
init_svisions()438 void svision_state::init_svisions()
439 {
440 	m_svision.timer1 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(svision_state::svision_timer),this));
441 	m_dma_finished = false;
442 	m_pet.on = true;
443 	m_pet.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(svision_state::svision_pet_timer),this));
444 }
445 
DEVICE_IMAGE_LOAD_MEMBER(svision_state::cart_load)446 DEVICE_IMAGE_LOAD_MEMBER( svision_state::cart_load )
447 {
448 	uint32_t size = m_cart->common_get_size("rom");
449 
450 	if (size > 0x80000)
451 	{
452 		image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size");
453 		return image_init_result::FAIL;
454 	}
455 
456 	m_cart->rom_alloc(size, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
457 	m_cart->common_load_rom(m_cart->get_rom_base(), size, "rom");
458 
459 	return image_init_result::PASS;
460 }
461 
machine_start()462 void svision_state::machine_start()
463 {
464 	std::string region_tag(m_cart->tag());
465 	region_tag.append(GENERIC_ROM_REGION_TAG);
466 	m_cart_rom = memregion(region_tag.c_str());
467 
468 	if (m_cart_rom)
469 	{
470 		int num_banks = m_cart_rom->bytes() / 0x4000;
471 		m_bank1->set_base(m_cart_rom->base());
472 		m_bank2->set_base(m_cart_rom->base() + (num_banks - 1) * 0x4000); // bank2 is set to the last bank
473 	}
474 }
475 
machine_reset()476 void svision_state::machine_reset()
477 {
478 	m_svision.timer_shot = false;
479 	m_dma_finished = false;
480 }
481 
482 
MACHINE_RESET_MEMBER(svision_state,tvlink)483 MACHINE_RESET_MEMBER(svision_state,tvlink)
484 {
485 	svision_state::machine_reset();
486 	m_tvlink.palette_on = false;
487 
488 	memset(m_reg + 0x800, 0xff, 0x40); // normally done from m_tvlink microcontroller
489 	m_reg[0x82a] = 0xdf;
490 
491 	m_tvlink.palette[0] = MAKE24_RGB32(svisionp_pens[0].r(), svisionp_pens[0].g(), svisionp_pens[0].b());
492 	m_tvlink.palette[1] = MAKE24_RGB32(svisionp_pens[1].r(), svisionp_pens[1].g(), svisionp_pens[1].b());
493 	m_tvlink.palette[2] = MAKE24_RGB32(svisionp_pens[2].r(), svisionp_pens[2].g(), svisionp_pens[2].b());
494 	m_tvlink.palette[3] = MAKE24_RGB32(svisionp_pens[3].r(), svisionp_pens[3].g(), svisionp_pens[3].b());
495 }
496 
svision_base(machine_config & config)497 void svision_state::svision_base(machine_config &config)
498 {
499 	config.set_default_layout(layout_svision);
500 
501 	SPEAKER(config, "lspeaker").front_left();
502 	SPEAKER(config, "rspeaker").front_right();
503 	SVISION_SND(config, m_sound, 4000000, m_maincpu, m_bank1);
504 	m_sound->add_route(0, "lspeaker", 0.50);
505 	m_sound->add_route(1, "rspeaker", 0.50);
506 	m_sound->irq_cb().set(FUNC(svision_state::sound_irq_w));
507 
508 	GENERIC_CARTSLOT(config, m_cart, generic_plain_slot, "svision_cart", "bin,ws,sv");
509 	m_cart->set_must_be_loaded(true);
510 	m_cart->set_device_load(FUNC(svision_state::cart_load));
511 
512 	SOFTWARE_LIST(config, "cart_list").set_original("svision");
513 }
514 
svision(machine_config & config)515 void svision_state::svision(machine_config &config)
516 {
517 	svision_base(config);
518 
519 	M65C02(config, m_maincpu, 4000000);
520 	m_maincpu->set_addrmap(AS_PROGRAM, &svision_state::svision_mem);
521 
522 	SCREEN(config, m_screen, SCREEN_TYPE_LCD);
523 	m_screen->set_refresh_hz(61);
524 	m_screen->set_size(3+160+3, 160);
525 	m_screen->set_visarea(3+0, 3+160-1, 0, 160-1);
526 	m_screen->set_screen_update(FUNC(svision_state::screen_update_svision));
527 	m_screen->set_palette(m_palette);
528 	m_screen->screen_vblank().set(FUNC(svision_state::frame_int_w));
529 
530 	PALETTE(config, m_palette, FUNC(svision_state::svision_palette), ARRAY_LENGTH(svision_pens));
531 }
532 
svisions(machine_config & config)533 void svision_state::svisions(machine_config &config)
534 {
535 	svision(config);
536 	TIMER(config, "pet_timer").configure_periodic(FUNC(svision_state::svision_pet_timer_dev), attotime::from_seconds(8));
537 }
538 
svisionp(machine_config & config)539 void svision_state::svisionp(machine_config &config)
540 {
541 	svision(config);
542 
543 	m_maincpu->set_clock(4430000);
544 	m_screen->set_refresh(HZ_TO_ATTOSECONDS(50));
545 	m_palette->set_init(FUNC(svision_state::svisionp_palette));
546 }
547 
svisionn(machine_config & config)548 void svision_state::svisionn(machine_config &config)
549 {
550 	svision(config);
551 	m_maincpu->set_clock(3560000/*?*/);
552 	m_screen->set_refresh(HZ_TO_ATTOSECONDS(60));
553 	m_palette->set_init(FUNC(svision_state::svisionn_palette));
554 }
555 
tvlinkp(machine_config & config)556 void svision_state::tvlinkp(machine_config &config)
557 {
558 	svisionp(config);
559 	m_maincpu->set_addrmap(AS_PROGRAM, &svision_state::tvlink_mem);
560 
561 	m_screen->set_no_palette();
562 	m_screen->set_screen_update(FUNC(svision_state::screen_update_tvlink));
563 
564 	MCFG_MACHINE_RESET_OVERRIDE(svision_state, tvlink)
565 }
566 
567 ROM_START(svision)
568 	ROM_REGION(0x80000, "maincpu", ROMREGION_ERASE00)
569 ROM_END
570 
571 /***************************************************************************
572 
573   Game driver(s)
574 
575 ***************************************************************************/
576 
577 #define rom_svisions rom_svision
578 #define rom_svisionn rom_svision
579 #define rom_svisionp rom_svision
580 #define rom_tvlinkp  rom_svision
581 
582 //    YEAR  NAME      PARENT   COMPAT  MACHINE   INPUT     STATE          INIT           COMPANY   FULLNAME                                       FLAGS
583 // marketed under a ton of firms and names
584 CONS(1992,  svision,  0,       0,      svision,  svision,  svision_state, init_svision,  "Watara", "Super Vision",                                0 )
585 // svdual 2 connected via communication port
586 CONS( 1992, svisions, svision, 0,      svisions, svisions, svision_state, init_svisions, "Watara", "Super Vision (PeT Communication Simulation)", 0 )
587 
588 CONS( 1993, svisionp, svision, 0,      svisionp, svision,  svision_state, init_svision,  "Watara", "Super Vision (PAL TV Link Colored)",          0 )
589 CONS( 1993, svisionn, svision, 0,      svisionn, svision,  svision_state, init_svision,  "Watara", "Super Vision (NTSC TV Link Colored)",         0 )
590 // svtvlink (2 supervisions)
591 // tvlink (pad supervision simulated)
592 CONS( 199?, tvlinkp,  svision, 0,      tvlinkp,  svision,  svision_state, init_svision,  "Watara", "TV Link PAL",                                 0 )
593