summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/sh/sh3comn.cpp8
-rw-r--r--src/devices/machine/am79c90.cpp2
-rw-r--r--src/devices/machine/dp8390.cpp18
-rw-r--r--src/devices/machine/mb8795.cpp2
-rw-r--r--src/devices/machine/smc91c9x.cpp9
-rw-r--r--src/devices/sound/flt_biquad.cpp8
-rw-r--r--src/devices/sound/flt_biquad.h3
-rw-r--r--src/emu/dinetwork.cpp13
-rw-r--r--src/emu/dinetwork.h5
-rw-r--r--src/emu/natkeyboard.cpp32
-rw-r--r--src/emu/natkeyboard.h1
-rw-r--r--src/frontend/mame/luaengine_input.cpp1
-rw-r--r--src/frontend/mame/ui/miscmenu.cpp41
-rw-r--r--src/mame/igs/goldstar.cpp136
-rw-r--r--src/mame/layout/linn_linndrum.lay9
-rw-r--r--src/mame/linn/linndrum.cpp201
-rw-r--r--src/mame/misc/deecoseal.cpp22
-rw-r--r--src/mame/misc/norautp.cpp56
-rw-r--r--src/mame/msx/msx_keyboard.cpp4
-rw-r--r--src/mame/sony/news_r4k.cpp4
-rw-r--r--src/osd/interface/nethandler.cpp1
-rw-r--r--src/osd/interface/nethandler.h27
-rw-r--r--src/osd/modules/lib/osdobj_common.cpp30
-rw-r--r--src/osd/modules/lib/osdobj_common.h14
-rw-r--r--src/osd/modules/netdev/netdev_common.cpp39
-rw-r--r--src/osd/modules/netdev/netdev_common.h36
-rw-r--r--src/osd/modules/netdev/netdev_module.h9
-rw-r--r--src/osd/modules/netdev/none.cpp19
-rw-r--r--src/osd/modules/netdev/pcap.cpp201
-rw-r--r--src/osd/modules/netdev/taptun.cpp105
-rw-r--r--src/osd/osdepend.h5
-rw-r--r--src/osd/osdnet.cpp110
-rw-r--r--src/osd/osdnet.h66
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