osd: Cleaned up MIDI and network interfaces a little more.

This commit is contained in:
Vas Crabb 2024-03-01 05:06:54 +11:00
parent 3191b41313
commit f28fe7db31
22 changed files with 340 additions and 338 deletions

View File

@ -2075,12 +2075,12 @@ if (BUSES["MC10"]~=null) then
MAME_DIR .. "src/devices/bus/mc10/mc10_cart.h", MAME_DIR .. "src/devices/bus/mc10/mc10_cart.h",
MAME_DIR .. "src/devices/bus/mc10/mcx128.cpp", MAME_DIR .. "src/devices/bus/mc10/mcx128.cpp",
MAME_DIR .. "src/devices/bus/mc10/mcx128.h", MAME_DIR .. "src/devices/bus/mc10/mcx128.h",
MAME_DIR .. "src/devices/bus/mc10/multiports_ext.cpp",
MAME_DIR .. "src/devices/bus/mc10/multiports_ext.h",
MAME_DIR .. "src/devices/bus/mc10/pak.cpp", MAME_DIR .. "src/devices/bus/mc10/pak.cpp",
MAME_DIR .. "src/devices/bus/mc10/pak.h", MAME_DIR .. "src/devices/bus/mc10/pak.h",
MAME_DIR .. "src/devices/bus/mc10/ram.cpp", MAME_DIR .. "src/devices/bus/mc10/ram.cpp",
MAME_DIR .. "src/devices/bus/mc10/ram.h", MAME_DIR .. "src/devices/bus/mc10/ram.h",
MAME_DIR .. "src/devices/bus/mc10/multiports_ext.cpp",
MAME_DIR .. "src/devices/bus/mc10/multiports_ext.h",
} }
end end

View File

@ -60,6 +60,7 @@ function osdmodulesbuild()
MAME_DIR .. "src/osd/interface/inputman.h", MAME_DIR .. "src/osd/interface/inputman.h",
MAME_DIR .. "src/osd/interface/inputseq.cpp", MAME_DIR .. "src/osd/interface/inputseq.cpp",
MAME_DIR .. "src/osd/interface/inputseq.h", MAME_DIR .. "src/osd/interface/inputseq.h",
MAME_DIR .. "src/osd/interface/midiport.h",
MAME_DIR .. "src/osd/interface/nethandler.cpp", MAME_DIR .. "src/osd/interface/nethandler.cpp",
MAME_DIR .. "src/osd/interface/nethandler.h", MAME_DIR .. "src/osd/interface/nethandler.h",
MAME_DIR .. "src/osd/modules/debugger/debug_module.h", MAME_DIR .. "src/osd/modules/debugger/debug_module.h",

View File

