summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/svision.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/svision.cpp')
-rw-r--r--src/mame/drivers/svision.cpp607
1 files changed, 607 insertions, 0 deletions
diff --git a/src/mame/drivers/svision.cpp b/src/mame/drivers/svision.cpp
new file mode 100644
index 00000000000..55045c506ec
--- /dev/null
+++ b/src/mame/drivers/svision.cpp
@@ -0,0 +1,607 @@
+// license:GPL-2.0+
+// copyright-holders:Peter Trauner
+/******************************************************************************
+ watara supervision handheld
+
+ PeT mess@utanet.at in december 2000
+******************************************************************************/
+
+#include "emu.h"
+#include "includes/svision.h"
+#include "softlist.h"
+
+#include "svision.lh"
+
+#define MAKE8_RGB32(red3, green3, blue2) ( ( (red3)<<(16+5)) | ( (green3)<<(8+5)) | ( (blue2)<<(0+6)) )
+#define MAKE9_RGB32(red3, green3, blue3) ( ( (red3)<<(16+5)) | ( (green3)<<(8+5)) | ( (blue3)<<(0+5)) )
+#define MAKE12_RGB32(red4, green4, blue4) ( ( (red4)<<(16+4)) | ((green4)<<(8+4)) | ((blue4)<<(0+4)) )
+#define MAKE24_RGB32(red8, green8, blue8) ( (((red8)&0xf8)<<16) | (((green8)&0xf8)<<8) | (((blue8)&0xf8)) )
+
+
+// in pixel
+#define XSIZE (m_reg[0]&~3)
+#define XPOS m_reg[2]
+#define YPOS m_reg[3]
+#define BANK m_reg[0x26]
+
+TIMER_CALLBACK_MEMBER(svision_state::svision_pet_timer)
+{
+ switch (m_pet.state)
+ {
+ case 0:
+ if ( m_joy2 )
+ {
+ m_pet.input = m_joy2->read();
+ }
+ /* fall through */
+
+ case 2: case 4: case 6: case 8:
+ case 10: case 12: case 14:
+ m_pet.clock = m_pet.state & 2;
+ m_pet.data = m_pet.input & 1;
+ m_pet.input >>= 1;
+ m_pet.state++;
+ break;
+
+ case 16+15:
+ m_pet.state = 0;
+ break;
+
+ default:
+ m_pet.state++;
+ break;
+ }
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(svision_state::svision_pet_timer_dev)
+{
+ svision_pet_timer(ptr,param);
+}
+
+void svision_state::svision_irq()
+{
+ int irq = m_svision.timer_shot && (BANK & 2);
+ irq = irq || (*m_dma_finished && (BANK & 4));
+
+ m_maincpu->set_input_line(M65C02_IRQ_LINE, irq ? ASSERT_LINE : CLEAR_LINE);
+}
+
+TIMER_CALLBACK_MEMBER(svision_state::svision_timer)
+{
+ m_svision.timer_shot = TRUE;
+ m_svision.timer1->enable(FALSE);
+ svision_irq();
+}
+
+READ8_MEMBER(svision_state::svision_r)
+{
+ int data = m_reg[offset];
+ switch (offset)
+ {
+ case 0x20:
+ data = m_joy->read();
+ break;
+
+ case 0x21:
+ data &= ~0xf;
+ data |= m_reg[0x22] & 0xf;
+ if (m_pet.on)
+ {
+ if (!m_pet.clock)
+ {
+ data &= ~4;
+ }
+ if (!m_pet.data)
+ {
+ data &= ~8;
+ }
+ }
+ break;
+
+ case 0x27:
+ data &= ~3;
+ if (m_svision.timer_shot)
+ {
+ data|=1;
+ }
+ if (*m_dma_finished)
+ {
+ data|=2;
+ }
+ break;
+
+ case 0x24:
+ m_svision.timer_shot = FALSE;
+ svision_irq();
+ break;
+
+ case 0x25:
+ *m_dma_finished = FALSE;
+ svision_irq();
+ break;
+
+ default:
+ logerror("%.6f svision read %04x %02x\n", machine().time().as_double(),offset,data);
+ break;
+ }
+
+ return data;
+}
+
+WRITE8_MEMBER(svision_state::svision_w)
+{
+ int value, delay, bank;
+
+ m_reg[offset] = data;
+
+ switch (offset)
+ {
+ case 2:
+ case 3:
+ break;
+
+ case 0x26: /* bits 5,6 memory management for a000? */
+ logerror("%.6f svision write %04x %02x\n", machine().time().as_double(), offset, data);
+ bank = ((m_reg[0x26] & 0xe0) >> 5) % (m_cart_rom->bytes() / 0x4000);
+ m_bank1->set_base(m_cart_rom->base() + (bank * 0x4000));
+ svision_irq();
+ break;
+
+ case 0x23: /* delta hero irq routine write */
+ value = data;
+ if (!data)
+ {
+ value = 0x100;
+ }
+ if (BANK & 0x10)
+ {
+ delay = 16384;
+ }
+ else
+ {
+ delay = 256;
+ }
+ m_svision.timer1->enable(TRUE);
+ m_svision.timer1->reset(m_maincpu->cycles_to_attotime(value * delay));
+ break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ m_sound->soundport_w(0, offset & 3, data);
+ break;
+
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ m_sound->soundport_w(1, offset & 3, data);
+ break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c:
+ m_sound->sounddma_w(space, offset - 0x18, data);
+ break;
+
+ case 0x28: case 0x29: case 0x2a:
+ m_sound->noise_w(space, offset - 0x28, data);
+ break;
+
+ default:
+ logerror("%.6f svision write %04x %02x\n", machine().time().as_double(), offset, data);
+ break;
+ }
+}
+
+READ8_MEMBER(svision_state::tvlink_r)
+{
+ switch(offset)
+ {
+ default:
+ if (offset >= 0x800 && offset < 0x840)
+ {
+ /* strange effects when modifying palette */
+ return svision_r(space, offset);
+ }
+ else
+ {
+ return svision_r(space, offset);
+ }
+ }
+}
+
+WRITE8_MEMBER(svision_state::tvlink_w)
+{
+ switch (offset)
+ {
+ case 0x0e:
+ m_reg[offset] = data;
+ m_tvlink.palette_on = data & 1;
+ if (m_tvlink.palette_on)
+ {
+ // hack, normally initialising with palette from ram
+ m_tvlink.palette[0] = MAKE12_RGB32(163/16,172/16,115/16); // these are the tron colors messured from screenshot
+ m_tvlink.palette[1] = MAKE12_RGB32(163/16,155/16,153/16);
+ m_tvlink.palette[2] = MAKE12_RGB32(77/16,125/16,73/16);
+ m_tvlink.palette[3] = MAKE12_RGB32(59/16,24/16,20/16);
+ }
+ else
+ {
+ // cleaner to use colors from compile time palette, or compose from "fixed" palette values
+ m_tvlink.palette[0]=MAKE12_RGB32(0,0,0);
+ m_tvlink.palette[1]=MAKE12_RGB32(5*16/256,18*16/256,9*16/256);
+ m_tvlink.palette[2]=MAKE12_RGB32(48*16/256,76*16/256,100*16/256);
+ m_tvlink.palette[3]=MAKE12_RGB32(190*16/256,190*16/256,190*16/256);
+ }
+ break;
+ default:
+ svision_w(space, offset,data);
+ if (offset >= 0x800 && offset < 0x840)
+ {
+ UINT16 c;
+ if (offset == 0x803 && data == 0x07)
+ {
+ /* tron hack */
+ m_reg[0x0804]=0x00;
+ m_reg[0x0805]=0x01;
+ m_reg[0x0806]=0x00;
+ m_reg[0x0807]=0x00;
+ }
+ c = m_reg[0x800] | (m_reg[0x804] << 8);
+ m_tvlink.palette[0] = MAKE9_RGB32( (c>>0)&7, (c>>3)&7, (c>>6)&7);
+ c = m_reg[0x801] | (m_reg[0x805] << 8);
+ m_tvlink.palette[1] = MAKE9_RGB32( (c>>0)&7, (c>>3)&7, (c>>6)&7);
+ c = m_reg[0x802] | (m_reg[0x806]<<8);
+ m_tvlink.palette[2]=MAKE9_RGB32( (c>>0)&7, (c>>3)&7, (c>>6)&7);
+ c = m_reg[0x803] | (m_reg[0x807]<<8);
+ m_tvlink.palette[3]=MAKE9_RGB32( (c>>0)&7, (c>>3)&7, (c>>6)&7);
+ /* writes to palette effect video color immediately */
+ /* some writes modify other registers, */
+ /* encoding therefor not known (rgb8 or rgb9) */
+ }
+ }
+}
+
+static ADDRESS_MAP_START( svision_mem , AS_PROGRAM, 8, svision_state )
+ AM_RANGE(0x0000, 0x1fff) AM_RAM
+ AM_RANGE(0x2000, 0x3fff) AM_READWRITE(svision_r, svision_w) AM_SHARE("reg")
+ AM_RANGE(0x4000, 0x5fff) AM_RAM AM_SHARE("videoram")
+ AM_RANGE(0x6000, 0x7fff) AM_NOP
+ AM_RANGE(0x8000, 0xbfff) AM_ROMBANK("bank1")
+ AM_RANGE(0xc000, 0xffff) AM_ROMBANK("bank2")
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( tvlink_mem , AS_PROGRAM, 8, svision_state )
+ AM_RANGE(0x0000, 0x1fff) AM_RAM
+ AM_RANGE(0x2000, 0x3fff) AM_READWRITE(tvlink_r, tvlink_w) AM_SHARE("reg")
+ AM_RANGE(0x4000, 0x5fff) AM_RAM AM_SHARE("videoram")
+ AM_RANGE(0x6000, 0x7fff) AM_NOP
+ AM_RANGE(0x8000, 0xbfff) AM_ROMBANK("bank1")
+ AM_RANGE(0xc000, 0xffff) AM_ROMBANK("bank2")
+ADDRESS_MAP_END
+
+static INPUT_PORTS_START( svision )
+ PORT_START("JOY")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("B")
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("A")
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SELECT) PORT_NAME("Select")
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START) PORT_NAME("Start/Pause")
+INPUT_PORTS_END
+
+static INPUT_PORTS_START( svisions )
+ PORT_START("JOY")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_PLAYER(1)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("B") PORT_PLAYER(1)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("A") PORT_PLAYER(1)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SELECT) PORT_NAME("Select") PORT_PLAYER(1)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START) PORT_NAME("Start/Pause") PORT_PLAYER(1)
+ PORT_START("JOY2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_PLAYER(2)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("2nd B") PORT_PLAYER(2)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("2nd A") PORT_PLAYER(2)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SELECT) PORT_NAME("2nd Select") PORT_PLAYER(2)
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START) PORT_NAME("2nd Start/Pause") PORT_PLAYER(2)
+INPUT_PORTS_END
+
+/* most games contain their graphics in roms, and have hardware to
+ draw complete rectangular objects */
+
+#define PALETTE_START 0
+
+/* palette in red, green, blue triples */
+static const unsigned char svision_palette[] =
+{
+#if 0
+ /* greens grabbed from a scan of a handheld
+ * in its best adjustment for contrast
+ */
+ 86, 121, 86,
+ 81, 115, 90,
+ 74, 107, 101,
+ 54, 78, 85
+#else
+ /* grabbed from chris covell's black white pics */
+ 0xe0, 0xe0, 0xe0,
+ 0xb9, 0xb9, 0xb9,
+ 0x54, 0x54, 0x54,
+ 0x12, 0x12, 0x12
+#endif
+};
+
+/* palette in red, green, blue tribles */
+static const unsigned char svisionp_palette[] =
+{
+ // pal
+ 1, 1, 3,
+ 5, 18, 9,
+ 48, 76, 100,
+ 190, 190, 190
+};
+
+/* palette in red, green, blue tribles */
+static const unsigned char svisionn_palette[] =
+{
+ 0, 0, 0,
+ 188, 242, 244, // darker
+ 129, 204, 255,
+ 245, 249, 248
+};
+
+PALETTE_INIT_MEMBER(svision_state, svision)
+{
+ for (int i = 0; i < sizeof(svision_palette) / 3; i++)
+ palette.set_pen_color(i, svision_palette[i*3], svision_palette[i*3+1], svision_palette[i*3+2]);
+}
+PALETTE_INIT_MEMBER(svision_state,svisionn)
+{
+ for (int i = 0; i < sizeof(svisionn_palette) / 3; i++)
+ palette.set_pen_color(i, svisionn_palette[i*3], svisionn_palette[i*3+1], svisionn_palette[i*3+2]);
+}
+PALETTE_INIT_MEMBER(svision_state,svisionp)
+{
+ for (int i = 0; i < sizeof(svisionn_palette) / 3; i++)
+ palette.set_pen_color(i, svisionp_palette[i*3], svisionp_palette[i*3+1], svisionp_palette[i*3+2]);
+}
+
+UINT32 svision_state::screen_update_svision(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ int x, y, i, j=XPOS/4+YPOS*0x30;
+ UINT8 *videoram = m_videoram;
+
+ if (BANK&8)
+ {
+ for (y=0; y<160; y++)
+ {
+ UINT16 *line = &bitmap.pix16(y, 3 - (XPOS & 3));
+ for (x=3-(XPOS&3),i=0; x<160+3 && x<XSIZE+3; x+=4,i++)
+ {
+ UINT8 b=videoram[j+i];
+ line[3]=((b>>6)&3)+PALETTE_START;
+ line[2]=((b>>4)&3)+PALETTE_START;
+ line[1]=((b>>2)&3)+PALETTE_START;
+ line[0]=((b>>0)&3)+PALETTE_START;
+ line+=4;
+ }
+ j += 0x30;
+ if (j >= 8160)
+ j = 0; //sssnake
+ }
+ }
+ else
+ {
+ bitmap.plot_box(3, 0, 162, 159, PALETTE_START);
+ }
+ return 0;
+}
+
+UINT32 svision_state::screen_update_tvlink(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ int x, y, i, j = XPOS/4+YPOS*0x30;
+ UINT8 *videoram = m_videoram;
+
+ if (BANK & 8)
+ {
+ for (y = 0; y < 160; y++)
+ {
+ UINT32 *line = &bitmap.pix32(y, 3 - (XPOS & 3));
+ for (x = 3 - (XPOS & 3), i = 0; x < 160 + 3 && x < XSIZE + 3; x += 4, i++)
+ {
+ UINT8 b=videoram[j+i];
+ line[3]=m_tvlink.palette[(b>>6)&3];
+ line[2]=m_tvlink.palette[(b>>4)&3];
+ line[1]=m_tvlink.palette[(b>>2)&3];
+ line[0]=m_tvlink.palette[(b>>0)&3];
+ line+=4;
+ }
+ j += 0x30;
+ if (j >= 8160)
+ j = 0; //sssnake
+ }
+ }
+ else
+ {
+ bitmap.plot_box(3, 0, 162, 159, m_palette->pen(PALETTE_START));
+ }
+ return 0;
+}
+
+INTERRUPT_GEN_MEMBER(svision_state::svision_frame_int)
+{
+ if (BANK & 1)
+ device.execute().set_input_line(INPUT_LINE_NMI, PULSE_LINE);
+
+ m_sound->sound_decrement();
+}
+
+DRIVER_INIT_MEMBER(svision_state, svision)
+{
+ m_svision.timer1 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(svision_state::svision_timer),this));
+ m_dma_finished = m_sound->dma_finished();
+ m_pet.on = FALSE;
+}
+
+DRIVER_INIT_MEMBER(svision_state, svisions)
+{
+ m_svision.timer1 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(svision_state::svision_timer),this));
+ m_dma_finished = m_sound->dma_finished();
+ m_pet.on = TRUE;
+ m_pet.timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(svision_state::svision_pet_timer),this));
+}
+
+DEVICE_IMAGE_LOAD_MEMBER( svision_state, svision_cart )
+{
+ UINT32 size = m_cart->common_get_size("rom");
+
+ if (size > 0x20000)
+ {
+ image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size");
+ return IMAGE_INIT_FAIL;
+ }
+
+ m_cart->rom_alloc(size, GENERIC_ROM8_WIDTH, ENDIANNESS_LITTLE);
+ m_cart->common_load_rom(m_cart->get_rom_base(), size, "rom");
+
+ return IMAGE_INIT_PASS;
+}
+
+void svision_state::machine_start()
+{
+ int num_banks;
+ std::string region_tag;
+ m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
+ num_banks = m_cart_rom->bytes() / 0x4000;
+
+ m_bank1 = membank("bank1");
+ m_bank2 = membank("bank2");
+ // bank1 is set to the first bank
+ // do not crash if no cart
+ if (num_banks)
+ {
+ m_bank1->set_base(m_cart_rom->base());
+ // bank2 is set to the last bank
+ m_bank2->set_base(m_cart_rom->base() + (num_banks - 1) * 0x4000);
+ }
+}
+
+void svision_state::machine_reset()
+{
+ m_svision.timer_shot = FALSE;
+ *m_dma_finished = FALSE;
+}
+
+
+MACHINE_RESET_MEMBER(svision_state,tvlink)
+{
+ svision_state::machine_reset();
+ m_tvlink.palette_on = FALSE;
+
+ memset(m_reg + 0x800, 0xff, 0x40); // normally done from m_tvlink microcontroller
+ m_reg[0x82a] = 0xdf;
+
+ m_tvlink.palette[0] = MAKE24_RGB32(svisionp_palette[(PALETTE_START+0)*3+0], svisionp_palette[(PALETTE_START+0)*3+1], svisionp_palette[(PALETTE_START+0)*3+2]);
+ m_tvlink.palette[1] = MAKE24_RGB32(svisionp_palette[(PALETTE_START+1)*3+0], svisionp_palette[(PALETTE_START+1)*3+1], svisionp_palette[(PALETTE_START+1)*3+2]);
+ m_tvlink.palette[2] = MAKE24_RGB32(svisionp_palette[(PALETTE_START+2)*3+0], svisionp_palette[(PALETTE_START+2)*3+1], svisionp_palette[(PALETTE_START+2)*3+2]);
+ m_tvlink.palette[3] = MAKE24_RGB32(svisionp_palette[(PALETTE_START+3)*3+0], svisionp_palette[(PALETTE_START+3)*3+1], svisionp_palette[(PALETTE_START+3)*3+2]);
+}
+
+static MACHINE_CONFIG_START( svision, svision_state )
+ /* basic machine hardware */
+ MCFG_CPU_ADD("maincpu", M65C02, 4000000) /* ? stz used! speed? */
+ MCFG_CPU_PROGRAM_MAP(svision_mem)
+ MCFG_CPU_VBLANK_INT_DRIVER("screen", svision_state, svision_frame_int)
+
+ /* video hardware */
+ MCFG_SCREEN_ADD("screen", LCD)
+ MCFG_SCREEN_REFRESH_RATE(61)
+ MCFG_SCREEN_SIZE(3+160+3, 160)
+ MCFG_SCREEN_VISIBLE_AREA(3+0, 3+160-1, 0, 160-1)
+ MCFG_SCREEN_UPDATE_DRIVER(svision_state, screen_update_svision)
+ MCFG_SCREEN_PALETTE("palette")
+
+ MCFG_PALETTE_ADD("palette", ARRAY_LENGTH(svision_palette) * 3)
+ MCFG_PALETTE_INIT_OWNER(svision_state, svision )
+
+ MCFG_DEFAULT_LAYOUT(layout_svision)
+
+ /* sound hardware */
+ MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
+ MCFG_SOUND_ADD("custom", SVISION_SND, 0)
+ MCFG_SOUND_ROUTE(0, "lspeaker", 0.50)
+ MCFG_SOUND_ROUTE(1, "rspeaker", 0.50)
+ SVISION_SND_IRQ_CB(svision_state, svision_irq)
+
+ /* cartridge */
+ MCFG_GENERIC_CARTSLOT_ADD("cartslot", generic_plain_slot, "svision_cart")
+ MCFG_GENERIC_EXTENSIONS("bin,ws,sv")
+ MCFG_GENERIC_MANDATORY
+ MCFG_GENERIC_LOAD(svision_state, svision_cart)
+
+ /* Software lists */
+ MCFG_SOFTWARE_LIST_ADD("cart_list", "svision")
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_DERIVED( svisions, svision )
+ MCFG_TIMER_DRIVER_ADD_PERIODIC("pet_timer", svision_state, svision_pet_timer_dev, attotime::from_seconds(8))
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_DERIVED( svisionp, svision )
+ MCFG_CPU_MODIFY("maincpu")
+ MCFG_CPU_CLOCK(4430000)
+ MCFG_SCREEN_MODIFY("screen")
+ MCFG_SCREEN_REFRESH_RATE(50)
+ MCFG_PALETTE_MODIFY("palette")
+ MCFG_PALETTE_INIT_OWNER(svision_state, svisionp)
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_DERIVED( svisionn, svision )
+ MCFG_CPU_MODIFY("maincpu")
+ MCFG_CPU_CLOCK(3560000/*?*/)
+ MCFG_SCREEN_MODIFY("screen")
+ MCFG_SCREEN_REFRESH_RATE(60)
+ MCFG_PALETTE_MODIFY("palette")
+ MCFG_PALETTE_INIT_OWNER(svision_state, svisionn)
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_DERIVED( tvlinkp, svisionp )
+ MCFG_CPU_MODIFY("maincpu")
+ MCFG_CPU_PROGRAM_MAP(tvlink_mem)
+
+ MCFG_MACHINE_RESET_OVERRIDE(svision_state, tvlink)
+
+ MCFG_SCREEN_MODIFY("screen")
+ MCFG_SCREEN_NO_PALETTE
+ MCFG_SCREEN_UPDATE_DRIVER(svision_state, screen_update_tvlink)
+
+MACHINE_CONFIG_END
+
+ROM_START(svision)
+ ROM_REGION(0x20000, "maincpu", ROMREGION_ERASE00)
+ROM_END
+
+
+#define rom_svisions rom_svision
+#define rom_svisionn rom_svision
+#define rom_svisionp rom_svision
+#define rom_tvlinkp rom_svision
+
+/***************************************************************************
+
+ Game driver(s)
+
+***************************************************************************/
+
+/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */
+// marketed under a ton of firms and names
+CONS(1992, svision, 0, 0, svision, svision, svision_state, svision, "Watara", "Super Vision", 0)
+// svdual 2 connected via communication port
+CONS( 1992, svisions, svision, 0,svisions, svisions, svision_state, svisions, "Watara", "Super Vision (PeT Communication Simulation)", 0 )
+
+CONS( 1993, svisionp, svision, 0,svisionp, svision, svision_state, svision, "Watara", "Super Vision (PAL TV Link Colored)", 0 )
+CONS( 1993, svisionn, svision, 0,svisionn, svision, svision_state, svision, "Watara", "Super Vision (NTSC TV Link Colored)", 0 )
+// svtvlink (2 supervisions)
+// tvlink (pad supervision simulated)
+CONS( 199?, tvlinkp, svision, 0,tvlinkp, svision, svision_state, svision, "Watara", "TV Link PAL", 0 )