diff options
Diffstat (limited to 'src/devices/bus/jvs/cyberlead.cpp')
-rw-r--r-- | src/devices/bus/jvs/cyberlead.cpp | 486 |
1 files changed, 486 insertions, 0 deletions
diff --git a/src/devices/bus/jvs/cyberlead.cpp b/src/devices/bus/jvs/cyberlead.cpp new file mode 100644 index 00000000000..5598da24cd9 --- /dev/null +++ b/src/devices/bus/jvs/cyberlead.cpp @@ -0,0 +1,486 @@ +// license:BSD-3-Clause +// copyright-holders:smf +/* + Namco Cyber Lead cabinet PCB + + CL1 I/OB I/O LED (I/O) PCB 8699014200 + CL1 LEDA I/O LED (LED) PCB 8699014500 + Both boards are required and use the same PCB, populated differently + |------------------------------------------------------------------------------------------------| + | J3 J4 J6 | + | J2 J5 | + | PROG I/OLEDM1 | + | AT29C020 SED1351F B A | + | C77 14.764Mhz PST592F J7 | + | HC257 HC257 HC257 N341256 | + | J1 | + | SW1 SW2 SW3 SW4 SW5 9264LF10L 12MHZ | + | 1P 2P | + | J13 J12 J11 J10 | + |------------------------------------------------------------------------------------------------| + +Notes: + J1 - 6 pin connector (I/O Only) + J2 - 2 pin power connector + J3 - 10 pin connector (I/O Only) + J4 - 12 pin connector (I/O Only) + J5 PROG - ? + J6 - 6 pin Mini DIN connector + J7 - 20 pin connector (LED Only) + J10 - 2 pin connector (I/O Only) + J11 - 12 pin connector (I/O Only) + J12 - 12 pin connector (I/O Only) + J13 - 2 pin connector (I/O Only) + A - USB A connector (I/O Only) + B - USB B connector (I/O Only) + HC257 - Quad 2-input multiplexer; 3-state (I/O Only) @IC1,IC2,IC3 + N341256 - NEC N341256 32k x8 SRAM @IC4 + AT29C020 - Atmel AT29C020 256k x8 FlashROM @IC5 + C77 - Namco C77 H8 MCU @IC6 + 14.76 - X1 14.7SC6M + SW1 - A push button + SW2 - B push button + SW3 - DSW4 + SW4 - Service push button + SW5 - Test push button + SED1351F - EPSON SED1351F LCD controller (LED Only) @IC7 + 9264LF10L - 8192x8 Bit Static RAM (LED Only) @IC8 + I/OLEDM1 - Altera EPM7064 @IC9 + PST592F - System reset @IC10 + 12MHz - OSC1 (LED Only) + ADM485JR - Analog Devices ADM485 low power EIA RS-485 transceiver (I/O Only) @IC11 + +Known games with LED data + + Aqua Rush + Attack Pla Rail (*) + Ehrgeiz (*) + Fighting Layer (Japan) (*) + Libero Grande + Mr. Driller + Soul Calibur + Super World Stadium '98 + Super World Stadium '99 + Tekken 3 (* up to rev D) + Tekken Tag Tournament + + (*) The only games that work with the unpatched CL1 I/OB Ver 1.03 rom +*/ + +#include "emu.h" +#include "cyberlead.h" +#include "cyberlead.lh" + +namco_cyberlead_device::namco_cyberlead_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + namco_cyberlead_device(mconfig, NAMCO_CYBERLEAD, tag, owner, clock) +{ +} + +namco_cyberlead_device::namco_cyberlead_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), + device_jvs_interface(mconfig, *this), + m_iocpu(*this, "iocpu"), + m_dsw(*this, "DSW"), + m_port7(*this, "PORT7"), + m_rs232(*this, "rs232") +{ +} + +void namco_cyberlead_device::device_add_mconfig(machine_config &config) +{ + NAMCO_C77(config, m_iocpu, 14.7456_MHz_XTAL); + m_iocpu->set_addrmap(AS_PROGRAM, &namco_cyberlead_device::iocpu_program_map); + m_iocpu->read_port4().set(FUNC(namco_cyberlead_device::iocpu_port_4_r)); + m_iocpu->write_port4().set(FUNC(namco_cyberlead_device::iocpu_port_4_w)); + m_iocpu->read_port5().set(FUNC(namco_cyberlead_device::iocpu_port_5_r)); + m_iocpu->write_port5().set(FUNC(namco_cyberlead_device::iocpu_port_5_w)); + m_iocpu->read_port6().set(FUNC(namco_cyberlead_device::iocpu_port_6_r)); + m_iocpu->write_port6().set(FUNC(namco_cyberlead_device::iocpu_port_6_w)); + m_iocpu->read_port7().set(FUNC(namco_cyberlead_device::iocpu_port_7_r)); + + m_iocpu->write_sci_tx<0>().set(FUNC(namco_cyberlead_device::txd)); + + config.set_maximum_quantum(attotime::from_hz(2 * 115200)); + + RS232_PORT(config, m_rs232); + m_rs232->option_add("namco_cyberlead_led", NAMCO_CYBERLEAD_LED); + m_rs232->set_option_machine_config("namco_cyberlead_led", [&config](device_t *device) + { + if (!(config.gamedrv().flags & machine_flags::SWAP_XY)) + config.set_default_layout(layout_cyberlead); + }); + + m_rs232->set_default_option("namco_cyberlead_led"); + m_rs232->rxd_handler().set(m_iocpu, FUNC(h8_device::sci_rx_w<1>)); + m_iocpu->write_sci_tx<1>().set(m_rs232, FUNC(rs232_port_device::write_txd)); + + add_jvs_port(config); +} + +namespace { + +static INPUT_PORTS_START(cyberleadjvs) + PORT_START("DSW") + PORT_DIPUNKNOWN_DIPLOC(0x08, IP_ACTIVE_LOW, "SW3:1") + PORT_DIPUNKNOWN_DIPLOC(0x04, IP_ACTIVE_LOW, "SW3:2") + PORT_DIPUNKNOWN_DIPLOC(0x02, IP_ACTIVE_LOW, "SW3:3") + PORT_DIPUNUSED_DIPLOC(0x01, IP_ACTIVE_LOW, "SW3:4") + + PORT_START("PORT7") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("LED Mode B") PORT_CODE(KEYCODE_B) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("LED Mode A") PORT_CODE(KEYCODE_A) + PORT_BIT(0x8c, IP_ACTIVE_LOW, IPT_UNKNOWN) // inputs? + PORT_BIT(0x70, IP_ACTIVE_LOW, IPT_UNKNOWN) // outputs? +INPUT_PORTS_END + +static INPUT_PORTS_START(cyberleadjvs_default) + PORT_INCLUDE(cyberleadjvs) + + PORT_START("SYSTEM") + PORT_SERVICE_NO_TOGGLE(0x80, IP_ACTIVE_HIGH) + + PORT_START("PLAYER1") + PORT_BIT(0x00000080, IP_ACTIVE_HIGH, IPT_START) + PORT_BIT(0x00000040, IP_ACTIVE_HIGH, IPT_SERVICE1) + PORT_BIT(0x00000020, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP) + PORT_BIT(0x00000010, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN) + PORT_BIT(0x00000008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT) + PORT_BIT(0x00000004, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT) + PORT_BIT(0x00000002, IP_ACTIVE_HIGH, IPT_BUTTON1) + PORT_BIT(0x00000001, IP_ACTIVE_HIGH, IPT_BUTTON2) + PORT_BIT(0x00008000, IP_ACTIVE_HIGH, IPT_BUTTON3) + PORT_BIT(0x00004000, IP_ACTIVE_HIGH, IPT_BUTTON4) + PORT_BIT(0x00002000, IP_ACTIVE_HIGH, IPT_BUTTON5) + PORT_BIT(0x00001000, IP_ACTIVE_HIGH, IPT_BUTTON6) + + PORT_START("PLAYER2") + PORT_BIT(0x00000080, IP_ACTIVE_HIGH, IPT_START) PORT_PLAYER(2) + PORT_BIT(0x00000020, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP) PORT_PLAYER(2) + PORT_BIT(0x00000010, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN) PORT_PLAYER(2) + PORT_BIT(0x00000008, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT) PORT_PLAYER(2) + PORT_BIT(0x00000004, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT) PORT_PLAYER(2) + PORT_BIT(0x00000002, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_PLAYER(2) + PORT_BIT(0x00000001, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_PLAYER(2) + PORT_BIT(0x00008000, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_PLAYER(2) + PORT_BIT(0x00004000, IP_ACTIVE_HIGH, IPT_BUTTON4) PORT_PLAYER(2) + PORT_BIT(0x00002000, IP_ACTIVE_HIGH, IPT_BUTTON5) PORT_PLAYER(2) + PORT_BIT(0x00001000, IP_ACTIVE_HIGH, IPT_BUTTON6) PORT_PLAYER(2) + + PORT_START("COIN1") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_COIN1) + + PORT_START("COIN2") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_COIN2) +INPUT_PORTS_END + +} // anonymous namespace + +ioport_constructor namco_cyberlead_device::device_input_ports() const +{ + return m_default_inputs ? INPUT_PORTS_NAME(cyberleadjvs_default) : INPUT_PORTS_NAME(cyberleadjvs); +} + +namespace { + +ROM_START( cyberleadjvs ) + ROM_REGION( 0x040000, "iocpu", 0 ) + ROM_LOAD( "cl1-iob.ic5", 0x000000, 0x040000, CRC(abb90360) SHA1(d938b1e1ae596d0ab1007352f61b0b800363c762) ) + ROM_FILL( 0xa6b, 0x1, 0x12 ) // HACK to improve compatibility, until newer revision is dumped +ROM_END + +} // anonymous namespace + +const tiny_rom_entry *namco_cyberlead_device::device_rom_region() const +{ + return ROM_NAME(cyberleadjvs); +} + +void namco_cyberlead_device::device_start() +{ +} + +void namco_cyberlead_device::rxd(int state) +{ + m_iocpu->sci_rx_w<0>(state); +} + +void namco_cyberlead_device::iocpu_program_map(address_map &map) +{ + map(0x0000, 0x3fff).rom().region("iocpu", 0); + map(0xc000, 0xfb7f).ram(); + map(0xff80, 0xff83).r(FUNC(namco_cyberlead_device::iocpu_in_r)); +} + +uint8_t namco_cyberlead_device::iocpu_in_r(offs_t offset) +{ + if (offset == 0) + { + const auto p1 = player_r(0, 0x80bf); + return ~bitswap<8>(p1, 15, 0, 1, 7, 2, 3, 4, 5); // BUTTON3, BUTTON2, BUTTON1, START, RIGHT, LEFT, DOWN, UP + } + else if (offset == 1) + { + const auto p2 = player_r(1, 0x80bf); + return ~bitswap<8>(p2, 15, 0, 1, 7, 2, 3, 4, 5); // BUTTON3, BUTTON2, BUTTON1, START, RIGHT, LEFT, DOWN, UP + } + else if (offset == 2) + { + const auto p1 = player_r(0, 0x7000); + const auto c1 = coin_r(0, 0x01); + return ~((BIT(c1, 0) << 3) | bitswap<3>(p1, 12, 13, 14)); // COIN, BUTTON6, BUTTON5, BUTTON4 + } + else if (offset == 3) + { + const auto p2 = player_r(1, 0x7000); + const auto c2 = coin_r(1, 0x01); + return ~((BIT(c2, 0) << 3) | bitswap<3>(p2, 12, 13, 14)); // COIN, BUTTON6, BUTTON5, BUTTON4 + } + + return 0xff; +} + +uint8_t namco_cyberlead_device::iocpu_port_4_r() +{ + return (1 << 7) | // unknown input + 0x63 | // unknown outputs + ((m_jvs_sense != jvs_port_device::sense::None) << 4) | ((m_jvs_sense != jvs_port_device::sense::Initialized) << 3) | + (1 << 2);// sense output +} + +void namco_cyberlead_device::iocpu_port_4_w(uint8_t data) +{ + sense(BIT(data, 2) ? jvs_port_device::sense::Initialized : jvs_port_device::sense::Uninitialized); +} + +uint8_t namco_cyberlead_device::iocpu_port_5_r() +{ + return 0xe9 | // unknown outputs + (1 << 4) | // unknown input + (1 << 2) | // rts + (1 << 1); // unknown input +} + +void namco_cyberlead_device::iocpu_port_5_w(uint8_t data) +{ + rts(BIT(data, 2)); +} + +uint8_t namco_cyberlead_device::iocpu_port_6_r() +{ + const auto system = system_r(0x80); + const auto p1 = player_r(0, 0x40); + + return (1 << 7) | // unknown + (3 << 5) | // coin counters + (BIT(~p1, 6) << 4) | // SERVICE1 + (BIT(m_dsw->read(), 1, 3) << 1) | // DSW1-3 TODO: confirm + (BIT(~system, 7) << 0); // TEST +} + +void namco_cyberlead_device::iocpu_port_6_w(uint8_t data) +{ + machine().bookkeeping().coin_counter_w(0, BIT(data, 6)); + machine().bookkeeping().coin_counter_w(1, BIT(data, 5)); +} + +uint8_t namco_cyberlead_device::iocpu_port_7_r() +{ + return m_port7->read(); +} + + +namco_cyberlead_led_device::namco_cyberlead_led_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, NAMCO_CYBERLEAD_LED, tag, owner, clock), + device_rs232_port_interface(mconfig, *this), + m_ledcpu(*this, "ledcpu"), + m_flash(*this, "flash"), + m_screen(*this, "led"), + m_scroll(*this, "scroll"), + m_sed1351f_ram(*this, "sed1351f_ram"), + m_sed1351f_control(*this, "sed1351f_control"), + m_dsw(*this, "DSW") +{ +} + +namespace { + +} // anonymous namespace + +void namco_cyberlead_led_device::device_add_mconfig(machine_config &config) +{ + NAMCO_C77(config, m_ledcpu, 14.7456_MHz_XTAL); + m_ledcpu->set_addrmap(AS_PROGRAM, &namco_cyberlead_led_device::ledcpu_program_map); + m_ledcpu->read_port6().set(FUNC(namco_cyberlead_led_device::ledcpu_port_6_r)); + + m_ledcpu->write_sci_tx<1>().set(FUNC(namco_cyberlead_led_device::output_rxd)); + + ATMEL_29C020(config, m_flash); + + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_native_aspect(); + m_screen->set_size(96 * 8, 16 * 8); + m_screen->set_visarea(0, (96 * 8) - 1, 0, (16 * 8) - 1); + m_screen->set_screen_update(FUNC(namco_cyberlead_led_device::screen_update)); + m_screen->set_refresh_hz(60); + m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500)); + m_screen->set_orientation(ROT180); + m_screen->screen_vblank().set([this](int state) + { + m_ledcpu->set_input_line(6, state ? ASSERT_LINE : CLEAR_LINE); + }); +} + +namespace { + +static INPUT_PORTS_START(cyberleadled) + PORT_START("DSW") + PORT_DIPNAME(0x08, 0x08, "Display Test") PORT_DIPLOCATION("SW3:1") // c9fb + PORT_DIPSETTING(0x08, "1 Time") + PORT_DIPSETTING(0x00, "4 Times") + PORT_DIPNAME(0x04, 0x04, "Disable Epilepsy Filter") PORT_DIPLOCATION("SW3:2") // c9fc + PORT_DIPSETTING(0x04, DEF_STR(Off)) + PORT_DIPSETTING(0x00, DEF_STR(On)) + PORT_DIPUNKNOWN_DIPLOC(0x02, IP_ACTIVE_LOW, "SW3:3") + PORT_DIPUNUSED_DIPLOC(0x01, IP_ACTIVE_LOW, "SW3:4") +INPUT_PORTS_END + +} // anonymous namespace + +ioport_constructor namco_cyberlead_led_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(cyberleadled); +} + +namespace { + +static const uint16_t led_gfx[] = +{ + 0b0001101010010000, + 0b0110111111100100, + 0b1011111111111001, + 0b1011111111111001, + 0b1011111111111001, + 0b0110111111100100, + 0b0001101010010000, + 0b0000010101000000, +}; + +ROM_START( cyberleadled ) + ROM_REGION( 0x40000, "flash", 0 ) + ROM_LOAD( "cl1-leda.ic5", 0x000000, 0x040000, CRC(5717e05f) SHA1(61d61338e1bb414af32dbdc1e24d54c02fb9196e) ) +ROM_END + +} // anonymous namespace + +const tiny_rom_entry *namco_cyberlead_led_device::device_rom_region() const +{ + return ROM_NAME(cyberleadled); +} + +void namco_cyberlead_led_device::device_start() +{ + for (int c = 0; c < 4; c++) + for (int i = 0; i < 4; i++) + { + int r = ((((0xff * c) / 3) + 0x2f) * i) / 3; + m_palette[c][i] = rgb_t(std::min(r, 0xff), r / 4, r / 3); + } + + m_flash_bank = 0; + + save_item(NAME(m_flash_bank)); +} + +void namco_cyberlead_led_device::input_txd(int state) +{ + m_ledcpu->sci_rx_w<1>(state); +} + +void namco_cyberlead_led_device::ledcpu_program_map(address_map &map) +{ + map(0x0000, 0x3fff).rw(m_flash, FUNC(intelfsh8_device::read), FUNC(intelfsh8_device::write)); + map(0x4000, 0x5fff).ram().share(m_sed1351f_ram); + map(0x6000, 0x600f).ram().share(m_sed1351f_control); + map(0x7000, 0x7001).ram().share(m_scroll); + map(0x8000, 0xbfff).rw(FUNC(namco_cyberlead_led_device::ledcpu_banked_flash_r), FUNC(namco_cyberlead_led_device::ledcpu_banked_flash_w)); + map(0xc000, 0xfb7f).ram(); + map(0xff84, 0xff87).w(FUNC(namco_cyberlead_led_device::ledcpu_flash_bank_w)); +} + +uint8_t namco_cyberlead_led_device::ledcpu_banked_flash_r(offs_t offset) +{ + return m_flash->read(offset + m_flash_bank); +} + +void namco_cyberlead_led_device::ledcpu_banked_flash_w(offs_t offset, uint8_t data) +{ + m_flash->write(offset + m_flash_bank, data); +} + +void namco_cyberlead_led_device::ledcpu_flash_bank_w(offs_t offset, uint8_t data) +{ + m_flash_bank = 0x4000 * (offset | (data << 2)); +} + +uint8_t namco_cyberlead_led_device::ledcpu_port_6_r() +{ + const auto system = 0; + const auto p1 = 0; + + return (1 << 7) | // unknown + (3 << 5) | // coin counters + (BIT(~p1, 6) << 4) | // SERVICE1 + (BIT(m_dsw->read(), 1, 3) << 1) | // DSW1-3 TODO: confirm + (BIT(~system, 7) << 0); // TEST +} + +uint32_t namco_cyberlead_led_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + int start = swapendian_int16(m_sed1351f_control[6 / 2]) & 0x1fff; + int scroll = ~m_ledcpu->space(AS_PROGRAM).read_byte(0xd0bf) & 3; + int scrollx = ((start & 0x1f) * 4) + scroll; + int scrolly = start >> 5; + + for (int y = cliprect.min_y; y <= cliprect.max_y; y++) + { + uint32_t *dst = &bitmap.pix(y, cliprect.min_x); + uint16_t *src = &m_sed1351f_ram[((scrolly + (y >> 3)) & 511) * 16]; + uint16_t gfx = led_gfx[y & 7]; + for (int x = cliprect.min_x; x <= cliprect.max_x; x++) + { + int p = (scrollx + (x >> 3)) & 127; + *dst++ = m_palette[BIT(src[p >> 3], (~p & 7) * 2, 2)][BIT(gfx, (x & 7) << 1, 2)]; + } + } + return 0; +} + +namespace { + +ROM_START( cyberleadajvs ) + ROM_REGION( 0x040000, "iocpu", 0 ) + ROM_LOAD( "cl1-iob.ic5", 0x000000, 0x040000, CRC(abb90360) SHA1(d938b1e1ae596d0ab1007352f61b0b800363c762) ) +ROM_END + +class namco_cyberleada_device : + public namco_cyberlead_device +{ +public: + namco_cyberleada_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0) + : namco_cyberlead_device(mconfig, NAMCO_CYBERLEADA, tag, owner, clock) + { + } + +protected: + virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD + { + return ROM_NAME(cyberleadajvs); + } +}; + +} // anonymous namespace + + +DEFINE_DEVICE_TYPE(NAMCO_CYBERLEAD, namco_cyberlead_device, "namco_cyberlead", "Namco Cyber Lead I/O LED(I/O) PCB 8699014200 (compatibility patch)") +DEFINE_DEVICE_TYPE_PRIVATE(NAMCO_CYBERLEADA, device_jvs_interface, namco_cyberleada_device, "namco_cyberleada", "Namco Cyber Lead I/O LED(I/O) PCB 8699014200") +DEFINE_DEVICE_TYPE(NAMCO_CYBERLEAD_LED, namco_cyberlead_led_device, "namco_cyberlead_led", "Namco Cyber Lead I/O LED(LED) PCB 8699014500") |