@ -469,7 +469,7 @@ includedirs {
} }
defines { defines {
"NL_DISABLE_DYNAMIC_LOAD=1", "NL_DISABLE_DYNAMIC_LOAD=1",
} }
files { files {
@ -747,7 +747,7 @@ if _OPTIONS["targetos"] == "macosx" then
} }
dependency { dependency {
{ "aueffectutil", MAME_DIR .. "src/tools/aueffectutil-Info.plist", true }, { "aueffectutil", MAME_DIR .. "src/tools/aueffectutil-Info.plist", true },
} }
links { links {

View File

@ -27,9 +27,9 @@
16 A3 33 GND 16 A3 33 GND
17 A5 34 GND 17 A5 34 GND
Alice 32 and Alice 90 have 2 more pins: Alice 32 and Alice 90 have 2 more pins:
35 IRQ (optional) 35 IRQ (optional)
36 SOUND 36 SOUND
SEL is an input to the MC-10 that allows the cartridge to remove SEL is an input to the MC-10 that allows the cartridge to remove
the internal chips from the bus. the internal chips from the bus.
@ -40,9 +40,9 @@
#include "mc10_cart.h" #include "mc10_cart.h"
#include "mcx128.h" #include "mcx128.h"
#include "multiports_ext.h"
#include "pak.h" #include "pak.h"
#include "ram.h" #include "ram.h"
#include "multiports_ext.h"
//#define VERBOSE 1 //#define VERBOSE 1
#include "logmacro.h" #include "logmacro.h"
@ -109,8 +109,6 @@ std::pair<std::error_condition, std::string> mc10cart_slot_device::call_load()
util::string_format("Unsupported cartridge size (must be no more than %u bytes)", m_cart->max_rom_length())); util::string_format("Unsupported cartridge size (must be no more than %u bytes)", m_cart->max_rom_length()));
} }
// TODO: add the min_rom_length() method to the interface
if (!loaded_through_softlist()) if (!loaded_through_softlist())
{ {
LOG("Allocating %u byte cartridge ROM region\n", len); LOG("Allocating %u byte cartridge ROM region\n", len);

View File

@ -1,35 +1,37 @@
/*************************************************************************** /***************************************************************************
multiports_ext.cpp multiports_ext.cpp
Emulation of the Alice Multiports Extension Emulation of the Alice Multiports Extension
Features: Features:
The extension provides an extension doubler and two joystick ports. The extension provides an extension doubler and two joystick ports.
The extension also provides (for the whole Alice family and MC-10): The extension also provides (for the whole Alice family and MC-10):
- 16K of RAM expansion ($5000-$8FFF) - 16K of RAM expansion ($5000-$8FFF)
- 64K of ROM expansion in two possible configurations: - 64K of ROM expansion in two possible configurations:
- 8K of ROM between $1000 and $2FFF, as 8 banks (Cartridge mode). - 8K of ROM between $1000 and $2FFF, as 8 banks (Cartridge mode).
- 16K of ROM between $C000 and $FFFF, as 4 banks (ROM mode). - 16K of ROM between $C000 and $FFFF, as 4 banks (ROM mode).
Only the RAM/ROM expansion is emulated here. Only the RAM/ROM expansion is emulated here.
Banks are selected by writing to: Banks are selected by writing to:
- $1000 to $1FFF in Cartridge mode (number of bank between 0 and 7) - $1000 to $1FFF in Cartridge mode (number of bank between 0 and 7)
- $C000 to $CFFF in ROM mode (number of bank between 0 and 3) - $C000 to $CFFF in ROM mode (number of bank between 0 and 3)
***************************************************************************/ ***************************************************************************/
#include "emu.h" #include "emu.h"
#include "multiports_ext.h" #include "multiports_ext.h"
namespace {
//************************************************************************** //**************************************************************************
// TYPE DECLARATIONS // TYPE DECLARATIONS
//************************************************************************** //**************************************************************************
class mc10_multiports_ext_device : public device_t, class mc10_multiports_ext_device : public device_t, public device_mc10cart_interface
public device_mc10cart_interface
{ {
public: public:
mc10_multiports_ext_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); mc10_multiports_ext_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
@ -43,7 +45,6 @@ protected:
// device_t implementation // device_t implementation
virtual void device_start() override; virtual void device_start() override;
virtual void device_reset() override; virtual void device_reset() override;
virtual void device_post_load() override;
void control_register_write(offs_t offset, u8 data); void control_register_write(offs_t offset, u8 data);
@ -56,8 +57,6 @@ private:
memory_share_creator<u8> m_extention_ram; memory_share_creator<u8> m_extention_ram;
}; };
DEFINE_DEVICE_TYPE_PRIVATE(ALICE_MULTIPORTS_EXT, device_mc10cart_interface, mc10_multiports_ext_device, "mc10_multiports_ext", "Fred_72 and 6502man's Multiports Extension")
//------------------------------------------------- //-------------------------------------------------
// IMPLEMENTATION // IMPLEMENTATION
//------------------------------------------------- //-------------------------------------------------
@ -68,7 +67,11 @@ mc10_multiports_ext_device::mc10_multiports_ext_device(const machine_config &mco
} }
mc10_multiports_ext_device::mc10_multiports_ext_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) mc10_multiports_ext_device::mc10_multiports_ext_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, type, tag, owner, clock), device_mc10cart_interface(mconfig, *this), m_bank(*this, "cart_bank"), rom_bank_index(0), m_extention_ram(*this, "ext_ram", 1024 * 16, ENDIANNESS_BIG) : device_t(mconfig, type, tag, owner, clock)
, device_mc10cart_interface(mconfig, *this)
, m_bank(*this, "cart_bank")
, rom_bank_index(0)
, m_extention_ram(*this, "ext_ram", 1024 * 16, ENDIANNESS_BIG)
{ {
} }
@ -86,8 +89,6 @@ void mc10_multiports_ext_device::multiports_mem(address_map &map)
void mc10_multiports_ext_device::device_start() void mc10_multiports_ext_device::device_start()
{ {
save_item(NAME(rom_bank_index));
owning_slot().memspace().install_device(0x1000, 0x2fff, *this, &mc10_multiports_ext_device::multiports_mem); owning_slot().memspace().install_device(0x1000, 0x2fff, *this, &mc10_multiports_ext_device::multiports_mem);
owning_slot().memspace().install_ram(0x5000, 0x8fff, &m_extention_ram[0]); owning_slot().memspace().install_ram(0x5000, 0x8fff, &m_extention_ram[0]);
} }
@ -96,38 +97,26 @@ void mc10_multiports_ext_device::device_start()
void mc10_multiports_ext_device::device_reset() void mc10_multiports_ext_device::device_reset()
{ {
rom_bank_index = 0; m_bank->set_entry(0);
update_bank();
}
void mc10_multiports_ext_device::device_post_load()
{
update_bank();
} }
void mc10_multiports_ext_device::control_register_write(offs_t offset, u8 data) void mc10_multiports_ext_device::control_register_write(offs_t offset, u8 data)
{ {
if (offset < 0x1000) if (offset < 0x1000)
{ m_bank->set_entry(data & 0x07);
rom_bank_index = data & 0x07;
update_bank();
}
}
void mc10_multiports_ext_device::update_bank()
{
m_bank.target()->set_entry(rom_bank_index);
} }
std::pair<std::error_condition, std::string> mc10_multiports_ext_device::load() std::pair<std::error_condition, std::string> mc10_multiports_ext_device::load()
{ {
memory_region *const romregion(memregion("^rom")); memory_region *const romregion(memregion("^rom"));
if (!romregion) if (romregion->bytes() < (0x2000 * 8))
{ return std::make_pair(image_error::INVALIDLENGTH, "Cartridge ROM must be at least 64KB");
return std::make_pair(image_error::BADSOFTWARE, "Software item lacks 'rom' data area");
}
m_bank.target()->configure_entries(0, 8, romregion->base(), 0x2000); m_bank->configure_entries(0, 8, romregion->base(), 0x2000);
return std::make_pair(std::error_condition(), std::string()); return std::make_pair(std::error_condition(), std::string());
} }
} // anonymous namespace
DEFINE_DEVICE_TYPE_PRIVATE(ALICE_MULTIPORTS_EXT, device_mc10cart_interface, mc10_multiports_ext_device, "mc10_multiports_ext", "Fred_72 and 6502man's Multiports Extension")

View File

