mirror of
https://github.com/holub/mame
synced 2025-04-20 23:42:22 +03:00
-bus/a2bus: Added Apple II Parallel Printer Interface Card.
-frontend/mame/audit.cpp: Fixed another annoying edge case. -Cleaned up RawInput code slightly.
This commit is contained in:
parent
da9213faaa
commit
cf7fe1e04d
@ -2330,6 +2330,8 @@ if (BUSES["A2BUS"]~=null) then
|
||||
MAME_DIR .. "src/devices/bus/a2bus/a2midi.h",
|
||||
MAME_DIR .. "src/devices/bus/a2bus/a2mockingboard.cpp",
|
||||
MAME_DIR .. "src/devices/bus/a2bus/a2mockingboard.h",
|
||||
MAME_DIR .. "src/devices/bus/a2bus/a2parprn.cpp",
|
||||
MAME_DIR .. "src/devices/bus/a2bus/a2parprn.h",
|
||||
MAME_DIR .. "src/devices/bus/a2bus/a2pic.cpp",
|
||||
MAME_DIR .. "src/devices/bus/a2bus/a2pic.h",
|
||||
MAME_DIR .. "src/devices/bus/a2bus/a2sam.cpp",
|
||||
|
233
src/devices/bus/a2bus/a2parprn.cpp
Normal file
233
src/devices/bus/a2bus/a2parprn.cpp
Normal file
@ -0,0 +1,233 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Vas Crabb
|
||||
#include "emu.h"
|
||||
#include "a2parprn.h"
|
||||
|
||||
//#define VERBOSE 1
|
||||
//#define LOG_OUTPUT_FUNC osd_printf_info
|
||||
#include "logmacro.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// FIXME: get proper PROM dumps.
|
||||
/*
|
||||
There are most likely multiple revisions.
|
||||
6309 and 74471 PROMs were used.
|
||||
|
||||
Example silkscreen:
|
||||
|
||||
SINGAPORE
|
||||
341-0005-00
|
||||
cAPPLE 78-02
|
||||
SN74S471N
|
||||
|
||||
Example label:
|
||||
|
||||
APPLE
|
||||
©1978
|
||||
|
||||
PROM image here is from entering a listing and zero-filling unused areas.
|
||||
|
||||
********************************
|
||||
* *
|
||||
* PRINTER CARD I FIRMWARE *
|
||||
* *
|
||||
* WOZ 11/1/77 *
|
||||
* APPLE COMPUTER INC. *
|
||||
* ALL RIGHTS RESERVED *
|
||||
* *
|
||||
********************************
|
||||
*/
|
||||
ROM_START(parprn)
|
||||
ROM_REGION(0x100, "prom", 0)
|
||||
ROM_LOAD( "prom.b4", 0x0000, 0x0100, BAD_DUMP CRC(00b742ca) SHA1(c67888354aa013f9cb882eeeed924e292734e717) )
|
||||
ROM_END
|
||||
|
||||
|
||||
INPUT_PORTS_START(parprn)
|
||||
PORT_START("CFG")
|
||||
PORT_CONFNAME(0x01, 0x00, "Acknowledge latching edge")
|
||||
PORT_CONFSETTING( 0x00, "Falling (/Y-B)")
|
||||
PORT_CONFSETTING( 0x01, "Rising (Y-B)")
|
||||
PORT_CONFNAME(0x06, 0x02, "Printer ready")
|
||||
PORT_CONFSETTING( 0x00, "Always (S5-C-D)")
|
||||
PORT_CONFSETTING( 0x02, "Acknowledge latch (Z-C-D)")
|
||||
PORT_CONFSETTING( 0x04, "ACK (Y-C-D)")
|
||||
PORT_CONFSETTING( 0x06, "/ACK (/Y-C-D)")
|
||||
PORT_CONFNAME(0x08, 0x00, "Strobe polarity")
|
||||
PORT_CONFSETTING( 0x00, "Negative (S5-A-/X, GND-X)")
|
||||
PORT_CONFSETTING( 0x08, "Positive (S5-X, GND-A-/X)")
|
||||
PORT_CONFNAME(0x10, 0x10, "Character width")
|
||||
PORT_CONFSETTING( 0x00, "7-bit")
|
||||
PORT_CONFSETTING( 0x10, "8-bit")
|
||||
INPUT_PORTS_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
|
||||
DEFINE_DEVICE_TYPE(A2BUS_PARPRN, a2bus_parprn_device, "a2parprn", "Apple II Parallel Printer Interface Card")
|
||||
|
||||
|
||||
|
||||
a2bus_parprn_device::a2bus_parprn_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
|
||||
device_t(mconfig, A2BUS_PARPRN, tag, owner, clock),
|
||||
device_a2bus_card_interface(mconfig, *this),
|
||||
m_printer_conn(*this, "prn"),
|
||||
m_printer_out(*this, "prn_out"),
|
||||
m_input_config(*this, "CFG"),
|
||||
m_prom(*this, "prom"),
|
||||
m_strobe_timer(nullptr),
|
||||
m_next_strobe(0U),
|
||||
m_ack_latch(0U),
|
||||
m_ack_in(1U)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------
|
||||
// device_a2bus_card_interface implementation
|
||||
//----------------------------------------------
|
||||
|
||||
u8 a2bus_parprn_device::read_c0nx(u8 offset)
|
||||
{
|
||||
if (!machine().side_effects_disabled())
|
||||
{
|
||||
LOG("Read C0n%01X (effective open-bus write)\n", offset);
|
||||
|
||||
// R/W is ignored, so it has the same effect as a write
|
||||
// the bus is open, but 74LS logic has low-impedance inputs so it's likely to latch 0xff
|
||||
write_c0nx(offset, 0xffU);
|
||||
}
|
||||
|
||||
return 0x00U;
|
||||
}
|
||||
|
||||
|
||||
void a2bus_parprn_device::write_c0nx(u8 offset, u8 data)
|
||||
{
|
||||
LOG("Write C0n%01X=%02X\n", offset, data);
|
||||
if (m_ack_latch)
|
||||
LOG("Clearing acknowledge latch\n");
|
||||
else
|
||||
LOG("Previous data not acknowledged\n");
|
||||
|
||||
ioport_value const cfg(m_input_config->read());
|
||||
|
||||
m_printer_out->write(data & (BIT(cfg, 8) ? 0xffU : 0x7fU));
|
||||
m_printer_conn->write_strobe(BIT(~cfg, 3));
|
||||
m_next_strobe = BIT(cfg, 3);
|
||||
m_ack_latch = 0U;
|
||||
m_strobe_timer->adjust(attotime::from_ticks(1, clock()));
|
||||
}
|
||||
|
||||
|
||||
u8 a2bus_parprn_device::read_cnxx(u8 offset)
|
||||
{
|
||||
ioport_value const cfg(m_input_config->read());
|
||||
|
||||
if (BIT(cfg, 2))
|
||||
{
|
||||
if (!BIT(offset, 6) || (BIT(offset, 7) && (BIT(cfg, 1) != m_ack_in)))
|
||||
offset |= 0x40U;
|
||||
else
|
||||
offset &= 0xbfU;
|
||||
}
|
||||
else if (BIT(cfg, 1))
|
||||
{
|
||||
if (!BIT(offset, 6) || (BIT(offset, 7) && !m_ack_latch))
|
||||
offset |= 0x40U;
|
||||
else
|
||||
offset &= 0xbfU;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset ^= 0x40U;
|
||||
}
|
||||
|
||||
return m_prom[offset];
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------
|
||||
// device_t implementation
|
||||
//----------------------------------------------
|
||||
|
||||
tiny_rom_entry const *a2bus_parprn_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME(parprn);
|
||||
}
|
||||
|
||||
|
||||
void a2bus_parprn_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
CENTRONICS(config, m_printer_conn, centronics_devices, "printer");
|
||||
m_printer_conn->ack_handler().set(FUNC(a2bus_parprn_device::ack_w));
|
||||
|
||||
OUTPUT_LATCH(config, m_printer_out);
|
||||
m_printer_conn->set_output_latch(*m_printer_out);
|
||||
}
|
||||
|
||||
|
||||
ioport_constructor a2bus_parprn_device::device_input_ports() const
|
||||
{
|
||||
return INPUT_PORTS_NAME(parprn);
|
||||
}
|
||||
|
||||
|
||||
void a2bus_parprn_device::device_start()
|
||||
{
|
||||
m_strobe_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(a2bus_parprn_device::update_strobe), this));
|
||||
|
||||
save_item(NAME(m_next_strobe));
|
||||
save_item(NAME(m_ack_latch));
|
||||
save_item(NAME(m_ack_in));
|
||||
}
|
||||
|
||||
|
||||
void a2bus_parprn_device::device_reset()
|
||||
{
|
||||
m_ack_latch = 1U;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------
|
||||
// printer status inputs
|
||||
//----------------------------------------------
|
||||
|
||||
WRITE_LINE_MEMBER(a2bus_parprn_device::ack_w)
|
||||
{
|
||||
if (bool(state) != bool(m_ack_in))
|
||||
{
|
||||
m_ack_in = state ? 1U : 0U;
|
||||
LOG("ACK=%u\n", m_ack_in);
|
||||
if (started() && (m_ack_in == BIT(m_input_config->read(), 0)))
|
||||
{
|
||||
LOG("Active ACK edge\n");
|
||||
m_ack_latch = 1U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------
|
||||
// timer handlers
|
||||
//----------------------------------------------
|
||||
|
||||
TIMER_CALLBACK_MEMBER(a2bus_parprn_device::update_strobe)
|
||||
{
|
||||
ioport_value const cfg(m_input_config->read());
|
||||
|
||||
LOG("Output /STROBE=%u\n", m_next_strobe);
|
||||
m_printer_conn->write_strobe(m_next_strobe);
|
||||
if (m_next_strobe == BIT(cfg, 3))
|
||||
{
|
||||
LOG("Start strobe timer\n");
|
||||
m_next_strobe = BIT(~cfg, 3);
|
||||
m_strobe_timer->adjust(attotime::from_ticks(1, clock()));
|
||||
}
|
||||
}
|
96
src/devices/bus/a2bus/a2parprn.h
Normal file
96
src/devices/bus/a2bus/a2parprn.h
Normal file
@ -0,0 +1,96 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Vas Crabb
|
||||
/***********************************************************************
|
||||
|
||||
Apple II Parallel Printer Interface Card
|
||||
|
||||
20-pin header:
|
||||
|
||||
GND 1 2 ACK
|
||||
SP1* 3 4 F
|
||||
SP2* 5 6 SP3*
|
||||
SP4* 7 8 STR
|
||||
SP5* 9 10 DP0
|
||||
DP1 11 12 DP2
|
||||
DP3 13 14 DP4
|
||||
DP5 15 16 DP6
|
||||
DP7 17 18 SP6*
|
||||
SP7* 19 20 GND
|
||||
|
||||
*spare, SP1-SP5 brought out to pads for wire mods
|
||||
|
||||
DIP jumper B1:
|
||||
no connection NC 1 16 B acknowledge latch clock
|
||||
no connection NC 2 15 D printer ready 1
|
||||
synchronised ACK Y 3 14 C printer ready 2
|
||||
synchronised /ACK /Y 4 13 A idle strobe
|
||||
acknowledge latch Q /Z 5 12 /X strobe on access
|
||||
acknowlwdge latch /Q Z 6 11 S5 +5V via 12kΩ resistor
|
||||
signal ground GND 7 10 X strobe after one cycle
|
||||
header pin 4 F 8 9 NC no connection
|
||||
|
||||
In real life, the card only samples the ACK input on rising
|
||||
edges of the phase 1 clock. Acknowledge pulses shorter than one
|
||||
microsecond may be ignored. This limitation is not emulated.
|
||||
|
||||
The card completely ignores the R/W line. The PROM driver uses
|
||||
and indexed write to access the C0nX region. This produces a
|
||||
spurious read, causing data to be latched and triggering a
|
||||
delayed strobe pulse. This is why the delay is important – the
|
||||
write needs to happen on the cycle immediately following the
|
||||
spurious read to prevent the open bus data from being printed.
|
||||
|
||||
The card was designed to allow user modifications. There are
|
||||
locations at 5A (16-pin) and 5B (20-pin) for additional DIP
|
||||
packages. Common modifications included stretching strobe
|
||||
and/or acknowledge pulses to improve reliability.
|
||||
|
||||
***********************************************************************/
|
||||
#ifndef MAME_BUS_A2BUS_A2PARPRN_H
|
||||
#define MAME_BUS_A2BUS_A2PARPRN_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "a2bus.h"
|
||||
#include "bus/centronics/ctronics.h"
|
||||
|
||||
class a2bus_parprn_device : public device_t, public device_a2bus_card_interface
|
||||
{
|
||||
public:
|
||||
a2bus_parprn_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
|
||||
|
||||
// device_a2bus_card_interface implementation
|
||||
virtual u8 read_c0nx(u8 offset) override;
|
||||
virtual void write_c0nx(u8 offset, u8 data) override;
|
||||
virtual u8 read_cnxx(u8 offset) override;
|
||||
|
||||
protected:
|
||||
// device_t implementation
|
||||
virtual tiny_rom_entry const *device_rom_region() const override;
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual ioport_constructor device_input_ports() const override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
// printer status inputs
|
||||
DECLARE_WRITE_LINE_MEMBER(ack_w);
|
||||
|
||||
// timer handlers
|
||||
TIMER_CALLBACK_MEMBER(update_strobe);
|
||||
|
||||
required_device<centronics_device> m_printer_conn;
|
||||
required_device<output_latch_device> m_printer_out;
|
||||
required_ioport m_input_config;
|
||||
required_region_ptr<u8> m_prom;
|
||||
emu_timer * m_strobe_timer;
|
||||
|
||||
u8 m_next_strobe; // B3 pin 13
|
||||
u8 m_ack_latch; // B2 pin 6
|
||||
u8 m_ack_in; // pin 2
|
||||
};
|
||||
|
||||
|
||||
DECLARE_DEVICE_TYPE(A2BUS_PARPRN, a2bus_parprn_device)
|
||||
|
||||
#endif // MAME_BUS_A2BUS_A2PARPRN_H
|
@ -1,6 +1,6 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Vas Crabb
|
||||
/*********************************************************************
|
||||
/***********************************************************************
|
||||
|
||||
Apple II Parallel Interface Card (670-0021)
|
||||
|
||||
@ -34,7 +34,18 @@
|
||||
|
||||
*wired to 500ns strobe but connector hole is blocked
|
||||
|
||||
*********************************************************************/
|
||||
This card has significant flaws:
|
||||
* The strobe pulse begins on the same rising edge of the phase 1
|
||||
clock as the data is latched. The parallel load input ito the
|
||||
strobe time counter (6A) is delayed slightly, but the load
|
||||
happens on the rising phase 1 clock edge. This could glitch
|
||||
on a real printer. MAME always sets the data outputs before
|
||||
starting the strobe pulse.
|
||||
* Acknowledge is ignored while the strobe output is active. If
|
||||
the printer acknowledges the data before the end of the strobe
|
||||
pulse, the card will miss it and wait forever.
|
||||
|
||||
***********************************************************************/
|
||||
#ifndef MAME_BUS_A2BUS_A2PIC_H
|
||||
#define MAME_BUS_A2BUS_A2PIC_H
|
||||
|
||||
|
@ -45,6 +45,35 @@ class parent_rom_vector : public std::vector<parent_rom>
|
||||
public:
|
||||
using std::vector<parent_rom>::vector;
|
||||
|
||||
void remove_redundant_parents()
|
||||
{
|
||||
while (!empty())
|
||||
{
|
||||
// find where the next parent starts
|
||||
auto const last(
|
||||
std::find_if(
|
||||
std::next(cbegin()),
|
||||
cend(),
|
||||
[this] (parent_rom const &r) { return &front().type.get() != &r.type.get(); }));
|
||||
|
||||
// examine dumped ROMs in this generation
|
||||
for (auto i = cbegin(); last != i; ++i)
|
||||
{
|
||||
if (!i->hashes.flag(util::hash_collection::FLAG_NO_DUMP))
|
||||
{
|
||||
auto const match(
|
||||
std::find_if(
|
||||
last,
|
||||
cend(),
|
||||
[&i] (parent_rom const &r) { return (i->length == r.length) && (i->hashes == r.hashes); }));
|
||||
if (cend() == match)
|
||||
return;
|
||||
}
|
||||
}
|
||||
erase(cbegin(), last);
|
||||
}
|
||||
}
|
||||
|
||||
std::add_pointer_t<device_type> find_shared_device(device_t ¤t, char const *name, util::hash_collection const &hashes, uint64_t length) const
|
||||
{
|
||||
// if we're examining a child device, it will always have a perfect match
|
||||
@ -172,6 +201,7 @@ media_auditor::summary media_auditor::audit_media(const char *validation)
|
||||
}
|
||||
}
|
||||
}
|
||||
parentroms.remove_redundant_parents();
|
||||
|
||||
// count ROMs required/found
|
||||
std::size_t found(0);
|
||||
|
@ -69,6 +69,7 @@ II Plus: RAM options reduced to 16/32/48 KB.
|
||||
#include "bus/a2bus/a2memexp.h"
|
||||
#include "bus/a2bus/a2midi.h"
|
||||
#include "bus/a2bus/a2mockingboard.h"
|
||||
#include "bus/a2bus/a2parprn.h"
|
||||
#include "bus/a2bus/a2pic.h"
|
||||
#include "bus/a2bus/a2sam.h"
|
||||
#include "bus/a2bus/a2scsi.h"
|
||||
@ -1308,7 +1309,9 @@ static void apple2_cards(device_slot_interface &device)
|
||||
device.option_add("ultraterm", A2BUS_ULTRATERM); /* Videx UltraTerm (original) */
|
||||
device.option_add("ultratermenh", A2BUS_ULTRATERMENH); /* Videx UltraTerm (enhanced //e) */
|
||||
device.option_add("aevm80", A2BUS_AEVIEWMASTER80); /* Applied Engineering ViewMaster 80 */
|
||||
device.option_add("parallel", A2BUS_PIC); /* Apple Parallel Interface Card */
|
||||
device.option_add("parprn", A2BUS_PARPRN); /* Apple II Parallel Printer Interface Card */
|
||||
device.option_add("parallel", A2BUS_PIC); /* Apple II Parallel Interface Card */
|
||||
device.option_add("grapplerplus", A2BUS_GRAPPLERPLUS); /* Orange Micro Grappler+ Printer Interface card */
|
||||
device.option_add("corvus", A2BUS_CORVUS); /* Corvus flat-cable HDD interface (see notes in a2corvus.c) */
|
||||
device.option_add("mcms1", A2BUS_MCMS1); /* Mountain Computer Music System, card 1 of 2 */
|
||||
device.option_add("mcms2", A2BUS_MCMS2); /* Mountain Computer Music System, card 2 of 2. must be in card 1's slot + 1! */
|
||||
@ -1326,7 +1329,6 @@ static void apple2_cards(device_slot_interface &device)
|
||||
device.option_add("applesurance", A2BUS_APPLESURANCE); /* Applesurance Diagnostic Controller */
|
||||
// device.option_add("magicmusician", A2BUS_MAGICMUSICIAN); /* Magic Musician Card */
|
||||
device.option_add("byte8251", A2BUS_BYTE8251); /* BYTE Magazine 8251 serial card */
|
||||
device.option_add("grapplerplus", A2BUS_GRAPPLERPLUS); /* Orange Micro Grappler+ Printer Interface card */
|
||||
}
|
||||
|
||||
void apple2_state::apple2_common(machine_config &config)
|
||||
|
@ -152,6 +152,7 @@ MIG RAM page 2 $CE02 is the speaker/slot bitfield and $CE03 is the paddle/accele
|
||||
#include "bus/a2bus/a2memexp.h"
|
||||
#include "bus/a2bus/a2midi.h"
|
||||
#include "bus/a2bus/a2mockingboard.h"
|
||||
#include "bus/a2bus/a2parprn.h"
|
||||
#include "bus/a2bus/a2pic.h"
|
||||
#include "bus/a2bus/a2sam.h"
|
||||
#include "bus/a2bus/a2scsi.h"
|
||||
@ -4505,7 +4506,9 @@ static void apple2_cards(device_slot_interface &device)
|
||||
device.option_add("ultraterm", A2BUS_ULTRATERM); /* Videx UltraTerm (original) */
|
||||
device.option_add("ultratermenh", A2BUS_ULTRATERMENH); /* Videx UltraTerm (enhanced //e) */
|
||||
device.option_add("aevm80", A2BUS_AEVIEWMASTER80); /* Applied Engineering ViewMaster 80 */
|
||||
device.option_add("parallel", A2BUS_PIC); /* Apple Parallel Interface Card */
|
||||
device.option_add("parprn", A2BUS_PARPRN); /* Apple II Parallel Printer Interface Card */
|
||||
device.option_add("parallel", A2BUS_PIC); /* Apple II Parallel Interface Card */
|
||||
device.option_add("grapplerplus", A2BUS_GRAPPLERPLUS); /* Orange Micro Grappler+ Printer Interface card */
|
||||
device.option_add("corvus", A2BUS_CORVUS); /* Corvus flat-cable HDD interface (see notes in a2corvus.c) */
|
||||
device.option_add("mcms1", A2BUS_MCMS1); /* Mountain Computer Music System, card 1 of 2 */
|
||||
device.option_add("mcms2", A2BUS_MCMS2); /* Mountain Computer Music System, card 2 of 2. must be in card 1's slot + 1! */
|
||||
@ -4529,7 +4532,6 @@ static void apple2_cards(device_slot_interface &device)
|
||||
device.option_add("uthernet", A2BUS_UTHERNET); /* A2RetroSystems Uthernet card */
|
||||
device.option_add("sider2", A2BUS_SIDER2); /* Advanced Tech Systems / First Class Peripherals Sider 2 SASI card */
|
||||
device.option_add("sider1", A2BUS_SIDER1); /* Advanced Tech Systems / First Class Peripherals Sider 1 SASI card */
|
||||
device.option_add("grapplerplus", A2BUS_GRAPPLERPLUS); /* Orange Micro Grappler+ Printer Interface card */
|
||||
}
|
||||
|
||||
static void apple2eaux_cards(device_slot_interface &device)
|
||||
|
@ -86,6 +86,7 @@
|
||||
#include "bus/a2bus/a2memexp.h"
|
||||
#include "bus/a2bus/a2midi.h"
|
||||
#include "bus/a2bus/a2mockingboard.h"
|
||||
#include "bus/a2bus/a2parprn.h"
|
||||
#include "bus/a2bus/a2pic.h"
|
||||
#include "bus/a2bus/a2sam.h"
|
||||
#include "bus/a2bus/a2scsi.h"
|
||||
@ -4572,7 +4573,9 @@ static void apple2_cards(device_slot_interface &device)
|
||||
device.option_add("ultraterm", A2BUS_ULTRATERM); /* Videx UltraTerm (original) */
|
||||
device.option_add("ultratermenh", A2BUS_ULTRATERMENH); /* Videx UltraTerm (enhanced //e) */
|
||||
device.option_add("aevm80", A2BUS_AEVIEWMASTER80); /* Applied Engineering ViewMaster 80 */
|
||||
device.option_add("parallel", A2BUS_PIC); /* Apple Parallel Interface Card */
|
||||
device.option_add("parprn", A2BUS_PARPRN); /* Apple II Parallel Printer Interface Card */
|
||||
device.option_add("parallel", A2BUS_PIC); /* Apple II Parallel Interface Card */
|
||||
device.option_add("grapplerplus", A2BUS_GRAPPLERPLUS); /* Orange Micro Grappler+ Printer Interface card */
|
||||
device.option_add("corvus", A2BUS_CORVUS); /* Corvus flat-cable HDD interface (see notes in a2corvus.c) */
|
||||
device.option_add("mcms1", A2BUS_MCMS1); /* Mountain Computer Music System, card 1 of 2 */
|
||||
device.option_add("mcms2", A2BUS_MCMS2); /* Mountain Computer Music System, card 2 of 2. must be in card 1's slot + 1! */
|
||||
@ -4594,7 +4597,6 @@ static void apple2_cards(device_slot_interface &device)
|
||||
device.option_add("uthernet", A2BUS_UTHERNET); /* A2RetroSystems Uthernet card */
|
||||
device.option_add("sider2", A2BUS_SIDER2); /* Advanced Tech Systems / First Class Peripherals Sider 2 SASI card */
|
||||
device.option_add("sider1", A2BUS_SIDER1); /* Advanced Tech Systems / First Class Peripherals Sider 1 SASI card */
|
||||
device.option_add("grapplerplus", A2BUS_GRAPPLERPLUS); /* Orange Micro Grappler+ Printer Interface card */
|
||||
}
|
||||
|
||||
void apple2gs_state::apple2gs(machine_config &config)
|
||||
|
@ -32,9 +32,8 @@
|
||||
#include "input_common.h"
|
||||
#include "input_windows.h"
|
||||
|
||||
//============================================================
|
||||
// MACROS
|
||||
//============================================================
|
||||
|
||||
namespace {
|
||||
|
||||
// Typedefs for dynamically loaded functions
|
||||
typedef UINT (WINAPI *get_rawinput_device_list_ptr)(PRAWINPUTDEVICELIST, PUINT, UINT);
|
||||
@ -48,17 +47,24 @@ private:
|
||||
HKEY m_key;
|
||||
|
||||
public:
|
||||
safe_regkey()
|
||||
: m_key(nullptr)
|
||||
safe_regkey() : m_key(nullptr) { }
|
||||
safe_regkey(safe_regkey const &) = delete;
|
||||
safe_regkey(safe_regkey &&key) : m_key(key.m_key) { key.m_key = nullptr; }
|
||||
explicit safe_regkey(HKEY key) : m_key(key) { }
|
||||
|
||||
~safe_regkey() { close(); }
|
||||
|
||||
safe_regkey &operator=(safe_regkey const &) = delete;
|
||||
|
||||
safe_regkey &operator=(safe_regkey &&key)
|
||||
{
|
||||
close();
|
||||
m_key = key.m_key;
|
||||
key.m_key = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit safe_regkey(HKEY key)
|
||||
: m_key(key)
|
||||
{
|
||||
}
|
||||
|
||||
bool valid() const { return m_key != nullptr; }
|
||||
explicit operator bool() const { return m_key != nullptr; }
|
||||
|
||||
void close()
|
||||
{
|
||||
@ -69,70 +75,68 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
~safe_regkey()
|
||||
operator HKEY() const { return m_key; }
|
||||
|
||||
safe_regkey open(std::wstring const &subkey) const { return open(m_key, subkey); }
|
||||
|
||||
std::wstring enum_key(int index) const
|
||||
{
|
||||
close();
|
||||
WCHAR keyname[MAX_PATH];
|
||||
DWORD namelen = MAX_PATH;
|
||||
if (RegEnumKeyEx(m_key, index, keyname, &namelen, nullptr, nullptr, nullptr, nullptr) == ERROR_SUCCESS)
|
||||
return std::wstring(keyname, namelen);
|
||||
else
|
||||
return std::wstring();
|
||||
}
|
||||
|
||||
operator HKEY() const { return m_key; }
|
||||
std::wstring query_string(WCHAR const *path) const
|
||||
{
|
||||
// first query to get the length
|
||||
DWORD datalen;
|
||||
if (RegQueryValueExW(m_key, path, nullptr, nullptr, nullptr, &datalen) != ERROR_SUCCESS)
|
||||
return std::wstring();
|
||||
|
||||
// allocate a buffer
|
||||
auto buffer = std::make_unique<WCHAR []>((datalen + (sizeof(WCHAR) * 2) - 1) / sizeof(WCHAR));
|
||||
|
||||
// now get the actual data
|
||||
if (RegQueryValueExW(m_key, path, nullptr, nullptr, reinterpret_cast<LPBYTE>(buffer.get()), &datalen) != ERROR_SUCCESS)
|
||||
return std::wstring();
|
||||
|
||||
buffer[datalen / sizeof(WCHAR)] = 0;
|
||||
return std::wstring(buffer.get());
|
||||
}
|
||||
|
||||
template <typename T> void foreach_subkey(T &&action) const
|
||||
{
|
||||
std::wstring name;
|
||||
for (int i = 0; ; i++)
|
||||
{
|
||||
name = enum_key(i);
|
||||
if (name.empty())
|
||||
break;
|
||||
|
||||
safe_regkey const subkey = open(name);
|
||||
if (!subkey)
|
||||
break;
|
||||
|
||||
bool const shouldcontinue = action(subkey);
|
||||
if (!shouldcontinue)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static safe_regkey open(HKEY basekey, std::wstring const &subkey)
|
||||
{
|
||||
HKEY key(nullptr);
|
||||
if (RegOpenKeyEx(basekey, subkey.c_str(), 0, KEY_READ, &key) == ERROR_SUCCESS)
|
||||
return safe_regkey(key);
|
||||
else
|
||||
return safe_regkey();
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================
|
||||
// reg_open_key
|
||||
//============================================================
|
||||
|
||||
static safe_regkey reg_open_key(HKEY basekey, const std::wstring &subkey)
|
||||
{
|
||||
HKEY key;
|
||||
if (RegOpenKeyEx(basekey, subkey.c_str(), 0, KEY_READ, &key) == ERROR_SUCCESS)
|
||||
return safe_regkey(key);
|
||||
|
||||
return safe_regkey();
|
||||
|
||||
}
|
||||
|
||||
//============================================================
|
||||
// reg_enum_key
|
||||
//============================================================
|
||||
|
||||
static std::wstring reg_enum_key(HKEY key, int index)
|
||||
{
|
||||
WCHAR keyname[MAX_PATH];
|
||||
DWORD namelen;
|
||||
if (RegEnumKeyEx(key, index, keyname, &namelen, nullptr, nullptr, nullptr, nullptr) == ERROR_SUCCESS)
|
||||
return std::wstring(keyname, namelen);
|
||||
|
||||
return std::wstring();
|
||||
}
|
||||
|
||||
//============================================================
|
||||
// reg_query_string
|
||||
//============================================================
|
||||
|
||||
static std::wstring reg_query_string(HKEY key, const TCHAR *path)
|
||||
{
|
||||
DWORD datalen;
|
||||
LONG result;
|
||||
|
||||
// first query to get the length
|
||||
result = RegQueryValueEx(key, path, nullptr, nullptr, nullptr, &datalen);
|
||||
if (result != ERROR_SUCCESS)
|
||||
return std::wstring();
|
||||
|
||||
// allocate a buffer
|
||||
auto buffer = std::make_unique<TCHAR[]>(datalen + sizeof(TCHAR));
|
||||
buffer[datalen / sizeof(TCHAR)] = 0;
|
||||
|
||||
// now get the actual data
|
||||
result = RegQueryValueEx(key, path, nullptr, nullptr, reinterpret_cast<LPBYTE>(buffer.get()), &datalen);
|
||||
if (result == ERROR_SUCCESS)
|
||||
return std::wstring(buffer.get());
|
||||
|
||||
// otherwise return an empty string
|
||||
return std::wstring();
|
||||
}
|
||||
|
||||
static std::wstring trim_prefix(const std::wstring &devicename)
|
||||
std::wstring trim_prefix(const std::wstring &devicename)
|
||||
{
|
||||
// remove anything prior to the final semicolon
|
||||
auto semicolon_index = devicename.find_last_of(';');
|
||||
@ -142,22 +146,22 @@ static std::wstring trim_prefix(const std::wstring &devicename)
|
||||
return devicename;
|
||||
}
|
||||
|
||||
static std::wstring compute_device_regpath(const std::wstring &name)
|
||||
std::wstring compute_device_regpath(const std::wstring &name)
|
||||
{
|
||||
static const std::wstring basepath(L"SYSTEM\\CurrentControlSet\\Enum\\");
|
||||
|
||||
// allocate a temporary string and concatenate the base path plus the name
|
||||
auto regpath_buffer = std::make_unique<TCHAR[]>(basepath.length() + 1 + name.length());
|
||||
auto regpath_buffer = std::make_unique<WCHAR []>(basepath.length() + 1 + name.length());
|
||||
wcscpy(regpath_buffer.get(), basepath.c_str());
|
||||
WCHAR * chdst = regpath_buffer.get() + basepath.length();
|
||||
WCHAR *chdst = regpath_buffer.get() + basepath.length();
|
||||
|
||||
// convert all # to \ in the name
|
||||
for (int i = 4; i < name.length(); i++)
|
||||
*chdst++ = (name[i] == '#') ? '\\' : name[i];
|
||||
*chdst++ = (name[i] == '#') ? L'\\' : name[i];
|
||||
*chdst = 0;
|
||||
|
||||
// remove the final chunk
|
||||
chdst = wcsrchr(regpath_buffer.get(), '\\');
|
||||
chdst = wcsrchr(regpath_buffer.get(), L'\\');
|
||||
if (chdst == nullptr)
|
||||
return std::wstring();
|
||||
|
||||
@ -166,15 +170,15 @@ static std::wstring compute_device_regpath(const std::wstring &name)
|
||||
return std::wstring(regpath_buffer.get());
|
||||
}
|
||||
|
||||
static std::wstring improve_name_from_base_path(const std::wstring ®path, bool *hid)
|
||||
std::wstring improve_name_from_base_path(const std::wstring ®path, bool *hid)
|
||||
{
|
||||
// now try to open the registry key
|
||||
auto device_key = reg_open_key(HKEY_LOCAL_MACHINE, regpath);
|
||||
if (!device_key.valid())
|
||||
auto device_key = safe_regkey::open(HKEY_LOCAL_MACHINE, regpath);
|
||||
if (!device_key)
|
||||
return std::wstring();
|
||||
|
||||
// fetch the device description; if it exists, we are finished
|
||||
auto regstring = reg_query_string(device_key, L"DeviceDesc");
|
||||
auto regstring = device_key.query_string(L"DeviceDesc");
|
||||
if (!regstring.empty())
|
||||
return trim_prefix(regstring);
|
||||
|
||||
@ -183,25 +187,7 @@ static std::wstring improve_name_from_base_path(const std::wstring ®path, boo
|
||||
return std::wstring();
|
||||
}
|
||||
|
||||
static void foreach_subkey(HKEY key, std::function<bool(HKEY)> action)
|
||||
{
|
||||
for (int i = 0; ; i++)
|
||||
{
|
||||
std::wstring name = reg_enum_key(key, i);
|
||||
if (name.empty())
|
||||
break;
|
||||
|
||||
safe_regkey subkey = reg_open_key(key, name);
|
||||
if (!subkey.valid())
|
||||
break;
|
||||
|
||||
bool shouldcontinue = action(subkey);
|
||||
if (!shouldcontinue)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static std::wstring improve_name_from_usb_path(const std::wstring ®path)
|
||||
std::wstring improve_name_from_usb_path(const std::wstring ®path)
|
||||
{
|
||||
static const std::wstring usbbasepath(L"SYSTEM\\CurrentControlSet\\Enum\\USB");
|
||||
|
||||
@ -213,31 +199,33 @@ static std::wstring improve_name_from_usb_path(const std::wstring ®path)
|
||||
std::wstring parentid = regpath.substr(last_slash_index + 1);
|
||||
|
||||
// open the USB key
|
||||
auto usb_key = reg_open_key(HKEY_LOCAL_MACHINE, usbbasepath);
|
||||
if (!usb_key.valid())
|
||||
auto usb_key = safe_regkey::open(HKEY_LOCAL_MACHINE, usbbasepath);
|
||||
if (!usb_key)
|
||||
return std::wstring();
|
||||
|
||||
std::wstring regstring;
|
||||
|
||||
foreach_subkey(usb_key, [®string, &parentid](HKEY subkey)
|
||||
{
|
||||
foreach_subkey(subkey, [®string, &parentid](HKEY endkey)
|
||||
{
|
||||
std::wstring endparentid = reg_query_string(endkey, L"ParentIdPrefix");
|
||||
usb_key.foreach_subkey(
|
||||
[®string, &parentid] (safe_regkey const &subkey)
|
||||
{
|
||||
subkey.foreach_subkey(
|
||||
[®string, &parentid] (safe_regkey const &endkey)
|
||||
{
|
||||
std::wstring endparentid = endkey.query_string(L"ParentIdPrefix");
|
||||
|
||||
// This key doesn't have a ParentIdPrefix
|
||||
if (endparentid.empty())
|
||||
return true;
|
||||
// This key doesn't have a ParentIdPrefix
|
||||
if (endparentid.empty())
|
||||
return true;
|
||||
|
||||
// do we have a match?
|
||||
if (parentid.find(endparentid) == 0)
|
||||
regstring = reg_query_string(endkey, L"DeviceDesc");
|
||||
// do we have a match?
|
||||
if (parentid.find(endparentid) == 0)
|
||||
regstring = endkey.query_string(L"DeviceDesc");
|
||||
|
||||
return regstring.empty();
|
||||
});
|
||||
return regstring.empty();
|
||||
});
|
||||
|
||||
return regstring.empty();
|
||||
});
|
||||
return regstring.empty();
|
||||
});
|
||||
|
||||
return trim_prefix(regstring);
|
||||
}
|
||||
@ -246,7 +234,7 @@ static std::wstring improve_name_from_usb_path(const std::wstring ®path)
|
||||
// rawinput_device_improve_name
|
||||
//============================================================
|
||||
|
||||
static std::wstring rawinput_device_improve_name(const std::wstring &name)
|
||||
std::wstring rawinput_device_improve_name(const std::wstring &name)
|
||||
{
|
||||
// The RAW name received is formatted as:
|
||||
// \??\type-id#hardware-id#instance-id#{DeviceClasses-id}
|
||||
@ -283,12 +271,11 @@ static std::wstring rawinput_device_improve_name(const std::wstring &name)
|
||||
class rawinput_device : public event_based_device<RAWINPUT>
|
||||
{
|
||||
private:
|
||||
HANDLE m_handle;
|
||||
HANDLE m_handle = nullptr;
|
||||
|
||||
public:
|
||||
rawinput_device(running_machine& machine, const char *name, const char *id, input_device_class deviceclass, input_module& module)
|
||||
: event_based_device(machine, name, id, deviceclass, module),
|
||||
m_handle(nullptr)
|
||||
rawinput_device(running_machine &machine, const char *name, const char *id, input_device_class deviceclass, input_module &module) :
|
||||
event_based_device(machine, name, id, deviceclass, module)
|
||||
{
|
||||
}
|
||||
|
||||
@ -305,9 +292,9 @@ class rawinput_keyboard_device : public rawinput_device
|
||||
public:
|
||||
keyboard_state keyboard;
|
||||
|
||||
rawinput_keyboard_device(running_machine& machine, const char *name, const char *id, input_module& module)
|
||||
: rawinput_device(machine, name, id, DEVICE_CLASS_KEYBOARD, module),
|
||||
keyboard({{0}})
|
||||
rawinput_keyboard_device(running_machine &machine, const char *name, const char *id, input_module &module) :
|
||||
rawinput_device(machine, name, id, DEVICE_CLASS_KEYBOARD, module),
|
||||
keyboard({{0}})
|
||||
{
|
||||
}
|
||||
|
||||
@ -341,9 +328,9 @@ private:
|
||||
public:
|
||||
mouse_state mouse;
|
||||
|
||||
rawinput_mouse_device(running_machine& machine, const char *name, const char *id, input_module& module)
|
||||
: rawinput_device(machine, name, id, DEVICE_CLASS_MOUSE, module),
|
||||
mouse({0})
|
||||
rawinput_mouse_device(running_machine &machine, const char *name, const char *id, input_module &module) :
|
||||
rawinput_device(machine, name, id, DEVICE_CLASS_MOUSE, module),
|
||||
mouse({0})
|
||||
{
|
||||
}
|
||||
|
||||
@ -401,8 +388,8 @@ private:
|
||||
public:
|
||||
mouse_state lightgun;
|
||||
|
||||
rawinput_lightgun_device(running_machine& machine, const char *name, const char *id, input_module& module)
|
||||
: rawinput_device(machine, name, id, DEVICE_CLASS_LIGHTGUN, module),
|
||||
rawinput_lightgun_device(running_machine &machine, const char *name, const char *id, input_module &module) :
|
||||
rawinput_device(machine, name, id, DEVICE_CLASS_LIGHTGUN, module),
|
||||
lightgun({0})
|
||||
{
|
||||
}
|
||||
@ -456,19 +443,14 @@ class rawinput_module : public wininput_module
|
||||
{
|
||||
private:
|
||||
osd::dynamic_module::ptr m_user32_dll;
|
||||
get_rawinput_device_list_ptr get_rawinput_device_list;
|
||||
get_rawinput_data_ptr get_rawinput_data;
|
||||
get_rawinput_device_info_ptr get_rawinput_device_info;
|
||||
register_rawinput_devices_ptr register_rawinput_devices;
|
||||
get_rawinput_device_list_ptr get_rawinput_device_list = nullptr;
|
||||
get_rawinput_data_ptr get_rawinput_data = nullptr;
|
||||
get_rawinput_device_info_ptr get_rawinput_device_info = nullptr;
|
||||
register_rawinput_devices_ptr register_rawinput_devices = nullptr;
|
||||
std::mutex m_module_lock;
|
||||
|
||||
public:
|
||||
rawinput_module(const char *type, const char* name)
|
||||
: wininput_module(type, name),
|
||||
get_rawinput_device_list(nullptr),
|
||||
get_rawinput_data(nullptr),
|
||||
get_rawinput_device_info(nullptr),
|
||||
register_rawinput_devices(nullptr)
|
||||
rawinput_module(const char *type, const char *name) : wininput_module(type, name)
|
||||
{
|
||||
}
|
||||
|
||||
@ -481,13 +463,7 @@ public:
|
||||
get_rawinput_device_info = m_user32_dll->bind<get_rawinput_device_info_ptr>("GetRawInputDeviceInfoW");
|
||||
register_rawinput_devices = m_user32_dll->bind<register_rawinput_devices_ptr>("RegisterRawInputDevices");
|
||||
|
||||
if (!get_rawinput_device_list || !get_rawinput_data ||
|
||||
!get_rawinput_device_info || !register_rawinput_devices )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return get_rawinput_device_list && get_rawinput_data && get_rawinput_device_info && register_rawinput_devices;
|
||||
}
|
||||
|
||||
void input_init(running_machine &machine) override
|
||||
@ -501,7 +477,7 @@ public:
|
||||
return;
|
||||
|
||||
auto rawinput_devices = std::make_unique<RAWINPUTDEVICELIST[]>(device_count);
|
||||
if ((*get_rawinput_device_list)(rawinput_devices.get(), &device_count, sizeof(RAWINPUTDEVICELIST)) == -1)
|
||||
if ((*get_rawinput_device_list)(rawinput_devices.get(), &device_count, sizeof(RAWINPUTDEVICELIST)) == UINT(-1))
|
||||
return;
|
||||
|
||||
// iterate backwards through devices; new devices are added at the head
|
||||
@ -533,7 +509,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void add_rawinput_device(running_machine& machine, RAWINPUTDEVICELIST * device) = 0;
|
||||
virtual void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST *device) = 0;
|
||||
virtual USHORT usagepage() = 0;
|
||||
virtual USHORT usage() = 0;
|
||||
|
||||
@ -550,16 +526,15 @@ protected:
|
||||
}
|
||||
|
||||
template<class TDevice>
|
||||
TDevice* create_rawinput_device(running_machine &machine, PRAWINPUTDEVICELIST rawinputdevice)
|
||||
TDevice *create_rawinput_device(running_machine &machine, PRAWINPUTDEVICELIST rawinputdevice)
|
||||
{
|
||||
TDevice* devinfo;
|
||||
UINT name_length = 0;
|
||||
// determine the length of the device name, allocate it, and fetch it if not nameless
|
||||
UINT name_length = 0;
|
||||
if ((*get_rawinput_device_info)(rawinputdevice->hDevice, RIDI_DEVICENAME, nullptr, &name_length) != 0)
|
||||
return nullptr;
|
||||
|
||||
std::unique_ptr<TCHAR[]> tname = std::make_unique<TCHAR[]>(name_length + 1);
|
||||
if (name_length > 1 && (*get_rawinput_device_info)(rawinputdevice->hDevice, RIDI_DEVICENAME, tname.get(), &name_length) == -1)
|
||||
std::unique_ptr<WCHAR []> tname = std::make_unique<WCHAR []>(name_length + 1);
|
||||
if (name_length > 1 && (*get_rawinput_device_info)(rawinputdevice->hDevice, RIDI_DEVICENAME, tname.get(), &name_length) == UINT(-1))
|
||||
return nullptr;
|
||||
|
||||
// if this is an RDP name, skip it
|
||||
@ -575,7 +550,7 @@ protected:
|
||||
// set device id to raw input name
|
||||
std::string utf8_id = osd::text::from_wstring(tname.get());
|
||||
|
||||
devinfo = devicelist()->create_device<TDevice>(machine, utf8_name.c_str(), utf8_id.c_str(), *this);
|
||||
TDevice *devinfo = devicelist()->create_device<TDevice>(machine, utf8_name.c_str(), utf8_id.c_str(), *this);
|
||||
|
||||
// Add the handle
|
||||
devinfo->set_handle(rawinputdevice->hDevice);
|
||||
@ -583,7 +558,7 @@ protected:
|
||||
return devinfo;
|
||||
}
|
||||
|
||||
bool handle_input_event(input_event eventid, void* eventdata) override
|
||||
bool handle_input_event(input_event eventid, void *eventdata) override
|
||||
{
|
||||
// Only handle raw input data
|
||||
if (!input_enabled() || eventid != INPUT_EVENT_RAWINPUT)
|
||||
@ -622,15 +597,18 @@ protected:
|
||||
auto *input = reinterpret_cast<RAWINPUT*>(data);
|
||||
|
||||
// find the device in the list and update
|
||||
auto target_device = std::find_if(devicelist()->begin(), devicelist()->end(), [input](auto &device)
|
||||
{
|
||||
auto devinfo = dynamic_cast<rawinput_device*>(device.get());
|
||||
return devinfo != nullptr && input->header.hDevice == devinfo->device_handle();
|
||||
});
|
||||
auto target_device = std::find_if(
|
||||
devicelist()->begin(),
|
||||
devicelist()->end(),
|
||||
[input] (auto const &device)
|
||||
{
|
||||
auto devinfo = dynamic_cast<rawinput_device *>(device.get());
|
||||
return devinfo && (input->header.hDevice == devinfo->device_handle());
|
||||
});
|
||||
|
||||
if (target_device != devicelist()->end())
|
||||
{
|
||||
static_cast<rawinput_device*>((*target_device).get())->queue_events(input, 1);
|
||||
static_cast<rawinput_device *>((*target_device).get())->queue_events(input, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -654,7 +632,8 @@ public:
|
||||
protected:
|
||||
USHORT usagepage() override { return 1; }
|
||||
USHORT usage() override { return 6; }
|
||||
void add_rawinput_device(running_machine& machine, RAWINPUTDEVICELIST * device) override
|
||||
|
||||
void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST *device) override
|
||||
{
|
||||
// make sure this is a keyboard
|
||||
if (device->dwType != RIM_TYPEKEYBOARD)
|
||||
@ -671,12 +650,12 @@ protected:
|
||||
for (int keynum = 0; keynum < MAX_KEYS; keynum++)
|
||||
{
|
||||
input_item_id itemid = table.map_di_scancode_to_itemid(keynum);
|
||||
TCHAR keyname[100];
|
||||
WCHAR keyname[100];
|
||||
|
||||
// generate the name
|
||||
if (GetKeyNameText(((keynum & 0x7f) << 16) | ((keynum & 0x80) << 17), keyname, ARRAY_LENGTH(keyname)) == 0)
|
||||
_sntprintf(keyname, ARRAY_LENGTH(keyname), TEXT("Scan%03d"), keynum);
|
||||
std::string name = osd::text::from_tstring(keyname);
|
||||
if (GetKeyNameTextW(((keynum & 0x7f) << 16) | ((keynum & 0x80) << 17), keyname, ARRAY_LENGTH(keyname)) == 0)
|
||||
_snwprintf(keyname, ARRAY_LENGTH(keyname), L"Scan%03d", keynum);
|
||||
std::string name = osd::text::from_wstring(keyname);
|
||||
|
||||
// add the item to the device
|
||||
devinfo->device()->add_item(name.c_str(), itemid, generic_button_get_state<std::uint8_t>, &devinfo->keyboard.state[keynum]);
|
||||
@ -699,7 +678,8 @@ public:
|
||||
protected:
|
||||
USHORT usagepage() override { return 1; }
|
||||
USHORT usage() override { return 2; }
|
||||
void add_rawinput_device(running_machine& machine, RAWINPUTDEVICELIST * device) override
|
||||
|
||||
void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST *device) override
|
||||
{
|
||||
// make sure this is a mouse
|
||||
if (device->dwType != RIM_TYPEMOUSE)
|
||||
@ -747,7 +727,8 @@ public:
|
||||
protected:
|
||||
USHORT usagepage() override { return 1; }
|
||||
USHORT usage() override { return 2; }
|
||||
void add_rawinput_device(running_machine& machine, RAWINPUTDEVICELIST * device) override
|
||||
|
||||
void add_rawinput_device(running_machine &machine, RAWINPUTDEVICELIST *device) override
|
||||
{
|
||||
|
||||
// make sure this is a mouse
|
||||
@ -781,6 +762,8 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
#else
|
||||
MODULE_NOT_SUPPORTED(keyboard_input_rawinput, OSD_KEYBOARDINPUT_PROVIDER, "rawinput")
|
||||
MODULE_NOT_SUPPORTED(mouse_input_rawinput, OSD_MOUSEINPUT_PROVIDER, "rawinput")
|
||||
|
@ -40,14 +40,10 @@ struct mouse_state
|
||||
class wininput_module : public input_module_base
|
||||
{
|
||||
protected:
|
||||
bool m_global_inputs_enabled;
|
||||
bool m_global_inputs_enabled = false;
|
||||
|
||||
public:
|
||||
wininput_module(const char * type, const char * name)
|
||||
: input_module_base(type, name),
|
||||
m_global_inputs_enabled(false)
|
||||
{
|
||||
}
|
||||
wininput_module(const char *type, const char *name) : input_module_base(type, name) { }
|
||||
|
||||
virtual ~wininput_module() { }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user