diff options
Diffstat (limited to 'src')
33 files changed, 757 insertions, 480 deletions
diff --git a/src/devices/cpu/sh/sh3comn.cpp b/src/devices/cpu/sh/sh3comn.cpp index 63b270cbb72..8b0f149cf6d 100644 --- a/src/devices/cpu/sh/sh3comn.cpp +++ b/src/devices/cpu/sh/sh3comn.cpp @@ -881,10 +881,10 @@ void sh3_base_device::irr0_w(offs_t offset, uint8_t data, uint8_t mem_mask) COMBINE_DATA(&m_irr0); logerror("'%s' (%08x): INTC unmapped internal write %02x & %02x (IRR0)\n", tag(), m_sh2_state->pc, data, mem_mask); // not sure if this is how we should clear lines in this core... - if (!(data & 0x01000000)) execute_set_input(0, CLEAR_LINE); - if (!(data & 0x02000000)) execute_set_input(1, CLEAR_LINE); - if (!(data & 0x04000000)) execute_set_input(2, CLEAR_LINE); - if (!(data & 0x08000000)) execute_set_input(3, CLEAR_LINE); + if (!(data & 0x01)) execute_set_input(0, CLEAR_LINE); + if (!(data & 0x02)) execute_set_input(1, CLEAR_LINE); + if (!(data & 0x04)) execute_set_input(2, CLEAR_LINE); + if (!(data & 0x08)) execute_set_input(3, CLEAR_LINE); } uint8_t sh3_base_device::irr1_r(offs_t offset, uint8_t mem_mask) diff --git a/src/devices/machine/am79c90.cpp b/src/devices/machine/am79c90.cpp index d08c2b93a5a..c2e56692461 100644 --- a/src/devices/machine/am79c90.cpp +++ b/src/devices/machine/am79c90.cpp @@ -709,8 +709,6 @@ void am7990_device_base::initialize() m_mode = init_block[0]; - set_promisc(m_mode & MODE_PROM); - put_u16le(&m_physical_addr[0], init_block[1]); put_u16le(&m_physical_addr[2], init_block[2]); put_u16le(&m_physical_addr[4], init_block[3]); diff --git a/src/devices/machine/dp8390.cpp b/src/devices/machine/dp8390.cpp index 2ed12551e78..af6bf323dd6 100644 --- a/src/devices/machine/dp8390.cpp +++ b/src/devices/machine/dp8390.cpp @@ -126,12 +126,23 @@ void dp8390_device::recv(uint8_t *buf, int len) { high16 = (m_regs.dcr & 4)?m_regs.rsar<<16:0; if(buf[0] & 1) { if(!memcmp((const char *)buf, "\xff\xff\xff\xff\xff\xff", 6)) { + // broadcast if(!(m_regs.rcr & 4)) return; - } else if (memcmp((const char *)buf, "\x09\x00\x07\xff\xff\xff", 6) != 0) { // not AppleTalk broadcast - return; // multicast + } else { + // multicast + if(!(m_regs.rcr & 8)) return; + unsigned const crc = util::crc32_creator::simple(buf, 6) >> 26; + if(!BIT(m_regs.mar[crc >> 3], crc & 7)) return; } m_regs.rsr = 0x20; - } else m_regs.rsr = 0; + } else if(m_regs.rcr & 0x10) { + // promiscuous + m_regs.rsr = 0; + } else { + // physical + if(memcmp(m_regs.par, buf, 6)) return; + m_regs.rsr = 0; + } len &= 0xffff; for(i = 0; i < len; i++) { @@ -403,7 +414,6 @@ void dp8390_device::cs_write(offs_t offset, uint8_t data) { break; case 0x0c: m_regs.rcr = data; - set_promisc((data & 0x10)?true:false); break; case 0x0d: m_regs.tcr = data; diff --git a/src/devices/machine/mb8795.cpp b/src/devices/machine/mb8795.cpp index 7d619a18d90..37ccf805a97 100644 --- a/src/devices/machine/mb8795.cpp +++ b/src/devices/machine/mb8795.cpp @@ -65,8 +65,6 @@ void mb8795_device::device_reset() txlen = rxlen = txcount = 0; - set_promisc(true); - start_send(); } diff --git a/src/devices/machine/smc91c9x.cpp b/src/devices/machine/smc91c9x.cpp index ea153bc2d58..baca4edceda 100644 --- a/src/devices/machine/smc91c9x.cpp +++ b/src/devices/machine/smc91c9x.cpp @@ -179,8 +179,6 @@ void smc91c9x_device::device_reset() m_reg[B3_ERCV] = 0x331f; m_regmask[B3_ERCV] = 0x009f; - set_promisc(false); - update_ethernet_irq(); // Reset MMU @@ -935,11 +933,6 @@ void smc91c9x_device::write(offs_t offset, u16 data, u16 mem_mask) m_reg[B0_EPH_STATUS] |= LINK_OK; } - if ((old_reg ^ new_reg) & PRMS) - { - set_promisc(new_reg & PRMS); - } - if (VERBOSE & LOG_GENERAL) { if (data & SOFT_RST) LOG(" SOFT RST\n"); @@ -972,8 +965,6 @@ void smc91c9x_device::write(offs_t offset, u16 data, u16 mem_mask) case B1_IA4_5: if ( ACCESSING_BITS_8_15 ) { - set_promisc(m_reg[B0_RCR] & PRMS); - u8 mac[6]; put_u16le(&mac[0], m_reg[B1_IA0_1]); put_u16le(&mac[2], m_reg[B1_IA2_3]); diff --git a/src/devices/sound/flt_biquad.cpp b/src/devices/sound/flt_biquad.cpp index de6bfe63462..e56c355ac95 100644 --- a/src/devices/sound/flt_biquad.cpp +++ b/src/devices/sound/flt_biquad.cpp @@ -527,6 +527,7 @@ void filter_biquad_device::recalc() break; // For highpass and friends, block the entire signal. case biquad_type::HIGHPASS1P: + case biquad_type::HIGHPASS1P1Z: case biquad_type::HIGHPASS: case biquad_type::BANDPASS: case biquad_type::PEAK: @@ -563,6 +564,13 @@ void filter_biquad_device::recalc() m_a1 = -m_a1; m_b1 = m_b2 = m_a2 = 0.0; break; + case biquad_type::HIGHPASS1P1Z: + normal = 1.0 / (K + 1.0); + m_b0 = normal; + m_b1 = -normal; + m_a1 = (K - 1.0) * normal; + m_b2 = m_a2 = 0.0; + break; case biquad_type::LOWPASS: m_b0 = Ksquared * normal; m_b1 = 2.0 * m_b0; diff --git a/src/devices/sound/flt_biquad.h b/src/devices/sound/flt_biquad.h index ad58a91de79..702e42f9dac 100644 --- a/src/devices/sound/flt_biquad.h +++ b/src/devices/sound/flt_biquad.h @@ -25,7 +25,8 @@ public: PEAK, LOWSHELF, HIGHSHELF, - RAWPARAMS + RAWPARAMS, + HIGHPASS1P1Z }; struct biquad_params diff --git a/src/emu/dinetwork.cpp b/src/emu/dinetwork.cpp index bbc5ee3054d..30e10361c97 100644 --- a/src/emu/dinetwork.cpp +++ b/src/emu/dinetwork.cpp @@ -4,7 +4,7 @@ #include "emu.h" #include "dinetwork.h" -#include "osdnet.h" +#include "osdepend.h" #include <algorithm> @@ -133,18 +133,9 @@ TIMER_CALLBACK_MEMBER(device_network_interface::recv_complete) start_net_device(); } -void device_network_interface::set_promisc(bool promisc) -{ - m_promisc = promisc; - if (m_dev) - m_dev->set_promisc(promisc); -} - void device_network_interface::set_mac(const u8 *mac) { std::copy_n(mac, std::size(m_mac), std::begin(m_mac)); - if (m_dev) - m_dev->set_mac(&m_mac[0]); } void device_network_interface::set_interface(int id) @@ -152,7 +143,7 @@ void device_network_interface::set_interface(int id) if (m_dev) stop_net_device(); - m_dev.reset(open_netdev(id, *this)); + m_dev = device().machine().osd().open_network_device(id, *this); if (m_dev) { if (!m_loopback_control) diff --git a/src/emu/dinetwork.h b/src/emu/dinetwork.h index 522f8b8d041..99fc1cb3a88 100644 --- a/src/emu/dinetwork.h +++ b/src/emu/dinetwork.h @@ -6,8 +6,6 @@ #include "interface/nethandler.h" -class osd_network_device; - class device_network_interface : public device_interface, public osd::network_handler { public: @@ -18,7 +16,6 @@ public: void interface_post_load() override ATTR_COLD; void set_interface(int id) ATTR_COLD; - void set_promisc(bool promisc); void set_mac(const u8 *mac); void set_loopback(bool loopback); @@ -52,7 +49,7 @@ private: void start_net_device(); void stop_net_device(); - std::unique_ptr<osd_network_device> m_dev; + std::unique_ptr<osd::network_device> m_dev; emu_timer *m_poll_timer; emu_timer *m_send_timer; emu_timer *m_recv_timer; diff --git a/src/emu/natkeyboard.cpp b/src/emu/natkeyboard.cpp index d250f4c3b82..1abe9a140ff 100644 --- a/src/emu/natkeyboard.cpp +++ b/src/emu/natkeyboard.cpp @@ -34,7 +34,8 @@ // CONSTANTS //************************************************************************** -const int KEY_BUFFER_SIZE = 4096; +const u32 KEY_BUFFER_CHUNK_SIZE = 0x1000; +const u32 KEY_BUFFER_MAX_SIZE = 0x800000; const char32_t INVALID_CHAR = '?'; @@ -47,7 +48,7 @@ const char32_t INVALID_CHAR = '?'; struct char_info { char32_t ch; - const char *alternate; // alternative string, in UTF-8 + const char *alternate; // alternative string, in UTF-8 static const char_info *find(char32_t target); }; @@ -344,7 +345,7 @@ natural_keyboard::natural_keyboard(running_machine &machine) build_codes(); if (!m_keyboards.empty()) { - m_buffer.resize(KEY_BUFFER_SIZE); + m_buffer.resize(KEY_BUFFER_CHUNK_SIZE); m_timer = machine.scheduler().timer_alloc(timer_expired_delegate(FUNC(natural_keyboard::timer), this)); } @@ -460,15 +461,9 @@ void natural_keyboard::post(std::u32string_view text, const attotime &rate) // set the fixed rate m_current_rate = rate; - // iterate over characters or until the buffer is full up + // iterate over characters for (char32_t ch : text) - { - if (full()) - break; - - // fetch next character post_char(ch, true); - } } @@ -832,10 +827,19 @@ void natural_keyboard::internal_post(char32_t ch) } // add to the buffer, resizing if necessary - m_buffer[m_bufend++] = ch; - if ((m_bufend + 1) % m_buffer.size() == m_bufbegin) - m_buffer.resize(m_buffer.size() + KEY_BUFFER_SIZE); - m_bufend %= m_buffer.size(); + m_buffer[m_bufend] = ch; + size_t size = m_buffer.size(); + + if ((m_bufend + 1) % size == m_bufbegin) + { + if (size >= KEY_BUFFER_MAX_SIZE) + return; + + m_buffer.insert(m_buffer.begin() + m_bufbegin, KEY_BUFFER_CHUNK_SIZE, INVALID_CHAR); + m_bufbegin += KEY_BUFFER_CHUNK_SIZE; + } + + m_bufend = (m_bufend + 1) % size; } diff --git a/src/emu/natkeyboard.h b/src/emu/natkeyboard.h index 6903f662e47..57b58ffd173 100644 --- a/src/emu/natkeyboard.h +++ b/src/emu/natkeyboard.h @@ -45,7 +45,6 @@ public: // getters and queries running_machine &machine() const { return m_machine; } bool empty() const { return (m_bufbegin == m_bufend); } - bool full() const { return ((m_bufend + 1) % m_buffer.size()) == m_bufbegin; } bool can_post() const { return m_have_charkeys || !m_queue_chars.isnull(); } bool is_posting() const { return (!empty() || (!m_charqueue_empty.isnull() && !m_charqueue_empty())); } bool in_use() const { return m_in_use; } diff --git a/src/frontend/mame/luaengine_input.cpp b/src/frontend/mame/luaengine_input.cpp index 04db2a13e84..8ec97321cfb 100644 --- a/src/frontend/mame/luaengine_input.cpp +++ b/src/frontend/mame/luaengine_input.cpp @@ -208,7 +208,6 @@ void lua_engine::initialize_input(sol::table &emu) natkeyboard_type["paste"] = &natural_keyboard::paste; natkeyboard_type["dump"] = static_cast<std::string (natural_keyboard::*)() const>(&natural_keyboard::dump); natkeyboard_type["empty"] = sol::property(&natural_keyboard::empty); - natkeyboard_type["full"] = sol::property(&natural_keyboard::full); natkeyboard_type["can_post"] = sol::property(&natural_keyboard::can_post); natkeyboard_type["is_posting"] = sol::property(&natural_keyboard::is_posting); natkeyboard_type["in_use"] = sol::property(&natural_keyboard::in_use, &natural_keyboard::set_in_use); diff --git a/src/frontend/mame/ui/miscmenu.cpp b/src/frontend/mame/ui/miscmenu.cpp index df5754a380e..377c34ed2d8 100644 --- a/src/frontend/mame/ui/miscmenu.cpp +++ b/src/frontend/mame/ui/miscmenu.cpp @@ -20,7 +20,6 @@ #include "infoxml.h" #include "mame.h" -#include "osdnet.h" #include "mameopts.h" #include "pluginopts.h" #include "dinetwork.h" @@ -29,6 +28,8 @@ #include "romload.h" #include "uiinput.h" +#include "osdepend.h" + #include "path.h" #include <algorithm> @@ -172,17 +173,17 @@ void menu_network_devices::populate() for (device_network_interface &network : network_interface_enumerator(machine().root_device())) { int curr = network.get_interface(); - const char *title = nullptr; - for (auto &entry : get_netdev_list()) + std::string_view title; + for (auto &entry : machine().osd().list_network_devices()) { - if (entry->id == curr) + if (entry.id == curr) { - title = entry->description; + title = entry.description; break; } } - item_append(network.device().tag(), title ? title : "------", FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, (void *)&network); + item_append(network.device().tag(), std::string(!title.empty() ? title : "------"), FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, (void *)&network); } item_append(menu_item_type::SEPARATOR); @@ -200,30 +201,34 @@ bool menu_network_devices::handle(event const *ev) } else if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT) { - // FIXME: this conflates presumably arbitrary interface ID numbers with 0-based indices device_network_interface *const network = (device_network_interface *)ev->itemref; - auto const &interfaces = get_netdev_list(); + auto const interfaces = machine().osd().list_network_devices(); int curr = network->get_interface(); + auto const found = std::find_if( + std::begin(interfaces), + std::end(interfaces), + [curr] (osd::network_device_info const &info) { return info.id == curr; }); + auto index = std::distance(interfaces.begin(), found); if (ev->iptkey == IPT_UI_LEFT) - curr--; - else - curr++; - if (curr == -2) - curr = interfaces.size() - 1; - network->set_interface(curr); + --index; + else if (std::end(interfaces) == found) + index = 0; + else if (std::size(interfaces) <= ++index) + index = -1; + network->set_interface((0 <= index) ? interfaces[index].id : -1); curr = network->get_interface(); - const char *title = nullptr; + std::string_view title; for (auto &entry : interfaces) { - if (entry->id == curr) + if (entry.id == curr) { - title = entry->description; + title = entry.description; break; } } - ev->item->set_subtext(title ? title : "------"); + ev->item->set_subtext(!title.empty() ? title : "------"); return true; } else diff --git a/src/mame/igs/goldstar.cpp b/src/mame/igs/goldstar.cpp index 11367ebdee7..ec058915368 100644 --- a/src/mame/igs/goldstar.cpp +++ b/src/mame/igs/goldstar.cpp @@ -9647,6 +9647,111 @@ static INPUT_PORTS_START( flaming7 ) INPUT_PORTS_END +static INPUT_PORTS_START( ttactoe ) + PORT_INCLUDE( lucky8 ) + + PORT_MODIFY( "DSW1" ) + PORT_DIPNAME( 0x01, 0x01, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW1:1") + PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW1:2") + PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW1:3") + PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x18, 0x18, "Double Up Game Pay Rate" ) PORT_DIPLOCATION("DSW1:4,5") // OK + PORT_DIPSETTING( 0x00, "90%" ) + PORT_DIPSETTING( 0x08, "80%" ) + PORT_DIPSETTING( 0x10, "70%" ) + PORT_DIPSETTING( 0x18, "60%" ) + PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW1:6") + PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW1:7") + PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW1:8") + PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + + PORT_MODIFY("DSW2") + PORT_DIPNAME( 0x03, 0x03, "Main Game Pay Rate" ) PORT_DIPLOCATION("DSW2:1,2") // OK + PORT_DIPSETTING( 0x03, "60%" ) + PORT_DIPSETTING( 0x02, "70%" ) + PORT_DIPSETTING( 0x01, "80%" ) + PORT_DIPSETTING( 0x00, "90%" ) + PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW2:3") + PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW2:4") + PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW2:5") + PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW2:6") + PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW2:7") + PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW2:8") + PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + + PORT_MODIFY("DSW3") + PORT_DIPNAME( 0x01, 0x01, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW4:1") + PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW4:2") + PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW4:3") + PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x08, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW4:4") + PORT_DIPSETTING( 0x08, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x70, 0x60, "Coin C Rate" ) PORT_DIPLOCATION("DSW4:5,6,7") // OK + PORT_DIPSETTING( 0x70, "10 Coins/1 Credit" ) + PORT_DIPSETTING( 0x10, "9 Coins/1 Credit" ) + PORT_DIPSETTING( 0x20, DEF_STR( 6C_1C ) ) + PORT_DIPSETTING( 0x30, DEF_STR( 5C_1C ) ) + PORT_DIPSETTING( 0x40, DEF_STR( 3C_1C ) ) + PORT_DIPSETTING( 0x50, DEF_STR( 2C_1C ) ) + PORT_DIPSETTING( 0x60, DEF_STR( 1C_1C ) ) + PORT_DIPNAME( 0x80, 0x80, "4th Coin" ) PORT_DIPLOCATION("DSW4:8") // OK + PORT_DIPSETTING( 0x80, "As Coin A" ) + PORT_DIPSETTING( 0x00, "As Hopper Line" ) + + PORT_MODIFY("DSW4") + PORT_DIPNAME( 0x07, 0x07, "Key In Rate" ) PORT_DIPLOCATION("DSW3:1,2,3") // OK + PORT_DIPSETTING( 0x00, DEF_STR( 1C_5C ) ) + PORT_DIPSETTING( 0x01, "1 Coin/10 Credits" ) + PORT_DIPSETTING( 0x02, "1 Coin/20 Credits" ) + PORT_DIPSETTING( 0x03, "1 Coin/25 Credits" ) + PORT_DIPSETTING( 0x04, "1 Coin/40 Credits" ) + PORT_DIPSETTING( 0x05, "1 Coin/50 Credits" ) + PORT_DIPSETTING( 0x06, "1 Coin/60 Credits" ) + PORT_DIPSETTING( 0x07, "1 Coin/100 Credits" ) + PORT_DIPNAME( 0x38, 0x38, "Coin A Rate" ) PORT_DIPLOCATION("DSW3:4,5,6") // OK + PORT_DIPSETTING( 0x38, DEF_STR( 1C_1C ) ) + PORT_DIPSETTING( 0x08, DEF_STR( 1C_2C ) ) + PORT_DIPSETTING( 0x10, DEF_STR( 1C_4C ) ) + PORT_DIPSETTING( 0x18, DEF_STR( 1C_5C ) ) + PORT_DIPSETTING( 0x20, DEF_STR( 1C_6C ) ) // manual says 1C/8C + PORT_DIPSETTING( 0x28, "1 Coin/10 Credits" ) + PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW3:7") + PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) PORT_DIPLOCATION("DSW3:8") + PORT_DIPSETTING( 0x80, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) +INPUT_PORTS_END + + + /***************************************************** * Graphics Layouts & Decode * *****************************************************/ @@ -15971,17 +16076,22 @@ ROM_END Tic Tac Toe. Sundance. - Bootleg of F5 hardware. + Bootleg of Wing F5 hardware. + + Another version exist with a daughterboard and 2x 68705 MCUs. */ ROM_START( ttactoe ) ROM_REGION( 0x10000, "maincpu", 0 ) ROM_LOAD( "tic_8.14b", 0x0000, 0x8000, CRC(a3b8f6ce) SHA1(e85803a0683f11f763bbcec82b0ab5b6dcc31d8f) ) - ROM_REGION( 0x18000, "gfx1", 0 ) - ROM_LOAD( "t5.7h", 0x00000, 0x8000, CRC(868fd100) SHA1(00b09049c34865206d324fb329cee74f35dce7ea) ) // 1ST AND 2ND HALF IDENTICAL - ROM_LOAD( "t6.8h", 0x08000, 0x8000, CRC(f39ac672) SHA1(80f1b734e4321917778ce226348c31b19dc677c7) ) // 1ST AND 2ND HALF IDENTICAL - ROM_LOAD( "t7.9h", 0x10000, 0x8000, CRC(8b23b265) SHA1(3fc66ab5844d49e12e20f30deb6aa0d07cac3333) ) // 1ST AND 2ND HALF IDENTICAL + ROM_REGION( 0xc000, "gfx1", 0 ) + ROM_LOAD( "t5.7h", 0x0000, 0x4000, CRC(868fd100) SHA1(00b09049c34865206d324fb329cee74f35dce7ea) ) // 1ST AND 2ND HALF IDENTICAL + ROM_IGNORE( 0x4000) + ROM_LOAD( "t6.8h", 0x4000, 0x4000, CRC(f39ac672) SHA1(80f1b734e4321917778ce226348c31b19dc677c7) ) // 1ST AND 2ND HALF IDENTICAL + ROM_IGNORE( 0x4000) + ROM_LOAD( "t7.9h", 0x8000, 0x4000, CRC(8b23b265) SHA1(3fc66ab5844d49e12e20f30deb6aa0d07cac3333) ) // 1ST AND 2ND HALF IDENTICAL + ROM_IGNORE( 0x4000) ROM_REGION( 0x8000, "gfx2", 0 ) ROM_LOAD( "t1.1h", 0x0000, 0x2000, CRC(be8b3c26) SHA1(369703a91f430af91083cde2bbec210fa355c4a7) ) @@ -15989,19 +16099,19 @@ ROM_START( ttactoe ) ROM_LOAD( "t3.4h", 0x4000, 0x2000, CRC(e2074f7f) SHA1(d2ccfd52372d37fd258d8544f0d53440b6b575f9) ) ROM_LOAD( "t4.5h", 0x6000, 0x2000, CRC(da56407d) SHA1(9a02c8b9d2489332ac64e8af5059bc6e7a1c9902) ) - // PROMs were not included in this set + // PROMs are the same as lucky8 (W4), colors were compared against the real ingame pics. ROM_REGION( 0x200, "proms", 0 ) - ROM_LOAD( "u4.bin", 0x0000, 0x0100, NO_DUMP CRC(23e81049) SHA1(78071dae70fad870e972d944642fb3a2374be5e4) ) - ROM_LOAD( "u5.bin", 0x0100, 0x0100, NO_DUMP CRC(526cf9d3) SHA1(eb779d70f2507d0f26d225ac8f5de8f2243599ca) ) + ROM_LOAD( "u4.bin", 0x0000, 0x0100, CRC(23e81049) SHA1(78071dae70fad870e972d944642fb3a2374be5e4) ) + ROM_LOAD( "u5.bin", 0x0100, 0x0100, CRC(526cf9d3) SHA1(eb779d70f2507d0f26d225ac8f5de8f2243599ca) ) ROM_REGION( 0x40, "proms2", 0 ) - ROM_LOAD( "u2.bin", 0x0000, 0x0020, NO_DUMP CRC(c6b41352) SHA1(d7c3b5aa32e4e456c9432a13bede1db6d62eb270) ) + ROM_LOAD( "u2.bin", 0x0000, 0x0020, CRC(c6b41352) SHA1(d7c3b5aa32e4e456c9432a13bede1db6d62eb270) ) ROM_REGION( 0x100, "unkprom", 0 ) - ROM_LOAD( "u3.bin", 0x0000, 0x0100, NO_DUMP CRC(1d668d4a) SHA1(459117f78323ea264d3a29f1da2889bbabe9e4be) ) + ROM_LOAD( "u3.bin", 0x0000, 0x0100, CRC(1d668d4a) SHA1(459117f78323ea264d3a29f1da2889bbabe9e4be) ) ROM_REGION( 0x20, "unkprom2", 0 ) - ROM_LOAD( "u1.bin", 0x0000, 0x0020, NO_DUMP CRC(6df3f972) SHA1(0096a7f7452b70cac6c0752cb62e24b643015b5c) ) + ROM_LOAD( "u1.bin", 0x0000, 0x0020, CRC(6df3f972) SHA1(0096a7f7452b70cac6c0752cb62e24b643015b5c) ) ROM_END /* @@ -23801,7 +23911,7 @@ GAME( 1995, wcat3, 0, wcat3, lucky8, wingco_state, init_wcat GAMEL( 199?, animalw, 0, lucky8, animalw, wingco_state, empty_init, ROT0, "bootleg", "Animal Wonders (ver A900)", MACHINE_NOT_WORKING, layout_lucky8 ) // inputs / DIPs need to be checked GAMEL( 1989, cb2, 0, lucky8, lucky8, wingco_state, init_cb2, ROT0, "Dyna", "Cherry Bonus II (V2.00 06/01)", MACHINE_NOT_WORKING, layout_lucky8 ) // I/O need to be checked, seems reasonably working GAMEL( 1990, cbaai, 0, lucky8, lucky8, wingco_state, empty_init, ROT0, "bootleg (A.A.I.)", "Cherry Bonus (A.A.I. bootleg)", MACHINE_NOT_WORKING, layout_lucky8 ) // jumps to 0xf430 but there's nothing there? -GAMEL( 199?, ttactoe, 0, lucky8, lucky8, wingco_state, empty_init, ROT0, "bootleg (Sundance)","Tic Tac Toe (Sundance bootleg of New Lucky 8 Lines)", MACHINE_NOT_WORKING, layout_lucky8 ) // I/O need to be checked, seems reasonably working +GAMEL( 199?, ttactoe, 0, lucky8, ttactoe, wingco_state, empty_init, ROT0, "bootleg (Sundance)","Tic Tac Toe (Sundance bootleg of New Lucky 8 Lines)", 0, layout_lucky8 ) // needs more DSW figured out GAME( 1985, luckylad, 0, luckylad, luckylad, wingco_state, empty_init, ROT0, "Wing Co., Ltd.", "Lucky Lady (Wing, encrypted)", MACHINE_NOT_WORKING | MACHINE_WRONG_COLORS ) // controls / dips, colors not correctly decoded @@ -23932,7 +24042,7 @@ GAME( 1996, cherry96, scmaster, unkch, unkch4, unkch_state, init_un GAME( 1998, rolling, scmaster, rolling, unkch4, unkch_state, empty_init, ROT0, "bootleg", "Rolling", MACHINE_NOT_WORKING ) // inputs, outputs // this has a 4th reel -GAME( 200?, ss2001, 0, ss2001, cmaster, cmaster_state, empty_init, ROT0, "bootleg", "Super Shanghai 2001", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) // TODO: everything +GAME( 200?, ss2001, 0, ss2001, cmaster, cmaster_state, empty_init, ROT0, "bootleg", "Super Shanghai 2001", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) // TODO: everything // ******************* Stealth sets ******************* diff --git a/src/mame/layout/linn_linndrum.lay b/src/mame/layout/linn_linndrum.lay index ede9314f83e..b60391d9ff4 100644 --- a/src/mame/layout/linn_linndrum.lay +++ b/src/mame/layout/linn_linndrum.lay @@ -67,7 +67,6 @@ copyright-holders:m1macrophage <element name="txt_tune_4"><text string="LO"><color red="0.82" green="0.43" blue="0.31"/></text></element> <element name="txt_tune_5"><text string="HI"><color red="0.82" green="0.43" blue="0.31"/></text></element> <element name="txt_tune_6"><text string="LO"><color red="0.82" green="0.43" blue="0.31"/></text></element> - <element name="txt_tune_7"><text string="HIHAT"><color red="0.82" green="0.43" blue="0.31"/></text></element> <element name="txt_mixer"><text string="MIXER"><color red="0.82" green="0.43" blue="0.31"/></text></element> <element name="txt_left_1"><text string="LEFT" align="1"><color red="0.82" green="0.43" blue="0.31"/></text></element> @@ -534,13 +533,16 @@ copyright-holders:m1macrophage <element ref="txt_tuning"><bounds x="1473" y="435" width="118" height="24"/></element> <element ref="line"><bounds x="1183" y="445" width="295" height="2"/></element> <element ref="line"><bounds x="1590" y="445" width="295" height="2"/></element> - <repeat count="7"> + <repeat count="6"> <param name="i" start="1" increment="1"/> <param name="x" start="1183" increment="106"/> <param name="knob_input" value="pot_tuning_~i~"/> <group ref="knob"><bounds x="~x~" y="495" width="54" height="54"/></group> <element ref="txt_tune_~i~"><bounds x="~x~" y="560" width="54" height="17"/></element> </repeat> + <param name="knob_input" value="pot_hihat_decay"/> + <group ref="knob"><bounds x="1819" y="495" width="54" height="54"/></group> + <element ref="txt_hihat"><bounds x="1819" y="560" width="54" height="17"/></element> <element ref="txt_snare"><bounds x="1183" y="582" width="54" height="17"/></element> <element ref="txt_toms"><bounds x="1395" y="582" width="54" height="17"/></element> <element ref="line"><bounds x="1286" y="590" width="108" height="2"/></element> @@ -608,10 +610,11 @@ copyright-holders:m1macrophage add_simplecounter_knob(view, "knob_pot_tempo", "pot_tempo", 1.5) add_simplecounter_knob(view, "knob_pot_volume", "pot_volume", 1.5) - for i = 1, 7 do + for i = 1, 6 do local knob_input = "pot_tuning_" .. i add_simplecounter_knob(view, "knob_" .. knob_input, knob_input, 3.5) end + add_simplecounter_knob(view, "knob_pot_hihat_decay", "pot_hihat_decay", 3.5) for i = 1, 16 do local pan_input = "pot_pan_" .. i diff --git a/src/mame/linn/linndrum.cpp b/src/mame/linn/linndrum.cpp index 1bfd8566775..edfb52c15e2 100644 --- a/src/mame/linn/linndrum.cpp +++ b/src/mame/linn/linndrum.cpp @@ -28,11 +28,12 @@ There are multiple voice architectures: There is a single, time-multiplexed DAC used for all voices, and each voice has its own output. All 8 voices can be played simultaneously, but only a single loudness variation of each. The bass drum is post-processed by a - CEM3320 VCF with a hardcoded envelope, but all other voices lack a - reconstruction filter. The hat is post-processed by a CEM3360 VCA, which can - operate in 2 variations: slow decay (open hat) and faster, user-controlled - decay (closed hat). There's a single clock for all voices, which is tuned by - a trimmer on the circuit board. + CEM3320 VCF with a hardcoded envelope, the output of which is routed to the + mixer and an individual output jack. The rest of the voices are sent to the + mixer unfiltered, but their individual outputs have a ~15.9KHz RC LPF. The hat + is post-processed by a CEM3360 VCA, which can operate in 2 variations: slow + decay (open hat) and faster, user-controlled decay (closed hat). There's a + single clock for all voices, which is tuned by a trimmer on the circuit board. * The "snare / sidestick" section consists of a single voice core (and single DAC) which can either play the sidestick, or the snare voice (4K samples @@ -57,14 +58,10 @@ There are multiple voice architectures: The driver is based on the LinnDrum's service manual and schematics, and is intended as an educational tool. -Most of the digital functionality is emulated. Audio is partially emulated. - Reasons for MACHINE_IMPERFECT_SOUND: * Missing a few sample checksums. * Missing bass drum LPF and filter envelope. -* Missing snare / sidestick volume envelope. * Missing tom / conga LPF and filter envelope. -* Inaccurate filter for "click". * Linear, instead of tanh response for hi-hat VCA. PCBoards: @@ -96,6 +93,7 @@ Example: #include "machine/rescap.h" #include "machine/timer.h" #include "sound/dac76.h" +#include "sound/flt_biquad.h" #include "sound/flt_rc.h" #include "sound/flt_vol.h" #include "sound/mixer.h" @@ -200,6 +198,7 @@ public: DECLARE_INPUT_CHANGED_MEMBER(mux_drum_tuning_changed); DECLARE_INPUT_CHANGED_MEMBER(snare_tuning_changed); DECLARE_INPUT_CHANGED_MEMBER(tom_tuning_changed); + DECLARE_INPUT_CHANGED_MEMBER(hat_decay_changed); protected: void device_add_mconfig(machine_config &config) override ATTR_COLD; @@ -222,6 +221,7 @@ private: void update_mux_drum_pitch(); void update_snare_pitch(); void update_tom_pitch(); + void update_hat_decay(); // Mux drums. required_ioport m_mux_tuning_trimmer; @@ -233,6 +233,8 @@ private: required_device<timer_device> m_hat_trigger_timer; // U37B (LM556). required_device<va_rc_eg_device> m_hat_eg; required_device<va_vca_device> m_hat_vca; // CEM3360 (U91B). + bool m_hat_open = false; + bool m_hat_triggered = false; std::array<bool, NUM_MUX_VOICES> m_mux_counting = { false, false, false, false, false, false, false, false }; std::array<u16, NUM_MUX_VOICES> m_mux_counters = { 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -266,7 +268,8 @@ private: required_ioport_array<NUM_MIXER_CHANNELS> m_volume; required_ioport_array<NUM_MIXER_CHANNELS> m_pan; required_ioport m_master_volume; - required_device_array<filter_rc_device, NUM_MIXER_CHANNELS> m_voice_hpf; + required_device_array<filter_rc_device, NUM_MIXER_CHANNELS - 1> m_voice_hpf; + required_device<filter_biquad_device> m_click_bpf; required_device<mixer_device> m_left_mixer; // 4558 op-amp (U1A). required_device<mixer_device> m_right_mixer; // 4558 op-amp (U1B). required_device<speaker_device> m_left_out; // 4558 op-amp (U2A). @@ -289,14 +292,15 @@ private: RES_R(0), // low conga RES_K(5.1), // cowbell RES_K(2.4), // clap - RES_K(0), // click + RES_R(0), // click }; static constexpr const float MIXER_R_FEEDBACK = RES_K(33); - static constexpr const float MIXER_R_BEEP = RES_K(510); + static constexpr const float MIXER_R_BEEP = RES_K(510); // Same value for left and right. static constexpr const float OUTPUT_R_INPUT = RES_K(10); // Input resistor of output stage opamp. static constexpr const float OUTPUT_R_FEEDBACK = RES_K(10); static constexpr const float OUTPUT_C_FEEDBACK = CAP_P(1000); + static constexpr const float R_ON_CD4053 = RES_R(125); // Typical Ron resistance for 15V supply (-7.5V / 7.5V). static constexpr const float VPLUS = 15; // Volts. static constexpr const float VCC = 5; // Volts. @@ -311,7 +315,7 @@ private: static constexpr const float HAT_R33 = RES_M(1); static constexpr const float HAT_R34 = RES_K(10); static constexpr const float HAT_DECAY_POT_R_MAX = RES_K(100); - static constexpr const float HAT_MAX_CV = VCC * RES_VOLTAGE_DIVIDER(RES_K(8.2), RES_K(10)); // R67, R66. + static constexpr const float HAT_EG2CV_SCALER = RES_VOLTAGE_DIVIDER(RES_K(8.2), RES_K(10)); // R67, R66. // The audio pipeline operates on voltage magnitudes. This scaler normalizes // the final output's range to approximately: -1 - 1. @@ -349,7 +353,7 @@ DEFINE_DEVICE_TYPE(LINNDRUM_AUDIO, linndrum_audio_device, "linndrum_audio_device linndrum_audio_device::linndrum_audio_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : device_t(mconfig, LINNDRUM_AUDIO, tag, owner, clock) , m_mux_tuning_trimmer(*this, ":pot_mux_tuning") - , m_hat_decay_pot(*this, ":pot_tuning_7") + , m_hat_decay_pot(*this, ":pot_hihat_decay") , m_mux_samples(*this, ":sample_mux_drum_%u", 0) , m_mux_timer(*this, "mux_drum_timer") , m_mux_dac(*this, "mux_drums_virtual_dac_%u", 1) @@ -376,6 +380,7 @@ linndrum_audio_device::linndrum_audio_device(const machine_config &mconfig, cons , m_pan(*this, ":pot_pan_%u", 1) , m_master_volume(*this, ":pot_volume") , m_voice_hpf(*this, "voice_hpf_%u", 1) + , m_click_bpf(*this, "click_bpf") , m_left_mixer(*this, "lmixer") , m_right_mixer(*this, "rmixer") , m_left_out(*this, "lspeaker") @@ -397,28 +402,18 @@ void linndrum_audio_device::mux_drum_w(int voice, u8 data, bool is_strobe) // remain unchanged, or it will get attenuated by a voltage divider. // The MUX is always configured in the "no attenuation" mode for the clap // and cowbell voices. - static constexpr const float ATTENUATION = RES_VOLTAGE_DIVIDER(RES_K(10), RES_K(3.3)); // R60, R62. + static constexpr const float ATTENUATION = RES_VOLTAGE_DIVIDER(RES_K(10), RES_K(3.3) + R_ON_CD4053); // R60, R62. const bool attenuate = !BIT(data, 1) && voice != MV_CLAP && voice != MV_COWBELL; m_mux_volume[voice]->set_gain(attenuate ? ATTENUATION : 1); if (voice == MV_HAT) { - float r = HAT_R33; - const bool is_open_hat = BIT(data, 2); - if (!is_open_hat) - { - const float r_decay = HAT_DECAY_POT_R_MAX * m_hat_decay_pot->read() / 100.0F; - r = RES_2_PARALLEL(HAT_R33, HAT_R34 + r_decay); - } - m_hat_eg->set_r(r); - LOGMASKED(LOG_HAT_EG, "Hat decay. Open: %d, r: %g\n", is_open_hat, r); - + m_hat_open = BIT(data, 2); + m_hat_triggered = is_strobe; + update_hat_decay(); if (is_strobe) - { - m_hat_eg->set_instant_v(HAT_MAX_CV); m_hat_trigger_timer->adjust(PERIOD_OF_555_MONOSTABLE(RES_K(510), CAP_U(0.01))); // R8, C4. - LOGMASKED(LOG_HAT_EG, "Hat EG triggered.\n"); - } + LOGMASKED(LOG_HAT_EG, "Hat EG write: %x, %d.\n", data, is_strobe); } LOGMASKED(LOG_STROBES, "Strobed mux drum %s: %02x (gain: %f)\n", @@ -450,6 +445,10 @@ void linndrum_audio_device::snare_w(u8 data) // the DAC. Bits D2 and D3 from the voice data bus (latched by U42, 74LS74) // control the voltage at the end of R72 and R71. + // While there is a capacitor (C29, 0.01 UF) attached to the DAC's Iref + // input, it is too small to have a musical effect. Changes in current will + // stablizie within 0.1 ms, and such changes only happen at voice trigger. + static constexpr const float R0 = RES_K(3.3); // R70. static constexpr const float R1 = RES_K(380); // R69. static constexpr const float R2 = RES_K(22); // R72. @@ -514,9 +513,7 @@ void linndrum_audio_device::tom_w(u8 data) void linndrum_audio_device::strobe_click_w(u8 /*data*/) { - static constexpr const float R10 = RES_K(100); - static constexpr const float C12 = CAP_U(0.01); - m_click_timer->adjust(PERIOD_OF_555_MONOSTABLE(R10, C12)); + m_click_timer->adjust(PERIOD_OF_555_MONOSTABLE(RES_K(100), CAP_U(0.01))); // R10, C12. m_click->level_w(1); LOGMASKED(LOG_STROBES, "Strobed click.\n"); } @@ -553,6 +550,11 @@ DECLARE_INPUT_CHANGED_MEMBER(linndrum_audio_device::tom_tuning_changed) update_tom_pitch(); } +DECLARE_INPUT_CHANGED_MEMBER(linndrum_audio_device::hat_decay_changed) +{ + update_hat_decay(); +} + void linndrum_audio_device::device_add_mconfig(machine_config &config) { // *** Mux drums section. @@ -578,7 +580,7 @@ void linndrum_audio_device::device_add_mconfig(machine_config &config) VA_RC_EG(config, m_hat_eg).set_c(HAT_C22); VA_VCA(config, m_hat_vca).configure_streaming_cv(true).configure_cem3360_linear_cv(); m_mux_volume[MV_HAT]->add_route(0, m_hat_vca, 1.0); - m_hat_eg->add_route(0, m_hat_vca, 1.0); + m_hat_eg->add_route(0, m_hat_vca, HAT_EG2CV_SCALER); // *** Snare / sidestick section. @@ -619,7 +621,6 @@ void linndrum_audio_device::device_add_mconfig(machine_config &config) } // *** Mixer. - const std::array<device_sound_interface *, NUM_MIXER_CHANNELS> voice_outputs = { m_mux_volume[MV_BASS], @@ -642,7 +643,9 @@ void linndrum_audio_device::device_add_mconfig(machine_config &config) MIXER(config, m_left_mixer); // U1A MIXER(config, m_right_mixer); // U1B - for (int i = 0; i < voice_outputs.size(); ++i) + + assert(voice_outputs.size() - 1 == MIX_CLICK); + for (int i = 0; i < voice_outputs.size() - 1; ++i) // Skip "click". { // The filter and gain will be configured in update_volume_and_pan(). FILTER_RC(config, m_voice_hpf[i]); @@ -651,6 +654,11 @@ void linndrum_audio_device::device_add_mconfig(machine_config &config) m_voice_hpf[i]->add_route(0, m_right_mixer, 1.0); } + FILTER_BIQUAD(config, m_click_bpf); // Configured in update_volume_and_pan(). + voice_outputs[MIX_CLICK]->add_route(0, m_click_bpf, 1.0); + m_click_bpf->add_route(0, m_left_mixer, 1.0); + m_click_bpf->add_route(0, m_right_mixer, 1.0); + auto &beep_hpf = FILTER_RC(config, "beep_hpf"); const float rc_r = RES_2_PARALLEL(MIXER_R_BEEP, MIXER_R_BEEP); beep_hpf.set_rc(filter_rc_device::HIGHPASS, rc_r, 0, 0, CAP_U(0.1)); // C17. Cutoff: ~6.24 Hz. @@ -677,6 +685,8 @@ void linndrum_audio_device::device_add_mconfig(machine_config &config) void linndrum_audio_device::device_start() { + save_item(NAME(m_hat_open)); + save_item(NAME(m_hat_triggered)); save_item(NAME(m_mux_counting)); save_item(NAME(m_mux_counters)); save_item(NAME(m_snare_counting)); @@ -696,6 +706,7 @@ void linndrum_audio_device::device_reset() update_mux_drum_pitch(); update_snare_pitch(); update_tom_pitch(); + update_hat_decay(); } void linndrum_audio_device::write_dac(dac76_device &dac, u8 sample) @@ -749,7 +760,8 @@ float linndrum_audio_device::get_snare_tom_pitch_cv(float v_tune) TIMER_DEVICE_CALLBACK_MEMBER(linndrum_audio_device::hat_trigger_timer_tick) { - m_hat_eg->set_target_v(0); + m_hat_triggered = false; + update_hat_decay(); LOGMASKED(LOG_HAT_EG, "Hat EG started decay.\n"); } @@ -851,7 +863,8 @@ void linndrum_audio_device::update_volume_and_pan(int channel) // Since we are interested in voltage gain, rather than actual voltage, // use 1V as the voice's output. static constexpr const float V_VOICE = 1; - // DC-blocking capacitor. Same value for all voice outputs. + // DC-blocking capacitor. Same value for all voice outputs except for the + // "click" and "beep" sounds. static constexpr const float C_VOICE = CAP_U(10); const s32 volume = m_volume[channel]->read(); @@ -864,8 +877,9 @@ void linndrum_audio_device::update_volume_and_pan(int channel) const float r_right_gnd = R1 + RES_2_PARALLEL(r_pan_right, R3); const float r_left_gnd = R2 + RES_2_PARALLEL(r_pan_left, R4); - // Resistance to ground as seen from the voice's output. - const float r_voice_gnd = r0 + RES_3_PARALLEL(r_vol_bottom, r_left_gnd, r_right_gnd); + // Resistance to ground as seen from the volume pot's wiper and the voice's output. + const float r_wiper_gnd = RES_3_PARALLEL(r_vol_bottom, r_left_gnd, r_right_gnd); + const float r_voice_gnd = r0 + r_wiper_gnd; float gain_left = 0; float gain_right = 0; @@ -891,11 +905,83 @@ void linndrum_audio_device::update_volume_and_pan(int channel) // Using -gain_*, because the summing op-amps are inverting. m_left_mixer->set_input_gain(channel, -gain_left); m_right_mixer->set_input_gain(channel, -gain_right); - m_voice_hpf[channel]->filter_rc_set_RC(filter_rc_device::HIGHPASS, r_voice_gnd, 0, 0, C_VOICE); - LOGMASKED(LOG_MIX, "Gain update for %s - left: %f, right: %f, HPF cutoff: %.2f Hz\n", - MIXER_CHANNEL_NAMES[channel], gain_left, gain_right, - 1.0F / (2 * float(M_PI) * r_voice_gnd * C_VOICE)); + if (channel == MIX_CLICK) + { + // Compared to the other voices, the click uses a different value for + // the DC blocking capacitor. Furthermore, there is a capacitor to ground + // at the volume pot wiper. The resulting filter acts as an HPF (cutoff: + // ~1.15 KHz) when the click volume is at max, and becomes a BPF whose + // characteristics change as the volume decreases. + + // Capacitor at the output of the 556 timer. + static constexpr const float C_CLICK_DCBLOCK = CAP_U(0.01); // C37 + // Capacitor to ground, at the wiper of the "click" volume fader. + static constexpr const float C_CLICK_WIPER = CAP_U(0.047); // No designation. + + // All "click" filter configurations result in singificant attenutation + // (< 0.2x), which makes the click very quiet. The filter characteristics + // (gain and Fc) have been verified with simulations. So it is possible + // there is an error in the schematic. Different capacitor values, or a + // supply of 15V (instead of the stated 5V) for the 556 timer generating + // the click could explain this. + // For now, scale by some number to match the volume of other voices. + static constexpr const float CLICK_GAIN_CORRECTION = 5; + + float fc = 0; + float q = 1; + float gain = 1; + if (volume >= 100) + { + // HPF transfer function: H(s) = (g * s) / (s + w) where + // g = C1 / (C1 + C2) + // w = 1 / (R * (C1 + C2)) + fc = 1.0F / (2 * float(M_PI) * r_voice_gnd * (C_CLICK_DCBLOCK + C_CLICK_WIPER)); + gain = C_CLICK_DCBLOCK / (C_CLICK_DCBLOCK + C_CLICK_WIPER); + m_click_bpf->modify(filter_biquad_device::biquad_type::HIGHPASS1P1Z, fc, 1, gain * CLICK_GAIN_CORRECTION); + } + else if (volume > 0) + { + // BPF transfer function: H(s) = (A * s) / (s ^ 2 + B * s + C) + // Where: + // A = 1 / (R1 * C2) + // B = (C1 * R1 + C1 * R2 + C2 * R2) / (R1 * R2 * C1 * C2) + // C = 1 / (R1 * R2 * C1 * C2). + // From the standard transfer function for BPFs, we have: + // A = gain * (w / Q) + // B = w / Q + // C = w ^ 2 + // The calculations of Fc, Q and gain below are derived from the + // equations above, with some algebra. + + const float x = sqrtf(r0 * r_wiper_gnd * C_CLICK_DCBLOCK * C_CLICK_WIPER); + const float y = C_CLICK_DCBLOCK * r0 + C_CLICK_DCBLOCK * r_wiper_gnd + C_CLICK_WIPER * r_wiper_gnd; + fc = 1.0F / (2 * float(M_PI) * x); + q = x / y; + gain = r_wiper_gnd * C_CLICK_DCBLOCK / y; + + // The transfer function above includes the effect of the volume + // potentiometer. But `gain_left` and `gain_right` already incorporate + // that effect. So it needs to be undone from the filter's gain. + gain *= 1.0F / RES_VOLTAGE_DIVIDER(r0, r_wiper_gnd); + + m_click_bpf->modify(filter_biquad_device::biquad_type::BANDPASS, fc, q, gain * CLICK_GAIN_CORRECTION); + } + // Else, if the volume is 0, don't change the BPF's configuration to avoid divisions by 0. + + LOGMASKED(LOG_MIX, "Gain update for %s - left: %f, right: %f, %s cutoff: %.2f Hz, Q: %.3f, Gain: %.3f\n", + MIXER_CHANNEL_NAMES[MIX_CLICK], gain_left, gain_right, + (volume >= 100) ? "HPF" : "BPF", fc, q, gain); + } + else + { + // The rest of the voices just have a DC-blocking filter. Its exact cutoff + // will depend on the volume and pan settings, but it won't be audible. + m_voice_hpf[channel]->filter_rc_set_RC(filter_rc_device::HIGHPASS, r_voice_gnd, 0, 0, C_VOICE); + LOGMASKED(LOG_MIX, "Gain update for %s - left: %f, right: %f, HPF cutoff: %.2f Hz\n", + MIXER_CHANNEL_NAMES[channel], gain_left, gain_right, + 1.0F / (2 * float(M_PI) * r_voice_gnd * C_VOICE)); + } } void linndrum_audio_device::update_master_volume() @@ -996,6 +1082,31 @@ void linndrum_audio_device::update_tom_pitch() knob_index, knob_value, cv, freq); } +void linndrum_audio_device::update_hat_decay() +{ + // When the hat is configed as "open", the EG will discharge through a 1M + // resistor. When the hat is "closed", a CD4053 will add a parallel + // discharge path through the "hihat decay" pot. + float eg_r = HAT_R33; + if (!m_hat_open) + { + const float r_decay_pot = HAT_DECAY_POT_R_MAX * m_hat_decay_pot->read() / 100.0F; + eg_r = RES_2_PARALLEL(HAT_R33, HAT_R34 + R_ON_CD4053 + r_decay_pot); + } + m_hat_eg->set_r(eg_r); + + // When the hat is strobed, it will trigger a 556 (U37A) timer in monostable + // mode (see mux_drum_w()). The timer's output pin is connected to the EG + // capacitor via a diode, and will maintain that capacitor at VCC until the + // timer expires. At that point, the EG capacitor will discharge through eg_r. + if (m_hat_triggered) + m_hat_eg->set_instant_v(VCC); + else + m_hat_eg->set_target_v(0); + + LOGMASKED(LOG_HAT_EG, "Hat decay. Open: %d, EG R: %f\n", m_hat_open, eg_r); +} + namespace { constexpr const char MAINCPU_TAG[] = "z80"; @@ -1443,8 +1554,8 @@ INPUT_PORTS_START(linndrum) PORT_ADJUSTER(52, "HI CONGAS TUNING") PORT_CHANGED_MEMBER(AUDIO_TAG, FUNC(linndrum_audio_device::tom_tuning_changed), 0) PORT_START("pot_tuning_6") PORT_ADJUSTER(40, "LO CONGAS TUNING") PORT_CHANGED_MEMBER(AUDIO_TAG, FUNC(linndrum_audio_device::tom_tuning_changed), 0) - PORT_START("pot_tuning_7") - PORT_ADJUSTER(50, "HIHAT DECAY") + PORT_START("pot_hihat_decay") + PORT_ADJUSTER(50, "HIHAT DECAY") PORT_CHANGED_MEMBER(AUDIO_TAG, FUNC(linndrum_audio_device::hat_decay_changed), 0) PORT_START("pot_pan_1") PORT_ADJUSTER(50, "BASS PAN") PORT_CHANGED_MEMBER(AUDIO_TAG, FUNC(linndrum_audio_device::mix_changed), MIX_BASS) diff --git a/src/mame/misc/deecoseal.cpp b/src/mame/misc/deecoseal.cpp index 23bfee7c24b..6be4deaee32 100644 --- a/src/mame/misc/deecoseal.cpp +++ b/src/mame/misc/deecoseal.cpp @@ -29,6 +29,7 @@ public: m_crtc(*this, "crtc"), m_duart(*this, "duart"), m_palette(*this, "palette"), + m_eeprom(*this, "eeprom"), m_vram(*this, "vram") { } @@ -41,6 +42,8 @@ private: void mcs51_map(address_map &map); void crtc_map(address_map &map); UPD7220_DISPLAY_PIXELS_MEMBER(draw); + u8 i2c_r(); + void i2c_w(u8 data); bool m_port0; @@ -49,6 +52,7 @@ private: required_device<upd7220_device> m_crtc; required_device<scn2681_device> m_duart; required_device<palette_device> m_palette; + required_device<i2c_x2404p_device> m_eeprom; required_shared_ptr<u16> m_vram; }; @@ -90,6 +94,7 @@ void deecoseal_state::io(address_map &map) map(0x0000, 0x0001).lr16([this](){ m_port0 = !m_port0; return m_port0 ? 0x10 : 0; }, "port0"); map(0x0110, 0x011f).rw(m_duart, FUNC(scn2681_device::read), FUNC(scn2681_device::write)).umask16(0x00ff); map(0x0180, 0x0183).rw(m_crtc, FUNC(upd7220_device::read), FUNC(upd7220_device::write)).umask16(0x00ff); + map(0x0200, 0x0200).rw(FUNC(deecoseal_state::i2c_r), FUNC(deecoseal_state::i2c_w)); } void deecoseal_state::mcs51_map(address_map &map) @@ -99,18 +104,29 @@ void deecoseal_state::mcs51_map(address_map &map) void deecoseal_state::crtc_map(address_map &map) { - map(0x0000, 0x3fff).ram().share("vram"); + map(0x0000, 0xffff).ram().share("vram"); } UPD7220_DISPLAY_PIXELS_MEMBER( deecoseal_state::draw ) { - u16 const gfx = m_vram[address & 0x3fff]; + u16 const gfx = m_vram[address]; pen_t const *const pen = m_palette->pens(); for(u16 i = 0; i < 16; i++) bitmap.pix(y, x + i) = pen[BIT(gfx, i)]; } +u8 deecoseal_state::i2c_r() +{ + return m_eeprom->read_sda() ? 0x10 : 0; +} + +void deecoseal_state::i2c_w(u8 data) +{ + m_eeprom->write_scl(data & 0x40 ? 1 : 0); + m_eeprom->write_sda(data & 0x10 ? 1 : 0); +} + void deecoseal_state::deecoseal(machine_config &config) { I80186(config, m_maincpu, XTAL(24'000'000)); @@ -120,7 +136,7 @@ void deecoseal_state::deecoseal(machine_config &config) I80C31(config, m_mcs51, XTAL(24'000'000) / 4).set_disable(); // clock? m_mcs51->set_addrmap(AS_PROGRAM, &deecoseal_state::mcs51_map); - I2C_X2404P(config, "eeprom"); + I2C_X2404P(config, m_eeprom); NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_1); // 2x 28c256 diff --git a/src/mame/misc/norautp.cpp b/src/mame/misc/norautp.cpp index 834744890ea..25973b42638 100644 --- a/src/mame/misc/norautp.cpp +++ b/src/mame/misc/norautp.cpp @@ -852,9 +852,11 @@ public: void noraut3(machine_config &config); void cgidjp(machine_config &config); void cdrawpkr(machine_config &config); + void krampcb4(machine_config &config); void init_enc(); void init_unka(); + void init_kram4(); protected: virtual void machine_start() override ATTR_COLD; @@ -900,7 +902,8 @@ private: void norautxp_portmap(address_map &map) ATTR_COLD; void nortest1_map(address_map &map) ATTR_COLD; void ssjkrpkr_map(address_map &map) ATTR_COLD; - + void krampcb4_map(address_map &map) ATTR_COLD; + uint8_t nvram_r(offs_t offset); void nvram_w(offs_t offset, uint8_t data); void nvunlock_w(offs_t offset, uint8_t data); @@ -939,6 +942,7 @@ void norautp_state::machine_start() save_item(NAME(m_nvunlock)); } + /********************************************* * Video Hardware * *********************************************/ @@ -1491,6 +1495,13 @@ void norautp_state::drhl_map(address_map &map) map(0x5400, 0x57ff).ram(); } +void norautp_state::krampcb4_map(address_map &map) +{ + map(0x0000, 0x3fff).rom(); + map(0xa000, 0xa7ff).ram().share("nvram"); +// map(0xff00, 0xffff).ram(); +} + void norautp_state::dphla_portmap(address_map &map) { @@ -2808,6 +2819,27 @@ void norautp_state::ssjkrpkr(machine_config &config) m_discrete->set_intf(dphl_discrete); } +void norautp_state::krampcb4(machine_config &config) +{ + noraut_base(config); + + // basic machine hardware + I8080(config.replace(), m_maincpu, DPHL_CPU_CLOCK); + m_maincpu->set_addrmap(AS_PROGRAM, &norautp_state::krampcb4_map); + m_maincpu->set_addrmap(AS_IO, &norautp_state::dphl_portmap); + m_maincpu->set_vblank_int("screen", FUNC(norautp_state::irq0_line_hold)); + m_screen->set_screen_update(FUNC(norautp_state::screen_update_dphl)); + + PALETTE(config.replace(), "palette", FUNC(norautp_state::bp_based_palette), 256); + + TIMER(config, "test_timer").configure_periodic(FUNC(norautp_state::test_timer_cb), attotime::from_usec(100)); + + m_display_line_control = true; + + // sound hardware + m_discrete->set_intf(dphl_discrete); +} + /********************************************* * Rom Load * @@ -6430,6 +6462,22 @@ void norautp_state::init_unka() } +void norautp_state::init_kram4() +{ + uint8_t *rom = memregion("maincpu")->base(); + std::vector<uint8_t> buffer(0x4000); + + memcpy(&buffer[0], rom, 0x4000); + + for (int i = 0; i < 0x4000; i++) + { + if ((i & 0x03) == 0x01) rom[i] = buffer[i + 0x01]; + if ((i & 0x03) == 0x02) rom[i] = buffer[i - 0x01]; + rom[i] = bitswap<8>(rom[i], 7, 5, 6, 4, 3, 2, 1, 0); + } +} + + /********************************************* * Game Drivers * *********************************************/ @@ -6509,9 +6557,9 @@ GAMEL( 198?, dphlunkb, 0, dphl, dphla, norautp_state, empty_ini GAME( 1989, pokplus, 0, dphlxtnd, norautp, norautp_state, empty_init, ROT0, "LJF Corporation", "Poker Plus 6 Cards (set 1)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING ) // encriypted GAME( 1989, pokplusa, pokplus, dphlxtnd, norautp, norautp_state, empty_init, ROT0, "LJF Corporation", "Poker Plus 6 Cards (set 2)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING ) // encriypted GAME( 1989, pokplusb, pokplus, dphlxtnd, norautp, norautp_state, empty_init, ROT0, "LJF Corporation", "Poker Plus 6 Cards (set 3)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING ) // encriypted -GAME( 198?, krampcb3, 0, dphl, dphl, norautp_state, empty_init, ROT0, "M.Kramer Manufacturing.", "unknown Kramer Poker (pcb3, encrypted)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING ) // encriypted -GAME( 198?, krampcb4, 0, dphl, dphl, norautp_state, empty_init, ROT0, "M.Kramer Manufacturing.", "unknown Kramer Poker (pcb4, encrypted)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING ) // encriypted -GAME( 198?, krampcb6, 0, dphl, dphl, norautp_state, empty_init, ROT0, "M.Kramer Manufacturing.", "unknown Kramer Poker (pcb6, encrypted)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING ) // encriypted +GAMEL( 198?, krampcb3, 0, krampcb4, dphl, norautp_state, empty_init, ROT0, "M.Kramer Manufacturing.", "unknown Kramer Poker (pcb3, encrypted)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING, layout_noraut10 ) // encriypted +GAMEL( 198?, krampcb4, 0, krampcb4, dphl, norautp_state, init_kram4, ROT0, "M.Kramer Manufacturing.", "unknown Kramer Poker (pcb4, encrypted)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING, layout_noraut10 ) // encriypted +GAMEL( 198?, krampcb6, 0, krampcb4, dphl, norautp_state, empty_init, ROT0, "M.Kramer Manufacturing.", "unknown Kramer Poker (pcb6, encrypted)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING, layout_noraut10 ) // encriypted // The following ones also have a custom 68705 MCU diff --git a/src/mame/msx/msx_keyboard.cpp b/src/mame/msx/msx_keyboard.cpp index 3c8ee0362da..804840e86d6 100644 --- a/src/mame/msx/msx_keyboard.cpp +++ b/src/mame/msx/msx_keyboard.cpp @@ -232,10 +232,10 @@ INPUT_PORTS_START(msxjp) PORT_MODIFY("KEY2") PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(':') PORT_CHAR('*') PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(']') PORT_CHAR('}') - PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("_") PORT_CODE(KEYCODE_TILDE) PORT_CHAR('_') + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("_") PORT_CODE(KEYCODE_TILDE) PORT_CHAR() PORT_CHAR('_') PORT_MODIFY("KEY6") - PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KANA") PORT_CODE(KEYCODE_PGDN) PORT_CHAR(UCHAR_MAMEKEY(F7)) + PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("KANA") PORT_CODE(KEYCODE_PGDN) PORT_CHAR(UCHAR_MAMEKEY(F7)) INPUT_PORTS_END diff --git a/src/mame/sony/news_r4k.cpp b/src/mame/sony/news_r4k.cpp index 81c5da9935e..4cb49448c94 100644 --- a/src/mame/sony/news_r4k.cpp +++ b/src/mame/sony/news_r4k.cpp @@ -453,10 +453,6 @@ void news_r4k_state::machine_common(machine_config &config) m_sonic->out_int_cb().set(m_sonic3, FUNC(cxd8452aq_device::irq_w)); m_sonic->set_bus(m_sonic3, 1); - // Use promiscuous mode to force network driver to accept all packets, since SONIC has its own filter (CAM table) - // Not sure if needing to use this means something else isn't set up correctly. - m_sonic->set_promisc(true); - // Unlike 68k and R3000 NEWS machines, the keyboard and mouse seem to share an interrupt // See https://github.com/NetBSD/src/blob/trunk/sys/arch/newsmips/apbus/ms_ap.c#L103 // where the mouse interrupt handler is initialized using the Keyboard interrupt. diff --git a/src/osd/interface/nethandler.cpp b/src/osd/interface/nethandler.cpp index 79823c2d7fd..f3715df9b12 100644 --- a/src/osd/interface/nethandler.cpp +++ b/src/osd/interface/nethandler.cpp @@ -16,7 +16,6 @@ namespace osd { network_handler::network_handler() noexcept - : m_promisc(false) { std::fill(std::begin(m_mac), std::end(m_mac), 0); } diff --git a/src/osd/interface/nethandler.h b/src/osd/interface/nethandler.h index 3a9a47ebd8b..9513b158d99 100644 --- a/src/osd/interface/nethandler.h +++ b/src/osd/interface/nethandler.h @@ -15,6 +15,7 @@ #include "osdcomm.h" #include <array> +#include <string_view> namespace osd { @@ -23,6 +24,7 @@ namespace osd { // TYPE DEFINITIONS //************************************************************************** + // base for virtual network interface handler class network_handler @@ -33,15 +35,36 @@ public: virtual void recv_cb(u8 *buf, int len) = 0; std::array<u8, 6> const &get_mac() noexcept { return m_mac; } - bool get_promisc() noexcept { return m_promisc; } protected: ~network_handler() = default; - bool m_promisc; std::array<u8, 6> m_mac; }; + +// interface to network device + +class network_device +{ +public: + virtual ~network_device() = default; + + virtual void start() = 0; + virtual void stop() = 0; + virtual void poll() = 0; + virtual int send(const void *buf, int len) = 0; +}; + + +// description of an available network device + +struct network_device_info +{ + int id; + std::string_view description; +}; + } // namespace osd #endif // MAME_OSD_INTERFACE_NETHANDLER_H diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp index e3c8d63b0d6..eed73f3097b 100644 --- a/src/osd/modules/lib/osdobj_common.cpp +++ b/src/osd/modules/lib/osdobj_common.cpp @@ -15,12 +15,12 @@ #include "modules/font/font_module.h" #include "modules/input/input_module.h" #include "modules/midi/midi_module.h" +#include "modules/netdev/netdev_module.h" #include "modules/monitor/monitor_module.h" #include "modules/netdev/netdev_module.h" #include "modules/render/render_module.h" #include "modules/sound/sound_module.h" -#include "osdnet.h" #include "watchdog.h" #include "emu.h" @@ -208,6 +208,7 @@ osd_common_t::osd_common_t(osd_options &options) , m_sound(nullptr) , m_debugger(nullptr) , m_midi(nullptr) + , m_network(nullptr) , m_keyboard_input(nullptr) , m_mouse_input(nullptr) , m_lightgun_input(nullptr) @@ -615,8 +616,8 @@ bool osd_common_t::execute_command(const char *command) { if (strcmp(command, OSDCOMMAND_LIST_NETWORK_ADAPTERS) == 0) { - osd_module &om = select_module_options<osd_module>(OSD_NETDEV_PROVIDER); - auto const &interfaces = get_netdev_list(); + auto &om = select_module_options<netdev_module>(OSD_NETDEV_PROVIDER); + auto const interfaces = om.list_devices(); if (interfaces.empty()) { printf("No supported network interfaces were found\n"); @@ -626,17 +627,17 @@ bool osd_common_t::execute_command(const char *command) printf("Available network interfaces:\n"); for (auto &entry : interfaces) { - printf(" %s\n", entry->description); + printf(" %.*s\n", int(entry.description.length()), entry.description.data()); } } - om.exit(); + dynamic_cast<osd_module &>(om).exit(); return true; } else if (strcmp(command, OSDCOMMAND_LIST_MIDI_DEVICES) == 0) { - osd_module &om = select_module_options<osd_module>(OSD_MIDI_PROVIDER); - auto const ports = dynamic_cast<midi_module &>(om).list_midi_ports(); + auto &om = select_module_options<midi_module>(OSD_MIDI_PROVIDER); + auto const ports = om.list_midi_ports(); if (ports.empty()) { printf("No MIDI ports were found\n"); @@ -657,7 +658,7 @@ bool osd_common_t::execute_command(const char *command) printf(port.default_output ? "%s (default)\n" : "%s\n", port.name.c_str()); } } - om.exit(); + dynamic_cast<osd_module &>(om).exit(); return true; } @@ -697,10 +698,10 @@ void osd_common_t::init_subsystems() m_debugger = &select_module_options<debug_module>(OSD_DEBUG_PROVIDER); - select_module_options<netdev_module>(OSD_NETDEV_PROVIDER); - m_midi = &select_module_options<midi_module>(OSD_MIDI_PROVIDER); + m_network = &select_module_options<netdev_module>(OSD_NETDEV_PROVIDER); + m_output = &select_module_options<output_module>(OSD_OUTPUT_PROVIDER); machine().output().set_global_notifier(output_notifier_callback, this); @@ -788,3 +789,12 @@ std::vector<osd::midi_port_info> osd_common_t::list_midi_ports() return m_midi->list_midi_ports(); } +std::unique_ptr<osd::network_device> osd_common_t::open_network_device(int id, osd::network_handler &handler) +{ + return m_network->open_device(id, handler); +} + +std::vector<osd::network_device_info> osd_common_t::list_network_devices() +{ + return m_network->list_devices(); +} diff --git a/src/osd/modules/lib/osdobj_common.h b/src/osd/modules/lib/osdobj_common.h index 820fe3edf21..991ebacfdce 100644 --- a/src/osd/modules/lib/osdobj_common.h +++ b/src/osd/modules/lib/osdobj_common.h @@ -197,6 +197,7 @@ class font_module; class input_module; class midi_module; class monitor_module; +class netdev_module; class osd_watchdog; class osd_window; class output_module; @@ -234,16 +235,22 @@ public: virtual void add_audio_to_recording(const int16_t *buffer, int samples_this_frame) override; virtual std::vector<ui::menu_item> get_slider_list() override; - // command option overrides - virtual bool execute_command(const char *command) override; - + // font interface virtual osd_font::ptr font_alloc() override; virtual bool get_font_families(std::string const &font_path, std::vector<std::pair<std::string, std::string> > &result) override; + // command option overrides + virtual bool execute_command(const char *command) override; + + // MIDI interface virtual std::unique_ptr<osd::midi_input_port> create_midi_input(std::string_view name) override; virtual std::unique_ptr<osd::midi_output_port> create_midi_output(std::string_view name) override; virtual std::vector<osd::midi_port_info> list_midi_ports() override; + // network interface + virtual std::unique_ptr<osd::network_device> open_network_device(int id, osd::network_handler &handler) override; + virtual std::vector<osd::network_device_info> list_network_devices() override; + // FIXME: everything below seems to be osd specific and not part of // this INTERFACE but part of the osd IMPLEMENTATION @@ -317,6 +324,7 @@ protected: sound_module* m_sound; debug_module* m_debugger; midi_module* m_midi; + netdev_module* m_network; input_module* m_keyboard_input; input_module* m_mouse_input; input_module* m_lightgun_input; diff --git a/src/osd/modules/netdev/netdev_common.cpp b/src/osd/modules/netdev/netdev_common.cpp new file mode 100644 index 00000000000..b6a2328c7a6 --- /dev/null +++ b/src/osd/modules/netdev/netdev_common.cpp @@ -0,0 +1,39 @@ +// license:BSD-3-Clause +// copyright-holders:Carl + +#include "netdev_common.h" + + +namespace osd { + +network_device_base::network_device_base(network_handler &handler) + : m_handler(handler) + , m_stopped(true) +{ +} + +network_device_base::~network_device_base() +{ +} + +void network_device_base::start() +{ + m_stopped = false; +} + +void network_device_base::stop() +{ + m_stopped = true; +} + +void network_device_base::poll() +{ + uint8_t *buf; + int len; + while (!m_stopped && (len = recv_dev(&buf))) + { + m_handler.recv_cb(buf, len); + } +} + +} // namespace osd diff --git a/src/osd/modules/netdev/netdev_common.h b/src/osd/modules/netdev/netdev_common.h new file mode 100644 index 00000000000..95d961a438a --- /dev/null +++ b/src/osd/modules/netdev/netdev_common.h @@ -0,0 +1,36 @@ +// license:BSD-3-Clause +// copyright-holders:Carl +#ifndef MAME_OSD_NETDEV_NETDEV_COMMON_H +#define MAME_OSD_NETDEV_NETDEV_COMMON_H + +#pragma once + +#include "interface/nethandler.h" + +#include <cstdint> + + +namespace osd { + +class network_device_base : public network_device +{ +public: + virtual ~network_device_base(); + + virtual void start() override; + virtual void stop() override; + virtual void poll() override; + +protected: + network_device_base(network_handler &handler); + + virtual int recv_dev(uint8_t **buf) = 0; + +private: + network_handler &m_handler; + bool m_stopped; +}; + +} // namespace osd + +#endif // MAME_OSD_NETDEV_NETDEV_COMMON_H diff --git a/src/osd/modules/netdev/netdev_module.h b/src/osd/modules/netdev/netdev_module.h index b102e56fbb8..3636c3a23cb 100644 --- a/src/osd/modules/netdev/netdev_module.h +++ b/src/osd/modules/netdev/netdev_module.h @@ -9,6 +9,11 @@ #pragma once +#include "interface/nethandler.h" + +#include <memory> +#include <vector> + //============================================================ // CONSTANTS @@ -20,7 +25,9 @@ class netdev_module { public: virtual ~netdev_module() = default; - // no specific routines below ... may change + + virtual std::unique_ptr<osd::network_device> open_device(int id, osd::network_handler &handler) = 0; + virtual std::vector<osd::network_device_info> list_devices() = 0; }; #endif // MAME_OSD_NETDEV_NETDEV_MODULE_H diff --git a/src/osd/modules/netdev/none.cpp b/src/osd/modules/netdev/none.cpp index 8441c002802..284ff51a962 100644 --- a/src/osd/modules/netdev/none.cpp +++ b/src/osd/modules/netdev/none.cpp @@ -8,6 +8,9 @@ #include "modules/osdmodule.h" +#include <memory> +#include <vector> + namespace osd { @@ -21,7 +24,21 @@ public: } virtual ~netdev_none() { } - virtual int init(osd_interface &osd, const osd_options &options) override { return 0; } + + virtual int init(osd_interface &osd, const osd_options &options) override + { + return 0; + } + + virtual std::unique_ptr<network_device> open_device(int id, network_handler &handler) override + { + return std::unique_ptr<network_device>(); + } + + virtual std::vector<network_device_info> list_devices() override + { + return std::vector<network_device_info>(); + } }; } // anonymous namespace diff --git a/src/osd/modules/netdev/pcap.cpp b/src/osd/modules/netdev/pcap.cpp index 77ca557f1de..8b5e20077fc 100644 --- a/src/osd/modules/netdev/pcap.cpp +++ b/src/osd/modules/netdev/pcap.cpp @@ -7,20 +7,25 @@ #if defined(OSD_NET_USE_PCAP) +#include "netdev_common.h" + #include "modules/lib/osdlib.h" -#include "osdnet.h" + #include "osdcore.h" // osd_printf_* #include "util/strformat.h" // string_format +#include <memory> +#include <vector> + #if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS) #include <windows.h> #undef interface #define LIB_NAME "wpcap.dll" #elif defined(SDLMAME_MACOSX) +#include <atomic> #include <pthread.h> -#include <libkern/OSAtomic.h> #define LIB_NAME "libpcap.dylib" #else @@ -47,10 +52,10 @@ typedef int (*pcap_dispatch_fn)(pcap_t *, int, pcap_handler, u_char *); class pcap_module : public osd_module, public netdev_module { public: - pcap_module() - : osd_module(OSD_NETDEV_PROVIDER, "pcap"), netdev_module(), - pcap_findalldevs_dl(nullptr), pcap_open_live_dl(nullptr), pcap_next_ex_dl(nullptr), pcap_compile_dl(nullptr), - pcap_close_dl(nullptr), pcap_setfilter_dl(nullptr), pcap_sendpacket_dl(nullptr), pcap_set_datalink_dl(nullptr), pcap_dispatch_dl(nullptr) + pcap_module() : + osd_module(OSD_NETDEV_PROVIDER, "pcap"), netdev_module(), + pcap_findalldevs_dl(nullptr), pcap_open_live_dl(nullptr), pcap_next_ex_dl(nullptr), pcap_compile_dl(nullptr), + pcap_close_dl(nullptr), pcap_setfilter_dl(nullptr), pcap_sendpacket_dl(nullptr), pcap_set_datalink_dl(nullptr), pcap_dispatch_dl(nullptr) { } @@ -84,6 +89,20 @@ public: return true; } + virtual std::unique_ptr<network_device> open_device(int id, network_handler &handler) override; + virtual std::vector<network_device_info> list_devices() override; + +private: + struct device_info + { + std::string name; + std::string description; + }; + + class netdev_pcap; + + std::vector<device_info> m_devices; + osd::dynamic_module::ptr pcap_dll; pcap_findalldevs_fn pcap_findalldevs_dl; @@ -97,132 +116,113 @@ public: pcap_dispatch_fn pcap_dispatch_dl; }; -// FIXME: bridge between pcap_module and netdev_pcap -static pcap_module *module = nullptr; - -#ifdef SDLMAME_MACOSX -struct netdev_pcap_context -{ - uint8_t *pkt; - int len; - pcap_t *p; - - uint8_t packets[32][1600]; - int packetlens[32]; - int head; - int tail; -}; -#endif - -class netdev_pcap : public osd_network_device +class pcap_module::netdev_pcap : public network_device_base { public: - netdev_pcap(const char *name, network_handler &ifdev); + netdev_pcap(pcap_module &module, const char *name, network_handler &handler); ~netdev_pcap(); - virtual int send(uint8_t *buf, int len) override; - virtual void set_mac(const uint8_t *mac) override; + virtual int send(void const *buf, int len) override; protected: virtual int recv_dev(uint8_t **buf) override; private: + pcap_module &m_module; pcap_t *m_p; #ifdef SDLMAME_MACOSX - struct netdev_pcap_context m_ctx; pthread_t m_thread; + uint8_t *pkt; + int len; + pcap_t *p; + + uint8_t packets[32][1600]; + int packetlens[32]; + std::atomic<int> head; + std::atomic<int> tail; + + static void pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes); + static void *pcap_blocker(void *arg); #endif }; #ifdef SDLMAME_MACOSX -static void netdev_pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) +void pcap_module::netdev_pcap::pcap_handler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) { - struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)user; + netdev_pcap *const ctx = reinterpret_cast<netdev_pcap *>(user); - if(!ctx->p) return; + if (!ctx->p) + return; - if(OSAtomicCompareAndSwapInt((ctx->head+1) & 0x1F, ctx->tail, &ctx->tail)) { + int const curr = ctx->head; + int const next = (curr + 1) & 0x1f; + if (ctx->tail.load(std::memory_order_acquire) == next) + { printf("buffer full, dropping packet\n"); return; } - memcpy(ctx->packets[ctx->head], bytes, h->len); - ctx->packetlens[ctx->head] = h->len; - OSAtomicCompareAndSwapInt(ctx->head, (ctx->head+1) & 0x1F, &ctx->head); + memcpy(ctx->packets[curr], bytes, h->len); + ctx->packetlens[curr] = h->len; + ctx->head.store(next, std::memory_order_release); } -static void *netdev_pcap_blocker(void *arg) { - struct netdev_pcap_context *ctx = (struct netdev_pcap_context*)arg; +void *pcap_module::netdev_pcap::pcap_blocker(void *arg) +{ + netdev_pcap *const ctx = reinterpret_cast<netdev_pcap *>(arg); - while(ctx && ctx->p) { - (*module->pcap_dispatch_dl)(ctx->p, 1, netdev_pcap_handler, (u_char*)ctx); - } + while (ctx && ctx->p) + (*ctx->m_module.pcap_dispatch_dl)(ctx->p, 1, &netdev_pcap::pcap_handler, reinterpret_cast<u_char *>(ctx)); - return 0; + return nullptr; } #endif -netdev_pcap::netdev_pcap(const char *name, network_handler &ifdev) - : osd_network_device(ifdev) +pcap_module::netdev_pcap::netdev_pcap(pcap_module &module, const char *name, network_handler &handler) : + network_device_base(handler), + m_module(module), + m_p(nullptr) { char errbuf[PCAP_ERRBUF_SIZE]; #if defined(SDLMAME_WIN32) || defined(OSD_WINDOWS) - m_p = (*module->pcap_open_live_dl)(name, 65535, 1, -1, errbuf); + m_p = (*m_module.pcap_open_live_dl)(name, 65535, 1, -1, errbuf); #else - m_p = (*module->pcap_open_live_dl)(name, 65535, 1, 1, errbuf); + m_p = (*m_module.pcap_open_live_dl)(name, 65535, 1, 1, errbuf); #endif if(!m_p) { osd_printf_error("Unable to open %s: %s\n", name, errbuf); return; } - if ((*module->pcap_set_datalink_dl)(m_p, DLT_EN10MB) == -1) + if ((*m_module.pcap_set_datalink_dl)(m_p, DLT_EN10MB) == -1) { osd_printf_error("Unable to set %s to ethernet", name); - (*module->pcap_close_dl)(m_p); + (*m_module.pcap_close_dl)(m_p); m_p = nullptr; return; } - netdev_pcap::set_mac(&get_mac()[0]); - -#ifdef SDLMAME_MACOSX - m_ctx.head = 0; - m_ctx.tail = 0; - m_ctx.p = m_p; - pthread_create(&m_thread, nullptr, netdev_pcap_blocker, &m_ctx); -#endif -} -void netdev_pcap::set_mac(const uint8_t *mac) -{ - struct bpf_program fp; - if(!m_p) return; #ifdef SDLMAME_MACOSX - auto filter = util::string_format("not ether src %02X:%02X:%02X:%02X:%02X:%02X and (ether dst %02X:%02X:%02X:%02X:%02X:%02X or ether multicast or ether broadcast or ether dst 09:00:07:ff:ff:ff)", (unsigned char)mac[0], (unsigned char)mac[1], (unsigned char)mac[2],(unsigned char)mac[3], (unsigned char)mac[4], (unsigned char)mac[5], (unsigned char)mac[0], (unsigned char)mac[1], (unsigned char)mac[2],(unsigned char)mac[3], (unsigned char)mac[4], (unsigned char)mac[5]); -#else - auto filter = util::string_format("ether dst %02X:%02X:%02X:%02X:%02X:%02X or ether multicast or ether broadcast", (unsigned char)mac[0], (unsigned char)mac[1], (unsigned char)mac[2],(unsigned char)mac[3], (unsigned char)mac[4], (unsigned char)mac[5]); + head = 0; + tail = 0; + p = m_p; + pthread_create(&m_thread, nullptr, &netdev_pcap::pcap_blocker, this); #endif - if ((*module->pcap_compile_dl)(m_p, &fp, filter.c_str(), 1, 0) == -1) { - osd_printf_error("Error with pcap_compile\n"); - } - if ((*module->pcap_setfilter_dl)(m_p, &fp) == -1) { - osd_printf_error("Error with pcap_setfilter\n"); - } } -int netdev_pcap::send(uint8_t *buf, int len) +int pcap_module::netdev_pcap::send(void const *buf, int len) { int ret; if(!m_p) { printf("send invoked, but no pcap context\n"); return 0; } - ret = (*module->pcap_sendpacket_dl)(m_p, buf, len); + ret = (*m_module.pcap_sendpacket_dl)(m_p, reinterpret_cast<const u_char *>(buf), len); printf("sent packet length %d, returned %d\n", len, ret); return ret ? len : 0; - //return (!pcap_sendpacket_dl(m_p, buf, len))?len:0; + //return (!pcap_sendpacket_dl(m_p, reinterpret_cast<const u_char *>(buf), len))?len:0; } -int netdev_pcap::recv_dev(uint8_t **buf) +int pcap_module::netdev_pcap::recv_dev(uint8_t **buf) { #ifdef SDLMAME_MACOSX uint8_t pktbuf[2048]; @@ -232,60 +232,48 @@ int netdev_pcap::recv_dev(uint8_t **buf) if(!m_p) return 0; // Empty - if(OSAtomicCompareAndSwapInt(m_ctx.head, m_ctx.tail, &m_ctx.tail)) { + + int const curr = tail; + if (head.load(std::memory_order_acquire) == curr) return 0; - } - memcpy(pktbuf, m_ctx.packets[m_ctx.tail], m_ctx.packetlens[m_ctx.tail]); - ret = m_ctx.packetlens[m_ctx.tail]; - OSAtomicCompareAndSwapInt(m_ctx.tail, (m_ctx.tail+1) & 0x1F, &m_ctx.tail); + memcpy(pktbuf, packets[curr], packetlens[curr]); + ret = packetlens[curr]; + tail.store((curr + 1) & 0x1f, std::memory_order_release); *buf = pktbuf; return ret; #else struct pcap_pkthdr *header; if(!m_p) return 0; - return ((*module->pcap_next_ex_dl)(m_p, &header, (const u_char **)buf) == 1)?header->len:0; + return ((*m_module.pcap_next_ex_dl)(m_p, &header, (const u_char **)buf) == 1)?header->len:0; #endif } -netdev_pcap::~netdev_pcap() +pcap_module::netdev_pcap::~netdev_pcap() { #ifdef SDLMAME_MACOSX - m_ctx.p = nullptr; + p = nullptr; pthread_cancel(m_thread); pthread_join(m_thread, nullptr); #endif - if(m_p) (*module->pcap_close_dl)(m_p); + if(m_p) (*m_module.pcap_close_dl)(m_p); m_p = nullptr; } -static CREATE_NETDEV(create_pcap) -{ - auto *dev = new netdev_pcap(ifname, ifdev); - return dynamic_cast<osd_network_device *>(dev); -} - int pcap_module::init(osd_interface &osd, const osd_options &options) { pcap_if_t *devs; char errbuf[PCAP_ERRBUF_SIZE]; - // FIXME: bridge between pcap_module and netdev_pcap - module = this; - if ((*pcap_findalldevs_dl)(&devs, errbuf) == -1) { osd_printf_error("Unable to get network devices: %s\n", errbuf); return 1; } - while(devs) + while (devs) { - if(devs->description) { - add_netdev(devs->name, devs->description, create_pcap); - } else { - add_netdev(devs->name, devs->name, create_pcap); - } + m_devices.emplace_back(device_info{ devs->name, devs->description ? devs->description : devs->name }); devs = devs->next; } return 0; @@ -293,7 +281,24 @@ int pcap_module::init(osd_interface &osd, const osd_options &options) void pcap_module::exit() { - clear_netdev(); + m_devices.clear(); +} + +std::unique_ptr<network_device> pcap_module::open_device(int id, network_handler &handler) +{ + if ((0 > id) || (m_devices.size() <= id)) + return nullptr; + + return std::make_unique<netdev_pcap>(*this, m_devices[id].name.c_str(), handler); +} + +std::vector<network_device_info> pcap_module::list_devices() +{ + std::vector<network_device_info> result; + result.reserve(m_devices.size()); + for (int id = 0; m_devices.size() > id; ++id) + result.emplace_back(network_device_info{ id, m_devices[id].description }); + return result; } } // anonymous namespace diff --git a/src/osd/modules/netdev/taptun.cpp b/src/osd/modules/netdev/taptun.cpp index c78ec9471e1..b765a667ae7 100644 --- a/src/osd/modules/netdev/taptun.cpp +++ b/src/osd/modules/netdev/taptun.cpp @@ -6,6 +6,17 @@ #if defined(OSD_NET_USE_TAPTUN) +#include "netdev_common.h" + +#include "osdcore.h" // osd_printf_verbose +#include "osdfile.h" // PATH_SEPARATOR + +#include "util/hashing.h" // crc32_creator +#include "util/unicode.h" + +#include <memory> +#include <vector> + #if defined(_WIN32) #include <windows.h> #include <winioctl.h> @@ -17,13 +28,6 @@ #include <cerrno> #endif -#include "osdcore.h" // osd_printf_verbose -#include "osdfile.h" // PATH_SEPARATOR -#include "osdnet.h" -#include "unicode.h" - -#include "util/hashing.h" // crc32_creator - #ifdef __linux__ #define IFF_TAP 0x0002 #define IFF_NO_PI 0x1000 @@ -52,22 +56,33 @@ public: } virtual ~taptun_module() { } - virtual int init(osd_interface &osd, const osd_options &options); - virtual void exit(); + virtual int init(osd_interface &osd, const osd_options &options) override; + virtual void exit() override; + + virtual bool probe() override { return true; } + + virtual std::unique_ptr<network_device> open_device(int id, network_handler &handler) override; + virtual std::vector<network_device_info> list_devices() override; - virtual bool probe() { return true; } +private: + struct device_info + { + std::string name; + std::string description; + }; + + std::vector<device_info> m_devices; }; -class netdev_tap : public osd_network_device +class netdev_tap : public network_device_base { public: - netdev_tap(const char *name, network_handler &ifdev); + netdev_tap(const char *name, network_handler &handler); ~netdev_tap(); - int send(uint8_t *buf, int len) override; - void set_mac(const uint8_t *mac) override; + int send(void const *buf, int len) override; protected: int recv_dev(uint8_t **buf) override; @@ -81,12 +96,11 @@ private: int m_fd = -1; char m_ifname[10]; #endif - char m_mac[6]; uint8_t m_buf[2048]; }; -netdev_tap::netdev_tap(const char *name, network_handler &ifdev) - : osd_network_device(ifdev) +netdev_tap::netdev_tap(const char *name, network_handler &handler) + : network_device_base(handler) { #if defined(__linux__) m_fd = -1; @@ -144,11 +158,6 @@ netdev_tap::~netdev_tap() #endif } -void netdev_tap::set_mac(const uint8_t *mac) -{ - memcpy(m_mac, mac, 6); -} - static u32 finalise_frame(u8 buf[], u32 length) { /* @@ -180,7 +189,7 @@ static u32 finalise_frame(u8 buf[], u32 length) } #if defined(_WIN32) -int netdev_tap::send(uint8_t *buf, int len) +int netdev_tap::send(void const *buf, int len) { OVERLAPPED overlapped = {}; @@ -244,7 +253,7 @@ static std::wstring safe_string(WCHAR value[], int length) } // find the friendly name for an adapter in the registry -static std::wstring get_connection_name(std::wstring &id) +static std::wstring get_connection_name(std::wstring const &id) { std::wstring result; @@ -326,7 +335,7 @@ static std::vector<std::wstring> get_tap_adapters() return result; } #else -int netdev_tap::send(uint8_t *buf, int len) +int netdev_tap::send(void const *buf, int len) { if(m_fd == -1) return 0; len = write(m_fd, buf, len); @@ -335,42 +344,52 @@ int netdev_tap::send(uint8_t *buf, int len) int netdev_tap::recv_dev(uint8_t **buf) { - int len; - if(m_fd == -1) return 0; - // exit if we didn't receive anything, got an error, got a broadcast or multicast packet, - // are in promiscuous mode or got a packet with our mac. - do { - len = read(m_fd, m_buf, sizeof(m_buf)); - } while((len > 0) && memcmp(&get_mac()[0], m_buf, 6) && !get_promisc() && !(m_buf[0] & 1)); + if (0 > m_fd) + return 0; + + int len = read(m_fd, m_buf, sizeof(m_buf)); if (len > 0) len = finalise_frame(m_buf, len); *buf = m_buf; - return (len == -1)?0:len; + return (len == -1) ? 0 : len; } #endif -static CREATE_NETDEV(create_tap) -{ - auto *dev = new netdev_tap(ifname, ifdev); - return dynamic_cast<osd_network_device *>(dev); -} - int taptun_module::init(osd_interface &osd, const osd_options &options) { #if defined(_WIN32) - for (std::wstring &id : get_tap_adapters()) - add_netdev(utf8_from_wstring(id).c_str(), utf8_from_wstring(get_connection_name(id)).c_str(), create_tap); + auto const adapters = get_tap_adapters(); + m_devices.reserve(adapters.size()); + for (std::wstring const &id : adapters) + m_devices.emplace_back(device_info{ utf8_from_wstring(id), utf8_from_wstring(get_connection_name(id)) }); #else - add_netdev("tap", "TAP/TUN Device", create_tap); + m_devices.emplace_back(device_info{ "tap", "TUN/TAP Device" }); #endif return 0; } void taptun_module::exit() { - clear_netdev(); + m_devices.clear(); +} + +std::unique_ptr<network_device> taptun_module::open_device(int id, network_handler &handler) +{ + if ((0 > id) || (m_devices.size() <= id)) + return nullptr; + + return std::make_unique<netdev_tap>(m_devices[id].name.c_str(), handler); +} + +std::vector<network_device_info> taptun_module::list_devices() +{ + std::vector<network_device_info> result; + result.reserve(m_devices.size()); + for (int id = 0; m_devices.size() > id; ++id) + result.emplace_back(network_device_info{ id, m_devices[id].description }); + return result; } } // anonymous namespace diff --git a/src/osd/osdepend.h b/src/osd/osdepend.h index 8e9a4be6d7a..ebad7883bbe 100644 --- a/src/osd/osdepend.h +++ b/src/osd/osdepend.h @@ -17,6 +17,7 @@ #include "bitmap.h" #include "interface/midiport.h" +#include "interface/nethandler.h" #include <cstdint> #include <memory> @@ -100,6 +101,10 @@ public: virtual std::unique_ptr<osd::midi_output_port> create_midi_output(std::string_view name) = 0; virtual std::vector<osd::midi_port_info> list_midi_ports() = 0; + // network interface + virtual std::unique_ptr<osd::network_device> open_network_device(int id, osd::network_handler &handler) = 0; + virtual std::vector<osd::network_device_info> list_network_devices() = 0; + protected: virtual ~osd_interface() { } }; diff --git a/src/osd/osdnet.cpp b/src/osd/osdnet.cpp deleted file mode 100644 index 7fe2f7b2eb7..00000000000 --- a/src/osd/osdnet.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Carl - -#include "osdnet.h" - -#include "interface/nethandler.h" - - -static std::vector<std::unique_ptr<osd_network_device::entry_t>> netdev_list; - -void add_netdev(const char *name, const char *description, create_netdev func) -{ - auto entry = std::make_unique<osd_network_device::entry_t>(); - entry->id = netdev_list.size(); - strncpy(entry->name, name, 255); - entry->name[255] = '\0'; - strncpy(entry->description, (description != nullptr) ? description : "(no name)", 255); - entry->description[255] = '\0'; - entry->func = func; - netdev_list.push_back(std::move(entry)); -} - -void clear_netdev() -{ - netdev_list.clear(); -} - -const std::vector<std::unique_ptr<osd_network_device::entry_t>>& get_netdev_list() -{ - return netdev_list; -} - -osd_network_device *open_netdev(int id, osd::network_handler &ifdev) -{ - for(auto &entry : netdev_list) - if(entry->id==id) - return entry->func(entry->name, ifdev); - return nullptr; -} - -osd_network_device::osd_network_device(osd::network_handler &ifdev) - : m_dev(ifdev) - , m_stopped(true) -{ -} - -osd_network_device::~osd_network_device() -{ -} - -void osd_network_device::start() -{ - m_stopped = false; -} - -void osd_network_device::stop() -{ - m_stopped = true; -} - -void osd_network_device::poll() -{ - uint8_t *buf; - int len; - //const char atalkmac[] = { 0x09, 0x00, 0x07, 0xff, 0xff, 0xff }; - while(!m_stopped && (len = recv_dev(&buf))) - { -#if 0 - if(buf[0] & 1) - { - if(memcmp("\xff\xff\xff\xff\xff\xff", buf, 6) && memcmp(atalkmac, buf, 6) && !m_dev.mcast_chk(buf, len)) continue; - } - else { - //const unsigned char *ourmac = (const unsigned char *)get_mac(); - //printf("our mac: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X dst mac: %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", ourmac[0], ourmac[1], ourmac[2], ourmac[3], ourmac[4], ourmac[5], buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); - if(memcmp(get_mac(), buf, 6) && !get_promisc()) continue; - } -#endif - - m_dev.recv_cb(buf, len); - } -} - -int osd_network_device::send(uint8_t *buf, int len) -{ - return 0; -} - -int osd_network_device::recv_dev(uint8_t **buf) -{ - return 0; -} - -void osd_network_device::set_mac(const uint8_t *mac) -{ -} - -void osd_network_device::set_promisc(bool promisc) -{ -} - -bool osd_network_device::get_promisc() -{ - return m_dev.get_promisc(); -} - -const std::array<uint8_t, 6> &osd_network_device::get_mac() -{ - return m_dev.get_mac(); -} diff --git a/src/osd/osdnet.h b/src/osd/osdnet.h deleted file mode 100644 index 8b21c38d395..00000000000 --- a/src/osd/osdnet.h +++ /dev/null @@ -1,66 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Carl -#ifndef MAME_OSD_OSDNET_H -#define MAME_OSD_OSDNET_H - -#pragma once - -#include "osdcomm.h" - -#include <algorithm> -#include <array> -#include <memory> -#include <vector> - - -namespace osd { class network_handler; } -class osd_network_device; - -#define CREATE_NETDEV(name) osd_network_device *name(const char *ifname, osd::network_handler &ifdev) -typedef osd_network_device *(*create_netdev)(const char *ifname, osd::network_handler &ifdev); - -class osd_network_device -{ -public: - struct entry_t - { - entry_t() - { - std::fill(std::begin(name), std::end(name), 0); - std::fill(std::begin(description), std::end(description), 0); - } - - int id = 0; - char name[256]; - char description[256]; - create_netdev func = nullptr; - }; - - osd_network_device(osd::network_handler &ifdev); - virtual ~osd_network_device(); - - void start(); - void stop(); - void poll(); - - virtual int send(uint8_t *buf, int len); - virtual void set_mac(const uint8_t *mac); - virtual void set_promisc(bool promisc); - - const std::array<uint8_t, 6> &get_mac(); - bool get_promisc(); - -protected: - virtual int recv_dev(uint8_t **buf); - -private: - osd::network_handler &m_dev; - bool m_stopped; -}; - -osd_network_device *open_netdev(int id, osd::network_handler &ifdev); -void add_netdev(const char *name, const char *description, create_netdev func); -void clear_netdev(); -const std::vector<std::unique_ptr<osd_network_device::entry_t>>& get_netdev_list(); - -#endif // MAME_OSD_OSDNET_H |