@ -10,8 +10,10 @@
#include "emu.h" #include "emu.h"
#include "midiin.h" #include "midiin.h"
#include "osdepend.h" #include "osdepend.h"
/*************************************************************************** /***************************************************************************
IMPLEMENTATION IMPLEMENTATION
***************************************************************************/ ***************************************************************************/
@ -183,11 +185,9 @@ std::pair<std::error_condition, std::string> midiin_device::call_load()
} }
else else
{ {
m_midi = machine().osd().create_midi_device(); m_midi = machine().osd().create_midi_input(filename());
if (!m_midi)
if (!m_midi->open_input(filename()))
{ {
m_midi.reset();
return std::make_pair(image_error::UNSPECIFIED, std::string()); return std::make_pair(image_error::UNSPECIFIED, std::string());
} }
@ -202,11 +202,7 @@ std::pair<std::error_condition, std::string> midiin_device::call_load()
void midiin_device::call_unload() void midiin_device::call_unload()
{ {
if (m_midi) if (!m_midi)
{
m_midi->close();
}
else
{ {
// send "all notes off" CC if unloading a MIDI file // send "all notes off" CC if unloading a MIDI file
for (u8 channel = 0; channel < 0x10; channel++) for (u8 channel = 0; channel < 0x10; channel++)

View File

@ -15,6 +15,8 @@
#include "diserial.h" #include "diserial.h"
#include "interface/midiport.h"
#include <memory> #include <memory>
#include <string> #include <string>
#include <system_error> #include <system_error>
@ -67,7 +69,7 @@ private:
void xmit_char(uint8_t data); void xmit_char(uint8_t data);
std::unique_ptr<osd_midi_device> m_midi; std::unique_ptr<osd::midi_input_port> m_midi;
required_ioport m_config; required_ioport m_config;
emu_timer *m_timer; emu_timer *m_timer;
devcb_write_line m_input_cb; devcb_write_line m_input_cb;

View File

@ -10,8 +10,10 @@
#include "emu.h" #include "emu.h"
#include "midiout.h" #include "midiout.h"
#include "osdepend.h" #include "osdepend.h"
/*************************************************************************** /***************************************************************************
IMPLEMENTATION IMPLEMENTATION
***************************************************************************/ ***************************************************************************/
@ -57,11 +59,9 @@ void midiout_device::device_reset()
std::pair<std::error_condition, std::string> midiout_device::call_load() std::pair<std::error_condition, std::string> midiout_device::call_load()
{ {
m_midi = machine().osd().create_midi_device(); m_midi = machine().osd().create_midi_output(filename());
if (!m_midi)
if (!m_midi->open_output(filename()))
{ {
m_midi.reset();
return std::make_pair(image_error::UNSPECIFIED, std::string()); return std::make_pair(image_error::UNSPECIFIED, std::string());
} }
@ -74,11 +74,7 @@ std::pair<std::error_condition, std::string> midiout_device::call_load()
void midiout_device::call_unload() void midiout_device::call_unload()
{ {
if (m_midi) m_midi.reset();
{
m_midi->close();
m_midi.reset();
}
} }
void midiout_device::rcv_complete() // Rx completed receiving byte void midiout_device::rcv_complete() // Rx completed receiving byte

View File

@ -15,6 +15,8 @@
#include "diserial.h" #include "diserial.h"
#include "interface/midiport.h"
#include <memory> #include <memory>
#include <string> #include <string>
#include <system_error> #include <system_error>
@ -59,7 +61,7 @@ protected:
virtual void rcv_complete() override; // Rx completed receiving byte virtual void rcv_complete() override; // Rx completed receiving byte
private: private:
std::unique_ptr<osd_midi_device> m_midi; std::unique_ptr<osd::midi_output_port> m_midi;
}; };
// device type definition // device type definition

View File

@ -38,7 +38,6 @@ class output_module;
// declared in osdepend.h // declared in osdepend.h
class osd_font; class osd_font;
class osd_interface; class osd_interface;
class osd_midi_device;

View File

@ -200,19 +200,21 @@ bool menu_network_devices::handle(event const *ev)
} }
else if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT) 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; device_network_interface *const network = (device_network_interface *)ev->itemref;
auto const &interfaces = get_netdev_list();
int curr = network->get_interface(); int curr = network->get_interface();
if (ev->iptkey == IPT_UI_LEFT) if (ev->iptkey == IPT_UI_LEFT)
curr--; curr--;
else else
curr++; curr++;
if (curr == -2) if (curr == -2)
curr = netdev_count() - 1; curr = interfaces.size() - 1;
network->set_interface(curr); network->set_interface(curr);
curr = network->get_interface(); curr = network->get_interface();
const char *title = nullptr; const char *title = nullptr;
for (auto &entry : get_netdev_list()) for (auto &entry : interfaces)
{ {
if (entry->id == curr) if (entry->id == curr)
{ {

View File

@ -0,0 +1,40 @@
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
/***************************************************************************
midiport.h
OSD interface to midi ports
***************************************************************************/
#ifndef MAME_OSD_INTERFACE_MIDIPORT_H
#define MAME_OSD_INTERFACE_MIDIPORT_H
#pragma once
#include <cstdint>
namespace osd {
class midi_input_port
{
public:
virtual ~midi_input_port() = default;
virtual bool poll() = 0;
virtual int read(uint8_t *pOut) = 0;
};
class midi_output_port
{
public:
virtual ~midi_output_port() = default;
virtual void write(uint8_t data) = 0;
};
} // namespace osd
#endif // MAME_OSD_INTERFACE_MIDIPORT_H

View File

@ -592,7 +592,19 @@ bool osd_common_t::execute_command(const char *command)
if (strcmp(command, OSDCOMMAND_LIST_NETWORK_ADAPTERS) == 0) if (strcmp(command, OSDCOMMAND_LIST_NETWORK_ADAPTERS) == 0)
{ {
osd_module &om = select_module_options<osd_module>(OSD_NETDEV_PROVIDER); osd_module &om = select_module_options<osd_module>(OSD_NETDEV_PROVIDER);
osd_list_network_adapters(); auto const &interfaces = get_netdev_list();
if (interfaces.empty())
{
printf("No supported network interfaces were found\n");
}
else
{
printf("Available network interfaces:\n");
for (auto &entry : interfaces)
{
printf(" %s\n", entry->description);
}
}
om.exit(); om.exit();
return true; return true;
@ -600,7 +612,27 @@ bool osd_common_t::execute_command(const char *command)
else if (strcmp(command, OSDCOMMAND_LIST_MIDI_DEVICES) == 0) else if (strcmp(command, OSDCOMMAND_LIST_MIDI_DEVICES) == 0)
{ {
osd_module &om = select_module_options<osd_module>(OSD_MIDI_PROVIDER); osd_module &om = select_module_options<osd_module>(OSD_MIDI_PROVIDER);
dynamic_cast<midi_module &>(om).list_midi_devices(); auto const ports = dynamic_cast<midi_module &>(om).list_midi_ports();
if (ports.empty())
{
printf("No MIDI ports were found\n");
}
else
{
printf("MIDI input ports:\n");
for (auto const &port : ports)
{
if (port.input)
printf(port.default_input ? "%s (default)\n" : "%s\n", port.name.c_str());
}
printf("\nMIDI output ports:\n");
for (auto const &port : ports)
{
if (port.output)
printf(port.default_output ? "%s (default)\n" : "%s\n", port.name.c_str());
}
}
om.exit(); om.exit();
return true; return true;
@ -717,7 +749,12 @@ bool osd_common_t::get_font_families(std::string const &font_path, std::vector<s
return m_font_module->get_font_families(font_path, result); return m_font_module->get_font_families(font_path, result);
} }
std::unique_ptr<osd_midi_device> osd_common_t::create_midi_device() std::unique_ptr<osd::midi_input_port> osd_common_t::create_midi_input(std::string_view name)
{ {
return m_midi->create_midi_device(); return m_midi->create_input(name);
}
std::unique_ptr<osd::midi_output_port> osd_common_t::create_midi_output(std::string_view name)
{
return m_midi->create_output(name);
} }

View File

@ -238,7 +238,8 @@ public:
virtual osd_font::ptr font_alloc() override; 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; virtual bool get_font_families(std::string const &font_path, std::vector<std::pair<std::string, std::string> > &result) override;
virtual std::unique_ptr<osd_midi_device> create_midi_device() override; 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;
// FIXME: everything below seems to be osd specific and not part of // FIXME: everything below seems to be osd specific and not part of
// this INTERFACE but part of the osd IMPLEMENTATION // this INTERFACE but part of the osd IMPLEMENTATION

View File

@ -9,9 +9,12 @@
#pragma once #pragma once
#include "osdepend.h" #include "interface/midiport.h"
#include <memory> #include <memory>
#include <string>
#include <string_view>
#include <vector>
//============================================================ //============================================================
@ -23,13 +26,23 @@
class midi_module class midi_module
{ {
public: public:
struct port_info
{
std::string name;
bool input;
bool output;
bool default_input;
bool default_output;
};
using port_info_vector = std::vector<port_info>;
virtual ~midi_module() = default; virtual ~midi_module() = default;
// specific routines // specific routines
virtual std::unique_ptr<osd_midi_device> create_midi_device() = 0; virtual std::unique_ptr<osd::midi_input_port> create_input(std::string_view name) = 0;
// FIXME: should return a list of strings ... virtual std::unique_ptr<osd::midi_output_port> create_output(std::string_view name) = 0;
virtual void list_midi_devices() = 0; virtual port_info_vector list_midi_ports() = 0;
}; };
#endif // MAME_OSD_MODULES_MIDI_MIDI_MODULE_H #endif // MAME_OSD_MODULES_MIDI_MIDI_MODULE_H

View File

@ -20,18 +20,6 @@ namespace osd {
namespace { namespace {
class osd_midi_device_none : public osd_midi_device
{
public:
virtual bool open_input(const char *devname) override { return false; }
virtual bool open_output(const char *devname) override { return false; }
virtual void close() override { }
virtual bool poll() override { return false; }
virtual int read(uint8_t *pOut) override { return 0; }
virtual void write(uint8_t data) override { }
};
class none_module : public osd_module, public midi_module class none_module : public osd_module, public midi_module
{ {
public: public:
@ -40,20 +28,11 @@ public:
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 void exit() override { } virtual void exit() override { }
virtual std::unique_ptr<osd_midi_device> create_midi_device() override; virtual std::unique_ptr<midi_input_port> create_input(std::string_view name) override { return nullptr; }
virtual void list_midi_devices() override; virtual std::unique_ptr<midi_output_port> create_output(std::string_view name) override { return nullptr; }
virtual port_info_vector list_midi_ports() override { return port_info_vector(); }
}; };
std::unique_ptr<osd_midi_device> none_module::create_midi_device()
{
return std::make_unique<osd_midi_device_none>();
}
void none_module::list_midi_devices()
{
osd_printf_warning("\nMIDI is not supported in this configuration\n");
}
} // anonymous namespace } // anonymous namespace
} // namespace osd } // namespace osd

View File

@ -14,6 +14,9 @@
#ifndef NO_USE_MIDI #ifndef NO_USE_MIDI
#include "interface/midiport.h"
#include "osdcore.h" // osd_printf_*
#include <portmidi.h> #include <portmidi.h>
#include <cstdio> #include <cstdio>
@ -36,45 +39,51 @@ public:
virtual int init(osd_interface &osd, const osd_options &options) override; virtual int init(osd_interface &osd, const osd_options &options) override;
virtual void exit() override; virtual void exit() override;
virtual std::unique_ptr<osd_midi_device> create_midi_device() override; virtual std::unique_ptr<midi_input_port> create_input(std::string_view name) override;
virtual void list_midi_devices() override; virtual std::unique_ptr<midi_output_port> create_output(std::string_view name) override;
virtual port_info_vector list_midi_ports() override;
}; };
static const int RX_EVENT_BUF_SIZE = 512; static constexpr unsigned RX_EVENT_BUF_SIZE = 512;
#define MIDI_SYSEX 0xf0 static constexpr uint8_t MIDI_SYSEX = 0xf0;
#define MIDI_EOX 0xf7 static constexpr uint8_t MIDI_EOX = 0xf7;
class osd_midi_device_pm : public osd_midi_device class midi_input_pm : public midi_input_port
{ {
public: public:
osd_midi_device_pm(): pmStream(nullptr), xmit_cnt(0), last_status(0), rx_sysex(false) { } midi_input_pm(PortMidiStream *stream) : m_stream(stream), m_rx_sysex(false) { }
virtual ~osd_midi_device_pm() { } virtual ~midi_input_pm();
virtual bool open_input(const char *devname) override;
virtual bool open_output(const char *devname) override;
virtual void close() override;
virtual bool poll() override; virtual bool poll() override;
virtual int read(uint8_t *pOut) override; virtual int read(uint8_t *pOut) override;
private:
PortMidiStream *const m_stream;
PmEvent m_evbuf[RX_EVENT_BUF_SIZE];
bool m_rx_sysex;
};
class midi_output_pm : public midi_output_port
{
public:
midi_output_pm(PortMidiStream *stream) : m_stream(stream), m_xmit_cnt(0), m_last_status(0) { }
virtual ~midi_output_pm();
virtual void write(uint8_t data) override; virtual void write(uint8_t data) override;
private: private:
PortMidiStream *pmStream; PortMidiStream *const m_stream;
PmEvent rx_evBuf[RX_EVENT_BUF_SIZE]; uint8_t m_xmit_in[4]; // Pm_Messages mean we can at most have 3 residue bytes
uint8_t xmit_in[4]; // Pm_Messages mean we can at most have 3 residue bytes int m_xmit_cnt;
int xmit_cnt; uint8_t m_last_status;
uint8_t last_status;
bool rx_sysex;
}; };
std::unique_ptr<osd_midi_device> pm_module::create_midi_device()
{
return std::make_unique<osd_midi_device_pm>();
}
int pm_module::init(osd_interface &osd, const osd_options &options) int pm_module::init(osd_interface &osd, const osd_options &options)
{ {
// FIXME: check error return code
Pm_Initialize(); Pm_Initialize();
return 0; return 0;
} }
@ -84,151 +93,126 @@ void pm_module::exit()
Pm_Terminate(); Pm_Terminate();
} }
void pm_module::list_midi_devices() std::unique_ptr<midi_input_port> pm_module::create_input(std::string_view name)
{ {
int num_devs = Pm_CountDevices();
const PmDeviceInfo *pmInfo;
printf("\n");
if (num_devs == 0)
{
printf("No MIDI ports were found\n");
return;
}
printf("MIDI input ports:\n");
for (int i = 0; i < num_devs; i++)
{
pmInfo = Pm_GetDeviceInfo(i);
if (pmInfo->input)
{
printf("%s %s\n", pmInfo->name, (i == Pm_GetDefaultInputDeviceID()) ? "(default)" : "");
}
}
printf("\nMIDI output ports:\n");
for (int i = 0; i < num_devs; i++)
{
pmInfo = Pm_GetDeviceInfo(i);
if (pmInfo->output)
{
printf("%s %s\n", pmInfo->name, (i == Pm_GetDefaultOutputDeviceID()) ? "(default)" : "");
}
}
}
bool osd_midi_device_pm::open_input(const char *devname)
{
int num_devs = Pm_CountDevices();
int found_dev = -1; int found_dev = -1;
const PmDeviceInfo *pmInfo; if (name == "default")
PortMidiStream *stm;
if (!strcmp("default", devname))
{ {
found_dev = Pm_GetDefaultInputDeviceID(); found_dev = Pm_GetDefaultInputDeviceID();
} }
else else
{ {
for (int i = 0; i < num_devs; i++) int const num_devs = Pm_CountDevices();
for (found_dev = 0; num_devs > found_dev; ++found_dev)
{ {
pmInfo = Pm_GetDeviceInfo(i); auto const info = Pm_GetDeviceInfo(found_dev);
if (info->input && (name == info->name))
if (pmInfo->input) break;
{
if (!strcmp(devname, pmInfo->name))
{
found_dev = i;
break;
}
}
} }
if (num_devs <= found_dev)
found_dev = -1;
} }
if (found_dev >= 0) if (0 > found_dev)
{ {
if (Pm_OpenInput(&stm, found_dev, nullptr, RX_EVENT_BUF_SIZE, nullptr, nullptr) == pmNoError) osd_printf_warning("No MIDI input device named '%s' was found.\n", name);
{ return nullptr;
pmStream = stm;
return true;
}
else
{
printf("Couldn't open PM device\n");
return false;
}
} }
else
PortMidiStream *stream = nullptr;
PmError const err = Pm_OpenInput(&stream, found_dev, nullptr, RX_EVENT_BUF_SIZE, nullptr, nullptr);
if (pmNoError != err)
{ {
return false; osd_printf_error("Error opening PortMidi device '%s' for input.\n", name);
return nullptr;
}
try
{
return std::make_unique<midi_input_pm>(stream);
}
catch (...)
{
Pm_Close(stream);
return nullptr;
} }
} }
bool osd_midi_device_pm::open_output(const char *devname) std::unique_ptr<midi_output_port> pm_module::create_output(std::string_view name)
{ {
int num_devs = Pm_CountDevices();
int found_dev = -1; int found_dev = -1;
const PmDeviceInfo *pmInfo; if (name == "default")
PortMidiStream *stm;
if (!strcmp("default", devname))
{ {
found_dev = Pm_GetDefaultOutputDeviceID(); found_dev = Pm_GetDefaultOutputDeviceID();
} }
else else
{ {
for (int i = 0; i < num_devs; i++) int const num_devs = Pm_CountDevices();
for (found_dev = 0; num_devs > found_dev; ++found_dev)
{ {
pmInfo = Pm_GetDeviceInfo(i); auto const info = Pm_GetDeviceInfo(found_dev);
if (info->output && (name == info->name))
if (pmInfo->output) break;
{
if (!strcmp(devname, pmInfo->name))
{
found_dev = i;
break;
}
}
} }
if (num_devs <= found_dev)
found_dev = -1;
} }
if (found_dev >= 0) PortMidiStream *stream = nullptr;
PmError const err = Pm_OpenOutput(&stream, found_dev, nullptr, 100, nullptr, nullptr, 0);
if (pmNoError != err)
{ {
if (Pm_OpenOutput(&stm, found_dev, nullptr, 100, nullptr, nullptr, 0) == pmNoError) osd_printf_error("Error opening PortMidi device '%s' for output.\n", name);
{ return nullptr;
pmStream = stm;
return true;
}
else
{
printf("Couldn't open PM device\n");
return false;
}
} }
else
try
{ {
return false; return std::make_unique<midi_output_pm>(stream);
}
catch (...)
{
Pm_Close(stream);
return nullptr;
} }
} }
void osd_midi_device_pm::close() midi_module::port_info_vector pm_module::list_midi_ports()
{ {
Pm_Close(pmStream); int const num_devs = Pm_CountDevices();
int const def_input = Pm_GetDefaultInputDeviceID();
int const def_output = Pm_GetDefaultOutputDeviceID();
port_info_vector result;
result.reserve(num_devs);
for (int i = 0; num_devs > i; ++i)
{
auto const pm_info = Pm_GetDeviceInfo(i);
result.emplace_back(port_info{
pm_info->name,
0 != pm_info->input,
0 != pm_info->output,
def_input == i,
def_output == i });
}
return result;
} }
bool osd_midi_device_pm::poll()
{
PmError chk = Pm_Poll(pmStream);
midi_input_pm::~midi_input_pm()
{
if (m_stream)
Pm_Close(m_stream);
}
bool midi_input_pm::poll()
{
PmError const chk = Pm_Poll(m_stream);
return (chk == pmGotData) ? true : false; return (chk == pmGotData) ? true : false;
} }
int osd_midi_device_pm::read(uint8_t *pOut) int midi_input_pm::read(uint8_t *pOut)
{ {
int msgsRead = Pm_Read(pmStream, rx_evBuf, RX_EVENT_BUF_SIZE); int msgsRead = Pm_Read(m_stream, m_evbuf, RX_EVENT_BUF_SIZE);
int bytesOut = 0; int bytesOut = 0;
if (msgsRead <= 0) if (msgsRead <= 0)
@ -238,23 +222,23 @@ int osd_midi_device_pm::read(uint8_t *pOut)
for (int msg = 0; msg < msgsRead; msg++) for (int msg = 0; msg < msgsRead; msg++)
{ {
uint8_t status = Pm_MessageStatus(rx_evBuf[msg].message); uint8_t status = Pm_MessageStatus(m_evbuf[msg].message);
if (rx_sysex) if (m_rx_sysex)
{ {
if (status & 0x80) // sys real-time imposing on us? if (status & 0x80) // sys real-time imposing on us?
{ {
if (status == 0xf2) if (status == 0xf2)
{ {
*pOut++ = status; *pOut++ = status;
*pOut++ = Pm_MessageData1(rx_evBuf[msg].message); *pOut++ = Pm_MessageData1(m_evbuf[msg].message);
*pOut++ = Pm_MessageData2(rx_evBuf[msg].message); *pOut++ = Pm_MessageData2(m_evbuf[msg].message);
bytesOut += 3; bytesOut += 3;
} }
else if (status == 0xf3) else if (status == 0xf3)
{ {
*pOut++ = status; *pOut++ = status;
*pOut++ = Pm_MessageData1(rx_evBuf[msg].message); *pOut++ = Pm_MessageData1(m_evbuf[msg].message);
bytesOut += 2; bytesOut += 2;
} }
else else
@ -263,7 +247,7 @@ int osd_midi_device_pm::read(uint8_t *pOut)
bytesOut++; bytesOut++;
if (status == MIDI_EOX) if (status == MIDI_EOX)
{ {
rx_sysex = false; m_rx_sysex = false;
} }
} }
} }
@ -271,15 +255,15 @@ int osd_midi_device_pm::read(uint8_t *pOut)
{ {
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
uint8_t byte = rx_evBuf[msg].message & 0xff; uint8_t byte = m_evbuf[msg].message & 0xff;
*pOut++ = byte; *pOut++ = byte;
bytesOut++; bytesOut++;
if (byte == MIDI_EOX) if (byte == MIDI_EOX)
{ {
rx_sysex = false; m_rx_sysex = false;
break; break;
} }
rx_evBuf[msg].message >>= 8; m_evbuf[msg].message >>= 8;
} }
} }
} }
@ -290,7 +274,7 @@ int osd_midi_device_pm::read(uint8_t *pOut)
case 0xc: // 2-byte messages case 0xc: // 2-byte messages
case 0xd: case 0xd:
*pOut++ = status; *pOut++ = status;
*pOut++ = Pm_MessageData1(rx_evBuf[msg].message); *pOut++ = Pm_MessageData1(m_evbuf[msg].message);
bytesOut += 2; bytesOut += 2;
break; break;
@ -300,30 +284,30 @@ int osd_midi_device_pm::read(uint8_t *pOut)
case 0: // System Exclusive case 0: // System Exclusive
{ {
*pOut++ = status; // this should be OK: the shortest legal sysex is F0 tt dd F7, I believe *pOut++ = status; // this should be OK: the shortest legal sysex is F0 tt dd F7, I believe
*pOut++ = (rx_evBuf[msg].message>>8) & 0xff; *pOut++ = (m_evbuf[msg].message>>8) & 0xff;
*pOut++ = (rx_evBuf[msg].message>>16) & 0xff; *pOut++ = (m_evbuf[msg].message>>16) & 0xff;
uint8_t last = *pOut++ = (rx_evBuf[msg].message>>24) & 0xff; uint8_t last = *pOut++ = (m_evbuf[msg].message>>24) & 0xff;
bytesOut += 4; bytesOut += 4;
rx_sysex = (last != MIDI_EOX); m_rx_sysex = (last != MIDI_EOX);
break; break;
} }
case 7: // End of System Exclusive case 7: // End of System Exclusive
*pOut++ = status; *pOut++ = status;
bytesOut += 1; bytesOut += 1;
rx_sysex = false; m_rx_sysex = false;
break; break;
case 2: // song pos case 2: // song pos
*pOut++ = status; *pOut++ = status;
*pOut++ = Pm_MessageData1(rx_evBuf[msg].message); *pOut++ = Pm_MessageData1(m_evbuf[msg].message);
*pOut++ = Pm_MessageData2(rx_evBuf[msg].message); *pOut++ = Pm_MessageData2(m_evbuf[msg].message);
bytesOut += 3; bytesOut += 3;
break; break;
case 3: // song select case 3: // song select
*pOut++ = status; *pOut++ = status;
*pOut++ = Pm_MessageData1(rx_evBuf[msg].message); *pOut++ = Pm_MessageData1(m_evbuf[msg].message);
bytesOut += 2; bytesOut += 2;
break; break;
@ -336,8 +320,8 @@ int osd_midi_device_pm::read(uint8_t *pOut)
default: default:
*pOut++ = status; *pOut++ = status;
*pOut++ = Pm_MessageData1(rx_evBuf[msg].message); *pOut++ = Pm_MessageData1(m_evbuf[msg].message);
*pOut++ = Pm_MessageData2(rx_evBuf[msg].message); *pOut++ = Pm_MessageData2(m_evbuf[msg].message);
bytesOut += 3; bytesOut += 3;
break; break;
} }
@ -347,57 +331,64 @@ int osd_midi_device_pm::read(uint8_t *pOut)
return bytesOut; return bytesOut;
} }
void osd_midi_device_pm::write(uint8_t data)
midi_output_pm::~midi_output_pm()
{
if (m_stream)
Pm_Close(m_stream);
}
void midi_output_pm::write(uint8_t data)
{ {
int bytes_needed = 0; int bytes_needed = 0;
PmEvent ev; PmEvent ev;
ev.timestamp = 0; // use the current time ev.timestamp = 0; // use the current time
// printf("write: %02x (%d)\n", data, xmit_cnt); // printf("write: %02x (%d)\n", data, m_xmit_cnt);
// reject data bytes when no valid status exists // reject data bytes when no valid status exists
if ((last_status == 0) && !(data & 0x80)) if ((m_last_status == 0) && !(data & 0x80))
{ {
xmit_cnt = 0; m_xmit_cnt = 0;
return; return;
} }
if (xmit_cnt >= 4) if (m_xmit_cnt >= 4)
{ {
printf("MIDI out: packet assembly overflow, contact MAMEdev!\n"); printf("MIDI out: packet assembly overflow, contact MAMEdev!\n");
return; return;
} }
// handle sysex // handle sysex
if (last_status == MIDI_SYSEX) if (m_last_status == MIDI_SYSEX)
{ {
// printf("sysex: %02x (%d)\n", data, xmit_cnt); // printf("sysex: %02x (%d)\n", data, m_xmit_cnt);
// if we get a status that isn't sysex, assume it's system common // if we get a status that isn't sysex, assume it's system common
if ((data & 0x80) && (data != MIDI_EOX)) if ((data & 0x80) && (data != MIDI_EOX))
{ {
// printf("common during sysex!\n"); // printf("common during sysex!\n");
ev.message = Pm_Message(data, 0, 0); ev.message = Pm_Message(data, 0, 0);
Pm_Write(pmStream, &ev, 1); Pm_Write(m_stream, &ev, 1);
return; return;
} }
xmit_in[xmit_cnt++] = data; m_xmit_in[m_xmit_cnt++] = data;
// if EOX or 4 bytes filled, transmit 4 bytes // if EOX or 4 bytes filled, transmit 4 bytes
if ((xmit_cnt == 4) || (data == MIDI_EOX)) if ((m_xmit_cnt == 4) || (data == MIDI_EOX))
{ {
ev.message = xmit_in[0] | (xmit_in[1]<<8) | (xmit_in[2]<<16) | (xmit_in[3]<<24); ev.message = m_xmit_in[0] | (m_xmit_in[1]<<8) | (m_xmit_in[2]<<16) | (m_xmit_in[3]<<24);
Pm_Write(pmStream, &ev, 1); Pm_Write(m_stream, &ev, 1);
xmit_in[0] = xmit_in[1] = xmit_in[2] = xmit_in[3] = 0; m_xmit_in[0] = m_xmit_in[1] = m_xmit_in[2] = m_xmit_in[3] = 0;
xmit_cnt = 0; m_xmit_cnt = 0;
// printf("SysEx packet: %08x\n", ev.message); // printf("SysEx packet: %08x\n", ev.message);
// if this is EOX, kill the running status // if this is EOX, kill the running status
if (data == MIDI_EOX) if (data == MIDI_EOX)
{ {
last_status = 0; m_last_status = 0;
} }
} }
@ -405,33 +396,33 @@ void osd_midi_device_pm::write(uint8_t data)
} }
// handle running status. don't allow system real-time messages to be considered as running status. // handle running status. don't allow system real-time messages to be considered as running status.
if ((xmit_cnt == 0) && (data & 0x80) && (data < 0xf8)) if ((m_xmit_cnt == 0) && (data & 0x80) && (data < 0xf8))
{ {
last_status = data; m_last_status = data;
} }
if ((xmit_cnt == 0) && !(data & 0x80)) if ((m_xmit_cnt == 0) && !(data & 0x80))
{ {
xmit_in[xmit_cnt++] = last_status; m_xmit_in[m_xmit_cnt++] = m_last_status;
xmit_in[xmit_cnt++] = data; m_xmit_in[m_xmit_cnt++] = data;
// printf("\trunning status: [%d] = %02x, [%d] = %02x, last_status = %02x\n", xmit_cnt-2, last_status, xmit_cnt-1, data, last_status); // printf("\trunning status: [%d] = %02x, [%d] = %02x, m_last_status = %02x\n", m_xmit_cnt-2, m_last_status, m_xmit_cnt-1, data, m_last_status);
} }
else else
{ {
xmit_in[xmit_cnt++] = data; m_xmit_in[m_xmit_cnt++] = data;
// printf("\tNRS: [%d] = %02x\n", xmit_cnt-1, data); // printf("\tNRS: [%d] = %02x\n", m_xmit_cnt-1, data);
} }
if ((xmit_cnt == 1) && (xmit_in[0] == MIDI_SYSEX)) if ((m_xmit_cnt == 1) && (m_xmit_in[0] == MIDI_SYSEX))
{ {
// printf("Start SysEx!\n"); // printf("Start SysEx!\n");
last_status = MIDI_SYSEX; m_last_status = MIDI_SYSEX;
return; return;
} }
// are we there yet? // are we there yet?
// printf("status check: %02x\n", xmit_in[0]); // printf("status check: %02x\n", m_xmit_in[0]);
switch ((xmit_in[0]>>4) & 0xf) switch ((m_xmit_in[0]>>4) & 0xf)
{ {
case 0xc: // 2-byte messages case 0xc: // 2-byte messages
case 0xd: case 0xd:
@ -439,7 +430,7 @@ void osd_midi_device_pm::write(uint8_t data)
break; break;
case 0xf: // system common case 0xf: // system common
switch (xmit_in[0] & 0xf) switch (m_xmit_in[0] & 0xf)
{ {
case 0: // System Exclusive is handled above case 0: // System Exclusive is handled above
break; break;
@ -464,11 +455,11 @@ void osd_midi_device_pm::write(uint8_t data)
break; break;
} }
if (xmit_cnt == bytes_needed) if (m_xmit_cnt == bytes_needed)
{ {
ev.message = Pm_Message(xmit_in[0], xmit_in[1], xmit_in[2]); ev.message = Pm_Message(m_xmit_in[0], m_xmit_in[1], m_xmit_in[2]);
Pm_Write(pmStream, &ev, 1); Pm_Write(m_stream, &ev, 1);
xmit_cnt = 0; m_xmit_cnt = 0;
} }
} }

View File

@ -117,7 +117,7 @@ struct netdev_pcap_context
class netdev_pcap : public osd_network_device class netdev_pcap : public osd_network_device
{ {
public: public:
netdev_pcap(const char *name, class network_handler &ifdev); netdev_pcap(const char *name, network_handler &ifdev);
~netdev_pcap(); ~netdev_pcap();
virtual int send(uint8_t *buf, int len) override; virtual int send(uint8_t *buf, int len) override;
@ -161,7 +161,7 @@ static void *netdev_pcap_blocker(void *arg) {
} }
#endif #endif
netdev_pcap::netdev_pcap(const char *name, class network_handler &ifdev) netdev_pcap::netdev_pcap(const char *name, network_handler &ifdev)
: osd_network_device(ifdev) : osd_network_device(ifdev)
{ {
char errbuf[PCAP_ERRBUF_SIZE]; char errbuf[PCAP_ERRBUF_SIZE];

View File

@ -63,7 +63,7 @@ public:
class netdev_tap : public osd_network_device class netdev_tap : public osd_network_device
{ {
public: public:
netdev_tap(const char *name, class network_handler &ifdev); netdev_tap(const char *name, network_handler &ifdev);
~netdev_tap(); ~netdev_tap();
int send(uint8_t *buf, int len) override; int send(uint8_t *buf, int len) override;
@ -85,7 +85,7 @@ private:
uint8_t m_buf[2048]; uint8_t m_buf[2048];
}; };
netdev_tap::netdev_tap(const char *name, class network_handler &ifdev) netdev_tap::netdev_tap(const char *name, network_handler &ifdev)
: osd_network_device(ifdev) : osd_network_device(ifdev)
{ {
#ifdef __linux__ #ifdef __linux__

View File

@ -20,12 +20,13 @@
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <string> #include <string>
#include <string_view>
#include <vector> #include <vector>
// forward references // forward references
class input_type_entry; class input_type_entry;
class osd_midi_device; namespace osd { class midi_input_port; class midi_output_port; }
namespace ui { class menu_item; } namespace ui { class menu_item; }
@ -93,28 +94,12 @@ public:
// command option overrides // command option overrides
virtual bool execute_command(const char *command) = 0; virtual bool execute_command(const char *command) = 0;
// midi interface // MIDI interface
virtual std::unique_ptr<osd_midi_device> create_midi_device() = 0; virtual std::unique_ptr<osd::midi_input_port> create_midi_input(std::string_view name) = 0;
virtual std::unique_ptr<osd::midi_output_port> create_midi_output(std::string_view name) = 0;
protected: protected:
virtual ~osd_interface() { } virtual ~osd_interface() { }
}; };
/***************************************************************************
MIDI I/O INTERFACES
***************************************************************************/
class osd_midi_device
{
public:
virtual ~osd_midi_device() { }
virtual bool open_input(const char *devname) = 0;
virtual bool open_output(const char *devname) = 0;
virtual void close() = 0;
virtual bool poll() = 0;
virtual int read(uint8_t *pOut) = 0;
virtual void write(uint8_t data) = 0;
};
#endif // MAME_OSD_OSDEPEND_H #endif // MAME_OSD_OSDEPEND_H

View File

@ -108,30 +108,3 @@ const std::array<uint8_t, 6> &osd_network_device::get_mac()
{ {
return m_dev.get_mac(); return m_dev.get_mac();
} }
int netdev_count()
{
return netdev_list.size();
}
void osd_list_network_adapters()
{
#ifdef USE_NETWORK
int num_devs = netdev_list.size();
if (num_devs == 0)
{
printf("No network adapters were found\n");
return;
}
printf("Available network adapters:\n");
for (auto &entry : netdev_list)
{
printf(" %s\n", entry->description);
}
#else
printf("Network is not supported in this build\n");
#endif
}

View File

@ -62,7 +62,5 @@ osd_network_device *open_netdev(int id, osd::network_handler &ifdev);
void add_netdev(const char *name, const char *description, create_netdev func); void add_netdev(const char *name, const char *description, create_netdev func);
void clear_netdev(); void clear_netdev();
const std::vector<std::unique_ptr<osd_network_device::entry_t>>& get_netdev_list(); const std::vector<std::unique_ptr<osd_network_device::entry_t>>& get_netdev_list();
int netdev_count();
void osd_list_network_adapters();
#endif // MAME_OSD_OSDNET_H #endif // MAME_OSD_OSDNET_H