diff options
Diffstat (limited to 'src/emu')
245 files changed, 7832 insertions, 6228 deletions
diff --git a/src/emu/bus/a7800/a78_slot.c b/src/emu/bus/a7800/a78_slot.c index e7f6da4f6cb..6332492a6c2 100644 --- a/src/emu/bus/a7800/a78_slot.c +++ b/src/emu/bus/a7800/a78_slot.c @@ -488,7 +488,7 @@ void a78_partialhash(hash_collection &dest, const unsigned char *data, void a78_cart_slot_device::call_unload() { - if (m_cart && m_cart->get_nvram_size()) + if (m_cart && m_cart->get_nvram_base() && m_cart->get_nvram_size()) battery_save(m_cart->get_nvram_base(), 0x800); } diff --git a/src/emu/bus/apricot/cards.c b/src/emu/bus/apricot/cards.c new file mode 100644 index 00000000000..9a97adffca6 --- /dev/null +++ b/src/emu/bus/apricot/cards.c @@ -0,0 +1,15 @@ +// license:GPL-2.0+ +// copyright-holders:Dirk Best +/*************************************************************************** + + ACT Apricot Expansion Slot Devices + +***************************************************************************/ + +#include "cards.h" + +SLOT_INTERFACE_START( apricot_expansion_cards ) + SLOT_INTERFACE("128k", APRICOT_128K_RAM) + SLOT_INTERFACE("256k", APRICOT_256K_RAM) + SLOT_INTERFACE("512k", APRICOT_512K_RAM) +SLOT_INTERFACE_END diff --git a/src/emu/bus/apricot/cards.h b/src/emu/bus/apricot/cards.h new file mode 100644 index 00000000000..67766d51a8e --- /dev/null +++ b/src/emu/bus/apricot/cards.h @@ -0,0 +1,19 @@ +// license:GPL-2.0+ +// copyright-holders:Dirk Best +/*************************************************************************** + + ACT Apricot Expansion Slot Devices + +***************************************************************************/ + +#pragma once + +#ifndef __APRICOT_CARDS_H__ +#define __APRICOT_CARDS_H__ + +#include "emu.h" +#include "ram.h" + +SLOT_INTERFACE_EXTERN( apricot_expansion_cards ); + +#endif // __APRICOT_CARDS_H__ diff --git a/src/emu/bus/apricot/expansion.c b/src/emu/bus/apricot/expansion.c new file mode 100644 index 00000000000..7fe2b2a721c --- /dev/null +++ b/src/emu/bus/apricot/expansion.c @@ -0,0 +1,192 @@ +// license:GPL-2.0+ +// copyright-holders:Dirk Best +/*************************************************************************** + + ACT Apricot Expansion Slot + +***************************************************************************/ + +#include "expansion.h" + + +//************************************************************************** +// EXPANSION SLOT DEVICE +//************************************************************************** + +const device_type APRICOT_EXPANSION_SLOT = &device_creator<apricot_expansion_slot_device>; + +//------------------------------------------------- +// apricot_expansion_slot_device - constructor +//------------------------------------------------- + +apricot_expansion_slot_device::apricot_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, APRICOT_EXPANSION_SLOT, "Apricot Expansion Slot", tag, owner, clock, "apricot_exp_slot", __FILE__), + device_slot_interface(mconfig, *this) +{ +} + +apricot_expansion_slot_device::apricot_expansion_slot_device(const machine_config &mconfig, device_type type, const char *name, + const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) : + device_t(mconfig, type, name, tag, owner, clock, shortname, source), + device_slot_interface(mconfig, *this) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void apricot_expansion_slot_device::device_start() +{ + device_apricot_expansion_card_interface *dev = dynamic_cast<device_apricot_expansion_card_interface *>(get_card_device()); + + if (dev) + { + apricot_expansion_bus_device *bus = downcast<apricot_expansion_bus_device *>(m_owner); + bus->add_card(dev); + } +} + + +//************************************************************************** +// EXPANSION BUS DEVICE +//************************************************************************** + +const device_type APRICOT_EXPANSION_BUS = &device_creator<apricot_expansion_bus_device>; + +//------------------------------------------------- +// apricot_expansion_bus_device - constructor +//------------------------------------------------- + +apricot_expansion_bus_device::apricot_expansion_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, APRICOT_EXPANSION_BUS, "Apricot Expansion Bus", tag, owner, clock, "apricot_exp_bus", __FILE__), + m_program(NULL), + m_io(NULL), + m_program_iop(NULL), + m_io_iop(NULL), + m_dma1_handler(*this), + m_dma2_handler(*this), + m_ext1_handler(*this), + m_ext2_handler(*this), + m_int2_handler(*this), + m_int3_handler(*this) +{ +} + +//------------------------------------------------- +// apricot_expansion_bus_device - destructor +//------------------------------------------------- + +apricot_expansion_bus_device::~apricot_expansion_bus_device() +{ + m_dev.detach_all(); +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void apricot_expansion_bus_device::device_start() +{ + // resolve callbacks + m_dma1_handler.resolve_safe(); + m_dma2_handler.resolve_safe(); + m_ext1_handler.resolve_safe(); + m_ext2_handler.resolve_safe(); + m_int2_handler.resolve_safe(); + m_int3_handler.resolve_safe(); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void apricot_expansion_bus_device::device_reset() +{ + cpu_device *cpu = m_owner->subdevice<cpu_device>(m_cpu_tag); + m_program = &cpu->space(AS_PROGRAM); + m_io = &cpu->space(AS_IO); + + cpu_device *iop = m_owner->subdevice<cpu_device>(m_iop_tag); + m_program_iop = &iop->space(AS_PROGRAM); + m_io_iop = &iop->space(AS_IO); +} + +//------------------------------------------------- +// add_card - add new card to our bus +//------------------------------------------------- + +void apricot_expansion_bus_device::add_card(device_apricot_expansion_card_interface *card) +{ + card->set_bus_device(this); + m_dev.append(*card); +} + +//------------------------------------------------- +// set_cpu_tag - set cpu we are attached to +//------------------------------------------------- + +void apricot_expansion_bus_device::set_cpu_tag(device_t &device, device_t *owner, const char *tag) +{ + apricot_expansion_bus_device &bus = dynamic_cast<apricot_expansion_bus_device &>(device); + bus.m_cpu_tag = tag; +} + +//------------------------------------------------- +// set_iop_tag - set iop we are attached to +//------------------------------------------------- + +void apricot_expansion_bus_device::set_iop_tag(device_t &device, device_t *owner, const char *tag) +{ + apricot_expansion_bus_device &bus = dynamic_cast<apricot_expansion_bus_device &>(device); + bus.m_iop_tag = tag; +} + +// callbacks from slot device to the host +WRITE_LINE_MEMBER( apricot_expansion_bus_device::dma1_w ) { m_dma1_handler(state); } +WRITE_LINE_MEMBER( apricot_expansion_bus_device::dma2_w ) { m_dma2_handler(state); } +WRITE_LINE_MEMBER( apricot_expansion_bus_device::ext1_w ) { m_ext1_handler(state); } +WRITE_LINE_MEMBER( apricot_expansion_bus_device::ext2_w ) { m_ext2_handler(state); } +WRITE_LINE_MEMBER( apricot_expansion_bus_device::int2_w ) { m_int2_handler(state); } +WRITE_LINE_MEMBER( apricot_expansion_bus_device::int3_w ) { m_int3_handler(state); } + +//------------------------------------------------- +// install_ram - attach ram to cpu/iop +//------------------------------------------------- + +void apricot_expansion_bus_device::install_ram(offs_t addrstart, offs_t addrend, void *baseptr) +{ + m_program->install_ram(addrstart, addrend, baseptr); + + if (m_program_iop) + m_program_iop->install_ram(addrstart, addrend, baseptr); +} + + +//************************************************************************** +// CARTRIDGE INTERFACE +//************************************************************************** + +//------------------------------------------------- +// device_apricot_expansion_card_interface - constructor +//------------------------------------------------- + +device_apricot_expansion_card_interface::device_apricot_expansion_card_interface(const machine_config &mconfig, device_t &device) : + device_slot_card_interface(mconfig, device), + m_next(NULL), + m_bus(NULL) +{ +} + +//------------------------------------------------- +// ~device_apricot_expansion_card_interface - destructor +//------------------------------------------------- + +device_apricot_expansion_card_interface::~device_apricot_expansion_card_interface() +{ +} + +void device_apricot_expansion_card_interface::set_bus_device(apricot_expansion_bus_device *bus) +{ + m_bus = bus; +} diff --git a/src/emu/bus/apricot/expansion.h b/src/emu/bus/apricot/expansion.h new file mode 100644 index 00000000000..91b3e8e31c8 --- /dev/null +++ b/src/emu/bus/apricot/expansion.h @@ -0,0 +1,208 @@ +// license:GPL-2.0+ +// copyright-holders:Dirk Best +/*************************************************************************** + + ACT Apricot Expansion Slot + + A B + + -12V 32 +12V + +5V 31 +5V + DB0 30 DB1 + DB2 29 DB3 + DB4 28 DB5 + DB6 27 DB7 + AB10 26 AB9 + AB11 25 AB12 + /AMWC 24 /MRDC + /DMA2 23 DT/R + /DMA1 22 /IORC + /MWTC 21 /RES + /IOWC 20 /AIOWC + GND 19 GND + /CLK5 18 DEN + /IRDY 17 /MRDY + /EXT1 16 /EXT2 + /INT3 15 /ALE + AB6 14 /INT2 + AB8 13 AB7 + DB9 12 DB8 + DB11 11 DB10 + DB13 10 DB12 + DB15 9 DB14 + AB2 8 AB1 + AB4 7 AB3 + AB0 6 AB5 + AB14 5 AB13 + AB15 4 AB16 + AB17 3 AB18 + AB19 2 /BHE + NMI 1 CLK15 + +***************************************************************************/ + +#pragma once + +#ifndef __APRICOT_EXPANSION_H__ +#define __APRICOT_EXPANSION_H__ + +#include "emu.h" + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_EXPANSION_ADD(_tag, _cpu_tag) \ + MCFG_DEVICE_ADD(_tag, APRICOT_EXPANSION_BUS, 0) \ + apricot_expansion_bus_device::set_cpu_tag(*device, owner, _cpu_tag); + +#define MCFG_EXPANSION_IOP_ADD(_tag) \ + apricot_expansion_bus_device::set_iop_tag(*device, owner, _tag); + +#define MCFG_EXPANSION_SLOT_ADD(_tag, _slot_intf, _def_slot) \ + MCFG_DEVICE_ADD(_tag, APRICOT_EXPANSION_SLOT, 0) \ + MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) + +#define MCFG_EXPANSION_DMA1_HANDLER(_devcb) \ + devcb = &apricot_expansion_bus_device::set_dma1_handler(*device, DEVCB_##_devcb); + +#define MCFG_EXPANSION_DMA2_HANDLER(_devcb) \ + devcb = &apricot_expansion_bus_device::set_dma2_handler(*device, DEVCB_##_devcb); + +#define MCFG_EXPANSION_EXT1_HANDLER(_devcb) \ + devcb = &apricot_expansion_bus_device::set_ext1_handler(*device, DEVCB_##_devcb); + +#define MCFG_EXPANSION_EXT2_HANDLER(_devcb) \ + devcb = &apricot_expansion_bus_device::set_ext2_handler(*device, DEVCB_##_devcb); + +#define MCFG_EXPANSION_INT2_HANDLER(_devcb) \ + devcb = &apricot_expansion_bus_device::set_int2_handler(*device, DEVCB_##_devcb); + +#define MCFG_EXPANSION_INT3_HANDLER(_devcb) \ + devcb = &apricot_expansion_bus_device::set_int3_handler(*device, DEVCB_##_devcb); + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// forward declaration +class device_apricot_expansion_card_interface; + + +// ======================> apricot_expansion_slot_device + +class apricot_expansion_slot_device : public device_t, public device_slot_interface +{ +public: + // construction/destruction + apricot_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + apricot_expansion_slot_device(const machine_config &mconfig, device_type type, const char *name, + const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + + // device-level overrides + virtual void device_start(); +}; + +// device type definition +extern const device_type APRICOT_EXPANSION_SLOT; + + +// ======================> apricot_expansion_bus_device + +class apricot_expansion_bus_device : public device_t +{ +public: + // construction/destruction + apricot_expansion_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual ~apricot_expansion_bus_device(); + + template<class _Object> static devcb_base &set_dma1_handler(device_t &device, _Object object) + { return downcast<apricot_expansion_bus_device &>(device).m_dma1_handler.set_callback(object); } + + template<class _Object> static devcb_base &set_dma2_handler(device_t &device, _Object object) + { return downcast<apricot_expansion_bus_device &>(device).m_dma2_handler.set_callback(object); } + + template<class _Object> static devcb_base &set_ext1_handler(device_t &device, _Object object) + { return downcast<apricot_expansion_bus_device &>(device).m_ext1_handler.set_callback(object); } + + template<class _Object> static devcb_base &set_ext2_handler(device_t &device, _Object object) + { return downcast<apricot_expansion_bus_device &>(device).m_ext2_handler.set_callback(object); } + + template<class _Object> static devcb_base &set_int2_handler(device_t &device, _Object object) + { return downcast<apricot_expansion_bus_device &>(device).m_int2_handler.set_callback(object); } + + template<class _Object> static devcb_base &set_int3_handler(device_t &device, _Object object) + { return downcast<apricot_expansion_bus_device &>(device).m_int3_handler.set_callback(object); } + + // inline configuration + static void set_cpu_tag(device_t &device, device_t *owner, const char *tag); + static void set_iop_tag(device_t &device, device_t *owner, const char *tag); + + void add_card(device_apricot_expansion_card_interface *card); + + // from cards + DECLARE_WRITE_LINE_MEMBER( dma1_w ); + DECLARE_WRITE_LINE_MEMBER( dma2_w ); + DECLARE_WRITE_LINE_MEMBER( ext1_w ); + DECLARE_WRITE_LINE_MEMBER( ext2_w ); + DECLARE_WRITE_LINE_MEMBER( int2_w ); + DECLARE_WRITE_LINE_MEMBER( int3_w ); + + void install_ram(offs_t addrstart, offs_t addrend, void *baseptr); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + +private: + simple_list<device_apricot_expansion_card_interface> m_dev; + + // address spaces we have access to + address_space *m_program; + address_space *m_io; + address_space *m_program_iop; + address_space *m_io_iop; + + devcb_write_line m_dma1_handler; + devcb_write_line m_dma2_handler; + devcb_write_line m_ext1_handler; + devcb_write_line m_ext2_handler; + devcb_write_line m_int2_handler; + devcb_write_line m_int3_handler; + + // configuration + const char *m_cpu_tag; + const char *m_iop_tag; +}; + +// device type definition +extern const device_type APRICOT_EXPANSION_BUS; + + +// ======================> device_apricot_expansion_card_interface + +class device_apricot_expansion_card_interface : public device_slot_card_interface +{ +public: + // construction/destruction + device_apricot_expansion_card_interface(const machine_config &mconfig, device_t &device); + virtual ~device_apricot_expansion_card_interface(); + + void set_bus_device(apricot_expansion_bus_device *bus); + + device_apricot_expansion_card_interface *next() const { return m_next; } + device_apricot_expansion_card_interface *m_next; + +protected: + apricot_expansion_bus_device *m_bus; +}; + + +// include here so drivers don't need to +#include "cards.h" + + +#endif // __APRICOT_EXPANSION_H__ diff --git a/src/emu/bus/apricot/ram.c b/src/emu/bus/apricot/ram.c new file mode 100644 index 00000000000..2221ae37227 --- /dev/null +++ b/src/emu/bus/apricot/ram.c @@ -0,0 +1,177 @@ +// license:GPL-2.0+ +// copyright-holders:Dirk Best +/*************************************************************************** + + ACT Apricot RAM Expansions + +***************************************************************************/ + +#include "ram.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type APRICOT_256K_RAM = &device_creator<apricot_256k_ram_device>; +const device_type APRICOT_128K_RAM = &device_creator<apricot_128k_ram_device>; +const device_type APRICOT_512K_RAM = &device_creator<apricot_512k_ram_device>; + + +//************************************************************************** +// APRICOT 256K RAM DEVICE +//************************************************************************** + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +static INPUT_PORTS_START( apricot_256k ) + PORT_START("sw") + PORT_DIPNAME(0x01, 0x00, "Base Address") + PORT_DIPSETTING(0x00, "40000H") + PORT_DIPSETTING(0x01, "80000H") +INPUT_PORTS_END + +ioport_constructor apricot_256k_ram_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( apricot_256k ); +} + +//------------------------------------------------- +// apricot_256k_ram_device - constructor +//------------------------------------------------- + +apricot_256k_ram_device::apricot_256k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, APRICOT_256K_RAM, "Apricot 256K RAM Expansion Board", tag, owner, clock, "apricot_256k_ram", __FILE__), + device_apricot_expansion_card_interface(mconfig, *this), + m_sw(*this, "sw") +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void apricot_256k_ram_device::device_start() +{ + m_ram.resize(0x40000 / 2); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void apricot_256k_ram_device::device_reset() +{ + if (m_sw->read() == 0) + m_bus->install_ram(0x40000, 0x7ffff, &m_ram[0]); + else + m_bus->install_ram(0x80000, 0xbffff, &m_ram[0]); +} + + +//************************************************************************** +// APRICOT 128K RAM DEVICE +//************************************************************************** + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +static INPUT_PORTS_START( apricot_128k ) + PORT_START("strap") + PORT_DIPNAME(0x03, 0x01, "Base Address") + PORT_DIPSETTING(0x00, "512K") + PORT_DIPSETTING(0x01, "256K - 384K") + PORT_DIPSETTING(0x02, "384K - 512K") +INPUT_PORTS_END + +ioport_constructor apricot_128k_ram_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( apricot_128k ); +} + +//------------------------------------------------- +// apricot_128_512k_ram_device - constructor +//------------------------------------------------- + +apricot_128k_ram_device::apricot_128k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, APRICOT_128K_RAM, "Apricot 128/512K RAM Expansion Board (128K)", tag, owner, clock, "apricot_128k_ram", __FILE__), + device_apricot_expansion_card_interface(mconfig, *this), + m_strap(*this, "strap") +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void apricot_128k_ram_device::device_start() +{ + m_ram.resize(0x20000 / 2); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void apricot_128k_ram_device::device_reset() +{ + if (m_strap->read() == 1) + m_bus->install_ram(0x40000, 0x5ffff, &m_ram[0]); + else if (m_strap->read() == 2) + m_bus->install_ram(0x60000, 0x7ffff, &m_ram[0]); +} + + +//************************************************************************** +// APRICOT 512K RAM DEVICE +//************************************************************************** + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +static INPUT_PORTS_START( apricot_512k ) + PORT_START("strap") + PORT_DIPNAME(0x03, 0x00, "Base Address") + PORT_DIPSETTING(0x00, "512K") + PORT_DIPSETTING(0x01, "256K - 384K") + PORT_DIPSETTING(0x02, "384K - 512K") +INPUT_PORTS_END + +ioport_constructor apricot_512k_ram_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( apricot_512k ); +} + +//------------------------------------------------- +// apricot_128_512k_ram_device - constructor +//------------------------------------------------- + +apricot_512k_ram_device::apricot_512k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, APRICOT_512K_RAM, "Apricot 128/512K RAM Expansion Board (512K)", tag, owner, clock, "apricot_512k_ram", __FILE__), + device_apricot_expansion_card_interface(mconfig, *this), + m_strap(*this, "strap") +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void apricot_512k_ram_device::device_start() +{ + m_ram.resize(0x80000 / 2); +} + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void apricot_512k_ram_device::device_reset() +{ + if (m_strap->read() == 0) + m_bus->install_ram(0x40000, 0xbffff, &m_ram[0]); +} diff --git a/src/emu/bus/apricot/ram.h b/src/emu/bus/apricot/ram.h new file mode 100644 index 00000000000..20ac01f2867 --- /dev/null +++ b/src/emu/bus/apricot/ram.h @@ -0,0 +1,89 @@ +// license:GPL-2.0+ +// copyright-holders:Dirk Best +/*************************************************************************** + + ACT Apricot RAM Expansions + +***************************************************************************/ + +#pragma once + +#ifndef __APRICOT_RAM__ +#define __APRICOT_RAM__ + +#include "emu.h" +#include "expansion.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + + +// ======================> apricot_256k_ram_device + +class apricot_256k_ram_device : public device_t, public device_apricot_expansion_card_interface +{ +public: + // construction/destruction + apricot_256k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + +protected: + virtual ioport_constructor device_input_ports() const; + virtual void device_start(); + virtual void device_reset(); + +private: + required_ioport m_sw; + + std::vector<UINT16> m_ram; +}; + + +// ======================> apricot_128k_ram_device + +class apricot_128k_ram_device : public device_t, public device_apricot_expansion_card_interface +{ +public: + // construction/destruction + apricot_128k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + +protected: + virtual ioport_constructor device_input_ports() const; + virtual void device_start(); + virtual void device_reset(); + +private: + required_ioport m_strap; + + std::vector<UINT16> m_ram; +}; + + +// ======================> apricot_512k_ram_device + +class apricot_512k_ram_device : public device_t, public device_apricot_expansion_card_interface +{ +public: + // construction/destruction + apricot_512k_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + +protected: + virtual ioport_constructor device_input_ports() const; + virtual void device_start(); + virtual void device_reset(); + +private: + required_ioport m_strap; + + std::vector<UINT16> m_ram; +}; + + +// device type definition +extern const device_type APRICOT_256K_RAM; +extern const device_type APRICOT_128K_RAM; +extern const device_type APRICOT_512K_RAM; + + +#endif // __APRICOT_RAM__ diff --git a/src/emu/bus/bml3/bml3mp1802.c b/src/emu/bus/bml3/bml3mp1802.c index af061edbab9..860d827caa3 100644 --- a/src/emu/bus/bml3/bml3mp1802.c +++ b/src/emu/bus/bml3/bml3mp1802.c @@ -23,12 +23,9 @@ const device_type BML3BUS_MP1802 = &device_creator<bml3bus_mp1802_device>; -static const floppy_interface bml3_mp1802_floppy_interface = -{ - FLOPPY_STANDARD_5_25_DSDD, - LEGACY_FLOPPY_OPTIONS_NAME(default), - NULL -}; +static SLOT_INTERFACE_START( mp1802_floppies ) + SLOT_INTERFACE("dd", FLOPPY_525_DD) +SLOT_INTERFACE_END WRITE_LINE_MEMBER( bml3bus_mp1802_device::bml3_wd17xx_intrq_w ) { @@ -46,11 +43,13 @@ ROM_START( mp1802 ) ROM_END MACHINE_CONFIG_FRAGMENT( mp1802 ) - MCFG_DEVICE_ADD("wd17xx", MB8866, 0) - MCFG_WD17XX_DEFAULT_DRIVE2_TAGS - MCFG_WD17XX_INTRQ_CALLBACK(WRITELINE(bml3bus_mp1802_device, bml3_wd17xx_intrq_w)) + MCFG_MB8866x_ADD("fdc", XTAL_1MHz) + MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(bml3bus_mp1802_device, bml3_wd17xx_intrq_w)) - MCFG_LEGACY_FLOPPY_2_DRIVES_ADD(bml3_mp1802_floppy_interface) + MCFG_FLOPPY_DRIVE_ADD("fdc:0", mp1802_floppies, "dd", floppy_image_device::default_floppy_formats) + MCFG_FLOPPY_DRIVE_ADD("fdc:1", mp1802_floppies, "dd", floppy_image_device::default_floppy_formats) + MCFG_FLOPPY_DRIVE_ADD("fdc:2", mp1802_floppies, "", floppy_image_device::default_floppy_formats) + MCFG_FLOPPY_DRIVE_ADD("fdc:3", mp1802_floppies, "", floppy_image_device::default_floppy_formats) MACHINE_CONFIG_END /*************************************************************************** @@ -78,34 +77,28 @@ const rom_entry *bml3bus_mp1802_device::device_rom_region() const READ8_MEMBER( bml3bus_mp1802_device::bml3_mp1802_r) { - return m_wd17xx->drq_r() ? 0x00 : 0x80; + return m_fdc->drq_r() ? 0x00 : 0x80; } WRITE8_MEMBER( bml3bus_mp1802_device::bml3_mp1802_w) { - int drive = data & 0x03; - int side = BIT(data, 4); - int motor = BIT(data, 3); - const char *floppy_name = NULL; - switch (drive) { - case 0: - floppy_name = FLOPPY_0; - break; - case 1: - floppy_name = FLOPPY_1; - break; - case 2: - floppy_name = FLOPPY_2; - break; - case 3: - floppy_name = FLOPPY_3; - break; + floppy_image_device *floppy = NULL; + + switch (data & 0x03) + { + case 0: floppy = m_floppy0->get_device(); break; + case 1: floppy = m_floppy1->get_device(); break; + case 2: floppy = m_floppy2->get_device(); break; + case 3: floppy = m_floppy3->get_device(); break; + } + + m_fdc->set_floppy(floppy); + + if (floppy) + { + floppy->mon_w(!BIT(data, 3)); + floppy->ss_w(BIT(data, 4)); } - legacy_floppy_image_device *floppy = subdevice<legacy_floppy_image_device>(floppy_name); - m_wd17xx->set_drive(drive); - floppy->floppy_mon_w(!motor); - floppy->floppy_drive_set_ready_state(ASSERT_LINE, 0); - m_wd17xx->set_side(side); } @@ -116,7 +109,11 @@ WRITE8_MEMBER( bml3bus_mp1802_device::bml3_mp1802_w) bml3bus_mp1802_device::bml3bus_mp1802_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, BML3BUS_MP1802, "Hitachi MP-1802 Floppy Controller Card", tag, owner, clock, "bml3mp1802", __FILE__), device_bml3bus_card_interface(mconfig, *this), - m_wd17xx(*this, "wd17xx") + m_fdc(*this, "fdc"), + m_floppy0(*this, "fdc:0"), + m_floppy1(*this, "fdc:1"), + m_floppy2(*this, "fdc:2"), + m_floppy3(*this, "fdc:3") { } @@ -134,8 +131,8 @@ void bml3bus_mp1802_device::device_start() // install into memory address_space &space_prg = machine().firstcpu->space(AS_PROGRAM); - space_prg.install_readwrite_handler(0xff00, 0xff03, read8_delegate(FUNC(mb8866_device::read),(mb8866_device*)m_wd17xx), write8_delegate(FUNC(mb8866_device::write),(mb8866_device*)m_wd17xx)); - space_prg.install_readwrite_handler(0xff04, 0xff04, read8_delegate(FUNC(bml3bus_mp1802_device::bml3_mp1802_r), this), write8_delegate(FUNC(bml3bus_mp1802_device::bml3_mp1802_w), this) ); + space_prg.install_readwrite_handler(0xff00, 0xff03, read8_delegate(FUNC(mb8866_t::read),(mb8866_t*)m_fdc), write8_delegate(FUNC(mb8866_t::write),(mb8866_t*)m_fdc)); + space_prg.install_readwrite_handler(0xff04, 0xff04, read8_delegate(FUNC(bml3bus_mp1802_device::bml3_mp1802_r), this), write8_delegate(FUNC(bml3bus_mp1802_device::bml3_mp1802_w), this)); // overwriting the main ROM (rather than using e.g. install_rom) should mean that bank switches for RAM expansion still work... UINT8 *mainrom = device().machine().root_device().memregion("maincpu")->base(); memcpy(mainrom + 0xf800, m_rom + 0xf800, 0x800); diff --git a/src/emu/bus/bml3/bml3mp1802.h b/src/emu/bus/bml3/bml3mp1802.h index 6569171a199..0c4088c0d4f 100644 --- a/src/emu/bus/bml3/bml3mp1802.h +++ b/src/emu/bus/bml3/bml3mp1802.h @@ -15,7 +15,8 @@ #include "emu.h" #include "bml3bus.h" #include "imagedev/flopdrv.h" -#include "machine/wd17xx.h" +#include "machine/wd_fdc.h" + //************************************************************************** // TYPE DEFINITIONS @@ -36,13 +37,18 @@ public: DECLARE_READ8_MEMBER(bml3_mp1802_r); DECLARE_WRITE8_MEMBER(bml3_mp1802_w); DECLARE_WRITE_LINE_MEMBER(bml3_wd17xx_intrq_w); + protected: virtual void device_start(); virtual void device_reset(); - required_device<mb8866_device> m_wd17xx; - private: + required_device<mb8866_t> m_fdc; + required_device<floppy_connector> m_floppy0; + required_device<floppy_connector> m_floppy1; + required_device<floppy_connector> m_floppy2; + required_device<floppy_connector> m_floppy3; + UINT8 *m_rom; }; diff --git a/src/emu/bus/cgenie/expansion/floppy.c b/src/emu/bus/cgenie/expansion/floppy.c index 45d7030f8cb..3221067b874 100644 --- a/src/emu/bus/cgenie/expansion/floppy.c +++ b/src/emu/bus/cgenie/expansion/floppy.c @@ -5,8 +5,6 @@ EACA Colour Genie Floppy Disc Controller TODO: - - Only native MESS .mfi files load (some sectors are marked DDM) - - FM mode disks can be formatted but don't work correctly - What's the exact FD1793 model? - How does it turn off the motor? - What's the source of the timer and the exact timings? @@ -33,11 +31,10 @@ const device_type CGENIE_FDC = &device_creator<cgenie_fdc_device>; DEVICE_ADDRESS_MAP_START( mmio, 8, cgenie_fdc_device ) AM_RANGE(0xe0, 0xe3) AM_MIRROR(0x10) AM_READWRITE(irq_r, select_w) - AM_RANGE(0xec, 0xef) AM_MIRROR(0x10) AM_DEVREAD("fd1793", fd1793_t, read) - AM_RANGE(0xec, 0xec) AM_MIRROR(0x10) AM_WRITE(command_w) - AM_RANGE(0xed, 0xed) AM_MIRROR(0x10) AM_DEVWRITE("fd1793", fd1793_t, track_w) - AM_RANGE(0xee, 0xee) AM_MIRROR(0x10) AM_DEVWRITE("fd1793", fd1793_t, sector_w) - AM_RANGE(0xef, 0xef) AM_MIRROR(0x10) AM_DEVWRITE("fd1793", fd1793_t, data_w) + AM_RANGE(0xec, 0xec) AM_MIRROR(0x10) AM_DEVREAD("fd1793", fd1793_t, status_r) AM_WRITE(command_w) + AM_RANGE(0xed, 0xed) AM_MIRROR(0x10) AM_DEVREADWRITE("fd1793", fd1793_t, track_r, track_w) + AM_RANGE(0xee, 0xee) AM_MIRROR(0x10) AM_DEVREADWRITE("fd1793", fd1793_t, sector_r, sector_w) + AM_RANGE(0xef, 0xef) AM_MIRROR(0x10) AM_DEVREADWRITE("fd1793", fd1793_t, data_r, data_w) ADDRESS_MAP_END FLOPPY_FORMATS_MEMBER( cgenie_fdc_device::floppy_formats ) diff --git a/src/emu/bus/coco/coco_fdc.c b/src/emu/bus/coco/coco_fdc.c index 49da5302b22..9be9039516d 100644 --- a/src/emu/bus/coco/coco_fdc.c +++ b/src/emu/bus/coco/coco_fdc.c @@ -73,7 +73,9 @@ #include "imagedev/flopdrv.h" #include "includes/coco.h" #include "imagedev/flopdrv.h" -#include "formats/coco_dsk.h" +#include "formats/dmk_dsk.h" +#include "formats/jvc_dsk.h" +#include "formats/vdk_dsk.h" /*************************************************************************** @@ -94,12 +96,15 @@ LOCAL VARIABLES ***************************************************************************/ -static const floppy_interface coco_floppy_interface = -{ - FLOPPY_STANDARD_5_25_DSHD, - LEGACY_FLOPPY_OPTIONS_NAME(coco), - "floppy_5_25" -}; +FLOPPY_FORMATS_MEMBER( coco_fdc_device::floppy_formats ) + FLOPPY_DMK_FORMAT, + FLOPPY_JVC_FORMAT, + FLOPPY_VDK_FORMAT +FLOPPY_FORMATS_END + +static SLOT_INTERFACE_START( coco_fdc_floppies ) + SLOT_INTERFACE("qd", FLOPPY_525_QD) +SLOT_INTERFACE_END /*************************************************************************** @@ -149,15 +154,17 @@ WRITE_LINE_MEMBER( coco_fdc_device::fdc_drq_w ) //************************************************************************** static MACHINE_CONFIG_FRAGMENT(coco_fdc) - MCFG_DEVICE_ADD(WD_TAG, WD1773, 0) - MCFG_WD17XX_DEFAULT_DRIVE4_TAGS - MCFG_WD17XX_INTRQ_CALLBACK(WRITELINE(coco_fdc_device, fdc_intrq_w)) - MCFG_WD17XX_DRQ_CALLBACK(WRITELINE(coco_fdc_device, fdc_drq_w)) + MCFG_WD1773x_ADD(WD_TAG, XTAL_8MHz) + MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(coco_fdc_device, fdc_intrq_w)) + MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(coco_fdc_device, fdc_drq_w)) + + MCFG_FLOPPY_DRIVE_ADD(WD_TAG ":0", coco_fdc_floppies, "qd", coco_fdc_device::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD(WD_TAG ":1", coco_fdc_floppies, "qd", coco_fdc_device::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD(WD_TAG ":2", coco_fdc_floppies, "", coco_fdc_device::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD(WD_TAG ":3", coco_fdc_floppies, "", coco_fdc_device::floppy_formats) MCFG_DEVICE_ADD(DISTO_TAG, MSM6242, XTAL_32_768kHz) MCFG_DS1315_ADD(CLOUD9_TAG) - - MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(coco_floppy_interface) MACHINE_CONFIG_END ROM_START( coco_fdc ) @@ -291,16 +298,17 @@ void coco_fdc_device::dskreg_w(UINT8 data) else if (data & 0x40) drive = 3; - legacy_floppy_image_device *floppy[4]; + floppy_image_device *floppy[4]; - floppy[0] = subdevice<legacy_floppy_image_device>(FLOPPY_0); - floppy[1] = subdevice<legacy_floppy_image_device>(FLOPPY_1); - floppy[2] = subdevice<legacy_floppy_image_device>(FLOPPY_2); - floppy[3] = subdevice<legacy_floppy_image_device>(FLOPPY_3); + floppy[0] = subdevice<floppy_connector>(WD_TAG ":0")->get_device(); + floppy[1] = subdevice<floppy_connector>(WD_TAG ":1")->get_device(); + floppy[2] = subdevice<floppy_connector>(WD_TAG ":2")->get_device(); + floppy[3] = subdevice<floppy_connector>(WD_TAG ":3")->get_device(); for (int i = 0; i < 4; i++) { - floppy[i]->floppy_mon_w(i == drive ? CLEAR_LINE : ASSERT_LINE); + if (floppy[i]) + floppy[i]->mon_w(i == drive ? CLEAR_LINE : ASSERT_LINE); } head = ((data & 0x40) && (drive != 3)) ? 1 : 0; @@ -309,8 +317,11 @@ void coco_fdc_device::dskreg_w(UINT8 data) update_lines(); - m_wd17xx->set_drive(drive); - m_wd17xx->set_side(head); + m_wd17xx->set_floppy(floppy[drive]); + + if (floppy[drive]) + floppy[drive]->ss_w(head); + m_wd17xx->dden_w(!BIT(m_dskreg, 5)); } @@ -379,7 +390,7 @@ WRITE8_MEMBER(coco_fdc_device::write) dskreg_w(data); break; case 8: - m_wd17xx->command_w(space, 0, data); + m_wd17xx->cmd_w(space, 0, data); break; case 9: m_wd17xx->track_w(space, 0, data); @@ -388,6 +399,7 @@ WRITE8_MEMBER(coco_fdc_device::write) m_wd17xx->sector_w(space, 0, data); break; case 11: + //printf("data w %02x\n", data); m_wd17xx->data_w(space, 0, data); break; }; @@ -413,10 +425,12 @@ WRITE8_MEMBER(coco_fdc_device::write) //************************************************************************** static MACHINE_CONFIG_FRAGMENT(dragon_fdc) - MCFG_DEVICE_ADD(WD2797_TAG, WD2797, 0) - MCFG_WD17XX_DEFAULT_DRIVE4_TAGS + MCFG_WD2797x_ADD(WD2797_TAG, XTAL_1MHz) - MCFG_LEGACY_FLOPPY_4_DRIVES_ADD(coco_floppy_interface) + MCFG_FLOPPY_DRIVE_ADD(WD2797_TAG ":0", coco_fdc_floppies, "qd", coco_fdc_device::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD(WD2797_TAG ":1", coco_fdc_floppies, "qd", coco_fdc_device::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD(WD2797_TAG ":2", coco_fdc_floppies, "", coco_fdc_device::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD(WD2797_TAG ":3", coco_fdc_floppies, "", coco_fdc_device::floppy_formats) MACHINE_CONFIG_END @@ -511,10 +525,20 @@ void dragon_fdc_device::dskreg_w(UINT8 data) data); } - if (data & 0x04) - m_wd2797->set_drive(data & 0x03); + floppy_image_device *floppy = NULL; + + switch (data & 0x03) + { + case 0: floppy = subdevice<floppy_connector>(WD2797_TAG ":0")->get_device(); break; + case 1: floppy = subdevice<floppy_connector>(WD2797_TAG ":1")->get_device(); break; + case 2: floppy = subdevice<floppy_connector>(WD2797_TAG ":2")->get_device(); break; + case 3: floppy = subdevice<floppy_connector>(WD2797_TAG ":3")->get_device(); break; + } + + m_wd2797->set_floppy(floppy); m_wd2797->dden_w(BIT(data, 3)); + m_dskreg = data; } @@ -556,12 +580,7 @@ WRITE8_MEMBER(dragon_fdc_device::write) switch(offset & 0xEF) { case 0: - m_wd2797->command_w(space, 0, data); - - /* disk head is encoded in the command byte */ - /* Only for type 3 & 4 commands */ - if (data & 0x80) - m_wd2797->set_side((data & 0x02) ? 1 : 0); + m_wd2797->cmd_w(space, 0, data); break; case 1: m_wd2797->track_w(space, 0, data); diff --git a/src/emu/bus/coco/coco_fdc.h b/src/emu/bus/coco/coco_fdc.h index 3456b00054f..8773a48bea4 100644 --- a/src/emu/bus/coco/coco_fdc.h +++ b/src/emu/bus/coco/coco_fdc.h @@ -9,7 +9,7 @@ #include "cococart.h" #include "machine/msm6242.h" #include "machine/ds1315.h" -#include "machine/wd17xx.h" +#include "machine/wd_fdc.h" //************************************************************************** @@ -37,6 +37,8 @@ public: coco_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); coco_fdc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + DECLARE_FLOPPY_FORMATS(floppy_formats); + // optional information overrides virtual machine_config_constructor device_mconfig_additions() const; virtual const rom_entry *device_rom_region() const; @@ -66,8 +68,8 @@ protected: UINT8 m_drq : 1; UINT8 m_intrq : 1; - optional_device<wd1773_device> m_wd17xx; /* WD17xx */ - optional_device<wd2797_device> m_wd2797; /* WD2797 */ + optional_device<wd1773_t> m_wd17xx; /* WD17xx */ + optional_device<wd2797_t> m_wd2797; /* WD2797 */ optional_device<ds1315_device> m_ds1315; /* DS1315 */ /* Disto RTC */ diff --git a/src/emu/bus/gameboy/gb_slot.c b/src/emu/bus/gameboy/gb_slot.c index 60c98447591..922dc91cce2 100644 --- a/src/emu/bus/gameboy/gb_slot.c +++ b/src/emu/bus/gameboy/gb_slot.c @@ -438,7 +438,7 @@ bool megaduck_cart_slot_device::call_load() void base_gb_cart_slot_device::call_unload() { - if (m_cart && m_cart->get_ram_size() && m_cart->get_has_battery()) + if (m_cart && m_cart->get_ram_base() && m_cart->get_ram_size() && m_cart->get_has_battery()) battery_save(m_cart->get_ram_base(), m_cart->get_ram_size()); } diff --git a/src/emu/bus/gameboy/mbc.c b/src/emu/bus/gameboy/mbc.c index b6f31714a3a..4c0a81459b6 100644 --- a/src/emu/bus/gameboy/mbc.c +++ b/src/emu/bus/gameboy/mbc.c @@ -368,8 +368,7 @@ WRITE8_MEMBER(gb_rom_mbc1_device::write_bank) m_ram_bank = data & 0x3; break; case 0x6000: // MBC1 Mode Register - default: - m_mode = (data & 0x1) ? MODE_4M_256k : MODE_16M_8k; + m_mode = (data & 0x1) ? MODE_4M_256k : MODE_16M_64k; break; } } @@ -399,31 +398,29 @@ WRITE8_MEMBER(gb_rom_mbc1_device::write_ram) READ8_MEMBER(gb_rom_mbc2_device::read_rom) { - if (offset < 0x4000) - return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)]; - else + if (offset & 0x4000) /* RB1 */ return m_rom[rom_bank_map[m_latch_bank2] * 0x4000 + (offset & 0x3fff)]; + else /* RB0 */ + return m_rom[rom_bank_map[m_latch_bank] * 0x4000 + (offset & 0x3fff)]; } WRITE8_MEMBER(gb_rom_mbc2_device::write_bank) { - if (offset < 0x2000) - m_ram_enable = ((data & 0x0f) == 0x0a) ? 1 : 0; - else if (offset < 0x4000) - { - // 4bits only - data &= 0x0f; - // bank = 0 => bank = 1 - if (data == 0) - data = 1; + // the mapper only has data lines D3..D0 + data &= 0x0f; - // The least significant bit of the upper address byte must be 1 - if (offset & 0x0100) - m_latch_bank2 = (m_latch_bank2 & 0x100) | data; + // the mapper only uses inputs A15..A14, A8 for register accesses + switch (offset & 0xc100) + { + case 0x0000: // RAM Enable Register + m_ram_enable = (data == 0x0a) ? 1 : 0; + break; + case 0x0100: // ROM Bank Register + m_latch_bank2 = (data == 0x00) ? 0x01 : data; + break; } } -// 1 bank only?? READ8_MEMBER(gb_rom_mbc2_device::read_ram) { if (!m_ram.empty() && m_ram_enable) diff --git a/src/emu/bus/gameboy/mbc.h b/src/emu/bus/gameboy/mbc.h index f1596cbd0a6..199501f5261 100644 --- a/src/emu/bus/gameboy/mbc.h +++ b/src/emu/bus/gameboy/mbc.h @@ -37,7 +37,7 @@ class gb_rom_mbc1_device : public gb_rom_mbc_device public: enum { - MODE_16M_8k = 0, /// 16Mbit ROM, 8kBit RAM + MODE_16M_64k = 0, /// 16Mbit ROM, 64kBit RAM MODE_4M_256k = 1, /// 4Mbit ROM, 256kBit RAM }; @@ -47,7 +47,7 @@ public: // device-level overrides virtual void device_start() { shared_start(); save_item(NAME(m_mode)); }; - virtual void device_reset() { shared_reset(); m_mode = MODE_16M_8k; }; + virtual void device_reset() { shared_reset(); m_mode = MODE_16M_64k; }; virtual void set_additional_wirings(UINT8 mask, int shift) { m_mask = mask; m_shift = shift; } // these get set at cart loading virtual DECLARE_READ8_MEMBER(read_rom); diff --git a/src/emu/bus/isa/gblaster.c b/src/emu/bus/isa/gblaster.c index 7cfe3a9b42b..9966f2353dd 100644 --- a/src/emu/bus/isa/gblaster.c +++ b/src/emu/bus/isa/gblaster.c @@ -35,8 +35,8 @@ WRITE8_MEMBER( isa8_gblaster_device::saa1099_1_16_w ) { switch(offset) { - case 0 : m_saa1099_1->control_w( space, offset, data ); break; - case 1 : m_saa1099_1->data_w( space, offset, data ); break; + case 0 : m_saa1099_1->data_w( space, offset, data ); break; + case 1 : m_saa1099_1->control_w( space, offset, data ); break; } } @@ -44,8 +44,29 @@ WRITE8_MEMBER( isa8_gblaster_device::saa1099_2_16_w ) { switch(offset) { - case 0 : m_saa1099_2->control_w( space, offset, data ); break; - case 1 : m_saa1099_2->data_w( space, offset, data ); break; + case 0 : m_saa1099_2->data_w( space, offset, data ); break; + case 1 : m_saa1099_2->control_w( space, offset, data ); break; + } +} + +READ8_MEMBER( isa8_gblaster_device::detect_r ) +{ + switch(offset) + { + case 0: + case 1: return 0x7f; break; // this register reportedly returns 0x3f on a Tandy 1000 TL, and 0x7f on a generic 486 PC. + case 6: + case 7: return detect_reg; break; + default: return 0xff; + } +} + +WRITE8_MEMBER( isa8_gblaster_device::detect_w ) +{ + switch(offset) + { + case 2: + case 3: detect_reg = (data & 0xff); break; } } @@ -77,7 +98,8 @@ isa8_gblaster_device::isa8_gblaster_device(const machine_config &mconfig, const device_t(mconfig, ISA8_GAME_BLASTER, "Game Blaster Sound Card", tag, owner, clock, "isa_gblaster", __FILE__), device_isa8_card_interface(mconfig, *this), m_saa1099_1(*this, "saa1099.1"), - m_saa1099_2(*this, "saa1099.2") + m_saa1099_2(*this, "saa1099.2"), + detect_reg(0xFF) { } @@ -90,6 +112,7 @@ void isa8_gblaster_device::device_start() set_isa_device(); m_isa->install_device(0x0220, 0x0221, 0, 0, read8_delegate( FUNC(isa8_gblaster_device::saa1099_16_r), this ), write8_delegate( FUNC(isa8_gblaster_device::saa1099_1_16_w), this ) ); m_isa->install_device(0x0222, 0x0223, 0, 0, read8_delegate( FUNC(isa8_gblaster_device::saa1099_16_r), this ), write8_delegate( FUNC(isa8_gblaster_device::saa1099_2_16_w), this ) ); + m_isa->install_device(0x0224, 0x022F, 0, 0, read8_delegate( FUNC(isa8_gblaster_device::detect_r), this ), write8_delegate( FUNC(isa8_gblaster_device::detect_w), this ) ); } //------------------------------------------------- diff --git a/src/emu/bus/isa/gblaster.h b/src/emu/bus/isa/gblaster.h index 2388f5bbd36..b2625e98975 100644 --- a/src/emu/bus/isa/gblaster.h +++ b/src/emu/bus/isa/gblaster.h @@ -29,6 +29,8 @@ public: DECLARE_READ8_MEMBER(saa1099_16_r); DECLARE_WRITE8_MEMBER(saa1099_1_16_w); DECLARE_WRITE8_MEMBER(saa1099_2_16_w); + DECLARE_READ8_MEMBER(detect_r); + DECLARE_WRITE8_MEMBER(detect_w); protected: // device-level overrides virtual void device_start(); @@ -37,6 +39,7 @@ private: // internal state required_device<saa1099_device> m_saa1099_1; required_device<saa1099_device> m_saa1099_2; + UINT8 detect_reg; }; diff --git a/src/emu/bus/isa/hdc.c b/src/emu/bus/isa/hdc.c index 594cd686cb2..0740130df29 100644 --- a/src/emu/bus/isa/hdc.c +++ b/src/emu/bus/isa/hdc.c @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Miodrag Milanovic +// copyright-holders:Wilbert Pol /********************************************************************** ISA 8 bit XT Hard Disk Controller diff --git a/src/emu/bus/isa/hdc.h b/src/emu/bus/isa/hdc.h index e8c6f68ce52..3d3890da8ea 100644 --- a/src/emu/bus/isa/hdc.h +++ b/src/emu/bus/isa/hdc.h @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Miodrag Milanovic +// copyright-holders:Wilbert Pol /********************************************************************** ISA 8 bit XT Hard Disk Controller diff --git a/src/emu/bus/isa/sblaster.c b/src/emu/bus/isa/sblaster.c index b37067a2923..d04d5bf8bc1 100644 --- a/src/emu/bus/isa/sblaster.c +++ b/src/emu/bus/isa/sblaster.c @@ -29,6 +29,7 @@ pro audio spectrum 16: 1 OPL3 2 x saa1099 chips + inherited from game blaster also on sound blaster 1.0 option on sound blaster 1.5 @@ -150,8 +151,8 @@ WRITE8_MEMBER( isa8_sblaster1_0_device::saa1099_1_16_w ) { switch(offset) { - case 0 : m_saa1099_1->control_w( space, offset, data ); break; - case 1 : m_saa1099_1->data_w( space, offset, data ); break; + case 0 : m_saa1099_1->data_w( space, offset, data ); break; + case 1 : m_saa1099_1->control_w( space, offset, data ); break; } } @@ -159,8 +160,8 @@ WRITE8_MEMBER( isa8_sblaster1_0_device::saa1099_2_16_w ) { switch(offset) { - case 0 : m_saa1099_2->control_w( space, offset, data ); break; - case 1 : m_saa1099_2->data_w( space, offset, data ); break; + case 0 : m_saa1099_2->data_w( space, offset, data ); break; + case 1 : m_saa1099_2->control_w( space, offset, data ); break; } } diff --git a/src/emu/bus/kc/d004.h b/src/emu/bus/kc/d004.h index 6f120ecfe71..79f45cba03a 100644 --- a/src/emu/bus/kc/d004.h +++ b/src/emu/bus/kc/d004.h @@ -11,7 +11,6 @@ #include "cpu/z80/z80.h" #include "machine/upd765.h" #include "machine/ataintf.h" -#include "formats/basicdsk.h" #include "imagedev/harddriv.h" diff --git a/src/emu/bus/megadrive/md_slot.c b/src/emu/bus/megadrive/md_slot.c index b53419b5528..af40c089d5a 100644 --- a/src/emu/bus/megadrive/md_slot.c +++ b/src/emu/bus/megadrive/md_slot.c @@ -552,7 +552,7 @@ int base_md_cart_slot_device::load_nonlist() void base_md_cart_slot_device::call_unload() { - if (m_cart && m_cart->get_nvram_size()) + if (m_cart && m_cart->get_nvram_base() && m_cart->get_nvram_size()) battery_save(m_cart->get_nvram_base(), m_cart->get_nvram_size()); } diff --git a/src/emu/bus/megadrive/svp.c b/src/emu/bus/megadrive/svp.c index 51921dbe5ac..324c5302a33 100644 --- a/src/emu/bus/megadrive/svp.c +++ b/src/emu/bus/megadrive/svp.c @@ -1,4 +1,4 @@ -// license:BSD-3-Clause +// license:??? // copyright-holders:Fabio Priuli,Pierpaolo Prazzoli,Grazvydas Ignotas /****************************************** SVP related *****************************************/ diff --git a/src/emu/bus/megadrive/svp.h b/src/emu/bus/megadrive/svp.h index dbacd98b1ba..0f128240a86 100644 --- a/src/emu/bus/megadrive/svp.h +++ b/src/emu/bus/megadrive/svp.h @@ -1,4 +1,4 @@ -// license:BSD-3-Clause +// license:??? // copyright-holders:Fabio Priuli,Pierpaolo Prazzoli,Grazvydas Ignotas #ifndef __MD_SVP_H #define __MD_SVP_H diff --git a/src/emu/bus/nubus/nubus_image.c b/src/emu/bus/nubus/nubus_image.c index 4a49cdac04c..d002a3badca 100644 --- a/src/emu/bus/nubus/nubus_image.c +++ b/src/emu/bus/nubus/nubus_image.c @@ -215,6 +215,8 @@ void nubus_image_device::device_start() filectx.curdir[0] = '.'; filectx.curdir[1] = '\0'; + filectx.dirp = NULL; + filectx.fd = NULL; } //------------------------------------------------- @@ -280,7 +282,7 @@ WRITE32_MEMBER( nubus_image_device::file_cmd_w ) strcpy((char*)filectx.filename, (char*)filectx.curdir); break; case kFileCmdSetDir: - if(filectx.filename[0] == '/') { + if ((filectx.filename[0] == '/') || (filectx.filename[0] == '$')) { strcpy((char*)filectx.curdir, (char*)filectx.filename); } else { strcat((char*)filectx.curdir, "/"); @@ -291,10 +293,15 @@ WRITE32_MEMBER( nubus_image_device::file_cmd_w ) if(filectx.dirp) osd_closedir(filectx.dirp); filectx.dirp = osd_opendir((const char *)filectx.curdir); case kFileCmdGetNextListing: - dp = osd_readdir(filectx.dirp); - if(dp) { - strncpy((char*)filectx.filename, dp->name, sizeof(filectx.filename)); - } else { + if (filectx.dirp) { + dp = osd_readdir(filectx.dirp); + if(dp) { + strncpy((char*)filectx.filename, dp->name, sizeof(filectx.filename)); + } else { + memset(filectx.filename, 0, sizeof(filectx.filename)); + } + } + else { memset(filectx.filename, 0, sizeof(filectx.filename)); } break; diff --git a/src/emu/bus/sega8/sega8_slot.c b/src/emu/bus/sega8/sega8_slot.c index 0aa73d2c6c2..92c80af2c61 100644 --- a/src/emu/bus/sega8/sega8_slot.c +++ b/src/emu/bus/sega8/sega8_slot.c @@ -410,7 +410,7 @@ bool sega8_cart_slot_device::call_load() void sega8_cart_slot_device::call_unload() { - if (m_cart && m_cart->get_ram_size() && m_cart->get_has_battery()) + if (m_cart && m_cart->get_ram_base() && m_cart->get_ram_size() && m_cart->get_has_battery()) battery_save(m_cart->get_ram_base(), m_cart->get_ram_size()); } diff --git a/src/emu/bus/ti99_peb/bwg.c b/src/emu/bus/ti99_peb/bwg.c index c4776777da0..2ae171b9423 100644 --- a/src/emu/bus/ti99_peb/bwg.c +++ b/src/emu/bus/ti99_peb/bwg.c @@ -31,7 +31,7 @@ Known issues (Feb 2014): - 1. The BwG controller cannot run with the Geneve or other non-9900 computers. + - The BwG controller cannot run with the Geneve or other non-9900 computers. The reason for that is the wait state logic. It assumes that when executing MOVB @>5FF6,*R2, first a value from 5FF7 is attempted to be read, just as the TI console does. In that case, wait states are inserted if @@ -39,12 +39,6 @@ only and therefore circumvent the wait state generation. This is in fact not an emulation glitch but the behavior of the real expansion card. - Resolved issues (Feb 2014): - - 1. The BwG controller failed to read single-density disks. This only occurs - with the legacy implementation because the modern floppy implementation - reproduces the correct recording format on the medium, so the controller - actually detects FM or MFM. *******************************************************************************/ @@ -704,498 +698,3 @@ const rom_entry *snug_bwg_device::device_rom_region() const } const device_type TI99_BWG = &device_creator<snug_bwg_device>; - -// ========================================================================== - -#define FDCLEG_TAG "wd1773" - -/* - Legacy implementation -*/ -snug_bwg_legacy_device::snug_bwg_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : ti_expansion_card_device(mconfig, TI99_BWG_LEG, "SNUG BwG Floppy Controller LEGACY", tag, owner, clock, "ti99_bwg_leg", __FILE__), - m_wd1773(*this, FDCLEG_TAG), - m_clock(*this, CLOCK_TAG) { } - -/* - Callback called at the end of DVENA pulse -*/ -void snug_bwg_legacy_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - m_DVENA = CLEAR_LINE; - set_ready_line(); -} - - -/* - Operate the wait state logic. -*/ -void snug_bwg_legacy_device::set_ready_line() -{ - // This is the wait state logic - if (TRACE_SIGNALS) logerror("bwg: address=%04x, DRQ=%d, INTRQ=%d, MOTOR=%d\n", m_address & 0xffff, m_DRQ, m_IRQ, m_DVENA); - line_state nready = (m_dataregLB && // Are we accessing 5ff7 - m_WAITena && // and the wait state generation is active (SBO 2) - (m_DRQ==CLEAR_LINE) && // and we are waiting for a byte - (m_IRQ==CLEAR_LINE) && // and there is no interrupt yet - (m_DVENA==ASSERT_LINE) // and the motor is turning? - )? ASSERT_LINE : CLEAR_LINE; // In that case, clear READY and thus trigger wait states - - if (TRACE_READY) if (nready==ASSERT_LINE) logerror("bwg: READY line = %d\n", (nready==CLEAR_LINE)? 1:0); - m_slot->set_ready((nready==CLEAR_LINE)? ASSERT_LINE : CLEAR_LINE); -} - -/* - Callback, called from the controller chip whenever DRQ/IRQ state change -*/ -WRITE_LINE_MEMBER( snug_bwg_legacy_device::intrq_w ) -{ - if (TRACE_SIGNALS) logerror("bwg: set intrq = %d\n", state); - m_IRQ = (line_state)state; - - // Note that INTB is actually not used in the TI-99 family. But the - // controller asserts the line nevertheless, probably intended for - // use in another planned TI system - m_slot->set_intb(state==ASSERT_LINE); - - // We need to explicitly set the READY line to release the datamux - set_ready_line(); -} - -WRITE_LINE_MEMBER( snug_bwg_legacy_device::drq_w ) -{ - if (TRACE_SIGNALS) logerror("bwg: set drq = %d\n", state); - m_DRQ = (line_state)state; - - // We need to explicitly set the READY line to release the datamux - set_ready_line(); -} - -SETADDRESS_DBIN_MEMBER( snug_bwg_legacy_device::setaddress_dbin ) -{ - // Selection login in the PAL and some circuits on the board - - // Is the card being selected? - m_address = offset; - m_inDsrArea = ((m_address & m_select_mask)==m_select_value); - - if (!m_inDsrArea) return; - - if (TRACE_ADDRESS) logerror("bwg: set address = %04x\n", offset & 0xffff); - - // Is the WD chip on the card being selected? - // We need the even and odd addresses for the wait state generation, - // but only the even addresses when we access it - m_WDsel0 = m_inDsrArea && !m_rtc_enabled - && ((state==ASSERT_LINE && ((m_address & 0x1ff8)==0x1ff0)) // read - || (state==CLEAR_LINE && ((m_address & 0x1ff8)==0x1ff8))); // write - - m_WDsel = m_WDsel0 && ((m_address & 1)==0); - - // Is the RTC selected on the card? (even addr) - m_RTCsel = m_inDsrArea && m_rtc_enabled && ((m_address & 0x1fe1)==0x1fe0); - - // RTC disabled: - // 5c00 - 5fef: RAM - // 5ff0 - 5fff: Controller (f0 = status, f2 = track, f4 = sector, f6 = data) - - // RTC enabled: - // 5c00 - 5fdf: RAM - // 5fe0 - 5fff: Clock (even addr) - - // Is RAM selected? We just check for the last 1K and let the RTC or WD - // just take control before - m_lastK = m_inDsrArea && ((m_address & 0x1c00)==0x1c00); - - // Is the data register port of the WD being selected? - // In fact, the address to read the data from is 5FF6, but the TI-99 datamux - // fetches both bytes from 5FF7 and 5FF6, the odd one first. The BwG uses - // the odd address to operate the READY line - m_dataregLB = m_WDsel0 && ((m_address & 0x07)==0x07); - - // Clear or assert the outgoing READY line - set_ready_line(); -} - -/* - Read a byte from ROM, RAM, FDC, or RTC. See setaddress_dbin for selection - logic. -*/ -READ8Z_MEMBER(snug_bwg_legacy_device::readz) -{ - if (m_inDsrArea && m_selected) - { - // 010x xxxx xxxx xxxx - if (m_lastK) - { - // ...1 11xx xxxx xxxx - if (m_rtc_enabled) - { - if (m_RTCsel) - { - // .... ..11 111x xxx0 - if (!space.debugger_access()) *value = m_clock->read(space, (m_address & 0x001e) >> 1); - if (TRACE_RW) logerror("bwg: read RTC: %04x -> %02x\n", m_address & 0xffff, *value); - } - else - { - *value = m_buffer_ram[(m_ram_page<<10) | (m_address & 0x03ff)]; - if (TRACE_RW) logerror("bwg: read ram: %04x (page %d)-> %02x\n", m_address & 0xffff, m_ram_page, *value); - } - } - else - { - if (m_WDsel) - { - // .... ..11 1111 0xx0 - // Note that the value is inverted again on the board, - // so we can drop the inversion - if (!space.debugger_access()) *value = m_wd1773->read(space, (m_address >> 1)&0x03); - if (TRACE_RW) logerror("bwg: read FDC: %04x -> %02x\n", m_address & 0xffff, *value); - if (TRACE_DATA) - { - if ((m_address & 0xffff)==0x5ff6) logerror("%02x ", *value); - else logerror("\n%04x: %02x", m_address&0xffff, *value); - } - } - else - { - *value = m_buffer_ram[(m_ram_page<<10) | (m_address & 0x03ff)]; - if (TRACE_RW) logerror("bwg: read ram: %04x (page %d)-> %02x\n", m_address & 0xffff, m_ram_page, *value); - } - } - } - else - { - *value = m_dsrrom[(m_rom_page<<13) | (m_address & 0x1fff)]; - if (TRACE_RW) logerror("bwg: read dsr: %04x (page %d)-> %02x\n", m_address & 0xffff, m_rom_page, *value); - } - } -} - -/* - Resets the drive geometry. This is required because the heuristic of - the default implementation sets the drive geometry to the geometry - of the medium. -*/ -void snug_bwg_legacy_device::set_geometry(legacy_floppy_image_device *drive, floppy_type_t type) -{ - // This assertion may fail when the names of the floppy devices change. - // Unfortunately, the wd17xx device assumes the floppy drives at root - // level, so we use an explicitly qualified tag. See peribox.h. - assert(drive != NULL); - drive->floppy_drive_set_geometry(type); -} - -void snug_bwg_legacy_device::set_all_geometries(floppy_type_t type) -{ - set_geometry(machine().device<legacy_floppy_image_device>(PFLOPPY_0), type); - set_geometry(machine().device<legacy_floppy_image_device>(PFLOPPY_1), type); - set_geometry(machine().device<legacy_floppy_image_device>(PFLOPPY_2), type); -} - -/* - Write a byte - 4000 - 5bff: ROM, ignore write (4 banks) - - rtc disabled: - 5c00 - 5fef: RAM - 5ff0 - 5fff: Controller (f8 = command, fa = track, fc = sector, fe = data) - - rtc enabled: - 5c00 - 5fdf: RAM - 5fe0 - 5fff: Clock (even addr) -*/ -WRITE8_MEMBER(snug_bwg_legacy_device::write) -{ - if (m_inDsrArea && m_selected) - { - if (m_lastK) - { - if (m_rtc_enabled) - { - if (m_RTCsel) - { - // .... ..11 111x xxx0 - if (TRACE_RW) logerror("bwg: write RTC: %04x <- %02x\n", m_address & 0xffff, data); - if (!space.debugger_access()) m_clock->write(space, (m_address & 0x001e) >> 1, data); - } - else - { - if (TRACE_RW) logerror("bwg: write ram: %04x (page %d) <- %02x\n", m_address & 0xffff, m_ram_page, data); - m_buffer_ram[(m_ram_page<<10) | (m_address & 0x03ff)] = data; - } - } - else - { - if (m_WDsel) - { - // .... ..11 1111 1xx0 - // Note that the value is inverted again on the board, - // so we can drop the inversion - if (TRACE_RW) logerror("bwg: write FDC: %04x <- %02x\n", m_address & 0xffff, data); - if (!space.debugger_access()) m_wd1773->write(space, (m_address >> 1)&0x03, data); - } - else - { - if (TRACE_RW) logerror("bwg: write ram: %04x (page %d) <- %02x\n", m_address & 0xffff, m_ram_page, data); - m_buffer_ram[(m_ram_page<<10) | (m_address & 0x03ff)] = data; - } - } - } - } -} - -/* - CRU read handler. *=inverted. - bit 0: DSK4 connected* - bit 1: DSK1 connected* - bit 2: DSK2 connected* - bit 3: DSK3 connected* - bit 4: Dip 1 - bit 5: Dip 2 - bit 6: Dip 3 - bit 7: Dip 4 -*/ -READ8Z_MEMBER(snug_bwg_legacy_device::crureadz) -{ - UINT8 reply = 0; - - if ((offset & 0xff00)==m_cru_base) - { - if ((offset & 0x00ff)==0) - { - // Assume that we have 4 drives connected - // If we want to do that properly, we need to check the actually - // available drives (not the images!). But why should we connect less? - reply = 0x00; - - // DIP switches. Note that a closed switch means 0 - // xx01 1111 11 = only dsk1; 10 = 1+2, 01=1/2/3, 00=1-4 - - if (m_dip1 != 0) reply |= 0x10; - if (m_dip2 != 0) reply |= 0x20; - reply |= (m_dip34 << 6); - *value = ~reply; - } - else - *value = 0; - if (TRACE_CRU) logerror("bwg: Read CRU = %02x\n", *value); - } -} - -WRITE8_MEMBER(snug_bwg_legacy_device::cruwrite) -{ - int drive, drivebit; - - if ((offset & 0xff00)==m_cru_base) - { - int bit = (offset >> 1) & 0x0f; - switch (bit) - { - case 0: - /* (De)select the card. Indicated by a LED on the board. */ - m_selected = (data != 0); - if (TRACE_CRU) logerror("bwg: Map DSR (bit 0) = %d\n", m_selected); - break; - - case 1: - /* Activate motor */ - if (data && !m_strobe_motor) - { /* on rising edge, set motor_running for 4.23s */ - if (TRACE_CRU) logerror("bwg: trigger motor (bit 1)\n"); - m_DVENA = ASSERT_LINE; - m_motor_on_timer->adjust(attotime::from_msec(4230)); - } - m_strobe_motor = (data != 0); - break; - - case 2: - /* Set disk ready/hold (bit 2) */ - // 0: ignore IRQ and DRQ - // 1: TMS9900 is stopped until IRQ or DRQ are set - // OR the motor stops rotating - rotates for 4.23s after write - // to CRU bit 1 - if (TRACE_CRU) logerror("bwg: arm wait state logic (bit 2) = %d\n", data); - m_WAITena = (data != 0); - break; - - case 4: - case 5: - case 6: - case 8: - /* Select drive 0-2 (DSK1-DSK3) (bits 4-6) */ - /* Select drive 3 (DSK4) (bit 8) */ - drive = (bit == 8) ? 3 : (bit - 4); /* drive # (0-3) */ - if (TRACE_CRU) logerror("bwg: set drive (bit %d) = %d\n", bit, data); - drivebit = 1<<drive; - - if (data != 0) - { - if ((m_DSEL & drivebit) == 0) /* select drive */ - { - if (m_DSEL != 0) - logerror("bwg: Multiple drives selected, %02x\n", m_DSEL); - m_DSEL |= drivebit; - m_wd1773->set_drive(drive); - } - } - else - m_DSEL &= ~drivebit; - break; - - case 7: - /* Select side of disk (bit 7) */ - m_SIDE = data; - if (TRACE_CRU) logerror("bwg: set side (bit 7) = %d\n", data); - m_wd1773->set_side(m_SIDE); - break; - - case 10: - /* double density enable (active low) */ - if (TRACE_CRU) logerror("bwg: set double density (bit 10) = %d\n", data); - m_wd1773->dden_w((data != 0) ? ASSERT_LINE : CLEAR_LINE); - break; - - case 11: - /* EPROM A13 */ - if (data != 0) - m_rom_page |= 1; - else - m_rom_page &= 0xfe; // 11111110 - if (TRACE_CRU) logerror("bwg: set ROM page (bit 11) = %d, page = %d\n", bit, m_rom_page); - break; - - case 13: - /* RAM A10 */ - m_ram_page = data; - if (TRACE_CRU) logerror("bwg: set RAM page (bit 13) = %d, page = %d\n", bit, m_ram_page); - break; - - case 14: - /* Override FDC with RTC (active high) */ - if (TRACE_CRU) logerror("bwg: turn on RTC (bit 14) = %d\n", data); - m_rtc_enabled = (data != 0); - break; - - case 15: - /* EPROM A14 */ - if (data != 0) - m_rom_page |= 2; - else - m_rom_page &= 0xfd; // 11111101 - if (TRACE_CRU) logerror("bwg: set ROM page (bit 15) = %d, page = %d\n", bit, m_rom_page); - break; - - case 3: - if (TRACE_CRU) logerror("bwg: set head load (bit 3) = %d\n", data); - break; - case 9: - case 12: - /* Unused (bit 3, 9 & 12) */ - if (TRACE_CRU) logerror("bwg: set unknown bit %d = %d\n", bit, data); - break; - } - } -} - -void snug_bwg_legacy_device::device_start(void) -{ - logerror("bwg: BWG start\n"); - m_dsrrom = memregion(DSRROM)->base(); - m_buffer_ram = memregion(BUFFER)->base(); - m_motor_on_timer = timer_alloc(MOTOR_TIMER); - m_cru_base = 0x1100; -} - -void snug_bwg_legacy_device::device_reset() -{ - logerror("bwg: BWG reset\n"); - - if (m_genmod) - { - m_select_mask = 0x1fe000; - m_select_value = 0x174000; - } - else - { - m_select_mask = 0x7e000; - m_select_value = 0x74000; - } - - m_strobe_motor = false; - m_DVENA = CLEAR_LINE; - m_DSEL = 0; - m_SIDE = 0; - ti99_set_80_track_drives(FALSE); - floppy_type_t type = FLOPPY_STANDARD_5_25_DSDD_40; - set_all_geometries(type); - m_DRQ = CLEAR_LINE; - m_IRQ = CLEAR_LINE; - m_WAITena = false; - m_rtc_enabled = false; - m_selected = false; - m_dataregLB = false; - m_inDsrArea = false; - - m_dip1 = ioport("BWGDIP1")->read(); - m_dip2 = ioport("BWGDIP2")->read(); - m_dip34 = ioport("BWGDIP34")->read(); - - m_rom_page = 0; - m_ram_page = 0; -} - -INPUT_PORTS_START( bwg_fdc_legacy ) - PORT_START( "BWGDIP1" ) - PORT_DIPNAME( 0x01, 0x00, "BwG step rate" ) - PORT_DIPSETTING( 0x00, "6 ms") - PORT_DIPSETTING( 0x01, "20 ms") - - PORT_START( "BWGDIP2" ) - PORT_DIPNAME( 0x01, 0x00, "BwG date/time display" ) - PORT_DIPSETTING( 0x00, "Hide") - PORT_DIPSETTING( 0x01, "Show") - - PORT_START( "BWGDIP34" ) - PORT_DIPNAME( 0x03, 0x03, "BwG drives" ) - PORT_DIPSETTING( 0x00, "DSK1 only") - PORT_DIPSETTING( 0x01, "DSK1-DSK2") - PORT_DIPSETTING( 0x02, "DSK1-DSK3") - PORT_DIPSETTING( 0x03, "DSK1-DSK4") -INPUT_PORTS_END - -MACHINE_CONFIG_FRAGMENT( bwg_fdc_legacy ) - MCFG_DEVICE_ADD(FDCLEG_TAG, WD1773, 0) - MCFG_WD17XX_DEFAULT_DRIVE4_TAGS - MCFG_WD17XX_INTRQ_CALLBACK(WRITELINE(snug_bwg_legacy_device, intrq_w)) - MCFG_WD17XX_DRQ_CALLBACK(WRITELINE(snug_bwg_legacy_device, drq_w)) - - MCFG_DEVICE_ADD(CLOCK_TAG, MM58274C, 0) - MCFG_MM58274C_MODE24(1) // 24 hour - MCFG_MM58274C_DAY1(0) // sunday -MACHINE_CONFIG_END - -ROM_START( bwg_fdc_legacy ) - ROM_REGION(0x8000, DSRROM, 0) - ROM_LOAD("bwg.bin", 0x0000, 0x8000, CRC(06f1ec89) SHA1(6ad77033ed268f986d9a5439e65f7d391c4b7651)) /* BwG disk DSR ROM */ - ROM_REGION(0x0800, BUFFER, 0) /* BwG RAM buffer */ - ROM_FILL(0x0000, 0x0400, 0x00) -ROM_END - -machine_config_constructor snug_bwg_legacy_device::device_mconfig_additions() const -{ - return MACHINE_CONFIG_NAME( bwg_fdc_legacy ); -} - -const rom_entry *snug_bwg_legacy_device::device_rom_region() const -{ - return ROM_NAME( bwg_fdc_legacy ); -} - -ioport_constructor snug_bwg_legacy_device::device_input_ports() const -{ - return INPUT_PORTS_NAME( bwg_fdc_legacy ); -} - -const device_type TI99_BWG_LEG = &device_creator<snug_bwg_legacy_device>; diff --git a/src/emu/bus/ti99_peb/bwg.h b/src/emu/bus/ti99_peb/bwg.h index 28e2f2f6dc6..a1012e06257 100644 --- a/src/emu/bus/ti99_peb/bwg.h +++ b/src/emu/bus/ti99_peb/bwg.h @@ -20,9 +20,6 @@ extern const device_type TI99_BWG; -/* - Implementation for modern floppy system. -*/ class snug_bwg_device : public ti_expansion_card_device { public: @@ -142,109 +139,4 @@ private: // Debugging bool m_debug_dataout; }; - -// ========================================================================= - -/* - Legacy implementation. -*/ - -#include "machine/wd17xx.h" - -extern const device_type TI99_BWG_LEG; - -class snug_bwg_legacy_device : public ti_expansion_card_device -{ -public: - snug_bwg_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - DECLARE_READ8Z_MEMBER(readz); - DECLARE_WRITE8_MEMBER(write); - DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin); - - DECLARE_WRITE_LINE_MEMBER( intrq_w ); - DECLARE_WRITE_LINE_MEMBER( drq_w ); - - DECLARE_READ8Z_MEMBER(crureadz); - DECLARE_WRITE8_MEMBER(cruwrite); - -protected: - virtual void device_start(void); - virtual void device_reset(void); - virtual const rom_entry *device_rom_region() const; - virtual machine_config_constructor device_mconfig_additions() const; - virtual ioport_constructor device_input_ports() const; - -private: - void set_ready_line(); - void set_all_geometries(floppy_type_t type); - void set_geometry(legacy_floppy_image_device *drive, floppy_type_t type); - virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); - - // Holds the status of the DRQ and IRQ lines. - line_state m_DRQ, m_IRQ; - - // DIP switch state - int m_dip1, m_dip2, m_dip34; - - // Page selection for ROM and RAM - int m_ram_page; // 0-1 - int m_rom_page; // 0-3 - - // When true, the READY line will be cleared (create wait states) when - // waiting for data from the controller. - bool m_WAITena; - - // Address in card area - bool m_inDsrArea; - - // WD selected - bool m_WDsel, m_WDsel0; - - // RTC selected - bool m_RTCsel; - - // last 1K area selected - bool m_lastK; - - // Data register +1 selected - bool m_dataregLB; - - /* Indicates whether the clock is mapped into the address space. */ - bool m_rtc_enabled; - - /* When TRUE, keeps DVENA high. */ - bool m_strobe_motor; - - // Signal DVENA. When TRUE, makes some drive turning. - line_state m_DVENA; - - // Recent address - int m_address; - - /* Indicates which drive has been selected. Values are 0, 1, 2, and 4. */ - // 000 = no drive - // 001 = drive 1 - // 010 = drive 2 - // 100 = drive 3 - int m_DSEL; - - /* Signal SIDSEL. 0 or 1, indicates the selected head. */ - int m_SIDE; - - // Link to the WD1773 controller on the board. - required_device<wd1773_device> m_wd1773; - - // Link to the real-time clock on the board. - required_device<mm58274c_device> m_clock; - - // count 4.23s from rising edge of motor_on - emu_timer* m_motor_on_timer; - - // DSR ROM - UINT8* m_dsrrom; - - // Buffer RAM - UINT8* m_buffer_ram; -}; - #endif diff --git a/src/emu/bus/ti99_peb/hfdc.c b/src/emu/bus/ti99_peb/hfdc.c index e67172342ac..5d4f84795d1 100644 --- a/src/emu/bus/ti99_peb/hfdc.c +++ b/src/emu/bus/ti99_peb/hfdc.c @@ -74,12 +74,12 @@ #define CLK_ADDR 0x0fe0 #define RAM_ADDR 0x1000 -#define TRACE_EMU 1 +#define TRACE_EMU 0 #define TRACE_CRU 0 #define TRACE_COMP 0 #define TRACE_RAM 0 #define TRACE_ROM 0 -#define TRACE_LINES 1 +#define TRACE_LINES 0 #define TRACE_MOTOR 0 #define TRACE_DMA 0 #define TRACE_INT 0 @@ -510,17 +510,27 @@ void myarc_hfdc_device::floppy_index_callback(floppy_image_device *floppy, int s */ void myarc_hfdc_device::harddisk_index_callback(mfm_harddisk_device *harddisk, int state) { - /* if (TRACE_LINES) */ if (state==1) logerror("%s: HD index pulse\n", tag()); + if (TRACE_LINES) if (state==1) logerror("%s: HD index pulse\n", tag()); set_bits(m_status_latch, HDC_DS_INDEX, (state==ASSERT_LINE)); signal_drive_status(); } /* + This is called back from the hard disk when READY becomes asserted. +*/ +void myarc_hfdc_device::harddisk_ready_callback(mfm_harddisk_device *harddisk, int state) +{ + if (TRACE_LINES) logerror("%s: HD READY = %d\n", tag(), state); + set_bits(m_status_latch, HDC_DS_READY, (state==ASSERT_LINE)); + signal_drive_status(); +} + +/* This is called back from the hard disk when seek_complete becomes asserted. */ void myarc_hfdc_device::harddisk_skcom_callback(mfm_harddisk_device *harddisk, int state) { - /* if (TRACE_LINES) */ if (state==1) logerror("%s: HD seek complete\n", tag()); + if (TRACE_LINES) logerror("%s: HD seek complete = %d\n", tag(), state); set_bits(m_status_latch, HDC_DS_SKCOM, (state==ASSERT_LINE)); signal_drive_status(); } @@ -674,6 +684,7 @@ WRITE8_MEMBER( myarc_hfdc_device::auxbus_out ) // Dir = 0 -> outward m_current_harddisk->direction_in_w((data & 0x20)? ASSERT_LINE : CLEAR_LINE); m_current_harddisk->step_w((data & 0x10)? ASSERT_LINE : CLEAR_LINE); + m_current_harddisk->headsel_w(data & 0x0f); } // We are pushing the drive status after OUTPUT2 @@ -728,6 +739,7 @@ void myarc_hfdc_device::connect_harddisk_unit(int index) if (m_current_harddisk != NULL) { m_current_harddisk->setup_index_pulse_cb(mfm_harddisk_device::index_pulse_cb(FUNC(myarc_hfdc_device::harddisk_index_callback), this)); + m_current_harddisk->setup_ready_cb(mfm_harddisk_device::ready_cb(FUNC(myarc_hfdc_device::harddisk_ready_callback), this)); m_current_harddisk->setup_seek_complete_cb(mfm_harddisk_device::seek_complete_cb(FUNC(myarc_hfdc_device::harddisk_skcom_callback), this)); } else @@ -993,8 +1005,8 @@ static SLOT_INTERFACE_START( hfdc_floppies ) SLOT_INTERFACE_END static SLOT_INTERFACE_START( hfdc_harddisks ) - SLOT_INTERFACE( "generic", MFM_HD_GENERIC ) // Generic high-level emulation -// SLOT_INTERFACE( "seagatemfm", MFM_HD_SEAGATE ) // Seagate ST-225 and others + SLOT_INTERFACE( "generic", MFMHD_GENERIC ) // Generic high-level emulation + SLOT_INTERFACE( "st225", MFMHD_ST225 ) // Seagate ST-225 and others SLOT_INTERFACE_END MACHINE_CONFIG_FRAGMENT( ti99_hfdc ) @@ -1012,9 +1024,9 @@ MACHINE_CONFIG_FRAGMENT( ti99_hfdc ) MCFG_FLOPPY_DRIVE_ADD("f4", hfdc_floppies, NULL, myarc_hfdc_device::floppy_formats) // NB: Hard disks don't go without image (other than floppy drives) - MCFG_MFM_HARDDISK_ADD("h1", hfdc_harddisks, NULL) - MCFG_MFM_HARDDISK_ADD("h2", hfdc_harddisks, NULL) - MCFG_MFM_HARDDISK_ADD("h3", hfdc_harddisks, NULL) + MCFG_MFM_HARDDISK_CONN_ADD("h1", hfdc_harddisks, NULL, MFM_BYTE, 3000, 20) + MCFG_MFM_HARDDISK_CONN_ADD("h2", hfdc_harddisks, NULL, MFM_BYTE, 2000, 20) + MCFG_MFM_HARDDISK_CONN_ADD("h3", hfdc_harddisks, NULL, MFM_BYTE, 2000, 20) MCFG_DEVICE_ADD(CLOCK_TAG, MM58274C, 0) MCFG_MM58274C_MODE24(1) // 24 hour @@ -1046,27 +1058,6 @@ ioport_constructor myarc_hfdc_device::device_input_ports() const const device_type TI99_HFDC = &device_creator<myarc_hfdc_device>; -mfm_harddisk_connector::mfm_harddisk_connector(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock): - device_t(mconfig, MFM_HD_CONNECTOR, "MFM hard disk connector", tag, owner, clock, "mfm_hd_connector", __FILE__), - device_slot_interface(mconfig, *this) -{ -} - -mfm_harddisk_connector::~mfm_harddisk_connector() -{ -} - -mfm_harddisk_device *mfm_harddisk_connector::get_device() -{ - return dynamic_cast<mfm_harddisk_device *>(get_card_device()); -} - -void mfm_harddisk_connector::device_start() -{ -} - -const device_type MFM_HD_CONNECTOR = &device_creator<mfm_harddisk_connector>; - // ========================================================================= /* diff --git a/src/emu/bus/ti99_peb/hfdc.h b/src/emu/bus/ti99_peb/hfdc.h index f7d7e9053b5..19e7d0fc321 100644 --- a/src/emu/bus/ti99_peb/hfdc.h +++ b/src/emu/bus/ti99_peb/hfdc.h @@ -69,6 +69,7 @@ private: // Callbacks for the index hole and seek complete void floppy_index_callback(floppy_image_device *floppy, int state); void harddisk_index_callback(mfm_harddisk_device *harddisk, int state); + void harddisk_ready_callback(mfm_harddisk_device *harddisk, int state); void harddisk_skcom_callback(mfm_harddisk_device *harddisk, int state); // Operate the floppy motors @@ -182,26 +183,6 @@ private: int m_readyflags; }; -/* Connector for a MFM hard disk. See also floppy.c */ -class mfm_harddisk_connector : public device_t, - public device_slot_interface -{ -public: - mfm_harddisk_connector(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - ~mfm_harddisk_connector(); - - mfm_harddisk_device *get_device(); - -protected: - void device_start(); -}; - -extern const device_type MFM_HD_CONNECTOR; - -#define MCFG_MFM_HARDDISK_ADD(_tag, _slot_intf, _def_slot) \ - MCFG_DEVICE_ADD(_tag, MFM_HD_CONNECTOR, 0) \ - MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false); - // ========================================================================= /* diff --git a/src/emu/bus/ti99_peb/peribox.c b/src/emu/bus/ti99_peb/peribox.c index 800acc9121f..c55fe82152c 100644 --- a/src/emu/bus/ti99_peb/peribox.c +++ b/src/emu/bus/ti99_peb/peribox.c @@ -431,16 +431,13 @@ SLOT_INTERFACE_END SLOT_INTERFACE_START( peribox_slot7 ) SLOT_INTERFACE("ide", TI99_IDE) SLOT_INTERFACE("usbsm", TI99_USBSM) - SLOT_INTERFACE("bwgleg", TI99_BWG_LEG) SLOT_INTERFACE("bwg", TI99_BWG) SLOT_INTERFACE("hfdc", TI99_HFDC_LEG) SLOT_INTERFACE("hfdcnew", TI99_HFDC) SLOT_INTERFACE_END SLOT_INTERFACE_START( peribox_slot8 ) - SLOT_INTERFACE("tifdcleg", TI99_FDC_LEG) SLOT_INTERFACE("tifdc", TI99_FDC) - SLOT_INTERFACE("bwgleg", TI99_BWG_LEG) SLOT_INTERFACE("bwg", TI99_BWG) SLOT_INTERFACE("hfdc", TI99_HFDC_LEG) SLOT_INTERFACE("hfdcnew", TI99_HFDC) @@ -497,7 +494,6 @@ SLOT_INTERFACE_START( peribox_slot7nobwg ) SLOT_INTERFACE_END SLOT_INTERFACE_START( peribox_slot8nobwg ) - SLOT_INTERFACE("tifdcleg", TI99_FDC_LEG) SLOT_INTERFACE("tifdc", TI99_FDC) SLOT_INTERFACE("hfdc", TI99_HFDC_LEG) SLOT_INTERFACE("hfdcnew", TI99_HFDC) diff --git a/src/emu/bus/ti99_peb/ti_fdc.c b/src/emu/bus/ti99_peb/ti_fdc.c index 44062149051..fe9d6133108 100644 --- a/src/emu/bus/ti99_peb/ti_fdc.c +++ b/src/emu/bus/ti99_peb/ti_fdc.c @@ -427,313 +427,3 @@ const rom_entry *ti_fdc_device::device_rom_region() const } const device_type TI99_FDC = &device_creator<ti_fdc_device>; -//=========================================================================== - -/*********************************************** - - Legacy implementation, to be removed - -***********************************************/ - -#define TI_FDCLEG_TAG "ti_dssd_controller_legacy" -#define FDCLEG_TAG "wd1771" - -ti_fdc_legacy_device::ti_fdc_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : ti_expansion_card_device(mconfig, TI99_FDC_LEG, "TI-99 Standard DSSD Floppy Controller LEGACY", tag, owner, clock, "ti99_fdc_leg", __FILE__), - m_fd1771(*this, FDCLEG_TAG) { } - -/* - callback called at the end of DVENA pulse -*/ -void ti_fdc_legacy_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - m_DVENA = CLEAR_LINE; - if (TRACE_MOTOR) logerror("tifdc: Motor off\n"); - set_ready_line(); -} - -/* - Operate the wait state logic. -*/ -void ti_fdc_legacy_device::set_ready_line() -{ - // This is the wait state logic - if (TRACE_SIGNALS) logerror("tifdc: address=%04x, DRQ=%d, INTRQ=%d, MOTOR=%d\n", m_address & 0xffff, m_DRQ, m_IRQ, m_DVENA); - line_state nready = (m_WDsel && // Are we accessing 5ffx (even addr)? - m_WAITena && // and the wait state generation is active (SBO 2) - (m_DRQ==CLEAR_LINE) && // and we are waiting for a byte - (m_IRQ==CLEAR_LINE) && // and there is no interrupt yet - (m_DVENA==ASSERT_LINE) // and the motor is turning? - )? ASSERT_LINE : CLEAR_LINE; // In that case, clear READY and thus trigger wait states - - if (TRACE_READY) logerror("tifdc: READY line = %d\n", (nready==CLEAR_LINE)? 1:0); - m_slot->set_ready((nready==CLEAR_LINE)? ASSERT_LINE : CLEAR_LINE); -} - -SETADDRESS_DBIN_MEMBER( ti_fdc_legacy_device::setaddress_dbin ) -{ - // Selection login in the PAL and some circuits on the board - - // Is the card being selected? - m_address = offset; - m_inDsrArea = ((m_address & m_select_mask)==m_select_value); - - if (!m_inDsrArea) return; - - if (TRACE_ADDRESS) logerror("tifdc: set address = %04x\n", offset & 0xffff); - - // Is the WD chip on the card being selected? - m_WDsel = m_inDsrArea && ((m_address & 0x1ff1)==0x1ff0); - - // Clear or assert the outgoing READY line - set_ready_line(); -} - -READ8Z_MEMBER(ti_fdc_legacy_device::readz) -{ - if (m_inDsrArea && m_selected) - { - // only use the even addresses from 1ff0 to 1ff6. - // Note that data is inverted. - // 0101 1111 1111 0xx0 - UINT8 reply = 0; - - if (m_WDsel && ((m_address & 9)==0)) - { - if (!space.debugger_access()) reply = m_fd1771->read(space, (offset >> 1)&0x03); - if (TRACE_DATA) - { - if ((m_address & 0xffff)==0x5ff6) logerror("%02x ", ~reply & 0xff); - else logerror("\n%04x: %02x", m_address&0xffff, ~reply & 0xff); - } - } - else - { - reply = m_dsrrom[m_address & 0x1fff]; - } - *value = reply; - if (TRACE_RW) logerror("ti_fdc: %04x -> %02x\n", offset & 0xffff, *value); - } -} - -WRITE8_MEMBER(ti_fdc_legacy_device::write) -{ - if (m_inDsrArea && m_selected) - { - if (TRACE_RW) logerror("ti_fdc: %04x <- %02x\n", offset & 0xffff, ~data & 0xff); - // only use the even addresses from 1ff8 to 1ffe. - // Note that data is inverted. - // 0101 1111 1111 1xx0 - if (m_WDsel && ((m_address & 9)==8)) - { - if (!space.debugger_access()) m_fd1771->write(space, (offset >> 1)&0x03, data); - } - } -} - -/* - The CRU read handler. - bit 0: HLD pin - bit 1-3: drive n active - bit 4: 0: motor strobe on - bit 5: always 0 - bit 6: always 1 - bit 7: selected side -*/ -READ8Z_MEMBER(ti_fdc_legacy_device::crureadz) -{ - if ((offset & 0xff00)==m_cru_base) - { - int addr = offset & 0x07; - UINT8 reply = 0; - if (addr == 0) - { - // deliver bits 0-7 - // TODO: HLD pin - // The DVENA state is returned inverted - if (m_DVENA==ASSERT_LINE) reply |= ((m_DSEL)<<1); - else reply |= 0x10; - reply |= 0x40; - if (m_SIDSEL) reply |= 0x80; - } - *value = reply; - if (TRACE_CRU) logerror("tifdc: Read CRU = %02x\n", *value); - } -} - -WRITE8_MEMBER(ti_fdc_legacy_device::cruwrite) -{ - int drive, drivebit; - - if ((offset & 0xff00)==m_cru_base) - { - int bit = (offset >> 1) & 0x07; - switch (bit) - { - case 0: - /* (De)select the card. Indicated by a LED on the board. */ - m_selected = (data!=0); - if (TRACE_CRU) logerror("tifdc: Map DSR (bit 0) = %d\n", m_selected); - break; - case 1: - /* Activate motor */ - if (data==1 && m_lastval==0) - { /* on rising edge, set motor_running for 4.23s */ - if (TRACE_CRU) logerror("tifdc: trigger motor (bit 1)\n"); - m_DVENA = ASSERT_LINE; - if (TRACE_MOTOR) logerror("tifdc: motor on\n"); - set_ready_line(); - m_motor_on_timer->adjust(attotime::from_msec(4230)); - } - m_lastval = data; - break; - - case 2: - /* Set disk ready/hold (bit 2) */ - // 0: ignore IRQ and DRQ - // 1: TMS9900 is stopped until IRQ or DRQ are set - // OR the motor stops rotating - rotates for 4.23s after write - // to CRU bit 1 - m_WAITena = (data != 0); - if (TRACE_CRU) logerror("tifdc: arm wait state logic (bit 2) = %d\n", data); - break; - - case 3: - /* Load disk heads (HLT pin) (bit 3). Not implemented. */ - if (TRACE_CRU) logerror("tifdc: set head load (bit 3) = %d\n", data); - break; - - case 4: - case 5: - case 6: - /* Select drive X (bits 4-6) */ - drive = bit-4; /* drive # (0-2) */ - if (TRACE_CRU) logerror("tifdc: set drive (bit %d) = %d\n", bit, data); - drivebit = 1<<drive; - - if (data != 0) - { - if ((m_DSEL & drivebit) == 0) /* select drive */ - { - if (m_DSEL != 0) - logerror("tifdc: Multiple drives selected, %02x\n", m_DSEL); - m_DSEL |= drivebit; - m_fd1771->set_drive(drive); - } - } - else - m_DSEL &= ~drivebit; - break; - - case 7: - /* Select side of disk (bit 7) */ - m_SIDSEL = data; - if (TRACE_CRU) logerror("tifdc: set side (bit 7) = %d\n", data); - m_fd1771->set_side(data); - break; - } - } -} - -/* - Resets the drive geometry. This is required because the heuristic of - the default implementation sets the drive geometry to the geometry - of the medium. -*/ -void ti_fdc_legacy_device::set_geometry(legacy_floppy_image_device *drive, floppy_type_t type) -{ - // This assertion may fail when the names of the floppy devices change. - // Unfortunately, the wd17xx device assumes the floppy drives at root - // level, so we use an explicitly qualified tag. See peribox.h. - assert (drive!=NULL); - drive->floppy_drive_set_geometry(type); -} - -void ti_fdc_legacy_device::set_all_geometries(floppy_type_t type) -{ - set_geometry(machine().device<legacy_floppy_image_device>(PFLOPPY_0), type); - set_geometry(machine().device<legacy_floppy_image_device>(PFLOPPY_1), type); - set_geometry(machine().device<legacy_floppy_image_device>(PFLOPPY_2), type); -} - -/* - Callback, called from the controller chip whenever DRQ/IRQ state change -*/ -WRITE_LINE_MEMBER( ti_fdc_legacy_device::intrq_w ) -{ - if (TRACE_SIGNALS) logerror("ti_fdc: set irq = %d\n", state); - m_IRQ = (line_state)state; - // Note that INTB is actually not used in the TI-99 family. But the - // controller asserts the line nevertheless, probably intended for - // use in another planned TI system - m_slot->set_intb(state); - set_ready_line(); -} - -WRITE_LINE_MEMBER( ti_fdc_legacy_device::drq_w ) -{ - if (TRACE_SIGNALS) logerror("ti_fdc: set drq = %d\n", state); - m_DRQ = (line_state)state; - set_ready_line(); -} - -void ti_fdc_legacy_device::device_start(void) -{ - logerror("ti_fdc: TI FDC (legacy) start\n"); - m_dsrrom = memregion(DSRROM)->base(); - m_motor_on_timer = timer_alloc(MOTOR_TIMER); - m_cru_base = 0x1100; -} - -void ti_fdc_legacy_device::device_reset(void) -{ - logerror("ti_fdc: TI FDC (legacy) reset\n"); - m_DSEL = 0; - m_SIDSEL = 0; - m_DVENA = CLEAR_LINE; - m_lastval = 0; - if (m_genmod) - { - m_select_mask = 0x1fe000; - m_select_value = 0x174000; - } - else - { - m_select_mask = 0x7e000; - m_select_value = 0x74000; - } - m_DRQ = CLEAR_LINE; - m_IRQ = CLEAR_LINE; - m_WAITena = false; - m_selected = false; - m_inDsrArea = false; - m_WDsel = false; - - ti99_set_80_track_drives(FALSE); - floppy_type_t type = FLOPPY_STANDARD_5_25_DSDD_40; - set_all_geometries(type); -} - -MACHINE_CONFIG_FRAGMENT( ti_fdc_legacy ) - MCFG_DEVICE_ADD(FDCLEG_TAG, FD1771, 0) - MCFG_WD17XX_DRIVE_TAGS(PFLOPPY_0, PFLOPPY_1, PFLOPPY_2, NULL) - MCFG_WD17XX_INTRQ_CALLBACK(WRITELINE(ti_fdc_legacy_device, intrq_w)) - MCFG_WD17XX_DRQ_CALLBACK(WRITELINE(ti_fdc_legacy_device, drq_w)) -MACHINE_CONFIG_END - -ROM_START( ti_fdc_legacy ) - ROM_REGION(0x2000, DSRROM, 0) - ROM_LOAD("disk.bin", 0x0000, 0x2000, CRC(8f7df93f) SHA1(ed91d48c1eaa8ca37d5055bcf67127ea51c4cad5)) /* TI disk DSR ROM */ -ROM_END - -machine_config_constructor ti_fdc_legacy_device::device_mconfig_additions() const -{ - return MACHINE_CONFIG_NAME( ti_fdc_legacy ); -} - -const rom_entry *ti_fdc_legacy_device::device_rom_region() const -{ - return ROM_NAME( ti_fdc_legacy ); -} - -const device_type TI99_FDC_LEG = &device_creator<ti_fdc_legacy_device>; diff --git a/src/emu/bus/ti99_peb/ti_fdc.h b/src/emu/bus/ti99_peb/ti_fdc.h index 10a2f1cf737..9fedb1c2590 100644 --- a/src/emu/bus/ti99_peb/ti_fdc.h +++ b/src/emu/bus/ti99_peb/ti_fdc.h @@ -108,85 +108,4 @@ private: // Debugging bool m_debug_dataout; }; - -//=========================================================================== - -/*********************************************** - - Legacy implementation - -***********************************************/ - -#include "machine/wd17xx.h" -#include "imagedev/flopdrv.h" - -extern const device_type TI99_FDC_LEG; - -class ti_fdc_legacy_device : public ti_expansion_card_device -{ -public: - ti_fdc_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - DECLARE_READ8Z_MEMBER(readz); - DECLARE_WRITE8_MEMBER(write); - DECLARE_SETADDRESS_DBIN_MEMBER(setaddress_dbin); - - DECLARE_WRITE_LINE_MEMBER( intrq_w ); - DECLARE_WRITE_LINE_MEMBER( drq_w ); - - DECLARE_READ8Z_MEMBER(crureadz); - DECLARE_WRITE8_MEMBER(cruwrite); - -protected: - virtual void device_start(void); - virtual void device_reset(void); - virtual const rom_entry *device_rom_region() const; - virtual machine_config_constructor device_mconfig_additions() const; - virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); - -private: - void set_ready_line(); - void set_all_geometries(floppy_type_t type); - void set_geometry(legacy_floppy_image_device *drive, floppy_type_t type); - - // Recent address - int m_address; - - // Holds the status of the DRQ and IRQ lines. - line_state m_DRQ, m_IRQ; - - // Needed for triggering the motor monoflop - UINT8 m_lastval; - - // Signal DVENA. When TRUE, makes some drive turning. - line_state m_DVENA; - - // When TRUE the CPU is halted while DRQ/IRQ are true. - bool m_WAITena; - - // WD chip selected - bool m_WDsel; - - // Set when address is in card area - bool m_inDsrArea; - - // Indicates which drive has been selected. Values are 0, 1, 2, and 4. - // 000 = no drive - // 001 = drive 1 - // 010 = drive 2 - // 100 = drive 3 - int m_DSEL; - - // Signal SIDSEL. 0 or 1, indicates the selected head. - int m_SIDSEL; - - // count 4.23s from rising edge of motor_on - emu_timer* m_motor_on_timer; - - // Link to the FDC1771 controller on the board. - required_device<fd1771_device> m_fd1771; - - // DSR ROM - UINT8* m_dsrrom; -}; - #endif diff --git a/src/emu/bus/vboy/slot.c b/src/emu/bus/vboy/slot.c index 0cbbb618419..da00aeaca04 100644 --- a/src/emu/bus/vboy/slot.c +++ b/src/emu/bus/vboy/slot.c @@ -213,7 +213,7 @@ bool vboy_cart_slot_device::call_load() void vboy_cart_slot_device::call_unload() { - if (m_cart && m_cart->get_eeprom_size()) + if (m_cart && m_cart->get_eeprom_base() && m_cart->get_eeprom_size()) battery_save(m_cart->get_eeprom_base(), m_cart->get_eeprom_size() * 4); } diff --git a/src/emu/bus/vtech/memexp/floppy.c b/src/emu/bus/vtech/memexp/floppy.c index dccba3f09b5..ef169703035 100644 --- a/src/emu/bus/vtech/memexp/floppy.c +++ b/src/emu/bus/vtech/memexp/floppy.c @@ -1,5 +1,5 @@ // license:GPL-2.0+ -// copyright-holders:Dirk Best +// copyright-holders:Dirk Best, Olivier Galibert /*************************************************************************** VTech Laser/VZ Floppy Controller Cartridge @@ -10,7 +10,7 @@ ***************************************************************************/ #include "floppy.h" -#include "formats/vtech1_dsk.h" + //************************************************************************** // DEVICE DEFINITIONS @@ -44,18 +44,14 @@ const rom_entry *floppy_controller_device::device_rom_region() const // machine configurations //------------------------------------------------- -FLOPPY_FORMATS_MEMBER( floppy_controller_device::floppy_formats ) - FLOPPY_MFI_FORMAT -FLOPPY_FORMATS_END - static SLOT_INTERFACE_START( laser_floppies ) - SLOT_INTERFACE( "525", FLOPPY_525_SSSD ) + SLOT_INTERFACE("525", FLOPPY_525_SSSD) SLOT_INTERFACE_END static MACHINE_CONFIG_FRAGMENT( floppy_controller ) MCFG_MEMEXP_SLOT_ADD("mem") - MCFG_FLOPPY_DRIVE_ADD("0", laser_floppies, "525", floppy_controller_device::floppy_formats) - MCFG_FLOPPY_DRIVE_ADD("1", laser_floppies, "525", floppy_controller_device::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD("0", laser_floppies, "525", floppy_image_device::default_floppy_formats) + MCFG_FLOPPY_DRIVE_ADD("1", laser_floppies, "525", floppy_image_device::default_floppy_formats) MACHINE_CONFIG_END machine_config_constructor floppy_controller_device::device_mconfig_additions() const diff --git a/src/emu/bus/vtech/memexp/floppy.h b/src/emu/bus/vtech/memexp/floppy.h index 940c6abc2ea..91c332332c1 100644 --- a/src/emu/bus/vtech/memexp/floppy.h +++ b/src/emu/bus/vtech/memexp/floppy.h @@ -1,5 +1,5 @@ // license:GPL-2.0+ -// copyright-holders:Dirk Best +// copyright-holders:Dirk Best, Olivier Galibert /*************************************************************************** VTech Laser/VZ Floppy Controller Cartridge @@ -38,8 +38,6 @@ public: DECLARE_READ8_MEMBER(rd_r); DECLARE_READ8_MEMBER(wpt_r); - DECLARE_FLOPPY_FORMATS( floppy_formats ); - protected: virtual const rom_entry *device_rom_region() const; virtual machine_config_constructor device_mconfig_additions() const; diff --git a/src/emu/bus/wswan/slot.c b/src/emu/bus/wswan/slot.c index 6e22ab1b40b..8da5f6e694d 100644 --- a/src/emu/bus/wswan/slot.c +++ b/src/emu/bus/wswan/slot.c @@ -232,7 +232,7 @@ bool ws_cart_slot_device::call_load() void ws_cart_slot_device::call_unload() { - if (m_cart && m_cart->get_nvram_size()) + if (m_cart && m_cart->get_nvram_base() && m_cart->get_nvram_size()) battery_save(m_cart->get_nvram_base(), m_cart->get_nvram_size()); } diff --git a/src/emu/cheat.c b/src/emu/cheat.c index fc19df4e83c..c5cce57604b 100644 --- a/src/emu/cheat.c +++ b/src/emu/cheat.c @@ -1134,25 +1134,30 @@ void cheat_manager::reload() m_lastline = 0; m_disabled = false; - // load the cheat file, MESS will load a crc32.xml ( eg. 01234567.xml ) - // and MAME will load gamename.xml + // load the cheat file, if it's a system that has a software list then try softlist_name/shortname.xml first, + // if it fails to load then try to load via crc32 - basename/crc32.xml ( eg. 01234567.xml ) image_interface_iterator iter(machine().root_device()); for (device_image_interface *image = iter.first(); image != NULL; image = iter.next()) if (image->exists()) { - // if we are loading through software lists, try to load shortname.xml + // if we are loading through a software list, try to load softlist_name/shortname.xml + // this allows the coexistence of arcade cheats with cheats for home conversions which + // have the same shortname if (image->software_entry() != NULL) { - load_cheats(image->basename()); + std::string filename; + strprintf(filename, "%s%s%s", image->software_list_name(), PATH_SEPARATOR, image->basename()); + load_cheats(filename.c_str()); break; } + // else we are loading outside the software list, try to load machine_basename/crc32.xml else { UINT32 crc = image->crc(); if (crc != 0) { std::string filename; - strprintf(filename,"%08X", crc); + strprintf(filename, "%s%s%08X", machine().basename(), PATH_SEPARATOR, crc); load_cheats(filename.c_str()); break; } diff --git a/src/emu/clifront.c b/src/emu/clifront.c index 094353041cc..f031a84ec0f 100644 --- a/src/emu/clifront.c +++ b/src/emu/clifront.c @@ -110,6 +110,8 @@ int cli_frontend::execute(int argc, char **argv) std::string option_errors; m_options.parse_command_line(argc, argv, option_errors); + m_options.parse_standard_inis(option_errors); + if (*(m_options.software_name()) != 0) { const game_driver *system = m_options.system(); @@ -175,7 +177,6 @@ int cli_frontend::execute(int argc, char **argv) } } - m_options.parse_standard_inis(option_errors); // parse the command line, adding any system-specific options if (!m_options.parse_command_line(argc, argv, option_errors)) { diff --git a/src/emu/cpu/alto2/a2roms.h b/src/emu/cpu/alto2/a2roms.h index f1ffba032da..abd218344c9 100644 --- a/src/emu/cpu/alto2/a2roms.h +++ b/src/emu/cpu/alto2/a2roms.h @@ -30,7 +30,7 @@ typedef struct { } prom_load_t; #define ZERO 0 -#define KEEP ~0 +#define KEEP ~0U #define AMAP_DEFAULT {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} #define AMAP_CONST_PROM {3,2,1,4,5,6,7,0,} diff --git a/src/emu/cpu/apexc/apexc.c b/src/emu/cpu/apexc/apexc.c index 7a982e01f53..77e5c919f44 100644 --- a/src/emu/cpu/apexc/apexc.c +++ b/src/emu/cpu/apexc/apexc.c @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Raphael Nabet /* cpu/apexc/apexc.c: APE(X)C CPU emulation diff --git a/src/emu/cpu/apexc/apexc.h b/src/emu/cpu/apexc/apexc.h index 98ebc825f35..538d903ab44 100644 --- a/src/emu/cpu/apexc/apexc.h +++ b/src/emu/cpu/apexc/apexc.h @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Raphael Nabet /* register names for apexc_get_reg & apexc_set_reg */ #pragma once diff --git a/src/emu/cpu/apexc/apexcdsm.c b/src/emu/cpu/apexc/apexcdsm.c index c79359c7025..81effc58b0e 100644 --- a/src/emu/cpu/apexc/apexcdsm.c +++ b/src/emu/cpu/apexc/apexcdsm.c @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Raphael Nabet /* cpu/apexc/apexcsm.c : APE(X)C CPU disassembler diff --git a/src/emu/cpu/arm7/arm7.c b/src/emu/cpu/arm7/arm7.c index b030275602b..65125f265f6 100644 --- a/src/emu/cpu/arm7/arm7.c +++ b/src/emu/cpu/arm7/arm7.c @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Steve Ellenoff,R. Belmont,Ryan Holtz /***************************************************************************** * @@ -8,18 +8,6 @@ * Copyright Steve Ellenoff, all rights reserved. * Thumb, DSP, and MMU support and many bugfixes by R. Belmont and Ryan Holtz. * - * - This source code is released as freeware for non-commercial purposes. - * - You are free to use and redistribute this code in modified or - * unmodified form, provided you list me in the credits. - * - If you modify this source code, you must add a notice to each modified - * source file that it has been changed. If you're a nice person, you - * will clearly mark each change too. :) - * - If you wish to use this for commercial purposes, please contact me at - * sellenoff@hotmail.com - * - The author of this copywritten work reserves the right to change the - * terms of its usage and license at any time, including retroactively - * - This entire notice must remain in the source code. - * * This work is based on: * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999' * #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76) diff --git a/src/emu/cpu/arm7/arm7.h b/src/emu/cpu/arm7/arm7.h index cb444cf69e4..9b98151494f 100644 --- a/src/emu/cpu/arm7/arm7.h +++ b/src/emu/cpu/arm7/arm7.h @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Steve Ellenoff,R. Belmont,Ryan Holtz /***************************************************************************** * @@ -7,18 +7,6 @@ * * Copyright Steve Ellenoff, all rights reserved. * - * - This source code is released as freeware for non-commercial purposes. - * - You are free to use and redistribute this code in modified or - * unmodified form, provided you list me in the credits. - * - If you modify this source code, you must add a notice to each modified - * source file that it has been changed. If you're a nice person, you - * will clearly mark each change too. :) - * - If you wish to use this for commercial purposes, please contact me at - * sellenoff@hotmail.com - * - The author of this copywritten work reserves the right to change the - * terms of its usage and license at any time, including retroactively - * - This entire notice must remain in the source code. - * * This work is based on: * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999' * #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76) diff --git a/src/emu/cpu/arm7/arm7core.h b/src/emu/cpu/arm7/arm7core.h index ba75a0ddf01..0883bae8291 100644 --- a/src/emu/cpu/arm7/arm7core.h +++ b/src/emu/cpu/arm7/arm7core.h @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Steve Ellenoff,R. Belmont,Ryan Holtz /***************************************************************************** * @@ -7,18 +7,6 @@ * * Copyright Steve Ellenoff, all rights reserved. * - * - This source code is released as freeware for non-commercial purposes. - * - You are free to use and redistribute this code in modified or - * unmodified form, provided you list me in the credits. - * - If you modify this source code, you must add a notice to each modified - * source file that it has been changed. If you're a nice person, you - * will clearly mark each change too. :) - * - If you wish to use this for commercial purposes, please contact me at - * sellenoff@hotmail.com - * - The author of this copywritten work reserves the right to change the - * terms of its usage and license at any time, including retroactively - * - This entire notice must remain in the source code. - * * This work is based on: * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999' * #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76) diff --git a/src/emu/cpu/arm7/arm7core.inc b/src/emu/cpu/arm7/arm7core.inc index 51abd756b1f..736d42b0262 100644 --- a/src/emu/cpu/arm7/arm7core.inc +++ b/src/emu/cpu/arm7/arm7core.inc @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Steve Ellenoff,R. Belmont,Ryan Holtz /***************************************************************************** * @@ -7,18 +7,6 @@ * * Copyright Steve Ellenoff, all rights reserved. * - * - This source code is released as freeware for non-commercial purposes. - * - You are free to use and redistribute this code in modified or - * unmodified form, provided you list me in the credits. - * - If you modify this source code, you must add a notice to each modified - * source file that it has been changed. If you're a nice person, you - * will clearly mark each change too. :) - * - If you wish to use this for commercial purposes, please contact me at - * sellenoff@hotmail.com - * - The author of this copywritten work reserves the right to change the - * terms of its usage and license at any time, including retroactively - * - This entire notice must remain in the source code. - * * This work is based on: * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999' * #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76) diff --git a/src/emu/cpu/arm7/arm7dasm.c b/src/emu/cpu/arm7/arm7dasm.c index 50bcae74a1e..b749d3624a2 100644 --- a/src/emu/cpu/arm7/arm7dasm.c +++ b/src/emu/cpu/arm7/arm7dasm.c @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Steve Ellenoff,R. Belmont,Ryan Holtz /***************************************************************************** * @@ -7,18 +7,6 @@ * * Copyright Steve Ellenoff, all rights reserved. * - * - This source code is released as freeware for non-commercial purposes. - * - You are free to use and redistribute this code in modified or - * unmodified form, provided you list me in the credits. - * - If you modify this source code, you must add a notice to each modified - * source file that it has been changed. If you're a nice person, you - * will clearly mark each change too. :) - * - If you wish to use this for commercial purposes, please contact me at - * sellenoff@hotmail.com - * - The author of this copywritten work reserves the right to change the - * terms of its usage and license at any time, including retroactively - * - This entire notice must remain in the source code. - * * This work is based on: * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999' * #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76) diff --git a/src/emu/cpu/arm7/arm7drc.inc b/src/emu/cpu/arm7/arm7drc.inc index 61b004c457e..fc97e35da1f 100644 --- a/src/emu/cpu/arm7/arm7drc.inc +++ b/src/emu/cpu/arm7/arm7drc.inc @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Steve Ellenoff,R. Belmont,Ryan Holtz /***************************************************************************** * @@ -9,18 +9,6 @@ * Thumb, DSP, and MMU support and many bugfixes by R. Belmont and Ryan Holtz. * Dyanmic Recompiler (DRC) / Just In Time Compiler (JIT) by Ryan Holtz. * - * - This source code is released as freeware for non-commercial purposes. - * - You are free to use and redistribute this code in modified or - * unmodified form, provided you list me in the credits. - * - If you modify this source code, you must add a notice to each modified - * source file that it has been changed. If you're a nice person, you - * will clearly mark each change too. :) - * - If you wish to use this for commercial purposes, please contact me at - * sellenoff@hotmail.com - * - The author of this copywritten work reserves the right to change the - * terms of its usage and license at any time, including retroactively - * - This entire notice must remain in the source code. - * * This work is based on: * #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999' * #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76) diff --git a/src/emu/cpu/arm7/arm7help.h b/src/emu/cpu/arm7/arm7help.h index 307da0e44ef..5625318b942 100644 --- a/src/emu/cpu/arm7/arm7help.h +++ b/src/emu/cpu/arm7/arm7help.h @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Steve Ellenoff,R. Belmont,Ryan Holtz /* ARM7 core helper Macros / Functions */ diff --git a/src/emu/cpu/arm7/arm7ops.c b/src/emu/cpu/arm7/arm7ops.c index 151299e1e98..9b96ca9054c 100644 --- a/src/emu/cpu/arm7/arm7ops.c +++ b/src/emu/cpu/arm7/arm7ops.c @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Steve Ellenoff,R. Belmont,Ryan Holtz #include "emu.h" #include "arm7.h" diff --git a/src/emu/cpu/arm7/arm7tdrc.inc b/src/emu/cpu/arm7/arm7tdrc.inc index e9847a97642..ee0573a32e7 100644 --- a/src/emu/cpu/arm7/arm7tdrc.inc +++ b/src/emu/cpu/arm7/arm7tdrc.inc @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Steve Ellenoff,R. Belmont,Ryan Holtz #include "emu.h" #include "arm7core.h" diff --git a/src/emu/cpu/arm7/arm7thmb.c b/src/emu/cpu/arm7/arm7thmb.c index 5e67464d284..3dfd46094aa 100644 --- a/src/emu/cpu/arm7/arm7thmb.c +++ b/src/emu/cpu/arm7/arm7thmb.c @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Steve Ellenoff,R. Belmont,Ryan Holtz #include "emu.h" #include "arm7.h" diff --git a/src/emu/cpu/cp1610/cp1610.c b/src/emu/cpu/cp1610/cp1610.c index 1dc911adf5e..1279a2cdd91 100644 --- a/src/emu/cpu/cp1610/cp1610.c +++ b/src/emu/cpu/cp1610/cp1610.c @@ -7,16 +7,6 @@ * * Copyright Frank Palazzolo, all rights reserved. * - * - This source code is released as freeware for non-commercial purposes. - * - You are free to use and redistribute this code in modified or - * unmodified form, provided you list me in the credits. - * - If you modify this source code, you must add a notice to each modified - * source file that it has been changed. If you're a nice person, you - * will clearly mark each change too. :) - * - If you wish to use this for commercial purposes, please contact me at - * palazzol@comcast.net - * - This entire notice must remain in the source code. - * * This work is based on Juergen Buchmueller's F8 emulation, * and the 'General Instruments CP1610' data sheets. * Special thanks to Joe Zbiciak for his GPL'd CP1610 emulator diff --git a/src/emu/cpu/cp1610/cp1610.h b/src/emu/cpu/cp1610/cp1610.h index 1b2e8657892..670fb0deac8 100644 --- a/src/emu/cpu/cp1610/cp1610.h +++ b/src/emu/cpu/cp1610/cp1610.h @@ -7,16 +7,6 @@ * * Copyright Frank Palazzolo, all rights reserved. * - * - This source code is released as freeware for non-commercial purposes. - * - You are free to use and redistribute this code in modified or - * unmodified form, provided you list me in the credits. - * - If you modify this source code, you must add a notice to each modified - * source file that it has been changed. If you're a nice person, you - * will clearly mark each change too. :) - * - If you wish to use this for commercial purposes, please contact me at - * palazzol@comcast.net - * - This entire notice must remain in the source code. - * *****************************************************************************/ #pragma once diff --git a/src/emu/cpu/hmcs40/hmcs40.c b/src/emu/cpu/hmcs40/hmcs40.c index 1adef6ea242..dabc9740004 100644 --- a/src/emu/cpu/hmcs40/hmcs40.c +++ b/src/emu/cpu/hmcs40/hmcs40.c @@ -90,7 +90,7 @@ ADDRESS_MAP_END // device definitions hmcs43_cpu_device::hmcs43_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT16 polarity, const char *shortname) - : hmcs40_cpu_device(mconfig, type, name, tag, owner, clock, FAMILY_HMCS43, polarity, 3, 10, 11, ADDRESS_MAP_NAME(program_1k), 7, ADDRESS_MAP_NAME(data_80x4), shortname, __FILE__) + : hmcs40_cpu_device(mconfig, type, name, tag, owner, clock, FAMILY_HMCS43, polarity, 3 /* stack levels */, 10 /* pc width */, 11 /* prg width */, ADDRESS_MAP_NAME(program_1k), 7 /* data width */, ADDRESS_MAP_NAME(data_80x4), shortname, __FILE__) { } hd38750_device::hd38750_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) @@ -188,6 +188,7 @@ void hmcs40_cpu_device::device_start() m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hmcs40_cpu_device::simple_timer_cb), this)); reset_prescaler(); + // resolve callbacks m_read_r0.resolve_safe(0); m_read_r1.resolve_safe(0); m_read_r2.resolve_safe(0); @@ -215,6 +216,7 @@ void hmcs40_cpu_device::device_start() m_prev_op = 0; m_i = 0; m_eint_line = 0; + m_halt = 0; m_pc = 0; m_prev_pc = 0; m_page = 0; @@ -242,6 +244,8 @@ void hmcs40_cpu_device::device_start() save_item(NAME(m_prev_op)); save_item(NAME(m_i)); save_item(NAME(m_eint_line)); + save_item(NAME(m_halt)); + save_item(NAME(m_timer_halted_remain)); save_item(NAME(m_pc)); save_item(NAME(m_prev_pc)); save_item(NAME(m_page)); @@ -477,9 +481,25 @@ void hmcs40_cpu_device::do_interrupt() void hmcs40_cpu_device::execute_set_input(int line, int state) { + state = (state) ? 1 : 0; + + // halt/unhalt mcu + if (line == HMCS40_INPUT_LINE_HLT && state != m_halt) + { + if (state) + { + m_timer_halted_remain = m_timer->remaining(); + m_timer->reset(); + } + else + m_timer->adjust(m_timer_halted_remain); + + m_halt = state; + return; + } + if (line != 0 && line != 1) return; - state = (state) ? 1 : 0; // external interrupt request on rising edge if (state && !m_int[line]) @@ -551,6 +571,13 @@ inline void hmcs40_cpu_device::increment_pc() void hmcs40_cpu_device::execute_run() { + // in HLT state, the internal clock is not running + if (m_halt) + { + m_icount = 0; + return; + } + while (m_icount > 0) { // LPU is handled 1 cycle later diff --git a/src/emu/cpu/hmcs40/hmcs40.h b/src/emu/cpu/hmcs40/hmcs40.h index 9e722f595a6..8b912739541 100644 --- a/src/emu/cpu/hmcs40/hmcs40.h +++ b/src/emu/cpu/hmcs40/hmcs40.h @@ -26,7 +26,6 @@ #define MCFG_HMCS40_WRITE_D_CB(_devcb) \ hmcs40_cpu_device::set_write_d_callback(*device, DEVCB_##_devcb); - enum { HMCS40_PORT_R0X = 0, @@ -39,6 +38,13 @@ enum HMCS40_PORT_R7X }; +enum +{ + HMCS40_INPUT_LINE_INT0 = 0, + HMCS40_INPUT_LINE_INT1, + HMCS40_INPUT_LINE_HLT +}; + // pinout reference @@ -181,6 +187,8 @@ protected: UINT8 m_i; // 4-bit immediate opcode param int m_eint_line; // which input_line caused an interrupt emu_timer *m_timer; + int m_halt; // internal HLT state + attotime m_timer_halted_remain; int m_icount; UINT16 m_pc; // Program Counter diff --git a/src/emu/cpu/i8089/i8089.c b/src/emu/cpu/i8089/i8089.c index 23b25d891a0..b81869bda1d 100644 --- a/src/emu/cpu/i8089/i8089.c +++ b/src/emu/cpu/i8089/i8089.c @@ -33,7 +33,7 @@ const device_type I8089 = &device_creator<i8089_device>; //------------------------------------------------- i8089_device::i8089_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : - cpu_device(mconfig, I8089, "Intel 8089", tag, owner, clock, "i8089", __FILE__), + cpu_device(mconfig, I8089, "I8089", tag, owner, clock, "i8089", __FILE__), m_icount(0), m_ch1(*this, "1"), m_ch2(*this, "2"), diff --git a/src/emu/cpu/i8089/i8089_channel.c b/src/emu/cpu/i8089/i8089_channel.c index 171a7ce0d24..fe7666ac17c 100644 --- a/src/emu/cpu/i8089/i8089_channel.c +++ b/src/emu/cpu/i8089/i8089_channel.c @@ -51,10 +51,13 @@ const device_type I8089_CHANNEL = &device_creator<i8089_channel>; i8089_channel::i8089_channel(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, I8089_CHANNEL, "Intel 8089 I/O Channel", tag, owner, clock, "i8089_channel", __FILE__), m_write_sintr(*this), + m_iop(NULL), m_icount(0), m_xfer_pending(false), m_dma_value(0), - m_dma_state(DMA_IDLE) + m_dma_state(DMA_IDLE), + m_drq(0), + m_prio(PRIO_IDLE) { } @@ -74,6 +77,7 @@ void i8089_channel::device_start() save_item(NAME(m_xfer_pending)); save_item(NAME(m_dma_value)); save_item(NAME(m_dma_state)); + save_item(NAME(m_drq)); save_item(NAME(m_prio)); for (int i = 0; i < ARRAY_LENGTH(m_r); i++) @@ -246,11 +250,13 @@ int i8089_channel::execute_run() break; case DMA_WAIT_FOR_SOURCE_DRQ: - fatalerror("%s('%s'): wait for source drq not supported\n", shortname(), tag()); + if (m_drq) + m_dma_state = DMA_FETCH; + break; case DMA_FETCH: if (VERBOSE_DMA) - logerror("%s('%s'): entering state: DMA_FETCH", shortname(), tag()); + logerror("%s('%s'): entering state: DMA_FETCH\n", shortname(), tag()); // source is 16-bit? if (BIT(m_r[PSW].w, 1)) @@ -306,7 +312,9 @@ int i8089_channel::execute_run() fatalerror("%s('%s'): dma translate requested\n", shortname(), tag()); case DMA_WAIT_FOR_DEST_DRQ: - fatalerror("%s('%s'): wait for destination drq not supported\n", shortname(), tag()); + if (m_drq) + m_dma_state = DMA_STORE; + break; case DMA_STORE: if (VERBOSE_DMA) @@ -834,5 +842,7 @@ WRITE_LINE_MEMBER( i8089_channel::ext_w ) WRITE_LINE_MEMBER( i8089_channel::drq_w ) { if (VERBOSE) - logerror("%s('%s'): ext_w: %d\n", shortname(), tag(), state); + logerror("%s('%s'): drq_w: %d\n", shortname(), tag(), state); + + m_drq = state; } diff --git a/src/emu/cpu/i8089/i8089_channel.h b/src/emu/cpu/i8089/i8089_channel.h index 9b4034603e5..7c1f5a6e445 100644 --- a/src/emu/cpu/i8089/i8089_channel.h +++ b/src/emu/cpu/i8089/i8089_channel.h @@ -186,6 +186,7 @@ private: bool m_xfer_pending; UINT16 m_dma_value; int m_dma_state; + bool m_drq; // dma state enum diff --git a/src/emu/cpu/i86/i86.c b/src/emu/cpu/i86/i86.c index 7a308da61a9..299d85b1f59 100644 --- a/src/emu/cpu/i86/i86.c +++ b/src/emu/cpu/i86/i86.c @@ -282,6 +282,8 @@ i8086_common_cpu_device::i8086_common_cpu_device(const machine_config &mconfig, , m_irq_state(0) , m_test_state(1) , m_pc(0) + , m_lock(false) + , m_lock_handler(*this) { static const BREGS reg_name[8]={ AL, CL, DL, BL, AH, CH, DH, BH }; @@ -391,6 +393,8 @@ void i8086_common_cpu_device::device_start() state_add(STATE_GENFLAGS, "GENFLAGS", m_TF).callimport().callexport().formatstr("%16s").noshow(); m_icountptr = &m_icount; + + m_lock_handler.resolve_safe(); } @@ -438,6 +442,7 @@ void i8086_common_cpu_device::device_reset() m_dst = 0; m_src = 0; m_halt = false; + m_lock = false; } @@ -1910,7 +1915,9 @@ bool i8086_common_cpu_device::common_op(UINT8 op) break; case 0xe4: // i_inal + if (m_lock) m_lock_handler(1); m_regs.b[AL] = read_port_byte( fetch() ); + if (m_lock) { m_lock_handler(0); m_lock = false; } CLK(IN_IMM8); break; @@ -2011,6 +2018,7 @@ bool i8086_common_cpu_device::common_op(UINT8 op) case 0xf0: // i_lock logerror("%s: %06x: Warning - BUSLOCK\n", tag(), pc()); + m_lock = true; m_no_interrupt = 1; CLK(NOP); break; diff --git a/src/emu/cpu/i86/i86.h b/src/emu/cpu/i86/i86.h index ff1c56c2e92..6e48fecd71e 100644 --- a/src/emu/cpu/i86/i86.h +++ b/src/emu/cpu/i86/i86.h @@ -14,6 +14,10 @@ extern const device_type I8088; #define INPUT_LINE_TEST 20 +#define MCFG_I8086_LOCK_HANDLER(_write) \ + devcb = &i8086_common_cpu_device::set_lock_handler(*device, DEVCB_##_write); + + enum { I8086_PC=0, @@ -29,6 +33,9 @@ public: // construction/destruction i8086_common_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + template<class _Object> static devcb_base &set_lock_handler(device_t &device, _Object object) + { return downcast<i8086_common_cpu_device &>(device).m_lock_handler.set_callback(object); } + protected: enum { @@ -325,6 +332,9 @@ protected: UINT8 m_timing[200]; bool m_halt; + + bool m_lock; + devcb_write_line m_lock_handler; }; class i8086_cpu_device : public i8086_common_cpu_device diff --git a/src/emu/cpu/lr35902/lr35902d.c b/src/emu/cpu/lr35902/lr35902d.c index 64af29a544c..cf6d61bd7d6 100644 --- a/src/emu/cpu/lr35902/lr35902d.c +++ b/src/emu/cpu/lr35902/lr35902d.c @@ -5,20 +5,6 @@ * lr35902d.c * Portable Sharp LR35902 disassembler * - * Copyright The MESS Team. - * - * - This source code is released as freeware for non-commercial purposes. - * - You are free to use and redistribute this code in modified or - * unmodified form, provided you list me in the credits. - * - If you modify this source code, you must add a notice to each modified - * source file that it has been changed. If you're a nice person, you - * will clearly mark each change too. :) - * - If you wish to use this for commercial purposes, please contact me at - * pullmoll@t-online.de - * - The author of this copywritten work reserves the right to change the - * terms of its usage and license at any time, including retroactively - * - This entire notice must remain in the source code. - * *****************************************************************************/ #include "emu.h" diff --git a/src/emu/cpu/m6809/hd6309.c b/src/emu/cpu/m6809/hd6309.c index 027c9b7511b..5b270d26c90 100644 --- a/src/emu/cpu/m6809/hd6309.c +++ b/src/emu/cpu/m6809/hd6309.c @@ -313,7 +313,7 @@ offs_t hd6309_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *o // read_operand //------------------------------------------------- -ATTR_FORCE_INLINE UINT8 hd6309_device::read_operand() +inline UINT8 hd6309_device::read_operand() { switch(m_addressing_mode) { @@ -332,7 +332,7 @@ ATTR_FORCE_INLINE UINT8 hd6309_device::read_operand() // read_operand //------------------------------------------------- -ATTR_FORCE_INLINE UINT8 hd6309_device::read_operand(int ordinal) +inline UINT8 hd6309_device::read_operand(int ordinal) { switch(m_addressing_mode) { @@ -356,7 +356,7 @@ ATTR_FORCE_INLINE UINT8 hd6309_device::read_operand(int ordinal) // write_operand //------------------------------------------------- -ATTR_FORCE_INLINE void hd6309_device::write_operand(UINT8 data) +inline void hd6309_device::write_operand(UINT8 data) { switch(m_addressing_mode) { @@ -375,7 +375,7 @@ ATTR_FORCE_INLINE void hd6309_device::write_operand(UINT8 data) // write_operand //------------------------------------------------- -ATTR_FORCE_INLINE void hd6309_device::write_operand(int ordinal, UINT8 data) +inline void hd6309_device::write_operand(int ordinal, UINT8 data) { switch(m_addressing_mode) { @@ -398,7 +398,7 @@ ATTR_FORCE_INLINE void hd6309_device::write_operand(int ordinal, UINT8 data) // bittest_register //------------------------------------------------- -ATTR_FORCE_INLINE UINT8 &hd6309_device::bittest_register() +inline UINT8 &hd6309_device::bittest_register() { switch(m_temp_im & 0xC0) { @@ -414,7 +414,7 @@ ATTR_FORCE_INLINE UINT8 &hd6309_device::bittest_register() // bittest_source //------------------------------------------------- -ATTR_FORCE_INLINE bool hd6309_device::bittest_source() +inline bool hd6309_device::bittest_source() { return (m_temp.b.l & (1 << ((m_temp_im >> 3) & 0x07))) ? true : false; } @@ -424,7 +424,7 @@ ATTR_FORCE_INLINE bool hd6309_device::bittest_source() // bittest_dest //------------------------------------------------- -ATTR_FORCE_INLINE bool hd6309_device::bittest_dest() +inline bool hd6309_device::bittest_dest() { return (bittest_register() & (1 << ((m_temp_im >> 0) & 0x07))) ? true : false; } @@ -434,7 +434,7 @@ ATTR_FORCE_INLINE bool hd6309_device::bittest_dest() // bittest_set //------------------------------------------------- -ATTR_FORCE_INLINE void hd6309_device::bittest_set(bool result) +inline void hd6309_device::bittest_set(bool result) { if (result) bittest_register() |= (1 << ((m_temp_im >> 0) & 0x07)); @@ -448,7 +448,7 @@ ATTR_FORCE_INLINE void hd6309_device::bittest_set(bool result) // read_exgtfr_register //------------------------------------------------- -ATTR_FORCE_INLINE m6809_base_device::exgtfr_register hd6309_device::read_exgtfr_register(UINT8 reg) +inline m6809_base_device::exgtfr_register hd6309_device::read_exgtfr_register(UINT8 reg) { UINT16 value = 0; @@ -486,7 +486,7 @@ ATTR_FORCE_INLINE m6809_base_device::exgtfr_register hd6309_device::read_exgtfr_ // write_exgtfr_register //------------------------------------------------- -ATTR_FORCE_INLINE void hd6309_device::write_exgtfr_register(UINT8 reg, m6809_base_device::exgtfr_register value) +inline void hd6309_device::write_exgtfr_register(UINT8 reg, m6809_base_device::exgtfr_register value) { switch(reg & 0x0F) { @@ -517,7 +517,7 @@ ATTR_FORCE_INLINE void hd6309_device::write_exgtfr_register(UINT8 reg, m6809_bas // tfr_read //------------------------------------------------- -ATTR_FORCE_INLINE bool hd6309_device::tfr_read(UINT8 opcode, UINT8 arg, UINT8 &data) +inline bool hd6309_device::tfr_read(UINT8 opcode, UINT8 arg, UINT8 &data) { PAIR16 *reg; @@ -550,7 +550,7 @@ ATTR_FORCE_INLINE bool hd6309_device::tfr_read(UINT8 opcode, UINT8 arg, UINT8 &d // tfr_write //------------------------------------------------- -ATTR_FORCE_INLINE bool hd6309_device::tfr_write(UINT8 opcode, UINT8 arg, UINT8 data) +inline bool hd6309_device::tfr_write(UINT8 opcode, UINT8 arg, UINT8 data) { PAIR16 *reg; @@ -789,7 +789,7 @@ bool hd6309_device::divd() // execute_one - try to execute a single instruction //------------------------------------------------- -ATTR_FORCE_INLINE void hd6309_device::execute_one() +inline void hd6309_device::execute_one() { switch(pop_state()) { diff --git a/src/emu/cpu/m6809/konami.c b/src/emu/cpu/m6809/konami.c index d86f44651d2..8dc2bf3ab78 100644 --- a/src/emu/cpu/m6809/konami.c +++ b/src/emu/cpu/m6809/konami.c @@ -120,7 +120,7 @@ offs_t konami_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT // read_operand //------------------------------------------------- -inline ATTR_FORCE_INLINE UINT8 konami_cpu_device::read_operand() +inline UINT8 konami_cpu_device::read_operand() { return super::read_operand(); } @@ -130,7 +130,7 @@ inline ATTR_FORCE_INLINE UINT8 konami_cpu_device::read_operand() // read_operand //------------------------------------------------- -inline ATTR_FORCE_INLINE UINT8 konami_cpu_device::read_operand(int ordinal) +inline UINT8 konami_cpu_device::read_operand(int ordinal) { switch(m_addressing_mode) { @@ -146,7 +146,7 @@ inline ATTR_FORCE_INLINE UINT8 konami_cpu_device::read_operand(int ordinal) // write_operand //------------------------------------------------- -ATTR_FORCE_INLINE void konami_cpu_device::write_operand(UINT8 data) +inline void konami_cpu_device::write_operand(UINT8 data) { super::write_operand(data); } @@ -157,7 +157,7 @@ ATTR_FORCE_INLINE void konami_cpu_device::write_operand(UINT8 data) // write_operand //------------------------------------------------- -ATTR_FORCE_INLINE void konami_cpu_device::write_operand(int ordinal, UINT8 data) +inline void konami_cpu_device::write_operand(int ordinal, UINT8 data) { switch(m_addressing_mode) { @@ -173,7 +173,7 @@ ATTR_FORCE_INLINE void konami_cpu_device::write_operand(int ordinal, UINT8 data) // ireg //------------------------------------------------- -ATTR_FORCE_INLINE UINT16 &konami_cpu_device::ireg() +inline UINT16 &konami_cpu_device::ireg() { switch(m_opcode & 0x70) { @@ -194,7 +194,7 @@ ATTR_FORCE_INLINE UINT16 &konami_cpu_device::ireg() // read_exgtfr_register //------------------------------------------------- -ATTR_FORCE_INLINE m6809_base_device::exgtfr_register konami_cpu_device::read_exgtfr_register(UINT8 reg) +inline m6809_base_device::exgtfr_register konami_cpu_device::read_exgtfr_register(UINT8 reg) { exgtfr_register result; result.word_value = 0x00FF; @@ -217,7 +217,7 @@ ATTR_FORCE_INLINE m6809_base_device::exgtfr_register konami_cpu_device::read_exg // write_exgtfr_register //------------------------------------------------- -ATTR_FORCE_INLINE void konami_cpu_device::write_exgtfr_register(UINT8 reg, m6809_base_device::exgtfr_register value) +inline void konami_cpu_device::write_exgtfr_register(UINT8 reg, m6809_base_device::exgtfr_register value) { switch(reg & 0x07) { @@ -287,7 +287,7 @@ template<class T> T konami_cpu_device::safe_shift_left(T value, UINT32 shift) // lmul //------------------------------------------------- -ATTR_FORCE_INLINE void konami_cpu_device::lmul() +inline void konami_cpu_device::lmul() { PAIR result; @@ -313,7 +313,7 @@ ATTR_FORCE_INLINE void konami_cpu_device::lmul() // divx //------------------------------------------------- -ATTR_FORCE_INLINE void konami_cpu_device::divx() +inline void konami_cpu_device::divx() { UINT16 result; UINT8 remainder; @@ -357,7 +357,7 @@ void konami_cpu_device::set_lines(UINT8 data) // execute_one - try to execute a single instruction //------------------------------------------------- -ATTR_FORCE_INLINE void konami_cpu_device::execute_one() +inline void konami_cpu_device::execute_one() { switch(pop_state()) { diff --git a/src/emu/cpu/m6809/m6809.c b/src/emu/cpu/m6809/m6809.c index 3b7fc33d94f..1b7b0e1e777 100644 --- a/src/emu/cpu/m6809/m6809.c +++ b/src/emu/cpu/m6809/m6809.c @@ -456,7 +456,7 @@ const char *m6809_base_device::inputnum_string(int inputnum) // read_exgtfr_register //------------------------------------------------- -ATTR_FORCE_INLINE m6809_base_device::exgtfr_register m6809_base_device::read_exgtfr_register(UINT8 reg) +m6809_base_device::exgtfr_register m6809_base_device::read_exgtfr_register(UINT8 reg) { exgtfr_register result; result.byte_value = 0xFF; @@ -483,7 +483,7 @@ ATTR_FORCE_INLINE m6809_base_device::exgtfr_register m6809_base_device::read_exg // write_exgtfr_register //------------------------------------------------- -ATTR_FORCE_INLINE void m6809_base_device::write_exgtfr_register(UINT8 reg, m6809_base_device::exgtfr_register value) +void m6809_base_device::write_exgtfr_register(UINT8 reg, m6809_base_device::exgtfr_register value) { switch(reg & 0x0F) { @@ -516,7 +516,7 @@ void m6809_base_device::log_illegal() // execute_one - try to execute a single instruction //------------------------------------------------- -ATTR_FORCE_INLINE void m6809_base_device::execute_one() +void m6809_base_device::execute_one() { switch(pop_state()) { diff --git a/src/emu/cpu/m6809/m6809.h b/src/emu/cpu/m6809/m6809.h index eb0633af44c..7b14a6882e5 100644 --- a/src/emu/cpu/m6809/m6809.h +++ b/src/emu/cpu/m6809/m6809.h @@ -147,27 +147,27 @@ protected: devcb_write_line m_lic_func; // LIC pin on the 6809E // eat cycles - ATTR_FORCE_INLINE void eat(int cycles) { m_icount -= cycles; } + inline void eat(int cycles) { m_icount -= cycles; } void eat_remaining(); // read a byte from given memory location - ATTR_FORCE_INLINE UINT8 read_memory(UINT16 address) { eat(1); return m_addrspace[AS_PROGRAM]->read_byte(address); } + inline UINT8 read_memory(UINT16 address) { eat(1); return m_addrspace[AS_PROGRAM]->read_byte(address); } // write a byte to given memory location - ATTR_FORCE_INLINE void write_memory(UINT16 address, UINT8 data) { eat(1); m_addrspace[AS_PROGRAM]->write_byte(address, data); } + inline void write_memory(UINT16 address, UINT8 data) { eat(1); m_addrspace[AS_PROGRAM]->write_byte(address, data); } // read_opcode() is like read_memory() except it is used for reading opcodes. In the case of a system // with memory mapped I/O, this function can be used to greatly speed up emulation. - ATTR_FORCE_INLINE UINT8 read_opcode(UINT16 address) { eat(1); return m_direct->read_decrypted_byte(address); } + inline UINT8 read_opcode(UINT16 address) { eat(1); return m_direct->read_decrypted_byte(address); } // read_opcode_arg() is identical to read_opcode() except it is used for reading opcode arguments. This // difference can be used to support systems that use different encoding mechanisms for opcodes // and opcode arguments. - ATTR_FORCE_INLINE UINT8 read_opcode_arg(UINT16 address) { eat(1); return m_direct->read_raw_byte(address); } + inline UINT8 read_opcode_arg(UINT16 address) { eat(1); return m_direct->read_raw_byte(address); } // read_opcode() and bump the program counter - ATTR_FORCE_INLINE UINT8 read_opcode() { return read_opcode(m_pc.w++); } - ATTR_FORCE_INLINE UINT8 read_opcode_arg() { return read_opcode_arg(m_pc.w++); } + inline UINT8 read_opcode() { return read_opcode(m_pc.w++); } + inline UINT8 read_opcode_arg() { return read_opcode_arg(m_pc.w++); } // state stack - implemented as a UINT32 void push_state(UINT8 state) { m_state = (m_state << 8) | state; } @@ -219,15 +219,15 @@ protected: template<class T> T set_flags(UINT8 mask, T r); // branch conditions - ATTR_FORCE_INLINE bool cond_hi() { return !(m_cc & CC_ZC); } // BHI/BLS - ATTR_FORCE_INLINE bool cond_cc() { return !(m_cc & CC_C); } // BCC/BCS - ATTR_FORCE_INLINE bool cond_ne() { return !(m_cc & CC_Z); } // BNE/BEQ - ATTR_FORCE_INLINE bool cond_vc() { return !(m_cc & CC_V); } // BVC/BVS - ATTR_FORCE_INLINE bool cond_pl() { return !(m_cc & CC_N); } // BPL/BMI - ATTR_FORCE_INLINE bool cond_ge() { return (m_cc & CC_N ? true : false) == (m_cc & CC_V ? true : false); } // BGE/BLT - ATTR_FORCE_INLINE bool cond_gt() { return cond_ge() && !(m_cc & CC_Z); } // BGT/BLE - ATTR_FORCE_INLINE void set_cond(bool cond) { m_cond = cond; } - ATTR_FORCE_INLINE bool branch_taken() { return m_cond; } + inline bool cond_hi() { return !(m_cc & CC_ZC); } // BHI/BLS + inline bool cond_cc() { return !(m_cc & CC_C); } // BCC/BCS + inline bool cond_ne() { return !(m_cc & CC_Z); } // BNE/BEQ + inline bool cond_vc() { return !(m_cc & CC_V); } // BVC/BVS + inline bool cond_pl() { return !(m_cc & CC_N); } // BPL/BMI + inline bool cond_ge() { return (m_cc & CC_N ? true : false) == (m_cc & CC_V ? true : false); } // BGE/BLT + inline bool cond_gt() { return cond_ge() && !(m_cc & CC_Z); } // BGT/BLE + inline void set_cond(bool cond) { m_cond = cond; } + inline bool branch_taken() { return m_cond; } // interrupt registers bool firq_saves_entire_state() { return false; } @@ -235,8 +235,8 @@ protected: UINT16 entire_state_registers() { return 0xFF; } // miscellaneous - exgtfr_register read_exgtfr_register(UINT8 reg); - void write_exgtfr_register(UINT8 reg, exgtfr_register value); + inline exgtfr_register read_exgtfr_register(UINT8 reg); + inline void write_exgtfr_register(UINT8 reg, exgtfr_register value); bool is_register_addressing_mode(); bool is_ea_addressing_mode() { return m_addressing_mode == ADDRESSING_MODE_EA; } UINT16 get_pending_interrupt(); @@ -255,7 +255,7 @@ private: int m_clock_divider; // functions - void execute_one(); + inline void execute_one(); const char *inputnum_string(int inputnum); }; diff --git a/src/emu/cpu/mcs51/mcs51.c b/src/emu/cpu/mcs51/mcs51.c index 94811d9851e..d3c73ecf0c6 100644 --- a/src/emu/cpu/mcs51/mcs51.c +++ b/src/emu/cpu/mcs51/mcs51.c @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Steve Ellenoff, Manuel Abadia, Couriersud /***************************************************************************** * @@ -13,18 +13,6 @@ * * Copyright Steve Ellenoff, all rights reserved. * - * - This source code is released as freeware for non-commercial purposes. - * - You are free to use and redistribute this code in modified or - * unmodified form, provided you list me in the credits. - * - If you modify this source code, you must add a notice to each modified - * source file that it has been changed. If you're a nice person, you - * will clearly mark each change too. :) - * - If you wish to use this for commercial purposes, please contact me at - * sellenoff@hotmail.com - * - The author of this copywritten work reserves the right to change the - * terms of its usage and license at any time, including retroactively - * - This entire notice must remain in the source code. - * * This work is based on: * #1) 'Intel(tm) MC51 Microcontroller Family Users Manual' and * #2) 8051 simulator by Travis Marlatte diff --git a/src/emu/cpu/mcs51/mcs51.h b/src/emu/cpu/mcs51/mcs51.h index e90b7d421c9..89caacafa49 100644 --- a/src/emu/cpu/mcs51/mcs51.h +++ b/src/emu/cpu/mcs51/mcs51.h @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Steve Ellenoff, Manuel Abadia, Couriersud /***************************************************************************** * @@ -13,18 +13,6 @@ * * Copyright Steve Ellenoff, all rights reserved. * - * - This source code is released as freeware for non-commercial purposes. - * - You are free to use and redistribute this code in modified or - * unmodified form, provided you list me in the credits. - * - If you modify this source code, you must add a notice to each modified - * source file that it has been changed. If you're a nice person, you - * will clearly mark each change too. :) - * - If you wish to use this for commercial purposes, please contact me at - * sellenoff@hotmail.com - * - The author of this copywritten work reserves the right to change the - * terms of its usage and license at any time, including retroactively - * - This entire notice must remain in the source code. - * * This work is based on: * #1) 'Intel(tm) MC51 Microcontroller Family Users Manual' and * #2) 8051 simulator by Travis Marlatte diff --git a/src/emu/cpu/mcs51/mcs51dasm.c b/src/emu/cpu/mcs51/mcs51dasm.c index 62187d4a692..0d16048855f 100644 --- a/src/emu/cpu/mcs51/mcs51dasm.c +++ b/src/emu/cpu/mcs51/mcs51dasm.c @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Steve Ellenoff /***************************************************************************** * @@ -13,18 +13,6 @@ * * Copyright Steve Ellenoff, all rights reserved. * - * - This source code is released as freeware for non-commercial purposes. - * - You are free to use and redistribute this code in modified or - * unmodified form, provided you list me in the credits. - * - If you modify this source code, you must add a notice to each modified - * source file that it has been changed. If you're a nice person, you - * will clearly mark each change too. :) - * - If you wish to use this for commercial purposes, please contact me at - * sellenoff@hotmail.com - * - The author of this copywritten work reserves the right to change the - * terms of its usage and license at any time, including retroactively - * - This entire notice must remain in the source code. - * * This work is based on: * #1) 'Intel(tm) MC51 Microcontroller Family Users Manual' and * #2) 8051 simulator by Travis Marlatte diff --git a/src/emu/cpu/mcs96/i8xc196.c b/src/emu/cpu/mcs96/i8xc196.c index 8e80da19cdb..19553280de2 100644 --- a/src/emu/cpu/mcs96/i8xc196.c +++ b/src/emu/cpu/mcs96/i8xc196.c @@ -69,4 +69,8 @@ UINT16 i8xc196_device::io_r16(UINT8 adr) return data; } +void i8xc196_device::do_exec_partial() +{ +} + #include "cpu/mcs96/i8xc196.inc" diff --git a/src/emu/cpu/mcs96/i8xc196.h b/src/emu/cpu/mcs96/i8xc196.h index cb41e693fe8..299f6c9128d 100644 --- a/src/emu/cpu/mcs96/i8xc196.h +++ b/src/emu/cpu/mcs96/i8xc196.h @@ -23,7 +23,6 @@ public: virtual void do_exec_full(); virtual void do_exec_partial(); - virtual void next(int cycles); virtual void io_w8(UINT8 adr, UINT8 data); virtual void io_w16(UINT8 adr, UINT16 data); virtual UINT8 io_r8(UINT8 adr); diff --git a/src/emu/cpu/melps4/m58846.c b/src/emu/cpu/melps4/m58846.c index e4842d28a6a..ac14baf797d 100644 --- a/src/emu/cpu/melps4/m58846.c +++ b/src/emu/cpu/melps4/m58846.c @@ -30,7 +30,7 @@ ADDRESS_MAP_END // device definitions m58846_device::m58846_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : melps4_cpu_device(mconfig, M58846, "M58846", tag, owner, clock, 11, ADDRESS_MAP_NAME(program_2kx9), 7, ADDRESS_MAP_NAME(data_128x4), "m58846", __FILE__) + : melps4_cpu_device(mconfig, M58846, "M58846", tag, owner, clock, 11, ADDRESS_MAP_NAME(program_2kx9), 7, ADDRESS_MAP_NAME(data_128x4), 12 /* number of D pins */, 2 /* subroutine page */, 1 /* interrupt page */, "m58846", __FILE__) { } @@ -50,10 +50,6 @@ offs_t m58846_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *o void m58846_device::device_start() { melps4_cpu_device::device_start(); - - // set fixed state - m_bm_page = 2; - m_int_page = 1; } @@ -115,6 +111,7 @@ void m58846_device::execute_one() case 0x0b: op_ose(); break; case 0x0c: op_tya(); break; case 0x0f: op_cma(); break; + // 0x18 RAR undocumented? case 0x10: op_cls(); break; case 0x11: op_clds(); break; diff --git a/src/emu/cpu/melps4/melps4.c b/src/emu/cpu/melps4/melps4.c index b9172f7745d..5fdd2b1cab6 100644 --- a/src/emu/cpu/melps4/melps4.c +++ b/src/emu/cpu/melps4/melps4.c @@ -23,11 +23,13 @@ *M58496: 72-pin QFP CMOS, 2Kx10 ROM, 128x4 internal + 256x4 external RAM, 1 timer, low-power *M58497: almost same as M58496 - MELPS 760 subfamily has more differences, document them when needed. + MELPS 760 family has more differences, document them when needed. + MELPS 720 family as well References: - - 1982 Mitsubishi LSI Data Book + - 1980 and 1982 Mitsubishi LSI Data Books + - M34550Mx-XXXFP datasheet (this one is MELPS 720 family) */ @@ -44,9 +46,10 @@ void melps4_cpu_device::state_string_export(const device_state_entry &entry, std { // obviously not from a single flags register, letters are made up case STATE_GENFLAGS: - strprintf(str, "%c%c%c%c", + strprintf(str, "%c%c%c%c%c", m_intp ? 'P':'p', m_inte ? 'I':'i', + m_sm ? 'S':'s', m_cps ? 'D':'d', m_cy ? 'C':'c' ); @@ -74,6 +77,20 @@ void melps4_cpu_device::device_start() m_data = &space(AS_DATA); m_prgmask = (1 << m_prgwidth) - 1; m_datamask = (1 << m_datawidth) - 1; + m_d_mask = (1 << m_d_pins) - 1; + + // resolve callbacks + m_read_k.resolve_safe(0); + m_read_d.resolve_safe(0); + m_read_s.resolve_safe(0); + m_read_f.resolve_safe(0); + + m_write_d.resolve_safe(); + m_write_s.resolve_safe(); + m_write_f.resolve_safe(); + m_write_g.resolve_safe(); + m_write_u.resolve_safe(); + m_write_t.resolve_safe(); // zerofill m_pc = 0; @@ -82,11 +99,19 @@ void melps4_cpu_device::device_start() m_op = 0; m_prev_op = 0; m_bitmask = 0; - + + m_port_d = 0; + m_port_s = 0; + m_port_f = 0; + + m_sm = m_sms = false; + m_ba_flag = false; + m_sp_param = 0; m_cps = 0; m_skip = false; m_inte = 0; m_intp = 1; + m_prohibit_irq = false; m_a = 0; m_b = 0; @@ -110,10 +135,19 @@ void melps4_cpu_device::device_start() save_item(NAME(m_prev_op)); save_item(NAME(m_bitmask)); + save_item(NAME(m_port_d)); + save_item(NAME(m_port_s)); + save_item(NAME(m_port_f)); + + save_item(NAME(m_sm)); + save_item(NAME(m_sms)); + save_item(NAME(m_ba_flag)); + save_item(NAME(m_sp_param)); save_item(NAME(m_cps)); save_item(NAME(m_skip)); save_item(NAME(m_inte)); save_item(NAME(m_intp)); + save_item(NAME(m_prohibit_irq)); save_item(NAME(m_a)); save_item(NAME(m_b)); @@ -131,7 +165,7 @@ void melps4_cpu_device::device_start() // register state for debugger state_add(STATE_GENPC, "curpc", m_pc).formatstr("%04X").noshow(); - state_add(STATE_GENFLAGS, "GENFLAGS", m_cy).formatstr("%4s").noshow(); + state_add(STATE_GENFLAGS, "GENFLAGS", m_cy).formatstr("%5s").noshow(); state_add(MELPS4_PC, "PC", m_pc).formatstr("%04X"); state_add(MELPS4_A, "A", m_a).formatstr("%2d"); // show in decimal @@ -158,6 +192,11 @@ void melps4_cpu_device::device_start() void melps4_cpu_device::device_reset() { + m_sm = m_sms = false; + m_ba_flag = false; + m_prohibit_irq = false; + + m_skip = false; m_op = m_prev_op = 0; m_pc = m_prev_pc = 0; m_inte = 0; @@ -166,6 +205,88 @@ void melps4_cpu_device::device_reset() m_v = 0; m_w = 0; + + // clear ports + write_d_pin(MELPS4_PORTD_CLR, 0); + write_gen_port(MELPS4_PORTS, 0); + write_gen_port(MELPS4_PORTF, 0); + write_gen_port(MELPS4_PORTG, 0); + write_gen_port(MELPS4_PORTU, 0); + m_write_t(0); +} + + + +//------------------------------------------------- +// i/o handling +//------------------------------------------------- + +UINT8 melps4_cpu_device::read_gen_port(int port) +{ + // input generic port + switch (port) + { + case MELPS4_PORTS: + return m_port_s | m_read_s(port, 0xff); + case MELPS4_PORTF: + return m_port_f | (m_read_f(port, 0xff) & 0xf); + + default: + break; + } + + return 0; +} + +void melps4_cpu_device::write_gen_port(int port, UINT8 data) +{ + // output generic port + switch (port) + { + case MELPS4_PORTS: + m_port_s = data; + m_write_s(port, data, 0xff); + break; + case MELPS4_PORTF: + m_port_f = data & 0xf; + m_write_f(port, data & 0xf, 0xff); + break; + case MELPS4_PORTG: + m_write_g(port, data & 0xf, 0xff); + break; + case MELPS4_PORTU: + m_write_u(port, data & 1, 0xff); + break; + + default: + break; + } +} + +int melps4_cpu_device::read_d_pin(int bit) +{ + // read port D, return state of selected pin + bit &= 0xf; + UINT16 d = (m_port_d | m_read_d(bit, 0xffff)) & m_d_mask; + return d >> bit & 1; +} + +void melps4_cpu_device::write_d_pin(int bit, int state) +{ + // clear all port D pins + if (bit == MELPS4_PORTD_CLR) + { + m_port_d = 0; + m_write_d(bit, 0, 0xffff); + } + + // set/reset one port D pin + else + { + bit &= 0xf; + m_port_d = ((m_port_d & (~(1 << bit))) | (state << bit)) & m_d_mask; + m_write_d(bit, m_port_d, 0xffff); + } } @@ -192,6 +313,10 @@ void melps4_cpu_device::execute_run() // remember previous state m_prev_op = m_op; m_prev_pc = m_pc; + + // irq is not accepted during skip or LXY, LA, EI, DI, RT/RTS/RTI or any branch + //.. + m_prohibit_irq = false; // fetch next opcode debugger_instruction_hook(this, m_pc); @@ -201,6 +326,13 @@ void melps4_cpu_device::execute_run() m_pc = (m_pc & ~0x7f) | ((m_pc + 1) & 0x7f); // stays in the same page // handle opcode if it's not skipped - execute_one(); + if (m_skip) + { + // if it's a long jump, skip next one as well + if (m_op != m_ba_op && (m_op & ~0xf) != m_sp_mask) + m_skip = false; + } + else + execute_one(); } } diff --git a/src/emu/cpu/melps4/melps4.h b/src/emu/cpu/melps4/melps4.h index d8b9380f7d7..023b0b9ba02 100644 --- a/src/emu/cpu/melps4/melps4.h +++ b/src/emu/cpu/melps4/melps4.h @@ -12,6 +12,56 @@ #include "emu.h" +// I/O ports setup + +// K input or A/D input port, up to 16 pins +#define MCFG_MELPS4_READ_K_CB(_devcb) \ + melps4_cpu_device::set_read_k_callback(*device, DEVCB_##_devcb); + +// D discrete I/O port, up to 16 pins - offset 0-15 for bit, 16 for all pins clear +#define MCFG_MELPS4_READ_D_CB(_devcb) \ + melps4_cpu_device::set_read_d_callback(*device, DEVCB_##_devcb); +#define MCFG_MELPS4_WRITE_D_CB(_devcb) \ + melps4_cpu_device::set_write_d_callback(*device, DEVCB_##_devcb); + +// 8-bit S generic I/O port +#define MCFG_MELPS4_READ_S_CB(_devcb) \ + melps4_cpu_device::set_read_s_callback(*device, DEVCB_##_devcb); +#define MCFG_MELPS4_WRITE_S_CB(_devcb) \ + melps4_cpu_device::set_write_s_callback(*device, DEVCB_##_devcb); + +// 4-bit F generic I/O port +#define MCFG_MELPS4_READ_F_CB(_devcb) \ + melps4_cpu_device::set_read_f_callback(*device, DEVCB_##_devcb); +#define MCFG_MELPS4_WRITE_F_CB(_devcb) \ + melps4_cpu_device::set_write_f_callback(*device, DEVCB_##_devcb); + +// 4-bit G generic output port +#define MCFG_MELPS4_WRITE_G_CB(_devcb) \ + melps4_cpu_device::set_write_g_callback(*device, DEVCB_##_devcb); + +// 1-bit U generic output port +#define MCFG_MELPS4_WRITE_U_CB(_devcb) \ + melps4_cpu_device::set_write_u_callback(*device, DEVCB_##_devcb); + +// T timer I/O pin (use execute_set_input for reads) +#define MCFG_MELPS4_WRITE_T_CB(_devcb) \ + melps4_cpu_device::set_write_t_callback(*device, DEVCB_##_devcb); + + +#define MELPS4_PORTD_CLR 16 + +// only generic ports here +enum +{ + MELPS4_PORTS = 0, + MELPS4_PORTF, + MELPS4_PORTG, + MELPS4_PORTU +}; + + + // pinout reference /* @@ -45,18 +95,44 @@ class melps4_cpu_device : public cpu_device { public: // construction/destruction - melps4_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data, const char *shortname, const char *source) + melps4_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data, int d_pins, UINT8 sm_page, UINT8 int_page, const char *shortname, const char *source) : cpu_device(mconfig, type, name, tag, owner, clock, shortname, source) , m_program_config("program", ENDIANNESS_LITTLE, 16, prgwidth, -1, program) , m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data) , m_prgwidth(prgwidth) , m_datawidth(datawidth) - , m_stack_levels(3) - , m_bm_page(14) - , m_int_page(12) + , m_d_pins(d_pins) + , m_sm_page(sm_page) + , m_int_page(int_page) , m_xami_mask(0xf) + , m_sp_mask(0x7<<4) + , m_ba_op(0x01) + , m_stack_levels(3) + , m_read_k(*this) + , m_read_d(*this) + , m_read_s(*this) + , m_read_f(*this) + , m_write_d(*this) + , m_write_s(*this) + , m_write_f(*this) + , m_write_g(*this) + , m_write_u(*this) + , m_write_t(*this) { } + // static configuration helpers + template<class _Object> static devcb_base &set_read_k_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_read_k.set_callback(object); } + template<class _Object> static devcb_base &set_read_d_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_read_d.set_callback(object); } + template<class _Object> static devcb_base &set_read_s_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_read_s.set_callback(object); } + template<class _Object> static devcb_base &set_read_f_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_read_f.set_callback(object); } + + template<class _Object> static devcb_base &set_write_d_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_write_d.set_callback(object); } + template<class _Object> static devcb_base &set_write_s_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_write_s.set_callback(object); } + template<class _Object> static devcb_base &set_write_f_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_write_f.set_callback(object); } + template<class _Object> static devcb_base &set_write_g_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_write_g.set_callback(object); } + template<class _Object> static devcb_base &set_write_u_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_write_u.set_callback(object); } + template<class _Object> static devcb_base &set_write_t_callback(device_t &device, _Object object) { return downcast<melps4_cpu_device &>(device).m_write_t.set_callback(object); } + protected: // device-level overrides virtual void device_start(); @@ -86,29 +162,41 @@ protected: int m_icount; - // fixed settings or mask options - int m_prgwidth; // number of bits and bitmask for ROM/RAM size + // fixed settings or mask options that differ between MCU type + int m_prgwidth; // number of bits and bitmask for ROM/RAM size: see melps4.c for info int m_datawidth; // " int m_prgmask; // " int m_datamask; // " + int m_d_pins; // number of D port pins and bitmask: 11 on '40,'41,'42,'44, 8 on '43, 12 on '45,'46, 16 on '47 + int m_d_mask; // " - UINT8 m_stack_levels; // 3 levels on MELPS 4, 12 levels on MELPS 41/42 - UINT8 m_bm_page; // short BM default page: 14 on '40 to '44, 2 on '45,'46, 0 on '47 + UINT8 m_sm_page; // subroutine default page: 14 on '40 to '44, 2 on '45,'46, 0 on '47 UINT8 m_int_page; // interrupt routine page: 12 on '40 to '44, 1 on '45,'46, 2 on '47 UINT8 m_xami_mask; // mask option for XAMI opcode on '40,'41,'45 (0xf for others) + UINT16 m_sp_mask; // SP opcode location(middle 4 bits): 7 on '40 to '46, 3 on '47 + UINT16 m_ba_op; // BA opcode location: 1 on '40 to '46, N/A on '47 + UINT8 m_stack_levels; // 3 levels on MELPS 4, 12 levels on MELPS 41/42 // internal state, misc regs UINT16 m_pc; // program counter (11 or 10-bit) UINT16 m_prev_pc; - UINT16 m_stack[12]; // callstack + UINT16 m_stack[12]; // callstack (SK0-SKx, same size as PC) UINT16 m_op; UINT16 m_prev_op; UINT8 m_bitmask; // opcode bit argument - + + UINT16 m_port_d; // last written port data + UINT8 m_port_s; // " + UINT8 m_port_f; // " + + bool m_sm, m_sms; // subroutine mode flag + stack + bool m_ba_flag; // temp flag indicates BA opcode was executed + UINT8 m_sp_param; // temp register holding SP opcode parameter UINT8 m_cps; // DP,CY or DP',CY' selected bool m_skip; // skip next opcode UINT8 m_inte; // interrupt enable flag UINT8 m_intp; // external interrupt polarity ('40 to '44) + bool m_prohibit_irq; // interrupt is prohibited during certain opcodes // work registers (unless specified, each is 4-bit) UINT8 m_a; // accumulator @@ -125,6 +213,24 @@ protected: UINT8 m_v; // timer control V UINT8 m_w; // timer control W + // i/o handlers + devcb_read16 m_read_k; + devcb_read16 m_read_d; + devcb_read8 m_read_s; + devcb_read8 m_read_f; + + devcb_write16 m_write_d; + devcb_write8 m_write_s; + devcb_write8 m_write_f; + devcb_write8 m_write_g; + devcb_write8 m_write_u; + devcb_write_line m_write_t; + + UINT8 read_gen_port(int port); + void write_gen_port(int port, UINT8 data); + int read_d_pin(int bit); + void write_d_pin(int bit, int state); + // misc internal helpers UINT8 ram_r(); void ram_w(UINT8 data); diff --git a/src/emu/cpu/melps4/melps4op.inc b/src/emu/cpu/melps4/melps4op.inc index 296a5b1a39a..476de900e93 100644 --- a/src/emu/cpu/melps4/melps4op.inc +++ b/src/emu/cpu/melps4/melps4op.inc @@ -19,10 +19,16 @@ inline void melps4_cpu_device::ram_w(UINT8 data) void melps4_cpu_device::pop_pc() { + m_pc = m_stack[0]; + for (int i = 0; i < m_stack_levels-1; i++) + m_stack[i] = m_stack[i+1]; } void melps4_cpu_device::push_pc() { + for (int i = m_stack_levels-1; i >= 1; i--) + m_stack[i] = m_stack[i-1]; + m_stack[0] = m_pc; } @@ -82,6 +88,7 @@ void melps4_cpu_device::op_tax() void melps4_cpu_device::op_lxy() { // LXY x,y: load immediate into X,Y, skip any next LXY + m_prohibit_irq = true; if ((m_op & ~0x3f) != (m_prev_op & ~0x3f)) { m_x = m_op >> 4 & 3; @@ -181,6 +188,7 @@ void melps4_cpu_device::op_xami() void melps4_cpu_device::op_la() { // LA n: load immediate into A, skip any next LA + m_prohibit_irq = true; if ((m_op & ~0xf) != (m_prev_op & ~0xf)) m_a = m_op & 0xf; } @@ -411,13 +419,13 @@ void melps4_cpu_device::op_tab2() void melps4_cpu_device::op_tva() { // TVA: transfer A to timer control V - op_illegal(); + m_v = m_a; } void melps4_cpu_device::op_twa() { // TWA: transfer A to timer control W - op_illegal(); + m_w = m_a; } void melps4_cpu_device::op_snz1() @@ -437,26 +445,57 @@ void melps4_cpu_device::op_snz2() void melps4_cpu_device::op_ba() { - // BA: x - op_illegal(); + // BA: indicate next branch is indirect + m_prohibit_irq = true; + m_ba_flag = true; } void melps4_cpu_device::op_sp() { - // SP: set page - op_illegal(); + // SP: set page for next branch + // note: mnemonic is guessed, manual names it BL or BML + m_prohibit_irq = true; + m_sp_param = m_op & 0xf; } void melps4_cpu_device::op_b() { - // B xy: branch in current page - op_illegal(); + // B xy: branch + m_prohibit_irq = true; + + // determine new page: + // - short call: subroutine page + // - short jump: current page, or sub. page + 1 when in sub. mode + // - long jump/call(B/BM preceded by SP): temp SP register + UINT8 page = m_pc >> 7; + if ((m_prev_op & ~0xf) == m_sp_mask) + { + m_sm = false; + page = m_sp_param; + } + else if (m_sm) + page = m_sm_page | (m_op >> 7 & 1); + + m_pc = page << 7 | (m_op & 0x7f); + + // if BA opcode was executed, set PC low 4 bits to A + if (m_ba_flag) + { + m_ba_flag = false; + m_pc = (m_pc & ~0xf) | m_a; + } } void melps4_cpu_device::op_bm() { - // BM xy call subroutine on page 14 - op_illegal(); + // BM xy call subroutine + // don't push stack on short calls when in subroutine mode + if (!m_sm || (m_prev_op & ~0xf) == m_sp_mask) + push_pc(); + + // set subroutine mode - it is reset after long jump/call or return + m_sm = true; + op_b(); } @@ -465,7 +504,9 @@ void melps4_cpu_device::op_bm() void melps4_cpu_device::op_rt() { // RT: return from subroutine - op_illegal(); + m_prohibit_irq = true; + m_sm = false; + pop_pc(); } void melps4_cpu_device::op_rts() @@ -478,7 +519,8 @@ void melps4_cpu_device::op_rts() void melps4_cpu_device::op_rti() { // RTI: return from interrupt routine - op_illegal(); + op_rt(); + m_sm = m_sms; } @@ -487,43 +529,44 @@ void melps4_cpu_device::op_rti() void melps4_cpu_device::op_cld() { // CLD: clear port D - op_illegal(); + write_d_pin(MELPS4_PORTD_CLR, 0); } void melps4_cpu_device::op_cls() { // CLS: clear port S - op_illegal(); + write_gen_port(MELPS4_PORTS, 0); } void melps4_cpu_device::op_clds() { // CLDS: CLD, CLS - op_illegal(); + op_cld(); + op_cls(); } void melps4_cpu_device::op_sd() { - // SD: set port D bit designated by Y - op_illegal(); + // SD: set port D pin designated by Y + write_d_pin(m_y, 1); } void melps4_cpu_device::op_rd() { - // RD: reset port D bit designated by Y - op_illegal(); + // RD: reset port D pin designated by Y + write_d_pin(m_y, 0); } void melps4_cpu_device::op_szd() { - // SZD: skip next if port D bit designated by Y is 0 - op_illegal(); + // SZD: skip next if port D pin designated by Y is 0 + m_skip = !read_d_pin(m_y); } void melps4_cpu_device::op_osab() { // OSAB: output A and B to port S - op_illegal(); + write_gen_port(MELPS4_PORTS, m_b << 4 | m_a); } void melps4_cpu_device::op_ospa() @@ -535,49 +578,50 @@ void melps4_cpu_device::op_ospa() void melps4_cpu_device::op_ose() { // OSE: output E to port S - op_illegal(); + write_gen_port(MELPS4_PORTS, m_e); } void melps4_cpu_device::op_ias() { // IAS i: transfer port S(hi/lo) to A - op_illegal(); + int shift = (m_op & 1) ? 0 : 4; + m_a = read_gen_port(MELPS4_PORTS) >> shift & 0xf; } void melps4_cpu_device::op_ofa() { // OFA: output A to port F - op_illegal(); + write_gen_port(MELPS4_PORTF, m_a); } void melps4_cpu_device::op_iaf() { // IAF: input port F to A - op_illegal(); + m_a = read_gen_port(MELPS4_PORTF); } void melps4_cpu_device::op_oga() { // OGA: output A to port G - op_illegal(); + write_gen_port(MELPS4_PORTG, m_a); } void melps4_cpu_device::op_iak() { // IAK: input port K to A - op_illegal(); + m_a = m_read_k(0, 0xffff) & 0xf; } void melps4_cpu_device::op_szk() { // SZK j: skip next if port K bit is reset - op_illegal(); + m_skip = !(m_read_k(0, 0xffff) & m_bitmask); } void melps4_cpu_device::op_su() { // SU/RU: set/reset port U - op_illegal(); + write_gen_port(MELPS4_PORTU, m_op & 1); } @@ -586,12 +630,14 @@ void melps4_cpu_device::op_su() void melps4_cpu_device::op_ei() { // EI: enable interrupt flag + m_prohibit_irq = true; m_inte = 1; } void melps4_cpu_device::op_di() { // DI: disable interrupt flag + m_prohibit_irq = true; m_inte = 0; } diff --git a/src/emu/cpu/mips/mips3.c b/src/emu/cpu/mips/mips3.c index 1b196f0fa4d..3b377dfa64f 100644 --- a/src/emu/cpu/mips/mips3.c +++ b/src/emu/cpu/mips/mips3.c @@ -1010,8 +1010,7 @@ inline bool mips3_device::RBYTE(offs_t address, UINT32 *result) { continue; } - UINT8 *fastbase = (UINT8*)m_fastram[ramnum].base - m_fastram[ramnum].start; - *result = fastbase[tlbaddress ^ m_byte_xor]; + *result = m_fastram[ramnum].offset_base8[tlbaddress ^ m_byte_xor]; return true; } *result = (*m_memory.read_byte)(*m_program, tlbaddress); @@ -1044,8 +1043,7 @@ inline bool mips3_device::RHALF(offs_t address, UINT32 *result) { continue; } - UINT8 *fastbase = (UINT8*)m_fastram[ramnum].base - m_fastram[ramnum].start; - *result = ((UINT16*)fastbase)[(tlbaddress ^ m_word_xor) >> 1]; + *result = m_fastram[ramnum].offset_base16[(tlbaddress ^ m_word_xor) >> 1]; return true; } *result = (*m_memory.read_word)(*m_program, tlbaddress); @@ -1078,8 +1076,7 @@ inline bool mips3_device::RWORD(offs_t address, UINT32 *result) { continue; } - UINT8 *fastbase = (UINT8*)m_fastram[ramnum].base - m_fastram[ramnum].start; - *result = ((UINT32*)fastbase)[tlbaddress >> 2]; + *result = m_fastram[ramnum].offset_base32[tlbaddress >> 2]; return true; } *result = (*m_memory.read_dword)(*m_program, tlbaddress); @@ -1181,8 +1178,7 @@ inline void mips3_device::WBYTE(offs_t address, UINT8 data) { continue; } - UINT8 *fastbase = (UINT8*)m_fastram[ramnum].base - m_fastram[ramnum].start; - fastbase[tlbaddress ^ m_byte_xor] = data; + m_fastram[ramnum].offset_base8[tlbaddress ^ m_byte_xor] = data; return; } (*m_memory.write_byte)(*m_program, tlbaddress, data); @@ -1216,8 +1212,7 @@ inline void mips3_device::WHALF(offs_t address, UINT16 data) { continue; } - void *fastbase = (UINT8*)m_fastram[ramnum].base - m_fastram[ramnum].start; - ((UINT16*)fastbase)[(tlbaddress ^ m_word_xor) >> 1] = data; + m_fastram[ramnum].offset_base16[(tlbaddress ^ m_word_xor) >> 1] = data; return; } (*m_memory.write_word)(*m_program, tlbaddress, data); @@ -1251,8 +1246,7 @@ inline void mips3_device::WWORD(offs_t address, UINT32 data) { continue; } - void *fastbase = (UINT8*)m_fastram[ramnum].base - m_fastram[ramnum].start; - ((UINT32*)fastbase)[tlbaddress >> 2] = data; + m_fastram[ramnum].offset_base32[tlbaddress >> 2] = data; return; } (*m_memory.write_dword)(*m_program, tlbaddress, data); diff --git a/src/emu/cpu/mips/mips3.h b/src/emu/cpu/mips/mips3.h index f0b860619ff..2cbdf93c28f 100644 --- a/src/emu/cpu/mips/mips3.h +++ b/src/emu/cpu/mips/mips3.h @@ -416,6 +416,9 @@ private: offs_t end; /* end of the RAM block */ UINT8 readonly; /* TRUE if read-only */ void * base; /* base in memory where the RAM lives */ + UINT8 * offset_base8; /* base in memory where the RAM lives, 8-bit pointer, with the start offset pre-applied */ + UINT16 * offset_base16; /* base in memory where the RAM lives, 16-bit pointer, with the start offset pre-applied */ + UINT32 * offset_base32; /* base in memory where the RAM lives, 32-bit pointer, with the start offset pre-applied */ } m_fastram[MIPS3_MAX_FASTRAM]; UINT64 m_debugger_temp; diff --git a/src/emu/cpu/mips/mips3drc.c b/src/emu/cpu/mips/mips3drc.c index 3e73d96f206..70c31df2220 100644 --- a/src/emu/cpu/mips/mips3drc.c +++ b/src/emu/cpu/mips/mips3drc.c @@ -182,6 +182,9 @@ void mips3_device::add_fastram(offs_t start, offs_t end, UINT8 readonly, void *b m_fastram[m_fastram_select].end = end; m_fastram[m_fastram_select].readonly = readonly; m_fastram[m_fastram_select].base = base; + m_fastram[m_fastram_select].offset_base8 = (UINT8*)base - start; + m_fastram[m_fastram_select].offset_base16 = (UINT16*)((UINT8*)base - start); + m_fastram[m_fastram_select].offset_base32 = (UINT32*)((UINT8*)base - start); m_fastram_select++; } } diff --git a/src/emu/cpu/mn10200/mn10200.c b/src/emu/cpu/mn10200/mn10200.c index e05c032c91c..0fdb1edd946 100644 --- a/src/emu/cpu/mn10200/mn10200.c +++ b/src/emu/cpu/mn10200/mn10200.c @@ -35,28 +35,88 @@ enum mn10200_flag FLAG_D15 = 0x8000 // ? }; -const device_type MN1020012A = &device_creator<mn10200_device>; -static ADDRESS_MAP_START( mn1020012_internal_map, AS_PROGRAM, 16, mn10200_device ) +const device_type MN1020012A = &device_creator<mn1020012a_device>; + +// internal memory maps +static ADDRESS_MAP_START( mn1020012a_internal_map, AS_PROGRAM, 16, mn10200_device ) AM_RANGE(0x00fc00, 0x00ffff) AM_READWRITE8(io_control_r, io_control_w, 0xffff) ADDRESS_MAP_END -mn10200_device::mn10200_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : cpu_device(mconfig, MN1020012A, "MN1020012A", tag, owner, clock, "mn1020012a", __FILE__), - m_program_config("program", ENDIANNESS_LITTLE, 16, 24, 0, ADDRESS_MAP_NAME(mn1020012_internal_map)), - m_io_config("data", ENDIANNESS_LITTLE, 8, 8, 0) + +// device definitions +mn1020012a_device::mn1020012a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : mn10200_device(mconfig, MN1020012A, "MN1020012A", tag, owner, clock, ADDRESS_MAP_NAME(mn1020012a_internal_map), "mn1020012a", __FILE__) +{ } + + +// disasm +void mn10200_device::state_string_export(const device_state_entry &entry, std::string &str) +{ + switch (entry.index()) + { + case STATE_GENFLAGS: + strprintf(str, "S=%d irq=%s im=%d %c%c%c%c %c%c%c%c", + (m_psw >> 12) & 3, + m_psw & FLAG_IE ? "on " : "off", + (m_psw >> 8) & 7, + m_psw & FLAG_VX ? 'V' : '-', + m_psw & FLAG_CX ? 'C' : '-', + m_psw & FLAG_NX ? 'N' : '-', + m_psw & FLAG_ZX ? 'Z' : '-', + m_psw & FLAG_VF ? 'v' : '-', + m_psw & FLAG_CF ? 'c' : '-', + m_psw & FLAG_NF ? 'n' : '-', + m_psw & FLAG_ZF ? 'z' : '-'); + break; + } +} + +offs_t mn10200_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) { + extern CPU_DISASSEMBLE( mn10200 ); + return CPU_DISASSEMBLE_NAME(mn10200)(this, buffer, pc, oprom, opram, options); } + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- +enum +{ + MN10200_PC = 0, + MN10200_PSW, + MN10200_MDR, + MN10200_D0, + MN10200_D1, + MN10200_D2, + MN10200_D3, + MN10200_A0, + MN10200_A1, + MN10200_A2, + MN10200_A3, + MN10200_NMICR, + MN10200_IAGR +}; + void mn10200_device::device_start() { m_program = &space(AS_PROGRAM); - m_io = &space(AS_IO); + + // resolve callbacks + m_read_port0.resolve_safe(0xff); + m_read_port1.resolve_safe(0xff); + m_read_port2.resolve_safe(0xff); + m_read_port3.resolve_safe(0xff); + m_read_port4.resolve_safe(0xff); + + m_write_port0.resolve_safe(); + m_write_port1.resolve_safe(); + m_write_port2.resolve_safe(); + m_write_port3.resolve_safe(); + m_write_port4.resolve_safe(); // init and register for savestates save_item(NAME(m_pc)); @@ -176,34 +236,6 @@ void mn10200_device::device_start() } -void mn10200_device::state_string_export(const device_state_entry &entry, std::string &str) -{ - switch (entry.index()) - { - case STATE_GENFLAGS: - strprintf(str, "S=%d irq=%s im=%d %c%c%c%c %c%c%c%c", - (m_psw >> 12) & 3, - m_psw & FLAG_IE ? "on " : "off", - (m_psw >> 8) & 7, - m_psw & FLAG_VX ? 'V' : '-', - m_psw & FLAG_CX ? 'C' : '-', - m_psw & FLAG_NX ? 'N' : '-', - m_psw & FLAG_ZX ? 'Z' : '-', - m_psw & FLAG_VF ? 'v' : '-', - m_psw & FLAG_CF ? 'c' : '-', - m_psw & FLAG_NF ? 'n' : '-', - m_psw & FLAG_ZF ? 'z' : '-'); - break; - } -} - - -offs_t mn10200_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) -{ - extern CPU_DISASSEMBLE( mn10200 ); - return CPU_DISASSEMBLE_NAME(mn10200)(this, buffer, pc, oprom, opram, options); -} - //------------------------------------------------- // device_reset - device-specific reset @@ -234,7 +266,10 @@ void mn10200_device::device_reset() } -// interrupts + +//------------------------------------------------- +// interrupts +//------------------------------------------------- void mn10200_device::take_irq(int level, int group) { @@ -332,7 +367,10 @@ void mn10200_device::execute_set_input(int irqnum, int state) } -// 8-bit timers + +//------------------------------------------------- +// timers +//------------------------------------------------- int mn10200_device::timer_tick_simple(int tmr) { @@ -405,7 +443,10 @@ TIMER_CALLBACK_MEMBER( mn10200_device::simple_timer_cb ) } -// opcode handlers + +//------------------------------------------------- +// opcode helpers +//------------------------------------------------- void mn10200_device::illegal(UINT8 prefix, UINT8 op) { @@ -479,9 +520,9 @@ void mn10200_device::do_jsr(UINT32 to, UINT32 ret) change_pc(to); } -void mn10200_device::do_branch(bool state) +void mn10200_device::do_branch(int condition) { - if (state) + if (condition) { m_cycles -= 1; change_pc(m_pc + (INT8)read_arg8(m_pc)); @@ -490,10 +531,15 @@ void mn10200_device::do_branch(bool state) +//------------------------------------------------- +// execute loop +//------------------------------------------------- + void mn10200_device::execute_run() { while (m_cycles > 0) { + // internal peripheral, external pin, or prev instruction may have changed irq state while (m_possible_irq) { @@ -579,13 +625,13 @@ void mn10200_device::execute_run() // add dn, dm case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: - m_d[op&3] = do_add(m_d[op&3], m_d[op>>2&3], 0); + m_d[op&3] = do_add(m_d[op&3], m_d[op>>2&3]); break; // sub dn, dm case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf: - m_d[op&3] = do_sub(m_d[op&3], m_d[op>>2&3], 0); + m_d[op&3] = do_sub(m_d[op&3], m_d[op>>2&3]); break; // extx dn @@ -634,19 +680,19 @@ void mn10200_device::execute_run() // add imm8, an case 0xd0: case 0xd1: case 0xd2: case 0xd3: - m_a[op&3] = do_add(m_a[op&3], (INT8)read_arg8(m_pc), 0); + m_a[op&3] = do_add(m_a[op&3], (INT8)read_arg8(m_pc)); m_pc += 1; break; // add imm8, dn case 0xd4: case 0xd5: case 0xd6: case 0xd7: - m_d[op&3] = do_add(m_d[op&3], (INT8)read_arg8(m_pc), 0); + m_d[op&3] = do_add(m_d[op&3], (INT8)read_arg8(m_pc)); m_pc += 1; break; // cmp imm8, dn case 0xd8: case 0xd9: case 0xda: case 0xdb: - do_sub(m_d[op&3], (INT8)read_arg8(m_pc), 0); + do_sub(m_d[op&3], (INT8)read_arg8(m_pc)); m_pc += 1; break; @@ -718,7 +764,7 @@ void mn10200_device::execute_run() // bra label8 case 0xea: - do_branch(true); + do_branch(); m_pc += 1; break; @@ -733,7 +779,7 @@ void mn10200_device::execute_run() // cmp imm16, an case 0xec: case 0xed: case 0xee: case 0xef: - do_sub(m_a[op&3], read_arg16(m_pc), 0); + do_sub(m_a[op&3], read_arg16(m_pc)); m_pc += 2; break; @@ -904,17 +950,17 @@ void mn10200_device::execute_run() { // add dm, an case 0x00: - m_a[op&3] = do_add(m_a[op&3], m_d[op>>2&3], 0); + m_a[op&3] = do_add(m_a[op&3], m_d[op>>2&3]); break; // sub dm, an case 0x10: - m_a[op&3] = do_sub(m_a[op&3], m_d[op>>2&3], 0); + m_a[op&3] = do_sub(m_a[op&3], m_d[op>>2&3]); break; // cmp dm, an case 0x20: - do_sub(m_a[op&3], m_d[op>>2&3], 0); + do_sub(m_a[op&3], m_d[op>>2&3]); break; // mov dm, an @@ -924,17 +970,17 @@ void mn10200_device::execute_run() // add an, am case 0x40: - m_a[op&3] = do_add(m_a[op&3], m_a[op>>2&3], 0); + m_a[op&3] = do_add(m_a[op&3], m_a[op>>2&3]); break; // sub an, am case 0x50: - m_a[op&3] = do_sub(m_a[op&3], m_a[op>>2&3], 0); + m_a[op&3] = do_sub(m_a[op&3], m_a[op>>2&3]); break; // cmp an, am case 0x60: - do_sub(m_a[op&3], m_a[op>>2&3], 0); + do_sub(m_a[op&3], m_a[op>>2&3]); break; // mov an, am @@ -962,17 +1008,17 @@ void mn10200_device::execute_run() // add an, dm case 0xc0: - m_d[op&3] = do_add(m_d[op&3], m_a[op>>2&3], 0); + m_d[op&3] = do_add(m_d[op&3], m_a[op>>2&3]); break; // sub an, dm case 0xd0: - m_d[op&3] = do_sub(m_d[op&3], m_a[op>>2&3], 0); + m_d[op&3] = do_sub(m_d[op&3], m_a[op>>2&3]); break; // cmp an, dm case 0xe0: - do_sub(m_d[op&3], m_a[op>>2&3], 0); + do_sub(m_d[op&3], m_a[op>>2&3]); break; // mov an, dm @@ -1123,7 +1169,7 @@ void mn10200_device::execute_run() // cmp dn, dm case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f: - do_sub(m_d[op&3], m_d[op>>2&3], 0); + do_sub(m_d[op&3], m_d[op>>2&3]); break; // mov dn, mdr @@ -1221,22 +1267,22 @@ void mn10200_device::execute_run() // add imm24, dn case 0x60: case 0x61: case 0x62: case 0x63: - m_d[op&3] = do_add(m_d[op&3], read_arg24(m_pc), 0); + m_d[op&3] = do_add(m_d[op&3], read_arg24(m_pc)); break; // add imm24, an case 0x64: case 0x65: case 0x66: case 0x67: - m_a[op&3] = do_add(m_a[op&3], read_arg24(m_pc), 0); + m_a[op&3] = do_add(m_a[op&3], read_arg24(m_pc)); break; // sub imm24, dn case 0x68: case 0x69: case 0x6a: case 0x6b: - m_d[op&3] = do_sub(m_d[op&3], read_arg24(m_pc), 0); + m_d[op&3] = do_sub(m_d[op&3], read_arg24(m_pc)); break; // sub imm24, an case 0x6c: case 0x6d: case 0x6e: case 0x6f: - m_a[op&3] = do_sub(m_a[op&3], read_arg24(m_pc), 0); + m_a[op&3] = do_sub(m_a[op&3], read_arg24(m_pc)); break; // mov imm24, dn @@ -1251,12 +1297,12 @@ void mn10200_device::execute_run() // cmp imm24, dn case 0x78: case 0x79: case 0x7a: case 0x7b: - do_sub(m_d[op&3], read_arg24(m_pc), 0); + do_sub(m_d[op&3], read_arg24(m_pc)); break; // cmp imm24, an case 0x7c: case 0x7d: case 0x7e: case 0x7f: - do_sub(m_a[op&3], read_arg24(m_pc), 0); + do_sub(m_a[op&3], read_arg24(m_pc)); break; // mov (d24, an), dm @@ -1514,12 +1560,12 @@ void mn10200_device::execute_run() // add imm16, an case 0x08: case 0x09: case 0x0a: case 0x0b: - m_a[op&3] = do_add(m_a[op&3], (INT16)read_arg16(m_pc), 0); + m_a[op&3] = do_add(m_a[op&3], (INT16)read_arg16(m_pc)); break; // sub imm16, an case 0x0c: case 0x0d: case 0x0e: case 0x0f: - m_a[op&3] = do_sub(m_a[op&3], (INT16)read_arg16(m_pc), 0); + m_a[op&3] = do_sub(m_a[op&3], (INT16)read_arg16(m_pc)); break; // and imm16, psw @@ -1537,12 +1583,12 @@ void mn10200_device::execute_run() // add imm16, dn case 0x18: case 0x19: case 0x1a: case 0x1b: - m_d[op&3] = do_add(m_d[op&3], (INT16)read_arg16(m_pc), 0); + m_d[op&3] = do_add(m_d[op&3], (INT16)read_arg16(m_pc)); break; // sub imm16, dn case 0x1c: case 0x1d: case 0x1e: case 0x1f: - m_d[op&3] = do_sub(m_d[op&3], (INT16)read_arg16(m_pc), 0); + m_d[op&3] = do_sub(m_d[op&3], (INT16)read_arg16(m_pc)); break; // mov an, (abs16) @@ -1564,7 +1610,7 @@ void mn10200_device::execute_run() // cmp imm16, dn case 0x48: case 0x49: case 0x4a: case 0x4b: - do_sub(m_d[op&3], (INT16)read_arg16(m_pc), 0); + do_sub(m_d[op&3], (INT16)read_arg16(m_pc)); break; // xor imm16, dn @@ -1644,7 +1690,10 @@ void mn10200_device::execute_run() } -// internal i/o + +//------------------------------------------------- +// internal i/o +//------------------------------------------------- WRITE8_MEMBER(mn10200_device::io_control_w) { @@ -2007,19 +2056,19 @@ WRITE8_MEMBER(mn10200_device::io_control_w) // outputs case 0x3c0: m_port[0].out = data; - m_io->write_byte(MN10200_PORT0, m_port[0].out | (m_port[0].dir ^ 0xff)); + m_write_port0(MN10200_PORT0, m_port[0].out | (m_port[0].dir ^ 0xff), 0xff); break; case 0x264: m_port[1].out = data; - m_io->write_byte(MN10200_PORT1, m_port[1].out | (m_port[1].dir ^ 0xff)); + m_write_port1(MN10200_PORT1, m_port[1].out | (m_port[1].dir ^ 0xff), 0xff); break; case 0x3c2: m_port[2].out = data & 0x0f; - m_io->write_byte(MN10200_PORT2, m_port[2].out | (m_port[2].dir ^ 0x0f)); + m_write_port2(MN10200_PORT2, m_port[2].out | (m_port[2].dir ^ 0x0f), 0xff); break; case 0x3c3: m_port[3].out = data & 0x1f; - m_io->write_byte(MN10200_PORT3, m_port[3].out | (m_port[3].dir ^ 0x1f)); + m_write_port3(MN10200_PORT3, m_port[3].out | (m_port[3].dir ^ 0x1f), 0xff); break; // directions (0=input, 1=output) @@ -2049,7 +2098,6 @@ WRITE8_MEMBER(mn10200_device::io_control_w) } - READ8_MEMBER(mn10200_device::io_control_r) { switch (offset) @@ -2151,13 +2199,13 @@ READ8_MEMBER(mn10200_device::io_control_r) // inputs case 0x3d0: - return m_io->read_byte(MN10200_PORT0) | m_port[0].dir; + return m_read_port0(MN10200_PORT0, 0xff) | m_port[0].dir; case 0x3d1: - return m_io->read_byte(MN10200_PORT1) | m_port[1].dir; + return m_read_port1(MN10200_PORT1, 0xff) | m_port[1].dir; case 0x3d2: - return (m_io->read_byte(MN10200_PORT2) & 0x0f) | m_port[2].dir; + return (m_read_port2(MN10200_PORT2, 0xff) & 0x0f) | m_port[2].dir; case 0x3d3: - return (m_io->read_byte(MN10200_PORT3) & 0x1f) | m_port[3].dir; + return (m_read_port3(MN10200_PORT3, 0xff) & 0x1f) | m_port[3].dir; // directions (0=input, 1=output) case 0x3e0: diff --git a/src/emu/cpu/mn10200/mn10200.h b/src/emu/cpu/mn10200/mn10200.h index 61ebb96fb0c..59be253f852 100644 --- a/src/emu/cpu/mn10200/mn10200.h +++ b/src/emu/cpu/mn10200/mn10200.h @@ -8,27 +8,14 @@ */ -#pragma once - #ifndef MN10200_H #define MN10200_H -enum -{ - MN10200_PC = 0, - MN10200_PSW, - MN10200_MDR, - MN10200_D0, - MN10200_D1, - MN10200_D2, - MN10200_D3, - MN10200_A0, - MN10200_A1, - MN10200_A2, - MN10200_A3, - MN10200_NMICR, - MN10200_IAGR -}; +// port setup +#define MCFG_MN10200_READ_PORT_CB(X, _devcb) \ + mn10200_device::set_read_port##X##_callback(*device, DEVCB_##_devcb); +#define MCFG_MN10200_WRITE_PORT_CB(X, _devcb) \ + mn10200_device::set_write_port##X##_callback(*device, DEVCB_##_devcb); enum { @@ -50,9 +37,6 @@ enum }; -extern const device_type MN1020012A; - - #define MN10200_NUM_PRESCALERS (2) #define MN10200_NUM_TIMERS_8BIT (10) #define MN10200_NUM_IRQ_GROUPS (31) @@ -62,7 +46,25 @@ class mn10200_device : public cpu_device { public: // construction/destruction - mn10200_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + mn10200_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, address_map_constructor program, const char *shortname, const char *source) + : cpu_device(mconfig, type, name, tag, owner, clock, shortname, source) + , m_program_config("program", ENDIANNESS_LITTLE, 16, 24, 0, program) + , m_read_port0(*this), m_read_port1(*this), m_read_port2(*this), m_read_port3(*this), m_read_port4(*this) + , m_write_port0(*this), m_write_port1(*this), m_write_port2(*this), m_write_port3(*this), m_write_port4(*this) + { } + + // static configuration helpers + template<class _Object> static devcb_base &set_read_port0_callback(device_t &device, _Object object) { return downcast<mn10200_device &>(device).m_read_port0.set_callback(object); } + template<class _Object> static devcb_base &set_read_port1_callback(device_t &device, _Object object) { return downcast<mn10200_device &>(device).m_read_port1.set_callback(object); } + template<class _Object> static devcb_base &set_read_port2_callback(device_t &device, _Object object) { return downcast<mn10200_device &>(device).m_read_port2.set_callback(object); } + template<class _Object> static devcb_base &set_read_port3_callback(device_t &device, _Object object) { return downcast<mn10200_device &>(device).m_read_port3.set_callback(object); } + template<class _Object> static devcb_base &set_read_port4_callback(device_t &device, _Object object) { return downcast<mn10200_device &>(device).m_read_port4.set_callback(object); } + + template<class _Object> static devcb_base &set_write_port0_callback(device_t &device, _Object object) { return downcast<mn10200_device &>(device).m_write_port0.set_callback(object); } + template<class _Object> static devcb_base &set_write_port1_callback(device_t &device, _Object object) { return downcast<mn10200_device &>(device).m_write_port1.set_callback(object); } + template<class _Object> static devcb_base &set_write_port2_callback(device_t &device, _Object object) { return downcast<mn10200_device &>(device).m_write_port2.set_callback(object); } + template<class _Object> static devcb_base &set_write_port3_callback(device_t &device, _Object object) { return downcast<mn10200_device &>(device).m_write_port3.set_callback(object); } + template<class _Object> static devcb_base &set_write_port4_callback(device_t &device, _Object object) { return downcast<mn10200_device &>(device).m_write_port4.set_callback(object); } DECLARE_READ8_MEMBER(io_control_r); DECLARE_WRITE8_MEMBER(io_control_w); @@ -76,16 +78,13 @@ protected: virtual UINT64 execute_clocks_to_cycles(UINT64 clocks) const { return (clocks + 2 - 1) / 2; } // internal /2 divider virtual UINT64 execute_cycles_to_clocks(UINT64 cycles) const { return (cycles * 2); } // internal /2 divider virtual UINT32 execute_min_cycles() const { return 1; } - virtual UINT32 execute_max_cycles() const { return 13; } + virtual UINT32 execute_max_cycles() const { return 13+7; } // max opcode cycles + interrupt duration virtual UINT32 execute_input_lines() const { return 4; } virtual void execute_run(); virtual void execute_set_input(int inputnum, int state); // device_memory_interface overrides - virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const - { - return (spacenum == AS_PROGRAM) ? &m_program_config : ( (spacenum == AS_IO) ? &m_io_config : NULL ); - } + virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : NULL; } // device_state_interface overrides void state_string_export(const device_state_entry &entry, std::string &str); @@ -97,10 +96,11 @@ protected: private: address_space_config m_program_config; - address_space_config m_io_config; - address_space *m_program; - address_space *m_io; + + // i/o handlers + devcb_read8 m_read_port0, m_read_port1, m_read_port2, m_read_port3, m_read_port4; + devcb_write8 m_write_port0, m_write_port1, m_write_port2, m_write_port3, m_write_port4; int m_cycles; @@ -112,6 +112,10 @@ private: UINT16 m_mdr; // interrupts + void take_irq(int level, int group); + void check_irq(); + void check_ext_irq(); + UINT8 m_icrl[MN10200_NUM_IRQ_GROUPS]; UINT8 m_icrh[MN10200_NUM_IRQ_GROUPS]; @@ -122,6 +126,11 @@ private: bool m_possible_irq; // timers + void refresh_timer(int tmr); + void refresh_all_timers(); + int timer_tick_simple(int tmr); + TIMER_CALLBACK_MEMBER( simple_timer_cb ); + attotime m_sysclock_base; emu_timer *m_timer_timers[MN10200_NUM_TIMERS_8BIT]; @@ -185,20 +194,25 @@ private: inline void change_pc(UINT32 pc) { m_pc = pc & 0xffffff; } - void take_irq(int level, int group); - void check_irq(); - void check_ext_irq(); - void refresh_timer(int tmr); - void refresh_all_timers(); - int timer_tick_simple(int tmr); - TIMER_CALLBACK_MEMBER( simple_timer_cb ); + // opcode helpers void illegal(UINT8 prefix, UINT8 op); - UINT32 do_add(UINT32 a, UINT32 b, UINT32 c); - UINT32 do_sub(UINT32 a, UINT32 b, UINT32 c); + UINT32 do_add(UINT32 a, UINT32 b, UINT32 c = 0); + UINT32 do_sub(UINT32 a, UINT32 b, UINT32 c = 0); void test_nz16(UINT16 v); void do_jsr(UINT32 to, UINT32 ret); - void do_branch(bool state); + void do_branch(int condition = 1); }; -#endif +class mn1020012a_device : public mn10200_device +{ +public: + mn1020012a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); +}; + + + +extern const device_type MN1020012A; + + +#endif // MN10200_H diff --git a/src/emu/cpu/pdp1/pdp1.c b/src/emu/cpu/pdp1/pdp1.c index 3c414bd5ed6..bb7beee4128 100644 --- a/src/emu/cpu/pdp1/pdp1.c +++ b/src/emu/cpu/pdp1/pdp1.c @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Raphael Nabet /* * Note: Original Java source written by: diff --git a/src/emu/cpu/pdp1/pdp1.h b/src/emu/cpu/pdp1/pdp1.h index c4c9c8c465e..f4d1281aa07 100644 --- a/src/emu/cpu/pdp1/pdp1.h +++ b/src/emu/cpu/pdp1/pdp1.h @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Raphael Nabet #pragma once diff --git a/src/emu/cpu/pdp1/pdp1dasm.c b/src/emu/cpu/pdp1/pdp1dasm.c index 036aa3e2f22..c8682ca1491 100644 --- a/src/emu/cpu/pdp1/pdp1dasm.c +++ b/src/emu/cpu/pdp1/pdp1dasm.c @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Raphael Nabet #include "emu.h" #include "cpu/pdp1/pdp1.h" diff --git a/src/emu/cpu/pdp1/tx0.c b/src/emu/cpu/pdp1/tx0.c index 1a3ab230f4b..03c8441d88f 100644 --- a/src/emu/cpu/pdp1/tx0.c +++ b/src/emu/cpu/pdp1/tx0.c @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Raphael Nabet /* TX-0 emulator diff --git a/src/emu/cpu/pdp1/tx0.h b/src/emu/cpu/pdp1/tx0.h index bdb492bbfc3..e88172bc8ff 100644 --- a/src/emu/cpu/pdp1/tx0.h +++ b/src/emu/cpu/pdp1/tx0.h @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Raphael Nabet #pragma once diff --git a/src/emu/cpu/pdp1/tx0dasm.c b/src/emu/cpu/pdp1/tx0dasm.c index 8eef06f832e..3d8a1daf9e1 100644 --- a/src/emu/cpu/pdp1/tx0dasm.c +++ b/src/emu/cpu/pdp1/tx0dasm.c @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Raphael Nabet #include "emu.h" #include "cpu/pdp1/tx0.h" diff --git a/src/emu/cpu/pic16c62x/pic16c62x.c b/src/emu/cpu/pic16c62x/pic16c62x.c index 42e92b0addf..1d2dae52b95 100644 --- a/src/emu/cpu/pic16c62x/pic16c62x.c +++ b/src/emu/cpu/pic16c62x/pic16c62x.c @@ -57,6 +57,15 @@ #include "pic16c62x.h" +const device_type PIC16C620 = &device_creator<pic16c620_device>; +const device_type PIC16C620A = &device_creator<pic16c620a_device>; +const device_type PIC16C621 = &device_creator<pic16c621_device>; +const device_type PIC16C621A = &device_creator<pic16c621a_device>; +const device_type PIC16C622 = &device_creator<pic16c622_device>; +const device_type PIC16C622A = &device_creator<pic16c622a_device>; + + + /**************************************************************************** * Internal Memory Map ****************************************************************************/ diff --git a/src/emu/cpu/rsp/rspcp2.c b/src/emu/cpu/rsp/rspcp2.c index 8371583c948..c7d15bec393 100644 --- a/src/emu/cpu/rsp/rspcp2.c +++ b/src/emu/cpu/rsp/rspcp2.c @@ -131,6 +131,7 @@ rsp_cop2::rsp_cop2(rsp_device &rsp, running_machine &machine) memset(m_v, 0, sizeof(m_v)); memset(m_vflag, 0, sizeof(m_vflag)); memset(m_accum, 0, sizeof(m_accum)); + m_rspcop2_state = (internal_rspcop2_state *)rsp.m_cache.alloc_near(sizeof(internal_rspcop2_state)); } rsp_cop2::~rsp_cop2() @@ -2567,7 +2568,7 @@ void rsp_cop2::handle_cop2(UINT32 op) inline void rsp_cop2::mfc2() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int el = (op >> 7) & 0xf; UINT16 b1 = VREG_B(VS1REG, (el+0) & 0xf); @@ -2577,7 +2578,7 @@ inline void rsp_cop2::mfc2() inline void rsp_cop2::cfc2() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; if (RTREG) { switch(RDREG) @@ -2636,7 +2637,7 @@ inline void rsp_cop2::cfc2() inline void rsp_cop2::mtc2() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int el = (op >> 7) & 0xf; VREG_B(VS1REG, (el+0) & 0xf) = (RTVAL >> 8) & 0xff; VREG_B(VS1REG, (el+1) & 0xf) = (RTVAL >> 0) & 0xff; @@ -2644,7 +2645,7 @@ inline void rsp_cop2::mtc2() inline void rsp_cop2::ctc2() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; switch(RDREG) { case 0: diff --git a/src/emu/cpu/rsp/rspcp2.h b/src/emu/cpu/rsp/rspcp2.h index 15857bd687c..18e9d59fbff 100644 --- a/src/emu/cpu/rsp/rspcp2.h +++ b/src/emu/cpu/rsp/rspcp2.h @@ -135,8 +135,13 @@ protected: UINT16 SATURATE_ACCUM(int accum, int slice, UINT16 negative, UINT16 positive); UINT16 SATURATE_ACCUM1(int accum, UINT16 negative, UINT16 positive); - UINT32 m_op; + // Data that needs to be stored close to the generated DRC code + struct internal_rspcop2_state + { + UINT32 op; + }; + internal_rspcop2_state *m_rspcop2_state; rsp_device& m_rsp; running_machine& m_machine; UINT32 m_vres[8]; /* used for temporary vector results */ diff --git a/src/emu/cpu/rsp/rspcp2d.c b/src/emu/cpu/rsp/rspcp2d.c index 3a5ca09b9ee..779fea5819c 100644 --- a/src/emu/cpu/rsp/rspcp2d.c +++ b/src/emu/cpu/rsp/rspcp2d.c @@ -94,7 +94,7 @@ static void cfunc_ctc2(void *param); #define CLEAR_CLIP2_FLAG(x) { m_vflag[CLIP2][x & 7] = 0; } #define CACHE_VALUES() \ - const int op = m_op; \ + const int op = m_rspcop2_state->op; \ const int vdreg = VDREG; \ const int vs1reg = VS1REG; \ const int vs2reg = VS2REG; \ @@ -137,10 +137,10 @@ void rsp_cop2_drc::cfunc_unimplemented_opcode() if ((m_machine.debug_flags & DEBUG_FLAG_ENABLED) != 0) { char string[200]; - rsp_dasm_one(string, ppc, m_op); + rsp_dasm_one(string, ppc, m_rspcop2_state->op); osd_printf_debug("%08X: %s\n", ppc, string); } - fatalerror("RSP: unknown opcode %02X (%08X) at %08X\n", m_op >> 26, m_op, ppc); + fatalerror("RSP: unknown opcode %02X (%08X) at %08X\n", m_rspcop2_state->op >> 26, m_rspcop2_state->op, ppc); } static void unimplemented_opcode(void *param) @@ -267,7 +267,7 @@ void rsp_cop2_drc::state_string_export(const int index, std::string &str) void rsp_cop2_drc::lbv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; UINT32 ea = 0; int dest = (op >> 16) & 0x1f; @@ -300,7 +300,7 @@ static void cfunc_lbv(void *param) void rsp_cop2_drc::lsv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xe; @@ -336,7 +336,7 @@ static void cfunc_lsv(void *param) void rsp_cop2_drc::llv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; UINT32 ea = 0; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; @@ -375,7 +375,7 @@ static void cfunc_llv(void *param) void rsp_cop2_drc::ldv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; UINT32 ea = 0; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; @@ -414,7 +414,7 @@ static void cfunc_ldv(void *param) void rsp_cop2_drc::lqv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int offset = (op & 0x7f); @@ -452,7 +452,7 @@ static void cfunc_lqv(void *param) void rsp_cop2_drc::lrv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -491,7 +491,7 @@ static void cfunc_lrv(void *param) void rsp_cop2_drc::lpv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -526,7 +526,7 @@ static void cfunc_lpv(void *param) void rsp_cop2_drc::luv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -561,7 +561,7 @@ static void cfunc_luv(void *param) void rsp_cop2_drc::lhv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -595,7 +595,7 @@ static void cfunc_lhv(void *param) void rsp_cop2_drc::lfv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -636,7 +636,7 @@ static void cfunc_lfv(void *param) void rsp_cop2_drc::lwv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -673,7 +673,7 @@ static void cfunc_lwv(void *param) void rsp_cop2_drc::ltv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -720,62 +720,62 @@ int rsp_cop2_drc::generate_lwc2(drcuml_block *block, rsp_device::compiler_state switch ((op >> 11) & 0x1f) { case 0x00: /* LBV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l UML_CALLC(block, cfunc_lbv, this); return TRUE; case 0x01: /* LSV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l UML_CALLC(block, cfunc_lsv, this); return TRUE; case 0x02: /* LLV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l UML_CALLC(block, cfunc_llv, this); return TRUE; case 0x03: /* LDV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l UML_CALLC(block, cfunc_ldv, this); return TRUE; case 0x04: /* LQV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l UML_CALLC(block, cfunc_lqv, this); return TRUE; case 0x05: /* LRV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l UML_CALLC(block, cfunc_lrv, this); return TRUE; case 0x06: /* LPV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l UML_CALLC(block, cfunc_lpv, this); return TRUE; case 0x07: /* LUV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l UML_CALLC(block, cfunc_luv, this); return TRUE; case 0x08: /* LHV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l UML_CALLC(block, cfunc_lhv, this); return TRUE; case 0x09: /* LFV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l UML_CALLC(block, cfunc_lfv, this); return TRUE; case 0x0a: /* LWV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l UML_CALLC(block, cfunc_lwv, this); return TRUE; case 0x0b: /* LTV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l UML_CALLC(block, cfunc_ltv, this); return TRUE; @@ -800,7 +800,7 @@ int rsp_cop2_drc::generate_lwc2(drcuml_block *block, rsp_device::compiler_state void rsp_cop2_drc::sbv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -831,7 +831,7 @@ static void cfunc_sbv(void *param) void rsp_cop2_drc::ssv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -868,7 +868,7 @@ static void cfunc_ssv(void *param) void rsp_cop2_drc::slv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -905,7 +905,7 @@ static void cfunc_slv(void *param) void rsp_cop2_drc::sdv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0x8; @@ -941,7 +941,7 @@ static void cfunc_sdv(void *param) void rsp_cop2_drc::sqv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -977,7 +977,7 @@ static void cfunc_sqv(void *param) void rsp_cop2_drc::srv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -1017,7 +1017,7 @@ static void cfunc_srv(void *param) void rsp_cop2_drc::spv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -1060,7 +1060,7 @@ static void cfunc_spv(void *param) void rsp_cop2_drc::suv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -1103,7 +1103,7 @@ static void cfunc_suv(void *param) void rsp_cop2_drc::shv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -1141,7 +1141,7 @@ static void cfunc_shv(void *param) void rsp_cop2_drc::sfv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -1182,7 +1182,7 @@ static void cfunc_sfv(void *param) void rsp_cop2_drc::swv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -1221,7 +1221,7 @@ static void cfunc_swv(void *param) void rsp_cop2_drc::stv() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int dest = (op >> 16) & 0x1f; int base = (op >> 21) & 0x1f; int index = (op >> 7) & 0xf; @@ -1270,62 +1270,62 @@ int rsp_cop2_drc::generate_swc2(drcuml_block *block, rsp_device::compiler_state switch ((op >> 11) & 0x1f) { case 0x00: /* SBV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_sbv, this); return TRUE; case 0x01: /* SSV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_ssv, this); return TRUE; case 0x02: /* SLV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_slv, this); return TRUE; case 0x03: /* SDV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_sdv, this); return TRUE; case 0x04: /* SQV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_sqv, this); return TRUE; case 0x05: /* SRV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_srv, this); return TRUE; case 0x06: /* SPV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_spv, this); return TRUE; case 0x07: /* SUV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_suv, this); return TRUE; case 0x08: /* SHV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_shv, this); return TRUE; case 0x09: /* SFV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_sfv, this); return TRUE; case 0x0a: /* SWV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_swv, this); return TRUE; case 0x0b: /* STV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_stv, this); return TRUE; @@ -2079,7 +2079,7 @@ static void cfunc_vaddb(void *param) void rsp_cop2_drc::vsaw() { - const int op = m_op; + const int op = m_rspcop2_state->op; const int vdreg = VDREG; const int el = EL; @@ -3264,217 +3264,217 @@ int rsp_cop2_drc::generate_vector_opcode(drcuml_block *block, rsp_device::compil switch (op & 0x3f) { case 0x00: /* VMULF */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vmulf, this); return TRUE; case 0x01: /* VMULU */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vmulu, this); return TRUE; case 0x04: /* VMUDL */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vmudl, this); return TRUE; case 0x05: /* VMUDM */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vmudm, this); return TRUE; case 0x06: /* VMUDN */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vmudn, this); return TRUE; case 0x07: /* VMUDH */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vmudh, this); return TRUE; case 0x08: /* VMACF */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vmacf, this); return TRUE; case 0x09: /* VMACU */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vmacu, this); return TRUE; case 0x0c: /* VMADL */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vmadl, this); return TRUE; case 0x0d: /* VMADM */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vmadm, this); return TRUE; case 0x0e: /* VMADN */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vmadn, this); return TRUE; case 0x0f: /* VMADH */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vmadh, this); return TRUE; case 0x10: /* VADD */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vadd, this); return TRUE; case 0x11: /* VSUB */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vsub, this); return TRUE; case 0x13: /* VABS */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vabs, this); return TRUE; case 0x14: /* VADDC */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vaddc, this); return TRUE; case 0x15: /* VSUBC */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vsubc, this); return TRUE; case 0x16: /* VADDB */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vaddb, this); return TRUE; case 0x17: /* VSUBB (reserved, functionally identical to VADDB) */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vaddb, this); return TRUE; case 0x18: /* VACCB (reserved, functionally identical to VADDB) */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vaddb, this); return TRUE; case 0x19: /* VSUCB (reserved, functionally identical to VADDB) */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vaddb, this); return TRUE; case 0x1d: /* VSAW */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vsaw, this); return TRUE; case 0x20: /* VLT */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vlt, this); return TRUE; case 0x21: /* VEQ */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_veq, this); return TRUE; case 0x22: /* VNE */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vne, this); return TRUE; case 0x23: /* VGE */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vge, this); return TRUE; case 0x24: /* VCL */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vcl, this); return TRUE; case 0x25: /* VCH */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vch, this); return TRUE; case 0x26: /* VCR */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vcr, this); return TRUE; case 0x27: /* VMRG */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vmrg, this); return TRUE; case 0x28: /* VAND */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vand, this); return TRUE; case 0x29: /* VNAND */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vnand, this); return TRUE; case 0x2a: /* VOR */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vor, this); return TRUE; case 0x2b: /* VNOR */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vnor, this); return TRUE; case 0x2c: /* VXOR */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vxor, this); return TRUE; case 0x2d: /* VNXOR */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vnxor, this); return TRUE; case 0x30: /* VRCP */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vrcp, this); return TRUE; case 0x31: /* VRCPL */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vrcpl, this); return TRUE; case 0x32: /* VRCPH */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vrcph, this); return TRUE; case 0x33: /* VMOV */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vmov, this); return TRUE; case 0x34: /* VRSQ */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vrsq, this); return TRUE; case 0x35: /* VRSQL */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vrsql, this); return TRUE; case 0x36: /* VRSQH */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_vrsqh, this); return TRUE; @@ -3483,7 +3483,7 @@ int rsp_cop2_drc::generate_vector_opcode(drcuml_block *block, rsp_device::compil return TRUE; default: - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, unimplemented_opcode, &m_rsp); return FALSE; } @@ -3496,7 +3496,7 @@ int rsp_cop2_drc::generate_vector_opcode(drcuml_block *block, rsp_device::compil void rsp_cop2_drc::mfc2() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int el = (op >> 7) & 0xf; UINT16 b1 = VREG_B(VS1REG, (el+0) & 0xf); @@ -3511,7 +3511,7 @@ static void cfunc_mfc2(void *param) void rsp_cop2_drc::cfc2() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; if (RTREG) { switch(RDREG) @@ -3576,7 +3576,7 @@ static void cfunc_cfc2(void *param) void rsp_cop2_drc::mtc2() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; int el = (op >> 7) & 0xf; VREG_B(VS1REG, (el+0) & 0xf) = (RTVAL >> 8) & 0xff; VREG_B(VS1REG, (el+1) & 0xf) = (RTVAL >> 0) & 0xff; @@ -3590,7 +3590,7 @@ static void cfunc_mtc2(void *param) void rsp_cop2_drc::ctc2() { - UINT32 op = m_op; + UINT32 op = m_rspcop2_state->op; switch(RDREG) { case 0: @@ -3706,7 +3706,7 @@ int rsp_cop2_drc::generate_cop2(drcuml_block *block, rsp_device::compiler_state case 0x00: /* MFCz */ if (RTREG != 0) { - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_mfc2, this); // callc mfc2 } return TRUE; @@ -3714,18 +3714,18 @@ int rsp_cop2_drc::generate_cop2(drcuml_block *block, rsp_device::compiler_state case 0x02: /* CFCz */ if (RTREG != 0) { - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_cfc2, this); // callc cfc2 } return TRUE; case 0x04: /* MTCz */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_mtc2, this); // callc mtc2 return TRUE; case 0x06: /* CTCz */ - UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_ctc2, this); // callc ctc2 return TRUE; diff --git a/src/emu/cpu/sc61860/sc61860.c b/src/emu/cpu/sc61860/sc61860.c index d0006cb4f23..a36c02a658a 100644 --- a/src/emu/cpu/sc61860/sc61860.c +++ b/src/emu/cpu/sc61860/sc61860.c @@ -8,18 +8,6 @@ * * Copyright Peter Trauner, all rights reserved. * - * - This source code is released as freeware for non-commercial purposes. - * - You are free to use and redistribute this code in modified or - * unmodified form, provided you list me in the credits. - * - If you modify this source code, you must add a notice to each modified - * source file that it has been changed. If you're a nice person, you - * will clearly mark each change too. :) - * - If you wish to use this for commercial purposes, please contact me at - * peter.trauner@jk.uni-linz.ac.at - * - The author of this copywritten work reserves the right to change the - * terms of its usage and license at any time, including retroactively - * - This entire notice must remain in the source code. - * * History of changes: * 29.7.2001 Several changes listed below taken by Mario Konegger * (konegger@itp.tu-graz.ac.at) diff --git a/src/emu/cpu/sc61860/sc61860.h b/src/emu/cpu/sc61860/sc61860.h index 51791715fcd..e34197f83f9 100644 --- a/src/emu/cpu/sc61860/sc61860.h +++ b/src/emu/cpu/sc61860/sc61860.h @@ -8,18 +8,6 @@ * * Copyright Peter Trauner, all rights reserved. * - * - This source code is released as freeware for non-commercial purposes. - * - You are free to use and redistribute this code in modified or - * unmodified form, provided you list me in the credits. - * - If you modify this source code, you must add a notice to each modified - * source file that it has been changed. If you're a nice person, you - * will clearly mark each change too. :) - * - If you wish to use this for commercial purposes, please contact me at - * peter.trauner@jk.uni-linz.ac.at - * - The author of this copywritten work reserves the right to change the - * terms of its usage and license at any time, including retroactively - * - This entire notice must remain in the source code. - * *****************************************************************************/ #pragma once diff --git a/src/emu/cpu/sc61860/scdasm.c b/src/emu/cpu/sc61860/scdasm.c index 8d7cc3ad43e..047ba7fae30 100644 --- a/src/emu/cpu/sc61860/scdasm.c +++ b/src/emu/cpu/sc61860/scdasm.c @@ -8,18 +8,6 @@ * * Copyright Peter Trauner, all rights reserved. * - * - This source code is released as freeware for non-commercial purposes. - * - You are free to use and redistribute this code in modified or - * unmodified form, provided you list me in the credits. - * - If you modify this source code, you must add a notice to each modified - * source file that it has been changed. If you're a nice person, you - * will clearly mark each change too. :) - * - If you wish to use this for commercial purposes, please contact me at - * peter.trauner@jk.uni-linz.ac.at - * - The author of this copywritten work reserves the right to change the - * terms of its usage and license at any time, including retroactively - * - This entire notice must remain in the source code. - * *****************************************************************************/ #include "emu.h" diff --git a/src/emu/cpu/sc61860/scops.inc b/src/emu/cpu/sc61860/scops.inc index a432d5a4c5f..bde6edd53e1 100644 --- a/src/emu/cpu/sc61860/scops.inc +++ b/src/emu/cpu/sc61860/scops.inc @@ -8,18 +8,6 @@ * * Copyright Peter Trauner, all rights reserved. * - * - This source code is released as freeware for non-commercial purposes. - * - You are free to use and redistribute this code in modified or - * unmodified form, provided you list me in the credits. - * - If you modify this source code, you must add a notice to each modified - * source file that it has been changed. If you're a nice person, you - * will clearly mark each change too. :) - * - If you wish to use this for commercial purposes, please contact me at - * peter.trauner@jk.uni-linz.ac.at - * - The author of this copywritten work reserves the right to change the - * terms of its usage and license at any time, including retroactively - * - This entire notice must remain in the source code. - * * History of changes: * 21.07.2001 Several changes listed below were made by Mario Konegger * (konegger@itp.tu-graz.ac.at) diff --git a/src/emu/cpu/scudsp/scudsp.c b/src/emu/cpu/scudsp/scudsp.c index 887c94cec1b..14d1565caa2 100644 --- a/src/emu/cpu/scudsp/scudsp.c +++ b/src/emu/cpu/scudsp/scudsp.c @@ -7,17 +7,6 @@ * * copyright Angelo Salese & Mariusz Wojcieszek, all rights reserved * - * - This source code is released as freeware for non-commercial purposes. - * - You are free to use and redistribute this code in modified or - * unmodified form, provided you list me in the credits. - * - If you modify this source code, you must add a notice to each modified - * source file that it has been changed. If you're a nice person, you - * will clearly mark each change too. :) - * - If you wish to use this for commercial purposes, please contact me at - * lordkale@libero.it or <insert_marusz_wojcieszek_mail_here> - * - This entire notice must remain in the source code. - * - * * Changelog: * 131010: Angelo Salese * - Converted to CPU structure diff --git a/src/emu/cpu/ssp1601/ssp1601.c b/src/emu/cpu/ssp1601/ssp1601.c index e9a5f39ac1c..94720fd7e73 100644 --- a/src/emu/cpu/ssp1601/ssp1601.c +++ b/src/emu/cpu/ssp1601/ssp1601.c @@ -1,4 +1,4 @@ -// license:BSD-3-Clause +// license:??? // copyright-holders:Pierpaolo Prazzoli,Grazvydas Ignotas /* * Samsung SSP1601 DSP emulator diff --git a/src/emu/cpu/tms0980/tms0980.c b/src/emu/cpu/tms0980/tms0980.c index 50f61788086..8275f09d815 100644 --- a/src/emu/cpu/tms0980/tms0980.c +++ b/src/emu/cpu/tms0980/tms0980.c @@ -187,6 +187,7 @@ const device_type TMS0270 = &device_creator<tms0270_cpu_device>; // 40-pin DIP, // TMS0260 is similar? except opla is 32 instead of 48 terms +// internal memory maps static ADDRESS_MAP_START(program_11bit_9, AS_PROGRAM, 16, tms1xxx_cpu_device) AM_RANGE(0x000, 0xfff) AM_ROM ADDRESS_MAP_END @@ -218,8 +219,9 @@ static ADDRESS_MAP_START(data_64x9_as4, AS_DATA, 8, tms1xxx_cpu_device) ADDRESS_MAP_END +// device definitions tms1000_cpu_device::tms1000_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : tms1xxx_cpu_device(mconfig, TMS1000, "TMS1000", tag, owner, clock, 8, 11, 6, 8, 2, 10, ADDRESS_MAP_NAME(program_10bit_8), 6, ADDRESS_MAP_NAME(data_64x4), "tms1000", __FILE__) + : tms1xxx_cpu_device(mconfig, TMS1000, "TMS1000", tag, owner, clock, 8 /* o pins */, 11 /* r pins */, 6 /* pc bits */, 8 /* byte width */, 2 /* x width */, 10 /* prg width */, ADDRESS_MAP_NAME(program_10bit_8), 6 /* data width */, ADDRESS_MAP_NAME(data_64x4), "tms1000", __FILE__) { } tms1000_cpu_device::tms1000_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT8 o_pins, UINT8 r_pins, UINT8 pc_bits, UINT8 byte_bits, UINT8 x_bits, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data, const char *shortname, const char *source) @@ -316,7 +318,7 @@ tms0270_cpu_device::tms0270_cpu_device(const machine_config &mconfig, const char { } - +// machine configs static MACHINE_CONFIG_FRAGMENT(tms1000) // microinstructions PLA, output PLA @@ -402,7 +404,7 @@ machine_config_constructor tms0270_cpu_device::device_mconfig_additions() const } - +// disasm offs_t tms1000_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) { extern CPU_DISASSEMBLE(tms1000); @@ -448,16 +450,17 @@ void tms1xxx_cpu_device::device_start() m_program = &space(AS_PROGRAM); m_data = &space(AS_DATA); - m_read_k.resolve_safe(0); - m_write_o.resolve_safe(); - m_write_r.resolve_safe(); - m_power_off.resolve_safe(); - m_o_mask = (1 << m_o_pins) - 1; m_r_mask = (1 << m_r_pins) - 1; m_pc_mask = (1 << m_pc_bits) - 1; m_x_mask = (1 << m_x_bits) - 1; + // resolve callbacks + m_read_k.resolve_safe(0); + m_write_o.resolve_safe(); + m_write_r.resolve_safe(); + m_power_off.resolve_safe(); + // zerofill m_pc = 0; m_sr = 0; diff --git a/src/emu/cpu/tms9900/9900dasm.c b/src/emu/cpu/tms9900/9900dasm.c index 010908290ed..7b3153e6c4c 100644 --- a/src/emu/cpu/tms9900/9900dasm.c +++ b/src/emu/cpu/tms9900/9900dasm.c @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Raphael Nabet /***************************************************************************** * diff --git a/src/emu/cpu/tms9900/99xxcore.h b/src/emu/cpu/tms9900/99xxcore.h index 794be20fcb4..cb94fac286f 100644 --- a/src/emu/cpu/tms9900/99xxcore.h +++ b/src/emu/cpu/tms9900/99xxcore.h @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Raphael Nabet /*************************************************************************** diff --git a/src/emu/cpu/ucom4/ucom4.c b/src/emu/cpu/ucom4/ucom4.c index 11d1513ed03..ceb074728e5 100644 --- a/src/emu/cpu/ucom4/ucom4.c +++ b/src/emu/cpu/ucom4/ucom4.c @@ -62,7 +62,7 @@ ADDRESS_MAP_END // device definitions upd553_cpu_device::upd553_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : ucom4_cpu_device(mconfig, NEC_D553, "uPD553", tag, owner, clock, NEC_UCOM43, 3, 11, ADDRESS_MAP_NAME(program_2k), 7, ADDRESS_MAP_NAME(data_96x4), "upd553", __FILE__) + : ucom4_cpu_device(mconfig, NEC_D553, "uPD553", tag, owner, clock, NEC_UCOM43, 3 /* stack levels */, 11 /* prg width */, ADDRESS_MAP_NAME(program_2k), 7 /* data width */, ADDRESS_MAP_NAME(data_96x4), "upd553", __FILE__) { } upd650_cpu_device::upd650_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) @@ -124,6 +124,7 @@ void ucom4_cpu_device::device_start() m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ucom4_cpu_device::simple_timer_cb), this)); + // resolve callbacks m_read_a.resolve_safe(0xf); m_read_b.resolve_safe(0xf); m_read_c.resolve_safe(0xf); diff --git a/src/emu/devdelegate.h b/src/emu/devdelegate.h index 2ce6cc9a0fa..ba1b82ab8ee 100644 --- a/src/emu/devdelegate.h +++ b/src/emu/devdelegate.h @@ -54,17 +54,21 @@ public: device_delegate(const basetype &src) : basetype(src), device_delegate_helper(src.m_device_name) { } device_delegate(const basetype &src, delegate_late_bind &object) : basetype(src, object), device_delegate_helper(src.m_device_name) { } template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { } +#ifdef USE_STATIC_DELEGATE template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { } template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_ref_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { } +#endif device_delegate &operator=(const thistype &src) { *static_cast<basetype *>(this) = src; m_device_name = src.m_device_name; return *this; } // provide additional constructors that take a device name string template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname) : basetype(funcptr, name, (_FunctionClass *)0), device_delegate_helper(devname) { } template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname, _FunctionClass *object) : basetype(funcptr, name, (_FunctionClass *)0), device_delegate_helper(devname) { } +#ifdef USE_STATIC_DELEGATE template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_func_type funcptr, const char *name, const char *devname, _FunctionClass *object) : basetype(funcptr, name, (_FunctionClass *)0), device_delegate_helper(devname) { } template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_ref_func_type funcptr, const char *name, const char *devname, _FunctionClass *object) : basetype(funcptr, name, (_FunctionClass *)0), device_delegate_helper(devname) { } device_delegate(typename basetype::template traits<device_t>::static_func_type funcptr, const char *name) : basetype(funcptr, name, (device_t *)0), device_delegate_helper(NULL) { } device_delegate(typename basetype::template traits<device_t>::static_ref_func_type funcptr, const char *name) : basetype(funcptr, name, (device_t *)0), device_delegate_helper(NULL) { } +#endif // and constructors that provide a search root device_delegate(const thistype &src, device_t &search_root) : basetype(src), device_delegate_helper(src.m_device_name) { bind_relative_to(search_root); } diff --git a/src/emu/emuopts.c b/src/emu/emuopts.c index c537ce6dc4e..c7df63d76d1 100644 --- a/src/emu/emuopts.c +++ b/src/emu/emuopts.c @@ -160,6 +160,13 @@ const options_entry emu_options::s_option_entries[] = { OPTION_UPDATEINPAUSE, "0", OPTION_BOOLEAN, "keep calling video updates while in pause" }, { OPTION_DEBUGSCRIPT, NULL, OPTION_STRING, "script for debugger" }, + // comm options + { NULL, NULL, OPTION_HEADER, "CORE COMM OPTIONS" }, + { OPTION_COMM_LOCAL_HOST, "0.0.0.0", OPTION_STRING, "local address to bind to" }, + { OPTION_COMM_LOCAL_PORT, "15112", OPTION_STRING, "local port to bind to" }, + { OPTION_COMM_REMOTE_HOST, "127.0.0.1", OPTION_STRING, "remote address to connect to" }, + { OPTION_COMM_REMOTE_PORT, "15112", OPTION_STRING, "remote port to connect to" }, + // misc options { NULL, NULL, OPTION_HEADER, "CORE MISC OPTIONS" }, { OPTION_DRC, "1", OPTION_BOOLEAN, "enable DRC cpu core if available" }, diff --git a/src/emu/emuopts.h b/src/emu/emuopts.h index ac2f18ac767..855e8eb19af 100644 --- a/src/emu/emuopts.h +++ b/src/emu/emuopts.h @@ -174,6 +174,12 @@ enum #define OPTION_UI_FONT "uifont" #define OPTION_RAMSIZE "ramsize" +// core comm options +#define OPTION_COMM_LOCAL_HOST "comm_localhost" +#define OPTION_COMM_LOCAL_PORT "comm_localport" +#define OPTION_COMM_REMOTE_HOST "comm_remotehost" +#define OPTION_COMM_REMOTE_PORT "comm_remoteport" + #define OPTION_CONFIRM_QUIT "confirm_quit" #define OPTION_UI_MOUSE "ui_mouse" @@ -343,6 +349,12 @@ public: const char *ui_font() const { return value(OPTION_UI_FONT); } const char *ram_size() const { return value(OPTION_RAMSIZE); } + // core comm options + const char *comm_localhost() const { return value(OPTION_COMM_LOCAL_HOST); } + const char *comm_localport() const { return value(OPTION_COMM_LOCAL_PORT); } + const char *comm_remotehost() const { return value(OPTION_COMM_REMOTE_HOST); } + const char *comm_remoteport() const { return value(OPTION_COMM_REMOTE_PORT); } + bool confirm_quit() const { return bool_value(OPTION_CONFIRM_QUIT); } bool ui_mouse() const { return bool_value(OPTION_UI_MOUSE); } diff --git a/src/emu/imagedev/floppy.c b/src/emu/imagedev/floppy.c index 3f704959d9f..b79cc0c71bd 100644 --- a/src/emu/imagedev/floppy.c +++ b/src/emu/imagedev/floppy.c @@ -661,6 +661,22 @@ UINT32 floppy_image_device::find_position(attotime &base, const attotime &when) return (delta*floppy_ratio_1).as_ticks(1000000000/1000); } +attotime floppy_image_device::get_next_index_time(std::vector<UINT32> &buf, int index, int delta, attotime base) +{ + UINT32 next_position; + int cells = buf.size(); + if(index+delta < cells) + next_position = buf[index+delta] & floppy_image::TIME_MASK; + else { + if((buf[cells-1]^buf[0]) & floppy_image::MG_MASK) + delta--; + index = index + delta - cells + 1; + next_position = 200000000 + (buf[index] & floppy_image::TIME_MASK); + } + + return base + attotime::from_nsec((UINT64(next_position)*2000/floppy_ratio_1+1)/2); +} + attotime floppy_image_device::get_next_transition(const attotime &from_when) { if(!image || mon) @@ -679,15 +695,10 @@ attotime floppy_image_device::get_next_transition(const attotime &from_when) if(index == -1) return attotime::never; - UINT32 next_position; - if(index < cells-1) - next_position = buf[index+1] & floppy_image::TIME_MASK; - else if((buf[index]^buf[0]) & floppy_image::MG_MASK) - next_position = 200000000; - else - next_position = 200000000 + (buf[1] & floppy_image::TIME_MASK); - - return base + attotime::from_nsec((UINT64(next_position)*2000/floppy_ratio_1+1)/2); + attotime result = get_next_index_time(buf, index, 1, base); + if(result > from_when) + return result; + return get_next_index_time(buf, index, 2, base); } void floppy_image_device::write_flux(const attotime &start, const attotime &end, int transition_count, const attotime *transitions) diff --git a/src/emu/imagedev/floppy.h b/src/emu/imagedev/floppy.h index 98834facc65..1130260cb81 100644 --- a/src/emu/imagedev/floppy.h +++ b/src/emu/imagedev/floppy.h @@ -186,6 +186,7 @@ protected: int find_index(UINT32 position, const std::vector<UINT32> &buf); void write_zone(UINT32 *buf, int &cells, int &index, UINT32 spos, UINT32 epos, UINT32 mg); void commit_image(); + attotime get_next_index_time(std::vector<UINT32> &buf, int index, int delta, attotime base); }; class ui_menu_control_floppy_image : public ui_menu_control_device_image { diff --git a/src/emu/input.c b/src/emu/input.c index 28337c7cf81..96fa1458368 100644 --- a/src/emu/input.c +++ b/src/emu/input.c @@ -139,7 +139,7 @@ static const code_string_table devclass_token_table[] = { DEVICE_CLASS_MOUSE, "MOUSECODE" }, { DEVICE_CLASS_LIGHTGUN, "GUNCODE" }, { DEVICE_CLASS_JOYSTICK, "JOYCODE" }, - { ~0, "UNKCODE" } + { ~0U, "UNKCODE" } }; // friendly strings for device classes @@ -149,7 +149,7 @@ static const code_string_table devclass_string_table[] = { DEVICE_CLASS_MOUSE, "Mouse" }, { DEVICE_CLASS_LIGHTGUN, "Gun" }, { DEVICE_CLASS_JOYSTICK, "Joy" }, - { ~0, "Unk" } + { ~0U, "Unk" } }; // token strings for item modifiers @@ -161,7 +161,7 @@ static const code_string_table modifier_token_table[] = { ITEM_MODIFIER_RIGHT, "RIGHT" }, { ITEM_MODIFIER_UP, "UP" }, { ITEM_MODIFIER_DOWN, "DOWN" }, - { ~0, "" } + { ~0U, "" } }; // friendly strings for item modifiers @@ -173,7 +173,7 @@ static const code_string_table modifier_string_table[] = { ITEM_MODIFIER_RIGHT, "Right" }, { ITEM_MODIFIER_UP, "Up" }, { ITEM_MODIFIER_DOWN, "Down" }, - { ~0, "" } + { ~0U, "" } }; // token strings for item classes @@ -182,7 +182,7 @@ static const code_string_table itemclass_token_table[] = { ITEM_CLASS_SWITCH, "SWITCH" }, { ITEM_CLASS_ABSOLUTE, "ABSOLUTE" }, { ITEM_CLASS_RELATIVE, "RELATIVE" }, - { ~0, "" } + { ~0U, "" } }; // token strings for standard item ids @@ -411,7 +411,7 @@ static const code_string_table itemid_token_table[] = { ITEM_ID_ADD_RELATIVE15,"ADDREL15" }, { ITEM_ID_ADD_RELATIVE16,"ADDREL16" }, - { ~0, NULL } + { ~0U, NULL } }; diff --git a/src/emu/machine/68561mpcc.c b/src/emu/machine/68561mpcc.c index c894f4c96ba..1b8a8895fed 100644 --- a/src/emu/machine/68561mpcc.c +++ b/src/emu/machine/68561mpcc.c @@ -23,8 +23,6 @@ const device_type MPCC68561 = &device_creator<mpcc68561_t>; #define LOG_MPCC (1) -#if 0 // future - /*************************************************************************** IMPLEMENTATION ***************************************************************************/ @@ -481,7 +479,3 @@ WRITE8_MEMBER( mpcc68561_t::reg_w ) break; } } - -#else - -#endif diff --git a/src/emu/machine/corvushd.c b/src/emu/machine/corvushd.c index 659945da93d..0444d3cb530 100644 --- a/src/emu/machine/corvushd.c +++ b/src/emu/machine/corvushd.c @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Brett Wyer, Raphael Nabet // // corvus_hd diff --git a/src/emu/machine/corvushd.h b/src/emu/machine/corvushd.h index 324fef4f1bf..bc83fa2585d 100644 --- a/src/emu/machine/corvushd.h +++ b/src/emu/machine/corvushd.h @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Brett Wyer, Raphael Nabet /***************************************************************************** * diff --git a/src/emu/machine/hdc9234.c b/src/emu/machine/hdc9234.c index c77783e463c..91c41fc21d6 100644 --- a/src/emu/machine/hdc9234.c +++ b/src/emu/machine/hdc9234.c @@ -22,39 +22,40 @@ #include "emu.h" #include "hdc9234.h" +#include "formats/imageutl.h" // Per-command debugging -#define TRACE_SELECT 1 -#define TRACE_STEP 1 -#define TRACE_RESTORE 1 -#define TRACE_SUBSTATES 1 -#define TRACE_READ 1 -#define TRACE_WRITE 1 -#define TRACE_READREG 1 -#define TRACE_SETREG 1 -#define TRACE_SETPTR 1 -#define TRACE_FORMAT 1 -#define TRACE_READTRACK 1 +#define TRACE_SELECT 0 +#define TRACE_STEP 0 +#define TRACE_RESTORE 0 +#define TRACE_SUBSTATES 0 +#define TRACE_READ 0 +#define TRACE_WRITE 0 +#define TRACE_READREG 0 +#define TRACE_SETREG 0 +#define TRACE_SETPTR 0 +#define TRACE_FORMAT 0 +#define TRACE_READTRACK 0 // Common states -#define TRACE_READID 1 -#define TRACE_VERIFY 1 -#define TRACE_TRANSFER 1 +#define TRACE_READID 0 +#define TRACE_VERIFY 0 +#define TRACE_TRANSFER 0 // Live states debugging -#define TRACE_LIVE 1 -#define TRACE_SHIFT 1 -#define TRACE_SYNC 1 +#define TRACE_LIVE 0 +#define TRACE_SHIFT 0 +#define TRACE_SYNC 0 // Misc debugging #define TRACE_DELAY 0 -#define TRACE_INT 1 -#define TRACE_LINES 1 -#define TRACE_INDEX 1 -#define TRACE_DMA 1 -#define TRACE_DONE 1 -#define TRACE_FAIL 1 -#define TRACE_AUXBUS 1 +#define TRACE_INT 0 +#define TRACE_LINES 0 +#define TRACE_INDEX 0 +#define TRACE_DMA 0 +#define TRACE_DONE 0 +#define TRACE_FAIL 0 +#define TRACE_AUXBUS 0 #define TRACE_DETAIL 0 @@ -335,12 +336,14 @@ enum SEARCH_IDAM, SEARCH_IDAM_FAILED, READ_TWO_MORE_A1_IDAM, + READ_IDENT, READ_ID_FIELDS_INTO_REGS, SEARCH_DAM, READ_TWO_MORE_A1_DAM, + READ_DATADEL_FLAG, SEARCH_DAM_FAILED, READ_SECTOR_DATA, - READ_SECTOR_DATA1, + READ_SECTOR_DATA_CONT, WRITE_DAM_AND_SECTOR, WRITE_SEC_SKIP_GAP2, WRITE_SEC_SKIP_GAP2_LOOP, @@ -464,6 +467,30 @@ bool hdc9234_device::on_track00() } /* + Seek completed? +*/ +bool hdc9234_device::seek_complete() +{ + return (m_register_r[DRIVE_STATUS] & HDC_DS_SKCOM)!=0; +} + +/* + Index hole? +*/ +bool hdc9234_device::index_hole() +{ + return (m_register_r[DRIVE_STATUS] & HDC_DS_INDEX)!=0; +} + +/* + Drive ready? +*/ +bool hdc9234_device::drive_ready() +{ + return (m_register_r[DRIVE_STATUS] & HDC_DS_READY)!=0; +} + +/* Accessor functions for specific parameters. */ int hdc9234_device::desired_head() @@ -545,11 +572,6 @@ int hdc9234_device::pulse_width() return time; } -bool hdc9234_device::rapid_steps() -{ - return (m_register_w[MODE] & MO_STEPRATE) == 0; -} - /* Delivers the sector size */ @@ -582,10 +604,41 @@ void hdc9234_device::wait_time(emu_timer *tm, const attotime &delay, int param) */ void hdc9234_device::wait_line(int line, line_state level, int substate, bool stopwrite) { - m_event_line = line; - m_line_level = level; - m_state_after_line = substate; - m_stopwrite = stopwrite; + bool line_at_level = true; + if (line == SEEKCOMP_LINE && (seek_complete() == (level==ASSERT_LINE))) + { + if (TRACE_LINES) logerror("%s: SEEK_COMPLETE line is already %d\n", tag(), level); + } + else + { + if (line == INDEX_LINE && (index_hole() == (level==ASSERT_LINE))) + { + if (TRACE_LINES) logerror("%s: INDEX line is already %d\n", tag(), level); + } + else + { + if (line == READY_LINE && (drive_ready() == (level==ASSERT_LINE))) + { + if (TRACE_LINES) logerror("%s: READY line is already %d\n", tag(), level); + } + else + { + // The line is not yet at the desired level; hence, arm the trigger. + m_event_line = line; + m_line_level = level; + m_state_after_line = substate; + m_stopwrite = stopwrite; + line_at_level = false; + } + } + } + + if (line_at_level) + { + m_substate = substate; + m_state_after_line = UNDEF; + reenter_command_processing(); + } } // ================================================================== @@ -666,6 +719,7 @@ void hdc9234_device::read_id(int& cont, bool implied_seek, bool wait_seek_comple if (wait_seek_complete) { // We have to wait for SEEK COMPLETE + if (TRACE_READID && TRACE_SUBSTATES) logerror("%s: Waiting for SEEK COMPLETE\n", tag()); wait_line(SEEKCOMP_LINE, ASSERT_LINE, READ_ID_SEEK_COMPLETE, false); cont = WAIT; } @@ -1065,7 +1119,7 @@ void hdc9234_device::restore_drive() { case RESTORE_CHECK: // Track 0 has not been reached yet - if ((m_register_r[DRIVE_STATUS] & HDC_DS_READY)==0) + if (!drive_ready()) { if (TRACE_RESTORE) logerror("%s: restore command: Drive not ready\n", tag()); // Does not look like a success, but this takes into account @@ -1257,7 +1311,7 @@ void hdc9234_device::poll_drives() break; case POLL2: - if ((m_register_r[DRIVE_STATUS] & HDC_DS_SKCOM)!=0) + if (seek_complete()) { // Seek complete has been set m_substate = DONE; @@ -1404,7 +1458,7 @@ void hdc9234_device::seek_read_id() int cont = NEXT; bool step_enable = (current_command() & 0x04)==1; - bool wait_seek_comp = ((current_command() & 0x02)==1) || rapid_steps(); + bool wait_seek_comp = (current_command() & 0x02)==1; bool do_verify = (current_command() & 0x01)==1; while (cont == NEXT) @@ -1477,7 +1531,7 @@ void hdc9234_device::read_sectors() switch (m_substate & 0xf0) { case READ_ID: - read_id(cont, implied_seek, rapid_steps()); + read_id(cont, implied_seek, true); // Always check SEEK COMPLETE break; case VERIFY: verify(cont, logical); // for physical, only verify the first sector @@ -1522,14 +1576,13 @@ void hdc9234_device::read_track() switch (m_substate) { case WAITINDEX0: - // Do we happen to have an index hole right now? - if ((m_register_r[DRIVE_STATUS] & HDC_DS_INDEX)==0) + if (!index_hole()) { m_substate = WAITINDEX1; } else { - // Waiting for the index line going down + // We're above the index hole; wait for the index line going down wait_line(INDEX_LINE, ASSERT_LINE, WAITINDEX1, false); cont = WAIT; } @@ -1650,15 +1703,14 @@ void hdc9234_device::format_track() switch (m_substate) { case WAITINDEX0: - // Do we happen to have an index hole right now? - if ((m_register_r[DRIVE_STATUS] & HDC_DS_INDEX)==0) + if (!index_hole()) { m_substate = WAITINDEX1; cont = NEXT; } else { - // Waiting for the index line going down + // We're above the index hole right now, so wait for the line going down wait_line(INDEX_LINE, ASSERT_LINE, WAITINDEX1, false); cont = WAIT; } @@ -1734,7 +1786,7 @@ void hdc9234_device::write_sectors() switch (m_substate & 0xf0) { case READ_ID: - read_id(cont, implied_seek, rapid_steps()); + read_id(cont, implied_seek, true); // Always check SEEK COMPLETE break; case VERIFY: verify(cont, logical); @@ -1780,6 +1832,39 @@ std::string hdc9234_device::ttsn() return tts(machine().time()); } +bool hdc9234_device::found_mark(int state) +{ + bool ismark = false; + if (using_floppy()) + { + if (state==SEARCH_IDAM) ismark = (m_live_state.shift_reg == fm_mode()? 0xf57e : 0x4489); + else + { + // f56a 1x1x + ismark = fm_mode()? ((m_live_state.shift_reg & 0xfffa) == 0xf56a) : (m_live_state.shift_reg == 0x4489); + } + } + else + { + switch (m_hd_encoding) + { + case MFM_BITS: + case MFM_BYTE: + ismark = (m_live_state.shift_reg == 0x4489); + break; + case SEPARATED: + // 0 0 0 0 1 0 1 0 + // 1 0 1 0 0 0 0 1 + ismark = (m_live_state.data_reg == 0xa1 && m_live_state.clock_reg == 0x0a); + break; + case SEPARATED_SIMPLE: + ismark = (m_live_state.data_reg == 0xa1 && m_live_state.clock_reg == 0xff); + break; + } + } + return ismark; +} + /* The controller starts to read bits from the disk. This method takes an argument for the state machine called at the end. @@ -1799,7 +1884,7 @@ void hdc9234_device::live_start(int state) m_live_state.data_reg = 0; m_live_state.last_data_bit = false; - pll_reset(m_live_state.time, m_write); + if (using_floppy()) pll_reset(m_live_state.time, m_write); m_checkpoint_state = m_live_state; // Save checkpoint @@ -1807,6 +1892,7 @@ void hdc9234_device::live_start(int state) live_run(); m_last_live_state = UNDEF; + if (TRACE_LIVE) logerror("%s: [%s] Live start end\n", tag(), ttsn().c_str()); // delete } void hdc9234_device::live_run() @@ -1833,9 +1919,9 @@ void hdc9234_device::live_run_until(attotime limit) if (TRACE_LIVE) { if (limit == attotime::never) - logerror("%s: [%s] live_run, live_state=%d, mode=%s\n", tag(), tts(m_live_state.time).c_str(), m_live_state.state, fm_mode()? "FM":"MFM"); + logerror("%s: [%s live] live_run, live_state=%d, mode=%s\n", tag(), tts(m_live_state.time).c_str(), m_live_state.state, fm_mode()? "FM":"MFM"); else - logerror("%s: [%s] live_run until %s, live_state=%d, mode=%s\n", tag(), tts(m_live_state.time).c_str(), tts(limit).c_str(), m_live_state.state, fm_mode()? "FM":"MFM"); + logerror("%s: [%s live] live_run until %s, live_state=%d, mode=%s\n", tag(), tts(m_live_state.time).c_str(), tts(limit).c_str(), m_live_state.state, fm_mode()? "FM":"MFM"); } if (limit == attotime::never) @@ -1867,7 +1953,7 @@ void hdc9234_device::live_run_until(attotime limit) if (TRACE_LIVE && m_last_live_state != SEARCH_IDAM) { - logerror("%s: [%s] SEARCH_IDAM [limit %s]\n", tag(),tts(m_live_state.time).c_str(), tts(limit).c_str()); + logerror("%s: [%s live] SEARCH_IDAM [limit %s]\n", tag(),tts(m_live_state.time).c_str(), tts(limit).c_str()); m_last_live_state = m_live_state.state; } @@ -1876,11 +1962,11 @@ void hdc9234_device::live_run_until(attotime limit) if (read_one_bit(limit)) { - if (TRACE_LIVE) logerror("%s: [%s] SEARCH_IDAM limit reached\n", tag(), tts(m_live_state.time).c_str()); + if (TRACE_LIVE) logerror("%s: [%s live] SEARCH_IDAM limit reached\n", tag(), tts(m_live_state.time).c_str()); return; } // logerror("%s: SEARCH_IDAM\n", tts(m_live_state.time).c_str()); - if (TRACE_SHIFT) logerror("%s: shift = %04x data=%02x c=%d\n", tts(m_live_state.time).c_str(), m_live_state.shift_reg, + if (TRACE_SHIFT) logerror("%s: [%s live] shift = %04x data=%02x c=%d\n", tag(), tts(m_live_state.time).c_str(), m_live_state.shift_reg, get_data_from_encoding(m_live_state.shift_reg), m_live_state.bit_counter); // [1] p. 9: The ID field sync mark must be found within 33,792 byte times @@ -1895,7 +1981,7 @@ void hdc9234_device::live_run_until(attotime limit) // MFM case if (m_live_state.shift_reg == 0x4489) { - if (TRACE_LIVE) logerror("%s: [%s] Found an A1 mark\n", tag(),tts(m_live_state.time).c_str()); + if (TRACE_LIVE) logerror("%s: [%s live] Found an A1 mark\n", tag(),tts(m_live_state.time).c_str()); m_live_state.crc = 0x443b; m_live_state.data_separator_phase = false; m_live_state.bit_counter = 0; @@ -1926,14 +2012,14 @@ void hdc9234_device::live_run_until(attotime limit) if (TRACE_LIVE && m_last_live_state != READ_TWO_MORE_A1_IDAM) { - logerror("%s: [%s] READ_TWO_MORE_A1\n", tag(),tts(m_live_state.time).c_str()); + logerror("%s: [%s live] READ_TWO_MORE_A1\n", tag(),tts(m_live_state.time).c_str()); m_last_live_state = m_live_state.state; } // Beyond time limit? if (read_one_bit(limit)) return; - if (TRACE_SHIFT) logerror("%s: shift = %04x data=%02x c=%d\n", tts(m_live_state.time).c_str(), m_live_state.shift_reg, + if (TRACE_SHIFT) logerror("%s: [%s live] shift = %04x data=%02x c=%d\n", tag(), tts(m_live_state.time).c_str(), m_live_state.shift_reg, get_data_from_encoding(m_live_state.shift_reg), m_live_state.bit_counter); if (m_live_state.bit_count_total > 33792*16) @@ -1955,12 +2041,12 @@ void hdc9234_device::live_run_until(attotime limit) m_live_state.state = SEARCH_IDAM; } else - if (TRACE_LIVE) logerror("%s: [%s] Found an A1 mark\n", tag(),tts(m_live_state.time).c_str()); + if (TRACE_LIVE) logerror("%s: [%s live] Found an A1 mark\n", tag(),tts(m_live_state.time).c_str()); // Continue break; } - if (TRACE_LIVE) logerror("%s: [%s] Found data value %02X\n", tag(),tts(m_live_state.time).c_str(), m_live_state.data_reg); + if (TRACE_LIVE) logerror("%s: [%s live] Found data value %02X\n", tag(),tts(m_live_state.time).c_str(), m_live_state.data_reg); // Check for ident field (fe, ff, fd, fc) if ((m_live_state.data_reg & 0xfc) != 0xfc) @@ -1981,7 +2067,7 @@ void hdc9234_device::live_run_until(attotime limit) case READ_ID_FIELDS_INTO_REGS: if (TRACE_LIVE && m_last_live_state != READ_ID_FIELDS_INTO_REGS) { - logerror("%s: [%s] READ_ID_FIELDS_INTO_REGS\n", tag(),tts(m_live_state.time).c_str()); + logerror("%s: [%s live] READ_ID_FIELDS_INTO_REGS\n", tag(),tts(m_live_state.time).c_str()); m_last_live_state = m_live_state.state; } @@ -2022,7 +2108,7 @@ void hdc9234_device::live_run_until(attotime limit) case SEARCH_DAM: if (TRACE_LIVE && m_last_live_state != SEARCH_DAM) { - logerror("%s: [%s] SEARCH_DAM\n", tag(),tts(m_live_state.time).c_str()); + logerror("%s: [%s live] SEARCH_DAM\n", tag(),tts(m_live_state.time).c_str()); m_last_live_state = m_live_state.state; } @@ -2031,7 +2117,7 @@ void hdc9234_device::live_run_until(attotime limit) if(read_one_bit(limit)) return; - if (TRACE_SHIFT) logerror("%s: shift = %04x data=%02x c=%d\n", tts(m_live_state.time).c_str(), m_live_state.shift_reg, + if (TRACE_SHIFT) logerror("%s: [%s live] shift = %04x data=%02x c=%d\n", tag(), tts(m_live_state.time).c_str(), m_live_state.shift_reg, get_data_from_encoding(m_live_state.shift_reg), m_live_state.bit_counter); if (!fm_mode()) @@ -2045,7 +2131,7 @@ void hdc9234_device::live_run_until(attotime limit) if (m_live_state.bit_counter >= 28*16 && m_live_state.shift_reg == 0x4489) { - if (TRACE_LIVE) logerror("%s: [%s] Found an A1 mark\n", tag(),tts(m_live_state.time).c_str()); + if (TRACE_LIVE) logerror("%s: [%s live] Found an A1 mark\n", tag(),tts(m_live_state.time).c_str()); m_live_state.crc = 0x443b; m_live_state.data_separator_phase = false; m_live_state.bit_counter = 0; @@ -2079,14 +2165,14 @@ void hdc9234_device::live_run_until(attotime limit) case READ_TWO_MORE_A1_DAM: { if (TRACE_LIVE && m_last_live_state != READ_TWO_MORE_A1_DAM) { - logerror("%s: [%s] READ_TWO_MORE_A1_DAM\n", tag(),tts(m_live_state.time).c_str()); + logerror("%s: [%s live] READ_TWO_MORE_A1_DAM\n", tag(),tts(m_live_state.time).c_str()); m_last_live_state = m_live_state.state; } if(read_one_bit(limit)) return; - if (TRACE_SHIFT) logerror("%s: shift = %04x data=%02x c=%d\n", tts(m_live_state.time).c_str(), m_live_state.shift_reg, + if (TRACE_SHIFT) logerror("%s: [%s live] shift = %04x data=%02x c=%d\n", tag(), tts(m_live_state.time).c_str(), m_live_state.shift_reg, get_data_from_encoding(m_live_state.shift_reg), m_live_state.bit_counter); // Repeat until we have collected 16 bits @@ -2103,12 +2189,12 @@ void hdc9234_device::live_run_until(attotime limit) return; } else - if (TRACE_LIVE) logerror("%s: [%s] Found an A1 mark\n", tag(),tts(m_live_state.time).c_str()); + if (TRACE_LIVE) logerror("%s: [%s live] Found an A1 mark\n", tag(),tts(m_live_state.time).c_str()); // Continue break; } - if (TRACE_LIVE) logerror("%s: [%s] Found data value %02X\n", tag(),tts(m_live_state.time).c_str(), m_live_state.data_reg); + if (TRACE_LIVE) logerror("%s: [%s live] Found data value %02X\n", tag(),tts(m_live_state.time).c_str(), m_live_state.data_reg); if ((m_live_state.data_reg & 0xff) == 0xf8) { @@ -2138,7 +2224,7 @@ void hdc9234_device::live_run_until(attotime limit) { if (TRACE_LIVE && m_last_live_state != READ_SECTOR_DATA) { - logerror("%s: [%s] READ_SECTOR_DATA\n", tag(),tts(m_live_state.time).c_str()); + logerror("%s: [%s live] READ_SECTOR_DATA\n", tag(),tts(m_live_state.time).c_str()); m_last_live_state = m_live_state.state; } @@ -2163,13 +2249,13 @@ void hdc9234_device::live_run_until(attotime limit) // Repeat until we have collected 16 bits if (m_live_state.bit_counter & 15) break; - if (TRACE_LIVE) logerror("%s: [%s] Found data value %02X, CRC=%04x\n", tag(),tts(m_live_state.time).c_str(), m_live_state.data_reg, m_live_state.crc); + if (TRACE_LIVE) logerror("%s: [%s live] Found data value %02X, CRC=%04x\n", tag(),tts(m_live_state.time).c_str(), m_live_state.data_reg, m_live_state.crc); int slot = (m_live_state.bit_counter >> 4)-1; if (slot < calc_sector_size()) { // Sector data - wait_for_realtime(READ_SECTOR_DATA1); + wait_for_realtime(READ_SECTOR_DATA_CONT); return; } else if (slot < calc_sector_size()+2) @@ -2184,7 +2270,7 @@ void hdc9234_device::live_run_until(attotime limit) } else { - if (TRACE_LIVE) logerror("%s: [%s] Sector read completed\n", tag(),tts(m_live_state.time).c_str()); + if (TRACE_LIVE) logerror("%s: [%s live] Sector read completed\n", tag(),tts(m_live_state.time).c_str()); wait_for_realtime(IDLE); } return; @@ -2193,10 +2279,10 @@ void hdc9234_device::live_run_until(attotime limit) break; } - case READ_SECTOR_DATA1: - if (TRACE_LIVE && m_last_live_state != READ_SECTOR_DATA1) + case READ_SECTOR_DATA_CONT: + if (TRACE_LIVE && m_last_live_state != READ_SECTOR_DATA_CONT) { - logerror("%s: [%s] READ_SECTOR_DATA1\n", tag(),tts(m_live_state.time).c_str()); + logerror("%s: [%s live] READ_SECTOR_DATA_CONT\n", tag(),tts(m_live_state.time).c_str()); m_last_live_state = m_live_state.state; } @@ -2242,7 +2328,7 @@ void hdc9234_device::live_run_until(attotime limit) // 5. Write the CRC bytes if (TRACE_LIVE) - logerror("%s: [%s] WRITE_DAM_AND_SECTOR\n", tag(), tts(m_live_state.time).c_str()); + logerror("%s: [%s live] WRITE_DAM_AND_SECTOR\n", tag(), tts(m_live_state.time).c_str()); skip_on_track(m_gap2_size, WRITE_DAM_SYNC); break; @@ -2559,14 +2645,14 @@ void hdc9234_device::live_run_until(attotime limit) // The pause is implemented by doing dummy reads on the floppy if (read_one_bit(limit)) { - if (TRACE_LIVE) logerror("%s: [%s] return; limit=%s\n", tag(), tts(m_live_state.time).c_str(), tts(limit).c_str()); + if (TRACE_LIVE) logerror("%s: [%s live] return; limit=%s\n", tag(), tts(m_live_state.time).c_str(), tts(limit).c_str()); return; } // Repeat until we have collected 16 bits if ((m_live_state.bit_counter & 15)==0) { - if (TRACE_READ && TRACE_DETAIL) logerror("%s: [%s] Read byte %02x, repeat = %d\n", tag(), tts(m_live_state.time).c_str(), m_live_state.data_reg, m_live_state.repeat); + if (TRACE_READ && TRACE_DETAIL) logerror("%s: [%s live] Read byte %02x, repeat = %d\n", tag(), tts(m_live_state.time).c_str(), m_live_state.data_reg, m_live_state.repeat); wait_for_realtime(READ_TRACK_NEXT_BYTE); return; } @@ -2637,8 +2723,8 @@ void hdc9234_device::live_run_until(attotime limit) */ void hdc9234_device::live_run_hd_until(attotime limit) { -// int slot = 0; - logerror("%s: live_run_hd\n", tag()); + int slot = 0; + if (TRACE_LIVE) logerror("%s: live_run_hd\n", tag()); if (m_live_state.state == IDLE || m_live_state.next_state != -1) return; @@ -2646,19 +2732,259 @@ void hdc9234_device::live_run_hd_until(attotime limit) if (TRACE_LIVE) { if (limit == attotime::never) - logerror("%s: [%s] live_run_hd, live_state=%d, mode=%s\n", tag(), tts(m_live_state.time).c_str(), m_live_state.state, fm_mode()? "FM":"MFM"); + logerror("%s: [%s live] live_run_hd, live_state=%d, mode=%s\n", tag(), tts(m_live_state.time).c_str(), m_live_state.state, fm_mode()? "FM":"MFM"); else - logerror("%s: [%s] live_run_hd until %s, live_state=%d, mode=%s\n", tag(), tts(m_live_state.time).c_str(), tts(limit).c_str(), m_live_state.state, fm_mode()? "FM":"MFM"); + logerror("%s: [%s live] live_run_hd until %s, live_state=%d, mode=%s\n", tag(), tts(m_live_state.time).c_str(), tts(limit).c_str(), m_live_state.state, fm_mode()? "FM":"MFM"); } + + // We did not specify an upper time bound, so we take the next index pulse + if (m_harddisk != NULL) limit = m_harddisk->track_end_time(); + while (true) { switch (m_live_state.state) { - case SEARCH_IDAM: - break; + case SEARCH_IDAM: + if (TRACE_LIVE && m_last_live_state != SEARCH_IDAM) + { + logerror("%s: [%s live] SEARCH_IDAM [limit %s]\n", tag(),tts(m_live_state.time).c_str(), tts(limit).c_str()); + m_last_live_state = m_live_state.state; + } + + // This bit will be set when the IDAM cannot be found + set_bits(m_register_r[CHIP_STATUS], CS_SYNCERR, false); + + if (read_from_mfmhd(limit)) + { + if (TRACE_LIVE) logerror("%s: [%s live] SEARCH_IDAM limit reached\n", tag(), tts(m_live_state.time).c_str()); + return; + } + + if (TRACE_LIVE) + if ((m_live_state.bit_counter & 0x000f)==0) logerror("%s: [%s live] Read %04x\n", tag(), tts(m_live_state.time).c_str(), m_live_state.shift_reg); + + // [1] p. 9: The ID field sync mark must be found within 33,792 byte times + if (m_live_state.bit_count_total > 33792*16) + { + wait_for_realtime(SEARCH_IDAM_FAILED); + return; + } + + if (found_mark(SEARCH_IDAM)) + { + if (TRACE_LIVE) logerror("%s: [%s live] Found an A1 mark\n", tag(), tts(m_live_state.time).c_str()); + m_live_state.crc = 0x443b; + m_live_state.data_separator_phase = false; + m_live_state.bit_counter = 0; + + m_live_state.state = READ_IDENT; + } + break; + + case SEARCH_IDAM_FAILED: + set_bits(m_register_r[CHIP_STATUS], CS_SYNCERR, true); + m_live_state.state = IDLE; + return; + + case READ_IDENT: + if (read_from_mfmhd(limit)) return; + + // Repeat until we have collected 16 bits (MFM_BITS; in the other modes this is always false) + if (m_live_state.bit_counter & 15) break; + + // Ident bytes are 111111xx + if ((m_live_state.data_reg & 0xfc) != 0xfc) + { + // This may happen when we accidentally locked onto the DAM. Look for the next IDAM. + if (TRACE_LIVE) logerror("%s: Missing ident byte after A1\n", tag()); + m_live_state.state = SEARCH_IDAM; + } + else + { + m_register_r[CURRENT_IDENT] = m_live_state.data_reg; + m_live_state.state = READ_ID_FIELDS_INTO_REGS; + slot = 0; + } + break; + + case READ_ID_FIELDS_INTO_REGS: + + if (TRACE_LIVE && m_last_live_state != READ_ID_FIELDS_INTO_REGS) + { + logerror("%s: [%s live] READ_ID_FIELDS_INTO_REGS\n", tag(),tts(m_live_state.time).c_str()); + m_last_live_state = m_live_state.state; + } + + if (read_from_mfmhd(limit)) return; + + // Repeat until we have collected 16 bits + if (m_live_state.bit_counter & 15) break; + + if (TRACE_LIVE) logerror("%s: slot %d = %02x, crc=%04x\n", tag(), slot, m_live_state.data_reg, m_live_state.crc); + m_register_r[id_field[slot++]] = m_live_state.data_reg; + + if(slot > 5) + { + // We successfully read the ID fields; let's wait for the machine time to catch up. + m_live_state.bit_count_total = 0; + + if ((current_command() & 0xfe) == 0x5a) + // Continue if we're reading a complete track + wait_for_realtime(READ_TRACK_ID_DONE); + else + // Live run is done here; it is the main state machine's turn again. + wait_for_realtime(IDLE); + return; + } + break; + + case SEARCH_DAM: + if (TRACE_LIVE && m_last_live_state != SEARCH_DAM) + { + logerror("%s: [%s live] SEARCH_DAM\n", tag(),tts(m_live_state.time).c_str()); + m_last_live_state = m_live_state.state; + } + set_bits(m_register_r[CHIP_STATUS], CS_DELDATA, false); + + if (read_from_mfmhd(limit)) return; + + if (TRACE_LIVE) + if ((m_live_state.bit_counter & 15)==0) logerror("%s: [%s live] Read %04x\n", tag(), tts(m_live_state.time).c_str(), m_live_state.shift_reg); + + if (m_live_state.bit_counter > 30*16) + { + if (TRACE_FAIL) logerror("%s: SEARCH_DAM failed\n", tag()); + wait_for_realtime(SEARCH_DAM_FAILED); + return; + } + + if (found_mark(SEARCH_DAM)) + { + if (TRACE_LIVE) logerror("%s: [%s live] Found an A1 mark\n", tag(),tts(m_live_state.time).c_str()); + m_live_state.crc = 0x443b; + m_live_state.data_separator_phase = false; + m_live_state.bit_counter = 0; + m_live_state.state = READ_DATADEL_FLAG; + } + break; + + case READ_DATADEL_FLAG: + if (read_from_mfmhd(limit)) return; + + if (m_live_state.bit_counter & 15) break; + + if ((m_live_state.data_reg & 0xff) == 0xf8) + { + if (TRACE_LIVE) logerror("%s: [%s live] Found deleted data mark F8 after DAM sync\n", tag(), tts(m_live_state.time).c_str()); + set_bits(m_register_r[CHIP_STATUS], CS_DELDATA, true); + } + else + { + if ((m_live_state.data_reg & 0xff) != 0xfb) + { + if (TRACE_FAIL) logerror("%s: [%s live] Missing FB/F8 data mark after DAM sync; found %04x\n", tag(), tts(m_live_state.time).c_str(), m_live_state.shift_reg); + wait_for_realtime(SEARCH_DAM_FAILED); + return; + } + } + m_live_state.bit_counter = 0; + m_live_state.state = READ_SECTOR_DATA; + break; + + case SEARCH_DAM_FAILED: + if (TRACE_FAIL) logerror("%s: SEARCH_DAM failed\n", tag()); + m_live_state.state = IDLE; + return; + + case READ_SECTOR_DATA: + if (TRACE_LIVE && m_last_live_state != READ_SECTOR_DATA) + { + logerror("%s: [%s live] READ_SECTOR_DATA\n", tag(),tts(m_live_state.time).c_str()); + m_last_live_state = m_live_state.state; + } + + if (read_from_mfmhd(limit)) return; + + // Request bus release + // For hard disk, get it only for the first byte and then keep the bus until the last byte. + // HD: bit_counter increases by 16 for MFM_BYTE, SEPARATED(_SIMPLE) and by 1 for MFM_BIT + if (m_transfer_enabled && (m_live_state.bit_counter == 1 || m_live_state.bit_counter == 16)) + { + set_bits(m_register_r[INT_STATUS], ST_OVRUN, true); + m_out_dmarq(ASSERT_LINE); + } + + // Repeat until we have collected 16 bits + if (m_live_state.bit_counter & 15) break; + + slot = (m_live_state.bit_counter >> 4)-1; + if (TRACE_LIVE) logerror("%s: [%s live] Found data value [%d/%d] = %02X, CRC=%04x\n", tag(),tts(m_live_state.time).c_str(), slot, calc_sector_size(), m_live_state.data_reg, m_live_state.crc); + + if (slot < calc_sector_size()) + { + // For the first byte, allow for the DMA acknowledge to be set. + if (slot == 0) + { + wait_for_realtime(READ_SECTOR_DATA_CONT); + return; + } + else m_live_state.state = READ_SECTOR_DATA_CONT; + } + else if (slot < calc_sector_size()+2) + { + // CRC + if (slot == calc_sector_size()+1) + { + m_out_dip(CLEAR_LINE); + m_out_dmarq(CLEAR_LINE); + checkpoint(); + + if ((current_command() & 0xfe)==0x5a) + { + // Reading a track? Continue with next ID. + wait_for_realtime(READ_TRACK_ID); + } + else + { + if (TRACE_LIVE) logerror("%s: [%s live] Sector read completed\n", tag(),tts(m_live_state.time).c_str()); + wait_for_realtime(IDLE); + } + return; + } + } + break; + + case READ_SECTOR_DATA_CONT: + + // Did the system CPU send the DMA ACK in the meantime? + if ((m_register_r[INT_STATUS] & ST_OVRUN)!=0) + { + if (TRACE_FAIL) logerror("%s: No DMA ACK - buffer overrun\n", tag()); + set_bits(m_register_r[INT_STATUS], TC_DATAERR, true); + m_live_state.state = IDLE; + return; + } + + if (m_transfer_enabled) + { + m_register_r[DATA] = m_register_w[DATA] = m_live_state.data_reg; + // See above: For hard disk do it only for the first byte / bit + if (m_live_state.bit_counter == 1 || m_live_state.bit_counter == 16) + m_out_dip(ASSERT_LINE); + + m_out_dma(0, m_register_r[DATA], 0xff); + if (TRACE_LIVE) logerror("%s: [%s live] Byte %02x sent via DMA\n", tag(),tts(m_live_state.time).c_str(), m_register_r[DATA] & 0xff); + } + m_live_state.state = READ_SECTOR_DATA; + + break; + + default: + if (TRACE_LIVE) logerror("%s: Unknown state: %d\n", tag(), m_live_state.state); + break; } - return; } + m_last_live_state = UNDEF; } /* @@ -2675,29 +3001,40 @@ void hdc9234_device::live_sync() if(m_live_state.time > machine().time()) { // If so, we must roll back to the last checkpoint - if (TRACE_SYNC) logerror("%s: [%s] Rolling back and replaying (%s)\n", tag(), ttsn().c_str(), tts(m_live_state.time).c_str()); + if (TRACE_SYNC) logerror("%s: [%s] Rolling back and replaying [%s live]\n", tag(), ttsn().c_str(), tts(m_live_state.time).c_str()); rollback(); + // and replay until we reach the machine time - live_run_until(machine().time()); - // Caught up, write on floppy image - m_pll.commit(m_floppy, m_live_state.time); + if (using_floppy()) + { + live_run_until(machine().time()); + // Caught up, commit bits from pll buffer to disk until live time (if there is something to write) + m_pll.commit(m_floppy, m_live_state.time); + } + else + { + // HD case + live_run_hd_until(machine().time()); + } } else { // We are behind machine time, so we will never get back to that // time, thus we can commit that position - if (TRACE_SYNC) logerror("%s: [%s] Committing (%s)\n", tag(), ttsn().c_str(), tts(m_live_state.time).c_str()); - // Write on floppy image - m_pll.commit(m_floppy, m_live_state.time); + if (TRACE_SYNC) logerror("%s: [%s] Committing [%s live]\n", tag(), ttsn().c_str(), tts(m_live_state.time).c_str()); + + // Commit bits from pll buffer to disk until live time (if there is something to write) + if (using_floppy()) + m_pll.commit(m_floppy, m_live_state.time); if (m_live_state.next_state != -1) - { m_live_state.state = m_live_state.next_state; - } if (m_live_state.state == IDLE) { - m_pll.stop_writing(m_floppy, m_live_state.time); + // Commit until live time and stop + if (using_floppy()) + m_pll.stop_writing(m_floppy, m_live_state.time); m_live_state.time = attotime::never; } } @@ -2711,12 +3048,13 @@ void hdc9234_device::live_abort() { if (!m_live_state.time.is_never() && m_live_state.time > machine().time()) { - if (TRACE_LIVE) logerror("%s: Abort; rolling back and replaying (%s)\n", ttsn().c_str(), tts(m_live_state.time).c_str()); + if (TRACE_LIVE) logerror("%s: [%s] Abort; rolling back and replaying [%s live]\n", tag(), ttsn().c_str(), tts(m_live_state.time).c_str()); rollback(); live_run_until(machine().time()); } - m_pll.stop_writing(m_floppy, m_live_state.time); + if (using_floppy()) m_pll.stop_writing(m_floppy, m_live_state.time); + m_live_state.time = attotime::never; m_live_state.state = IDLE; m_live_state.next_state = -1; @@ -2774,7 +3112,7 @@ void hdc9234_device::wait_for_realtime(int state) { m_live_state.next_state = state; m_timer->adjust(m_live_state.time - machine().time()); - if (TRACE_LIVE) logerror("%s: [%s] Waiting for real time [%s] to catch up\n", tag(), tts(m_live_state.time).c_str(), tts(machine().time()).c_str()); + if (TRACE_LIVE) logerror("%s: [%s live] Waiting for real time [%s] to catch up; next state = %d\n", tag(), tts(m_live_state.time).c_str(), ttsn().c_str(), state); } /* @@ -2897,7 +3235,7 @@ void hdc9234_device::encode_byte(UINT8 byte) m_live_state.bit_counter = 16; m_live_state.last_data_bit = raw & 1; m_live_state.shift_reg = m_live_state.shift_reg_save = raw; - if (TRACE_WRITE && TRACE_DETAIL) logerror("%s: [%s] Write %02x (%04x)\n", tag(), tts(m_live_state.time).c_str(), byte, raw); + if (TRACE_WRITE && TRACE_DETAIL) logerror("%s: [%s live] Write %02x (%04x)\n", tag(), tts(m_live_state.time).c_str(), byte, raw); checkpoint(); } @@ -2911,7 +3249,7 @@ void hdc9234_device::encode_raw(UINT16 raw) m_live_state.bit_counter = 16; m_live_state.shift_reg = m_live_state.shift_reg_save = raw; m_live_state.last_data_bit = raw & 1; - if (TRACE_WRITE && TRACE_DETAIL) logerror("%s: [%s] Write %02x (%04x)\n", tag(), tts(m_live_state.time).c_str(), get_data_from_encoding(raw), raw); + if (TRACE_WRITE && TRACE_DETAIL) logerror("%s: [%s live] Write %02x (%04x)\n", tag(), tts(m_live_state.time).c_str(), get_data_from_encoding(raw), raw); checkpoint(); } @@ -2940,14 +3278,88 @@ void hdc9234_device::pll_reset(const attotime &when, bool output) void hdc9234_device::checkpoint() { - // Write on floppy image - m_pll.commit(m_floppy, m_live_state.time); + // Commit bits from pll buffer to disk until live time (if there is something to write) + if (using_floppy()) m_pll.commit(m_floppy, m_live_state.time); m_checkpoint_state = m_live_state; m_checkpoint_pll = m_pll; } // =========================================================================== +// HD support +/* + Read the bit or complete byte from the hard disk at the point of time + specified by the time in the live_state. + Return true: the time limit has been reached + Return false: valid return + + Updates the CRC and the shift register. Also, the time is updated. + +*/ +bool hdc9234_device::read_from_mfmhd(const attotime &limit) +{ + UINT16 data = 0; + bool offlimit = m_harddisk->read(m_live_state.time, limit, data); + + // We have reached the time limit + if (offlimit) return true; + + if (m_hd_encoding == MFM_BITS) + { + // Push bit into shift register + m_live_state.shift_reg = (m_live_state.shift_reg << 1) | data; + m_live_state.bit_counter++; + // Used for timeout handling + m_live_state.bit_count_total++; + + // Clock bit (false) or data bit (true)? + if (m_live_state.data_separator_phase==true) + { + m_live_state.data_reg = (m_live_state.data_reg << 1) | data; + // Update CRC + if ((m_live_state.crc ^ (data ? 0x8000 : 0x0000)) & 0x8000) + m_live_state.crc = (m_live_state.crc << 1) ^ 0x1021; + else + m_live_state.crc = m_live_state.crc << 1; + } + + m_live_state.data_separator_phase = !m_live_state.data_separator_phase; + } + else + { + UINT16 separated = data; + m_live_state.shift_reg = data; + + if (m_hd_encoding == MFM_BYTE) + { + for (int i=0; i < 8; i++) + { + separated <<= 1; + if (data & 0x8000) separated |= 0x0100; + data <<= 1; + if (data & 0x8000) separated |= 0x0001; + data <<= 1; + } + } + + // Push byte into data / clock register + m_live_state.clock_reg = (separated >> 8) & 0xff; + m_live_state.data_reg = separated & 0xff; + m_live_state.bit_counter += 16; + // Used for timeout handling + m_live_state.bit_count_total += 16; + + // Update CRC + m_live_state.crc = ccitt_crc16_one(m_live_state.crc, m_live_state.data_reg); + m_live_state.data_separator_phase = false; + } + + return false; +} + + +// =========================================================================== + /* Read a byte of data from the controller The address (offset) encodes the C/D* line (command and /data) @@ -3074,6 +3486,7 @@ void hdc9234_device::process_command() void hdc9234_device::reenter_command_processing() { + if (TRACE_DELAY) logerror("%s: Re-enter command processing; live state = %d\n", tag(), m_live_state.state); // Do we have a live run on the track? if (m_live_state.state != IDLE) { @@ -3085,6 +3498,7 @@ void hdc9234_device::reenter_command_processing() // We're here when there is no live_run anymore // Where were we last time? // Take care not to restart commands because of the index callback + if (TRACE_DELAY) logerror("%s: Continue with substate %d\n", tag(), m_substate); if (m_executing && m_substate != UNDEF) (this->*m_command)(); auxbus_out(); } @@ -3184,31 +3598,36 @@ void hdc9234_device::auxbus_in(UINT8 data) (data&HDC_DS_SKCOM)? 1:0, (data&HDC_DS_TRK00)? 1:0, (data&HDC_DS_UDEF)? 1:0, (data&HDC_DS_WRPROT)? 1:0, (data&HDC_DS_READY)? 1:0, (data&HDC_DS_WRFAULT)? 1:0); - UINT8 prev = m_register_r[DRIVE_STATUS]; + + bool previndex = index_hole(); + bool prevready = drive_ready(); + bool prevskcom = seek_complete(); + m_register_r[DRIVE_STATUS] = data; - if ((prev & HDC_DS_INDEX) != (data & HDC_DS_INDEX)) - { - // Check whether index value changed - index_callback((data & HDC_DS_INDEX)? ASSERT_LINE : CLEAR_LINE); - } + // Call a handler if the respective flag changed + if (previndex != index_hole()) index_handler(); + if (prevready != drive_ready()) ready_handler(); + if (prevskcom != seek_complete()) seek_complete_handler(); +} - if ((prev & HDC_DS_READY) != (data & HDC_DS_READY)) - { - // Check whether ready value changed - ready_callback((data & HDC_DS_READY)? ASSERT_LINE : CLEAR_LINE); - } +bool hdc9234_device::waiting_for_line(int line, int level) +{ + return (m_event_line == line && m_state_after_line != UNDEF && m_line_level == level); +} - if ((prev & HDC_DS_SKCOM) != (data & HDC_DS_SKCOM)) - { - // Check whether seek complete value changed - seek_complete_callback((data & HDC_DS_SKCOM)? ASSERT_LINE : CLEAR_LINE); - } +bool hdc9234_device::waiting_for_other_line(int line) +{ + return (m_state_after_line != UNDEF && m_event_line != line); } -void hdc9234_device::index_callback(int level) +/* + Handlers for incoming signal lines. +*/ +void hdc9234_device::index_handler() { - if (TRACE_LINES) logerror("%s: [%s] Index callback level=%d\n", tag(), ttsn().c_str(), level); + int level = index_hole()? ASSERT_LINE : CLEAR_LINE; + if (TRACE_LINES) logerror("%s: [%s] Index handler; level=%d\n", tag(), ttsn().c_str(), level); // Synchronize our position on the track live_sync(); @@ -3219,24 +3638,31 @@ void hdc9234_device::index_callback(int level) if (m_wait_for_index) m_stop_after_index = true; } - if (m_event_line == INDEX_LINE && level == m_line_level && m_state_after_line != UNDEF) + if (waiting_for_line(INDEX_LINE, level)) { if (TRACE_LINES) logerror("%s: [%s] Index pulse level=%d triggers event\n", tag(), ttsn().c_str(), level); m_substate = m_state_after_line; m_state_after_line = UNDEF; if (m_stopwrite) { - m_pll.stop_writing(m_floppy, m_live_state.time); + if (using_floppy()) m_pll.stop_writing(m_floppy, m_live_state.time); m_live_state.state = IDLE; } + reenter_command_processing(); + } + else + { + // Live processing waits for INDEX + // For harddisk we will continue processing on the falling edge + if (!waiting_for_other_line(INDEX_LINE) && (using_floppy() || level == CLEAR_LINE)) + reenter_command_processing(); } - - reenter_command_processing(); } -void hdc9234_device::ready_callback(int level) +void hdc9234_device::ready_handler() { - if (TRACE_LINES) logerror("%s: [%s] Ready callback level=%d\n", tag(), ttsn().c_str(), level); + int level = drive_ready()? ASSERT_LINE : CLEAR_LINE; + if (TRACE_LINES) logerror("%s: [%s] Ready handler; level=%d\n", tag(), ttsn().c_str(), level); // Set the interrupt status flag set_bits(m_register_r[INT_STATUS], ST_RDYCHNG, true); @@ -3251,7 +3677,8 @@ void hdc9234_device::ready_callback(int level) set_interrupt(ASSERT_LINE); } - if (m_event_line == READY_LINE && level == m_line_level && m_state_after_line != UNDEF) + // This is actually not needed, since we never wait for READY + if (waiting_for_line(READY_LINE, level)) { m_substate = m_state_after_line; m_state_after_line = UNDEF; @@ -3259,14 +3686,15 @@ void hdc9234_device::ready_callback(int level) } } -void hdc9234_device::seek_complete_callback(int level) +void hdc9234_device::seek_complete_handler() { - if (TRACE_LINES) logerror("%s: [%s] Seek complete callback level=%d\n", tag(), ttsn().c_str(), level); + int level = seek_complete()? ASSERT_LINE : CLEAR_LINE; + if (TRACE_LINES) logerror("%s: [%s] Seek complete handler; level=%d\n", tag(), ttsn().c_str(), level); // Synchronize our position on the track live_sync(); - if (m_event_line == SEEKCOMP_LINE && level == m_line_level && m_state_after_line != UNDEF) + if (waiting_for_line(SEEKCOMP_LINE, level)) { m_substate = m_state_after_line; m_state_after_line = UNDEF; @@ -3382,6 +3810,8 @@ void hdc9234_device::connect_floppy_drive(floppy_image_device* floppy) void hdc9234_device::connect_hard_drive(mfm_harddisk_device* harddisk) { m_harddisk = harddisk; + m_hd_encoding = m_harddisk->get_encoding(); + if (TRACE_DETAIL) logerror("%s: HD encoding = %d\n", tag(), m_hd_encoding); } /* diff --git a/src/emu/machine/hdc9234.h b/src/emu/machine/hdc9234.h index 8317545c552..b6dad3fa4f2 100644 --- a/src/emu/machine/hdc9234.h +++ b/src/emu/machine/hdc9234.h @@ -173,10 +173,16 @@ private: // Timer callback void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); - // Callbacks - void ready_callback(int level); - void index_callback(int level); - void seek_complete_callback(int level); + // Handlers for incoming signals + void ready_handler(); + void index_handler(); + void seek_complete_handler(); + + // Wait for this line? + bool waiting_for_line(int line, int level); + + // Wait for some other line? + bool waiting_for_other_line(int line); // Wait for some time to pass or for a line to change level void wait_time(emu_timer *tm, int microsec, int next_substate); @@ -212,6 +218,7 @@ private: int byte_counter; bool data_separator_phase; bool last_data_bit; + UINT8 clock_reg; UINT8 data_reg; int state; int next_state; @@ -241,11 +248,14 @@ private: void rollback(); void checkpoint(); + // Found a mark + bool found_mark(int state); + // Delivers the data bits from the given encoding UINT8 get_data_from_encoding(UINT16 raw); // ============================================== - // PLL functions and interface to floppy + // PLL functions and interface to floppy and harddisk // ============================================== // Phase-locked loops @@ -254,6 +264,9 @@ private: // Clock divider value UINT8 m_clock_divider; + // MFM HD encoding type + mfmhd_enc_t m_hd_encoding; + // Resets the PLL to the given time void pll_reset(const attotime &when, bool write); @@ -283,6 +296,9 @@ private: // Skips bytes on the track void skip_on_track(int count, int next_state); + // Read from the MFM HD + bool read_from_mfmhd(const attotime &limit); + // ============================================== // Command state machine // ============================================== @@ -368,6 +384,18 @@ private: // Are we in FM mode? bool fm_mode(); + // Seek completed? + bool seek_complete(); + + // Are we on track 0? + bool on_track00(); + + // Are we at the index hole? + bool index_hole(); + + // Is the attached drive ready? + bool drive_ready(); + // Delivers the desired head int desired_head(); @@ -398,12 +426,6 @@ private: // Sector size as read from the track int calc_sector_size(); - // Are we on track 0? - bool on_track00(); - - // Are we using rapid steps (needed to decide to wait for seek complete) - bool rapid_steps(); - // Is the currently selected drive a floppy drive? bool using_floppy(); diff --git a/src/emu/machine/idehd.c b/src/emu/machine/idehd.c index ffb9a026ea8..2cd59aa0892 100644 --- a/src/emu/machine/idehd.c +++ b/src/emu/machine/idehd.c @@ -394,7 +394,7 @@ void ata_mass_storage_device::fill_buffer() { set_dasp(ASSERT_LINE); - start_busy(TIME_BETWEEN_SECTORS, PARAM_COMMAND); + start_busy(TIME_PER_SECTOR, PARAM_COMMAND); } break; } diff --git a/src/emu/machine/mm58274c.c b/src/emu/machine/mm58274c.c index bc1b27daede..db2d1d07dcf 100644 --- a/src/emu/machine/mm58274c.c +++ b/src/emu/machine/mm58274c.c @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Raphael Nabet /*************************************************************************** diff --git a/src/emu/machine/mm58274c.h b/src/emu/machine/mm58274c.h index 729e1a65fad..225340721ea 100644 --- a/src/emu/machine/mm58274c.h +++ b/src/emu/machine/mm58274c.h @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Raphael Nabet #ifndef __MM58274C_H__ #define __MM58274C_H__ diff --git a/src/emu/machine/mos6526.c b/src/emu/machine/mos6526.c index e65070d3d67..3d9561b36f7 100644 --- a/src/emu/machine/mos6526.c +++ b/src/emu/machine/mos6526.c @@ -809,12 +809,18 @@ READ8_MEMBER( mos6526_device::read ) switch (offset & 0x0f) { case PRA: - data = (m_read_pa(0) & ~m_ddra) | (m_pra & m_ddra); + if (m_ddra != 0xff) + data = (m_read_pa(0) & ~m_ddra) | (m_pra & m_ddra); + else + data = m_read_pa(0) & m_pra; m_pa_in = data; break; case PRB: - data = (m_read_pb(0) & ~m_ddrb) | (m_prb & m_ddrb); + if (m_ddrb != 0xff) + data = (m_read_pb(0) & ~m_ddrb) | (m_prb & m_ddrb); + else + data = m_read_pb(0) & m_prb; m_pb_in = data; if (CRA_PBON) diff --git a/src/emu/machine/netlist.c b/src/emu/machine/netlist.c index 125f34c9f33..7b7767afea1 100644 --- a/src/emu/machine/netlist.c +++ b/src/emu/machine/netlist.c @@ -13,6 +13,7 @@ #include "netlist/nl_base.h" #include "netlist/nl_setup.h" #include "netlist/nl_factory.h" +#include "netlist/nl_parser.h" #include "netlist/devices/net_lib.h" #include "debugger.h" @@ -294,7 +295,7 @@ void netlist_mame_device_t::device_start() //printf("clock is %d\n", clock()); m_netlist = global_alloc_clear(netlist_mame_t(*this)); - m_setup = global_alloc_clear(netlist_setup_t(*m_netlist)); + m_setup = global_alloc_clear(netlist_setup_t(m_netlist)); netlist().init_object(*m_netlist, "netlist"); m_setup->init(); @@ -633,3 +634,14 @@ void netlist_mame_sound_device_t::sound_stream_update(sound_stream &stream, stre m_out[i]->buffer_reset(cur); } } + +// ---------------------------------------------------------------------------------------- +// memregion source support +// ---------------------------------------------------------------------------------------- + +bool netlist_source_memregion_t::parse(netlist_setup_t *setup, const pstring name) +{ + const char *mem = (const char *)downcast<netlist_mame_t &>(setup->netlist()).machine().root_device().memregion(m_name.cstr())->base(); + netlist_parser p(*setup); + return p.parse(mem, name); +} diff --git a/src/emu/machine/netlist.h b/src/emu/machine/netlist.h index c6e8e2ce396..829124595b5 100644 --- a/src/emu/machine/netlist.h +++ b/src/emu/machine/netlist.h @@ -60,8 +60,21 @@ // Extensions to interface netlist with MAME code .... // ---------------------------------------------------------------------------------------- -#define NETLIST_MEMREGION(_name) \ - setup.parse((char *)downcast<netlist_mame_t &>(setup.netlist()).machine().root_device().memregion(_name)->base()); +class netlist_source_memregion_t : public netlist_setup_t::source_t +{ +public: + netlist_source_memregion_t(pstring name) + : netlist_setup_t::source_t(), m_name(name) + { + } + + bool parse(netlist_setup_t *setup, const pstring name); +private: + pstring m_name; +}; + +#define MEMREGION_SOURCE(_name) \ + setup.register_source(palloc(netlist_source_memregion_t, _name)); #define NETDEV_ANALOG_CALLBACK_MEMBER(_name) \ void _name(const double data, const attotime &time) diff --git a/src/emu/machine/ti99_hd.c b/src/emu/machine/ti99_hd.c index 1f3029a1200..49aeb5b69d1 100644 --- a/src/emu/machine/ti99_hd.c +++ b/src/emu/machine/ti99_hd.c @@ -14,22 +14,21 @@ **************************************************************************/ +// TODO: Format + #include "emu.h" #include "formats/imageutl.h" #include "harddisk.h" #include "ti99_hd.h" -#define TI99HD_BLOCKNOTFOUND -1 - -#define LOG logerror -#define VERBOSE 0 - -#define GAP1 16 -#define GAP2 8 -#define GAP3 15 -#define GAP4 340 -#define SYNC 13 +#define TRACE_STEPS 0 +#define TRACE_SIGNALS 0 +#define TRACE_READ 0 +#define TRACE_CACHE 0 +#define TRACE_RWTRACK 0 +#define TRACE_BITS 0 +#define TRACE_DETAIL 0 enum { @@ -45,10 +44,27 @@ enum STEP_SETTLE }; +#define TRACKSLOTS 5 +#define TRACKIMAGE_SIZE 10416 // Provide the buffer for a complete track, including preambles and gaps + +std::string mfm_harddisk_device::tts(const attotime &t) +{ + char buf[256]; + int nsec = t.attoseconds / ATTOSECONDS_PER_NANOSECOND; + sprintf(buf, "%4d.%03d,%03d,%03d", int(t.seconds), nsec/1000000, (nsec/1000)%1000, nsec % 1000); + return buf; +} + mfm_harddisk_device::mfm_harddisk_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) : harddisk_image_device(mconfig, type, name, tag, owner, clock, shortname, source), device_slot_card_interface(mconfig, *this) { + m_spinupms = 10000; + m_cachelines = TRACKSLOTS; +} + +mfm_harddisk_device::~mfm_harddisk_device() +{ } void mfm_harddisk_device::device_start() @@ -56,14 +72,15 @@ void mfm_harddisk_device::device_start() m_index_timer = timer_alloc(INDEX_TM); m_spinup_timer = timer_alloc(SPINUP_TM); m_seek_timer = timer_alloc(SEEK_TM); + m_rev_time = attotime::from_hz(60); // MFM drives have a revolution rate of 3600 rpm (i.e. 60/sec) m_index_timer->adjust(attotime::from_hz(60), 0, attotime::from_hz(60)); - // Spinup may take up to 24 seconds - m_spinup_timer->adjust(attotime::from_msec(8000)); + m_current_cylinder = 615; // Park position + m_spinup_timer->adjust(attotime::from_msec(m_spinupms)); - m_current_cylinder = 10; // for test purpose + m_cache = global_alloc(mfmhd_trackimage_cache); } void mfm_harddisk_device::device_reset() @@ -74,6 +91,27 @@ void mfm_harddisk_device::device_reset() m_seek_inward = false; m_track_delta = 0; m_step_line = CLEAR_LINE; + m_recalibrated = false; +} + +void mfm_harddisk_device::device_stop() +{ + global_free(m_cache); +} + +bool mfm_harddisk_device::call_load() +{ + setup_characteristics(); + bool loaded = harddisk_image_device::call_load(); + if (loaded==IMAGE_INIT_PASS) + { + m_cache->init(get_chd_file(), tag(), m_max_cylinder, m_max_heads, m_cachelines, m_encoding); + } + else + { + logerror("%s: Could not load CHD\n", tag()); + } + return loaded; } void mfm_harddisk_device::setup_index_pulse_cb(index_pulse_cb cb) @@ -81,27 +119,56 @@ void mfm_harddisk_device::setup_index_pulse_cb(index_pulse_cb cb) m_index_pulse_cb = cb; } +void mfm_harddisk_device::setup_ready_cb(ready_cb cb) +{ + m_ready_cb = cb; +} + void mfm_harddisk_device::setup_seek_complete_cb(seek_complete_cb cb) { m_seek_complete_cb = cb; } +attotime mfm_harddisk_device::track_end_time() +{ + // We back up two microseconds before the track end to avoid the + // index pulse to appear earlier (because of rounding effects) + attotime nexttime = m_rev_time - attotime::from_nsec(2000); + attotime endtime = attotime::never; + + if (!m_ready) + { + // estimate the next index time; during power-up we assume half the rotational speed + // Should never be relevant, though, because READY is false. + nexttime = nexttime * 2; + } + + if (!m_revolution_start_time.is_never()) + { + endtime = m_revolution_start_time + nexttime; + if (TRACE_DETAIL) logerror("%s: Track start time = %s, end time = %s\n", tag(), tts(m_revolution_start_time).c_str(), tts(endtime).c_str()); + } + return endtime; +} + void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { switch (id) { case INDEX_TM: /* Simple index hole handling. We assume that there is only a short pulse. */ + m_revolution_start_time = machine().time(); if (!m_index_pulse_cb.isnull()) { m_index_pulse_cb(this, ASSERT_LINE); m_index_pulse_cb(this, CLEAR_LINE); } break; + case SPINUP_TM: - m_ready = true; - logerror("%s: Spinup complete, drive is ready\n", tag()); + recalibrate(); break; + case SEEK_TM: switch (m_step_phase) { @@ -117,7 +184,7 @@ void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int // Start the settle timer m_step_phase = STEP_SETTLE; m_seek_timer->adjust(attotime::from_usec(16800)); - logerror("%s: Arrived at target track %d, settling ...\n", tag(), m_current_cylinder); + if (TRACE_STEPS && TRACE_DETAIL) logerror("%s: Arrived at target cylinder %d, settling ...\n", tag(), m_current_cylinder); } break; case STEP_SETTLE: @@ -126,9 +193,19 @@ void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int else { // Seek completed - logerror("%s: Settling done at cylinder %d, seek complete\n", tag(), m_current_cylinder); + if (!m_recalibrated) + { + m_ready = true; + m_recalibrated = true; + if (TRACE_SIGNALS) logerror("%s: Spinup complete, drive recalibrated and positioned at cylinder %d; drive is READY\n", tag(), m_current_cylinder); + if (!m_ready_cb.isnull()) m_ready_cb(this, ASSERT_LINE); + } + else + { + if (TRACE_SIGNALS) logerror("%s: Settling done at cylinder %d, seek complete\n", tag(), m_current_cylinder); + } m_seek_complete = true; - m_seek_complete_cb(this, ASSERT_LINE); + if (!m_seek_complete_cb.isnull()) m_seek_complete_cb(this, ASSERT_LINE); m_step_phase = STEP_COLLECT; } break; @@ -136,11 +213,22 @@ void mfm_harddisk_device::device_timer(emu_timer &timer, device_timer_id id, int } } +void mfm_harddisk_device::recalibrate() +{ + if (TRACE_STEPS) logerror("%s: Recalibrate to track 0\n", tag()); + direction_in_w(CLEAR_LINE); + while (-m_track_delta < 620) + { + step_w(ASSERT_LINE); + step_w(CLEAR_LINE); + } +} + void mfm_harddisk_device::head_move() { int steps = m_track_delta; if (steps < 0) steps = -steps; - logerror("%s: Moving head by %d step(s) %s\n", tag(), steps, (m_track_delta<0)? "outward" : "inward"); + if (TRACE_STEPS) logerror("%s: Moving head by %d step(s) %s\n", tag(), steps, (m_track_delta<0)? "outward" : "inward"); int disttime = steps*200; m_step_phase = STEP_MOVING; @@ -156,7 +244,7 @@ void mfm_harddisk_device::head_move() void mfm_harddisk_device::direction_in_w(line_state line) { m_seek_inward = (line == ASSERT_LINE); - logerror("%s: Setting seek direction %s\n", tag(), m_seek_inward? "inward" : "outward"); + if (TRACE_STEPS && TRACE_DETAIL) logerror("%s: Setting seek direction %s\n", tag(), m_seek_inward? "inward" : "outward"); } /* @@ -210,15 +298,15 @@ void mfm_harddisk_device::step_w(line_state line) { m_step_phase = STEP_COLLECT; m_seek_complete = false; - m_seek_complete_cb(this, CLEAR_LINE); + if (!m_seek_complete_cb.isnull()) m_seek_complete_cb(this, CLEAR_LINE); } // Counter will be adjusted according to the direction (+-1) m_track_delta += (m_seek_inward)? +1 : -1; - logerror("%s: Got seek pulse; track delta %d\n", tag(), m_track_delta); + if (TRACE_STEPS && TRACE_DETAIL) logerror("%s: Got seek pulse; track delta %d\n", tag(), m_track_delta); if (m_track_delta < -670 || m_track_delta > 670) { - logerror("%s: Excessive step pulses - doing auto-truncation\n", tag()); + if (TRACE_STEPS) logerror("%s: Excessive step pulses - doing auto-truncation\n", tag()); m_autotruncation = true; } m_seek_timer->adjust(attotime::from_usec(250)); @@ -226,12 +314,516 @@ void mfm_harddisk_device::step_w(line_state line) m_step_line = line; } +/* + Reading bytes from the hard disk. + This is the byte-level access to the hard disk. We deliver the next data byte + together with the clock byte. + + Returns true if the time limit will be exceeded before reading the complete byte. + Otherwise returns the byte at the given position together with the clock byte. +*/ +bool mfm_harddisk_device::read(attotime &from_when, const attotime &limit, UINT16 &cdata) +{ + UINT16* track = m_cache->get_trackimage(m_current_cylinder, m_current_head); + + if (track==NULL) + { + // What shall we do in this case? + throw emu_fatalerror("Cannot read CHD image"); + } + + // We stop some few cells early each track, so lift the from_when time over + // the 2 microseconds. + if (from_when < m_revolution_start_time) from_when = m_revolution_start_time; + + // Calculate the position in the track, given the from_when time and the revolution_start_time. + // Each cell takes 100 ns (10 MHz) + + int cell = (from_when - m_revolution_start_time).as_ticks(10000000); + + attotime fw = from_when; + + from_when += attotime::from_nsec((m_encoding==MFM_BITS)? 100 : 1600); + if (from_when > limit) return true; + + + int bytepos = cell / 16; + + // Reached the end + if (bytepos >= 10416) + { + if (TRACE_DETAIL) logerror("%s: Reached end: rev_start = %s, live = %s\n", tag(), tts(m_revolution_start_time).c_str(), tts(fw).c_str()); + m_revolution_start_time += m_rev_time; + cell = (from_when - m_revolution_start_time).as_ticks(10000000); + bytepos = cell / 16; + } + + if (bytepos < 0) + { + if (TRACE_DETAIL) logerror("%s: Negative cell number: rev_start = %s, live = %s\n", tag(), tts(m_revolution_start_time).c_str(), tts(fw).c_str()); + bytepos = 0; + } + + if (m_encoding == MFM_BITS) + { + // We will deliver a single bit + int cellno = cell % 16; + cdata = ((track[bytepos] << cellno) & 0x8000) >> 15; + if (TRACE_BITS) logerror("%s: Reading (c=%d,h=%d,bit=%d) at cell %d [%s] = %d\n", tag(), m_current_cylinder, m_current_head, cellno, cell, tts(fw).c_str(), cdata); + } + else + { + // We will deliver a whole byte + if (TRACE_READ) logerror("%s: Reading (c=%d,h=%d) at position %d\n", tag(), m_current_cylinder, m_current_head, bytepos); + cdata = track[bytepos]; + } + return false; +} + mfm_hd_generic_device::mfm_hd_generic_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) -: mfm_harddisk_device(mconfig, MFM_HD_GENERIC, "Generic MFM hard disk (byte level)", tag, owner, clock, "mfm_harddisk", __FILE__) +: mfm_harddisk_device(mconfig, MFMHD_GENERIC, "Generic MFM hard disk", tag, owner, clock, "mfm_harddisk", __FILE__) +{ +} + +void mfm_hd_generic_device::setup_characteristics() +{ + m_max_cylinder = 0; + m_max_heads = 0; +} + +const device_type MFMHD_GENERIC = &device_creator<mfm_hd_generic_device>; + +mfm_hd_st225_device::mfm_hd_st225_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) +: mfm_harddisk_device(mconfig, MFMHD_ST225, "Seagate ST-225 MFM hard disk", tag, owner, clock, "mfm_hd_st225", __FILE__) { } -const device_type MFM_HD_GENERIC = &device_creator<mfm_hd_generic_device>; +void mfm_hd_st225_device::setup_characteristics() +{ + m_max_cylinder = 615; + m_max_heads = 4; +} + +const device_type MFMHD_ST225 = &device_creator<mfm_hd_st225_device>; + +// =========================================================== +// Track cache +// The cache holds track images to be read by the controller. +// This is a write-back LRU cache. +// =========================================================== + +mfmhd_trackimage_cache::mfmhd_trackimage_cache(): + m_tracks(NULL) +{ + m_current_crc = 0; +} + +mfmhd_trackimage_cache::~mfmhd_trackimage_cache() +{ + mfmhd_trackimage* current = m_tracks; + if (TRACE_CACHE) logerror("%s: MFM HD cache destroy\n", tag()); + + // Still dirty? + while (current != NULL) + { + if (TRACE_CACHE) logerror("%s: MFM HD cache: evict line cylinder=%d head=%d\n", tag(), current->cylinder, current->head); + if (current->dirty) write_back(current); + global_free_array(current->encdata); + mfmhd_trackimage* currenttmp = current->next; + global_free(current); + current = currenttmp; + } +} + +/* + Initialize the cache by loading the first <trackslots> tracks. +*/ +void mfmhd_trackimage_cache::init(chd_file* chdfile, const char* dtag, int maxcyl, int maxhead, int trackslots, mfmhd_enc_t encoding) +{ + m_encoding = encoding; + m_tagdev = dtag; + + if (TRACE_CACHE) logerror("%s: MFM HD cache init; using encoding %d\n", m_tagdev, encoding); + chd_error state = CHDERR_NONE; + mfmhd_trackimage* previous = NULL; + mfmhd_trackimage* current = NULL; + std::string metadata; + + m_chd = chdfile; + + if (chdfile==NULL) + { + logerror("%s: chdfile is null\n", tag()); + return; + } + + // Read the hard disk metadata + state = chdfile->read_metadata(HARD_DISK_METADATA_TAG, 0, metadata); + if (state != CHDERR_NONE) + { + throw emu_fatalerror("Failed to read CHD metadata"); + } + + // Parse the metadata + if (sscanf(metadata.c_str(), HARD_DISK_METADATA_FORMAT, &m_cylinders, &m_heads, &m_sectors_per_track, &m_sectorsize) != 4) + { + throw emu_fatalerror("Invalid metadata"); + } + + if (maxcyl != 0 && m_cylinders > maxcyl) + { + throw emu_fatalerror("Image geometry does not fit this kind of hard drive: drive=(%d,%d), image=(%d,%d)", maxcyl, maxhead, m_cylinders, m_heads); + } + + // Load some tracks into the cache + int track = 0; + int head = 0; + int cylinder = 0; + while (track < trackslots) + { + if (TRACE_CACHE && TRACE_DETAIL) logerror("%s: MFM HD allocate cache slot\n", tag()); + previous = current; + current = global_alloc(mfmhd_trackimage); + current->encdata = global_alloc_array(UINT16, TRACKIMAGE_SIZE); + + // Load the first tracks into the slots + state = load_track(current, cylinder, head, 32, 256, 4); + + if (state != CHDERR_NONE) throw emu_fatalerror("Cannot load (c=%d,h=%d) from hard disk", cylinder, head); + + // We will read all heads per cylinder first, then go to the next cylinder. + if (++head >= m_heads) + { + head = 0; + cylinder++; + } + current->next = NULL; + + if (previous != NULL) + previous->next = current; + else + // Head + m_tracks = current; + + // Count the number of loaded tracks + track++; + } +} + +/* + Returns the linear sector number, given the CHS data. + + C,H,S + | 0,0,0 | 0,0,1 | 0,0,2 | ... + | 0,1,0 | 0,1,1 | 0,1,2 | ... + ... + | 1,0,0 | ... + ... +*/ +int mfmhd_trackimage_cache::chs_to_lba(int cylinder, int head, int sector) +{ + if ((cylinder < m_cylinders) && (head < m_heads) && (sector < m_sectors_per_track)) + { + return (cylinder * m_heads + head) * m_sectors_per_track + sector; + } + else return -1; +} + +/* + Delivers the track image. + First look up the track image in the cache. If not present, load it from + the CHD, convert it, and evict the least recently used line. + The searched track will be the first in m_tracks. +*/ +UINT16* mfmhd_trackimage_cache::get_trackimage(int cylinder, int head) +{ + // Search the cached track images + mfmhd_trackimage* current = m_tracks; + mfmhd_trackimage* previous = NULL; + + chd_error state = CHDERR_NONE; + + // Repeat the search. This loop should run at most twice; once for a direct hit, + // and twice on miss, then the second iteration will be a hit. + while (state == CHDERR_NONE) + { + // A simple linear search + while (current != NULL) + { + if (current->cylinder == cylinder && current->head == head) + { + // found it + // move it to the front of the chain for LRU + if (previous != NULL) + { + previous->next = current->next; // pull out here + current->next = m_tracks; // put the previous head into the next field + m_tracks = current; // set this line as new head + } + return current->encdata; + } + else + { + // Don't lose the pointer to the next tail + if (current->next != NULL) previous = current; + current = current->next; + } + } + // If we are here, we have a cache miss. + // Evict the last line + // Load the new line into that line + // Then look it up again, which will move it to the front + + // previous points to the second to last element + current = previous->next; + if (TRACE_CACHE) logerror("%s: MFM HD cache: evict line (c=%d,h=%d)\n", tag(), current->cylinder, current->head); + + if (current->dirty) write_back(current); + state = load_track(current, cylinder, head, 32, 256, 4); + } + // If we are here we have a CHD error. + return NULL; +} + +/* + Create MFM encoding. +*/ +void mfmhd_trackimage_cache::mfm_encode(mfmhd_trackimage* slot, int& position, UINT8 byte, int count) +{ + mfm_encode_mask(slot, position, byte, count, 0x00); +} + +void mfmhd_trackimage_cache::mfm_encode_a1(mfmhd_trackimage* slot, int& position) +{ + m_current_crc = 0xffff; + mfm_encode_mask(slot, position, 0xa1, 1, 0x04); + // 0x443b; CRC for A1 +} + +void mfmhd_trackimage_cache::mfm_encode_mask(mfmhd_trackimage* slot, int& position, UINT8 byte, int count, int mask) +{ + UINT16 encclock = 0; + UINT16 encdata = 0; + UINT8 thisbyte = byte; + bool mark = (mask != 0x00); + + m_current_crc = ccitt_crc16_one(m_current_crc, byte); + + for (int i=0; i < 8; i++) + { + encdata <<= 1; + encclock <<= 1; + + if (m_encoding == MFM_BITS || m_encoding == MFM_BYTE) + { + // skip one position for later interleaving + encdata <<= 1; + encclock <<= 1; + } + + if (thisbyte & 0x80) + { + // Encoding 1 => 01 + encdata |= 1; + m_lastbit = true; + } + else + { + // Encoding 0 => x0 + // If the bit in the mask is set, suppress the clock bit + // Also, if we use the simplified encoding, don't set the clock bits + if (m_lastbit == false && m_encoding != SEPARATED_SIMPLE && (mask & 0x80) == 0) encclock |= 1; + m_lastbit = false; + } + mask <<= 1; + // For simplified encoding, set all clock bits to indicate a mark + if (m_encoding == SEPARATED_SIMPLE && mark) encclock |= 1; + thisbyte <<= 1; + } + + if (m_encoding == MFM_BITS || m_encoding == MFM_BYTE) + encclock <<= 1; + else + encclock <<= 8; + + slot->encdata[position++] = (encclock | encdata); + + // When we write the byte multiple times, check whether the next encoding + // differs from the previous because of the last bit + + if (m_encoding == MFM_BITS || m_encoding == MFM_BYTE) + { + encclock &= 0x7fff; + if ((byte & 0x80)==0 && m_lastbit==false) encclock |= 0x8000; + } + + for (int j=1; j < count; j++) + { + slot->encdata[position++] = (encclock | encdata); + m_current_crc = ccitt_crc16_one(m_current_crc, byte); + } +} + +/* + Load a track from the CHD. +*/ +chd_error mfmhd_trackimage_cache::load_track(mfmhd_trackimage* slot, int cylinder, int head, int sectorcount, int size, int interleave) +{ + chd_error state = CHDERR_NONE; + + UINT8 sector_content[1024]; + + if (TRACE_RWTRACK) logerror("%s: MFM HD cache: load (c=%d,h=%d) from CHD\n", tag(), cylinder, head); + + m_lastbit = false; + int position = 0; // will be incremented by each encode call + + // Gap 1 + mfm_encode(slot, position, 0x4e, 16); + + int sec_il_start = 0; + int sec_number = 0; + + // Round up + int delta = (sectorcount + interleave-1) / interleave; + + if (TRACE_DETAIL) logerror("cyl=%02x head=%02x: sector sequence = ", cylinder&0xff, head&0xff); + for (int sector = 0; sector < sectorcount; sector++) + { + if (TRACE_DETAIL) logerror("%02d ", sec_number); + // Sync gap + mfm_encode(slot, position, 0x00, 13); + + // Write IDAM + mfm_encode_a1(slot, position); + mfm_encode(slot, position, 0xfe); // ID field? + + // Write header + mfm_encode(slot, position, cylinder & 0xff); + mfm_encode(slot, position, head & 0xff); + mfm_encode(slot, position, sec_number); + mfm_encode(slot, position, (size >> 7)-1); + + // Write CRC for header. + int crc = m_current_crc; + mfm_encode(slot, position, (crc >> 8) & 0xff); + mfm_encode(slot, position, crc & 0xff); + + // Gap 2 + mfm_encode(slot, position, 0x4e, 3); + + // Sync + mfm_encode(slot, position, 0x00, 13); + + // Write DAM + mfm_encode_a1(slot, position); + mfm_encode(slot, position, 0xfb); + + // Get sector content from CHD + chd_error state = m_chd->read_units(chs_to_lba(cylinder, head, sec_number), sector_content); + if (state != CHDERR_NONE) + break; + + for (int i=0; i < size; i++) + mfm_encode(slot, position, sector_content[i]); + + // Write CRC for content. + crc = m_current_crc; + mfm_encode(slot, position, (crc >> 8) & 0xff); + mfm_encode(slot, position, crc & 0xff); + + // Gap 3 + mfm_encode(slot, position, 0x00, 3); + mfm_encode(slot, position, 0x4e, 19); + + // Calculate next sector number + sec_number += delta; + if (sec_number >= sectorcount) sec_number = ++sec_il_start; + } + if (TRACE_DETAIL) logerror("\n"); + + // Gap 4 + if (state == CHDERR_NONE) + { + // Fill the rest with 0x4e + mfm_encode(slot, position, 0x4e, TRACKIMAGE_SIZE-position); + if (TRACE_DETAIL) + { + showtrack(slot->encdata, TRACKIMAGE_SIZE); + } + } + + slot->dirty = false; + slot->cylinder = cylinder; + slot->head = head; + + return state; +} + +/* + TODO: Maybe use a scheduled write-back in addition to the eviction. +*/ +void mfmhd_trackimage_cache::write_back(mfmhd_trackimage* slot) +{ + if (TRACE_RWTRACK) logerror("%s: MFM HD cache: write back (c=%d,h=%d) to CHD\n", tag(), slot->cylinder, slot->head); + slot->dirty = false; +} + +/* + For debugging. Outputs the byte array in a xxd-like way. +*/ +void mfmhd_trackimage_cache::showtrack(UINT16* enctrack, int length) +{ + for (int i=0; i < length; i+=16) + { + logerror("%07x: ", i); + for (int j=0; j < 16; j++) + { + logerror("%04x ", enctrack[i+j]); + } + logerror(" "); + logerror("\n"); + } +} + +// ================================================================ + +mfm_harddisk_connector::mfm_harddisk_connector(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock): + device_t(mconfig, MFM_HD_CONNECTOR, "MFM hard disk connector", tag, owner, clock, "mfm_hd_connector", __FILE__), + device_slot_interface(mconfig, *this) +{ +} + +mfm_harddisk_connector::~mfm_harddisk_connector() +{ +} + +mfm_harddisk_device* mfm_harddisk_connector::get_device() +{ + return dynamic_cast<mfm_harddisk_device *>(get_card_device()); +} + +void mfm_harddisk_connector::configure(mfmhd_enc_t encoding, int spinupms, int cache) +{ + m_encoding = encoding; + m_spinupms = spinupms; + m_cachesize = cache; +} + +void mfm_harddisk_connector::device_config_complete() +{ + mfm_harddisk_device *dev = get_device(); + if (dev != NULL) + { + dev->set_encoding(m_encoding); + dev->set_spinup_time(m_spinupms); + dev->set_cache_size(m_cachesize); + } +} + +const device_type MFM_HD_CONNECTOR = &device_creator<mfm_harddisk_connector>; + +// ================================================================ // =========================================================================== // Legacy implementation @@ -239,6 +831,17 @@ const device_type MFM_HD_GENERIC = &device_creator<mfm_hd_generic_device>; #include "smc92x4.h" +#define TI99HD_BLOCKNOTFOUND -1 + +#define LOG logerror +#define VERBOSE 0 + +#define GAP1 16 +#define GAP2 8 +#define GAP3 15 +#define GAP4 340 +#define SYNC 13 + mfm_harddisk_legacy_device::mfm_harddisk_legacy_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, TI99_MFMHD_LEG, "MFM Harddisk LEGACY", tag, owner, clock, "mfm_harddisk_leg", __FILE__) { diff --git a/src/emu/machine/ti99_hd.h b/src/emu/machine/ti99_hd.h index 7f2a5cddf7b..02f5d4fb4e5 100644 --- a/src/emu/machine/ti99_hd.h +++ b/src/emu/machine/ti99_hd.h @@ -17,56 +17,206 @@ #include "emu.h" #include "imagedev/harddriv.h" +/* + Determine how data are passed from the hard disk to the controller. We + allow for different degrees of hardware emulation. +*/ +enum mfmhd_enc_t +{ + MFM_BITS, // One bit at a time + MFM_BYTE, // One data byte with interleaved clock bits + SEPARATED, // 8 clock bits (most sig byte), one data byte (least sig byte) + SEPARATED_SIMPLE // MSB: 00/FF (standard / mark) clock, LSB: one data byte +}; + +class mfmhd_trackimage +{ +public: + bool dirty; + int cylinder; + int head; + UINT16* encdata; // MFM encoding per byte + mfmhd_trackimage* next; +}; + +class mfmhd_trackimage_cache +{ +public: + mfmhd_trackimage_cache(); + ~mfmhd_trackimage_cache(); + void init(chd_file* chdfile, const char* tag, int maxcyl, int maxhead, int trackslots, mfmhd_enc_t encoding); + UINT16* get_trackimage(int cylinder, int head); + +private: + void mfm_encode(mfmhd_trackimage* slot, int& position, UINT8 byte, int count=1); + void mfm_encode_a1(mfmhd_trackimage* slot, int& position); + void mfm_encode_mask(mfmhd_trackimage* slot, int& position, UINT8 byte, int count, int mask); + chd_error load_track(mfmhd_trackimage* slot, int cylinder, int head, int sectorcount, int size, int interleave); + void write_back(mfmhd_trackimage* timg); + int chs_to_lba(int cylinder, int head, int sector); + chd_file* m_chd; + + const char* m_tagdev; + mfmhd_trackimage* m_tracks; + mfmhd_enc_t m_encoding; + bool m_lastbit; + int m_current_crc; + int m_cylinders; + int m_heads; + int m_sectors_per_track; + int m_sectorsize; + void showtrack(UINT16* enctrack, int length); + const char* tag() { return m_tagdev; } +}; + class mfm_harddisk_device : public harddisk_image_device, public device_slot_card_interface { public: mfm_harddisk_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + ~mfm_harddisk_device(); typedef delegate<void (mfm_harddisk_device*, int)> index_pulse_cb; + typedef delegate<void (mfm_harddisk_device*, int)> ready_cb; typedef delegate<void (mfm_harddisk_device*, int)> seek_complete_cb; void setup_index_pulse_cb(index_pulse_cb cb); + void setup_ready_cb(ready_cb cb); void setup_seek_complete_cb(seek_complete_cb cb); + // Configuration + void set_encoding(mfmhd_enc_t encoding) { m_encoding = encoding; } + void set_spinup_time(int spinupms) { m_spinupms = spinupms; } + void set_cache_size(int tracks) { m_cachelines = tracks; } + + mfmhd_enc_t get_encoding() { return m_encoding; } + // Active low lines. We're using ASSERT=0 / CLEAR=1 line_state ready_r() { return m_ready? ASSERT_LINE : CLEAR_LINE; } line_state seek_complete_r() { return m_seek_complete? ASSERT_LINE : CLEAR_LINE; } ; line_state trk00_r() { return m_current_cylinder==0? ASSERT_LINE : CLEAR_LINE; } + // Data output towards controller + bool read(attotime &from_when, const attotime &limit, UINT16 &data); + // Step void step_w(line_state line); void direction_in_w(line_state line); + // Head select + void headsel_w(int head) { m_current_head = head & 0x0f; } + + bool call_load(); + + // Tells us the time when the track ends (next index pulse) + attotime track_end_time(); + protected: void device_start(); + void device_stop(); void device_reset(); + void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + + virtual void setup_characteristics() = 0; + std::string tts(const attotime &t); + emu_timer *m_index_timer, *m_spinup_timer, *m_seek_timer; index_pulse_cb m_index_pulse_cb; + ready_cb m_ready_cb; seek_complete_cb m_seek_complete_cb; - void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + + int m_max_cylinder; + int m_max_heads; private: + mfmhd_enc_t m_encoding; + int m_spinupms; + int m_cachelines; bool m_ready; int m_current_cylinder; + int m_current_head; int m_track_delta; int m_step_phase; bool m_seek_complete; bool m_seek_inward; //bool m_seeking; bool m_autotruncation; + bool m_recalibrated; line_state m_step_line; // keep the last state + attotime m_spinup_time; + attotime m_revolution_start_time; + attotime m_rev_time; + + mfmhd_trackimage_cache* m_cache; + + void prepare_track(int cylinder, int head); void head_move(); + void recalibrate(); }; class mfm_hd_generic_device : public mfm_harddisk_device { public: mfm_hd_generic_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + +protected: + void setup_characteristics(); +}; + +extern const device_type MFMHD_GENERIC; + +class mfm_hd_st225_device : public mfm_harddisk_device +{ +public: + mfm_hd_st225_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + +protected: + void setup_characteristics(); +}; + +extern const device_type MFMHD_ST225; + +/* Connector for a MFM hard disk. See also floppy.c */ +class mfm_harddisk_connector : public device_t, + public device_slot_interface +{ +public: + mfm_harddisk_connector(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + ~mfm_harddisk_connector(); + + mfm_harddisk_device *get_device(); + + void configure(mfmhd_enc_t encoding, int spinupms, int cache); + +protected: + void device_start() { }; + void device_config_complete(); + +private: + mfmhd_enc_t m_encoding; + int m_spinupms; + int m_cachesize; }; -extern const device_type MFM_HD_GENERIC; +extern const device_type MFM_HD_CONNECTOR; + +/* + Add a harddisk connector. + Parameters: + _tag = Tag of the connector + _slot_intf = Selection of hard drives + _def_slot = Default hard drive + _enc = Encoding (see comments in ti99_hd.c) + _spinupms = Spinup time in milliseconds (some configurations assume that the + user has turned on the hard disk before turning on the system. We cannot + emulate this, so we allow for shorter times) + _cache = number of cached MFM tracks +*/ +#define MCFG_MFM_HARDDISK_CONN_ADD(_tag, _slot_intf, _def_slot, _enc, _spinupms, _cache) \ + MCFG_DEVICE_ADD(_tag, MFM_HD_CONNECTOR, 0) \ + MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) \ + static_cast<mfm_harddisk_connector *>(device)->configure(_enc, _spinupms, _cache); // =========================================================================== // Legacy implementation diff --git a/src/emu/machine/tms1024.c b/src/emu/machine/tms1024.c index b5dfd018b87..d728f7dfd28 100644 --- a/src/emu/machine/tms1024.c +++ b/src/emu/machine/tms1024.c @@ -1,36 +1,75 @@ // license:BSD-3-Clause // copyright-holders:hap -/********************************************************************** +/* - Texas Instruments TMS1024, TMS1025 I/O expander emulation + Texas Instruments TMS1024/TMS1025 I/O expander + + No documentation was available, just a pinout. + Other than more port pins, TMS1025 is assumed to be same as TMS1024. + + TODO: + - writes to port 0 + - what's the MS pin? + - strobe is on rising edge? or falling edge? -**********************************************************************/ +*/ #include "machine/tms1024.h" const device_type TMS1024 = &device_creator<tms1024_device>; +const device_type TMS1025 = &device_creator<tms1025_device>; //------------------------------------------------- -// tms1024_device - constructor +// constructor //------------------------------------------------- tms1024_device::tms1024_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : device_t(mconfig, TMS1024, "TMS1024", tag, owner, clock, "tms1024", __FILE__) + : device_t(mconfig, TMS1024, "TMS1024 I/O Expander", tag, owner, clock, "tms1024", __FILE__), + m_write_port1(*this), m_write_port2(*this), m_write_port3(*this), m_write_port4(*this), m_write_port5(*this), m_write_port6(*this), m_write_port7(*this) { } +tms1024_device::tms1024_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + m_write_port1(*this), m_write_port2(*this), m_write_port3(*this), m_write_port4(*this), m_write_port5(*this), m_write_port6(*this), m_write_port7(*this) +{ +} + +tms1025_device::tms1025_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : tms1024_device(mconfig, TMS1025, "TMS1025 I/O Expander", tag, owner, clock, "tms1025", __FILE__) +{ +} + + + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- void tms1024_device::device_start() { - // resolve callbacks + // resolve callbacks (there is no port 0) + m_write_port1.resolve_safe(); m_write_port[0] = &m_write_port1; + m_write_port2.resolve_safe(); m_write_port[1] = &m_write_port2; + m_write_port3.resolve_safe(); m_write_port[2] = &m_write_port3; + m_write_port4.resolve_safe(); m_write_port[3] = &m_write_port4; + m_write_port5.resolve_safe(); m_write_port[4] = &m_write_port5; + m_write_port6.resolve_safe(); m_write_port[5] = &m_write_port6; + m_write_port7.resolve_safe(); m_write_port[6] = &m_write_port7; + + // zerofill + m_h = 0; + m_s = 0; + m_std = 0; // register for savestates + save_item(NAME(m_h)); + save_item(NAME(m_s)); + save_item(NAME(m_std)); } + //------------------------------------------------- // device_reset - device-specific reset //------------------------------------------------- @@ -40,4 +79,33 @@ void tms1024_device::device_reset() } -// handlers + +//------------------------------------------------- +// handlers +//------------------------------------------------- + +WRITE8_MEMBER(tms1024_device::write_h) +{ + // H1,2,3,4: data for outputs A,B,C,D + m_h = data & 0xf; +} + +WRITE8_MEMBER(tms1024_device::write_s) +{ + // S0,1,2: select port + m_s = data & 7; +} + +WRITE_LINE_MEMBER(tms1024_device::write_std) +{ + state = (state) ? 1 : 0; + + // output on rising edge + if (state && !m_std) + { + if (m_s != 0) + (*m_write_port[m_s-1])((offs_t)(m_s-1), m_h); + } + + m_std = state; +} diff --git a/src/emu/machine/tms1024.h b/src/emu/machine/tms1024.h index e5afe4ea75e..e91c0ca5a2d 100644 --- a/src/emu/machine/tms1024.h +++ b/src/emu/machine/tms1024.h @@ -1,10 +1,39 @@ // license:BSD-3-Clause // copyright-holders:hap -/********************************************************************** +/* - Texas Instruments TMS1024, TMS1025 I/O expander emulation + Texas Instruments TMS1024/TMS1025 I/O expander -********************************************************************** +*/ + +#ifndef _TMS1024_H_ +#define _TMS1024_H_ + +#include "emu.h" + + +// ports setup + +// 4-bit ports (3210 = DCBA) +// valid ports: 4-7 for TMS1024, 1-7 for TMS1025 +#define MCFG_TMS1024_WRITE_PORT_CB(X, _devcb) \ + tms1024_device::set_write_port##X##_callback(*device, DEVCB_##_devcb); + +enum +{ + TMS1024_PORT1 = 0, + TMS1024_PORT2, + TMS1024_PORT3, + TMS1024_PORT4, + TMS1024_PORT5, + TMS1024_PORT6, + TMS1024_PORT7 +}; + + +// pinout reference + +/* ____ ____ ____ ____ Vss 1 |* \_/ | 28 H2 Vss 1 |* \_/ | 40 H2 @@ -23,48 +52,59 @@ D5 14 |___________| 15 A6 D4 14 | | 27 A7 A5 15 | | 26 D6 B5 16 | | 25 C6 - C5 17 | | 24 B6 - D5 18 | | 23 A6 - A2 19 | | 22 D2 - B2 20 |___________| 21 C2 - -**********************************************************************/ - -#ifndef _TMS1024_H_ -#define _TMS1024_H_ - -#include "emu.h" - - -//************************************************************************** -// INTERFACE CONFIGURATION MACROS -//************************************************************************** - -#define MCFG_TMS1024_ADD(_tag) \ - MCFG_DEVICE_ADD(_tag, TMS1024, 0) - + CE: Chip Enable C5 17 | | 24 B6 + MS: Master S.? D5 18 | | 23 A6 + STD: STrobe Data? A2 19 | | 22 D2 + S: Select B2 20 |___________| 21 C2 + H: Hold? -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** +*/ -// ======================> tms1024_device class tms1024_device : public device_t { public: tms1024_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + tms1024_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); // static configuration helpers + template<class _Object> static devcb_base &set_write_port1_callback(device_t &device, _Object object) { return downcast<tms1024_device &>(device).m_write_port1.set_callback(object); } + template<class _Object> static devcb_base &set_write_port2_callback(device_t &device, _Object object) { return downcast<tms1024_device &>(device).m_write_port2.set_callback(object); } + template<class _Object> static devcb_base &set_write_port3_callback(device_t &device, _Object object) { return downcast<tms1024_device &>(device).m_write_port3.set_callback(object); } + template<class _Object> static devcb_base &set_write_port4_callback(device_t &device, _Object object) { return downcast<tms1024_device &>(device).m_write_port4.set_callback(object); } + template<class _Object> static devcb_base &set_write_port5_callback(device_t &device, _Object object) { return downcast<tms1024_device &>(device).m_write_port5.set_callback(object); } + template<class _Object> static devcb_base &set_write_port6_callback(device_t &device, _Object object) { return downcast<tms1024_device &>(device).m_write_port6.set_callback(object); } + template<class _Object> static devcb_base &set_write_port7_callback(device_t &device, _Object object) { return downcast<tms1024_device &>(device).m_write_port7.set_callback(object); } + + DECLARE_WRITE8_MEMBER(write_h); + DECLARE_WRITE8_MEMBER(write_s); + DECLARE_WRITE_LINE_MEMBER(write_std); protected: // device-level overrides virtual void device_start(); virtual void device_reset(); + + UINT8 m_h; // 4-bit data latch + UINT8 m_s; // 3-bit port select + UINT8 m_std; // strobe pin + + // callbacks + devcb_write8 m_write_port1, m_write_port2, m_write_port3, m_write_port4, m_write_port5, m_write_port6, m_write_port7; + devcb_write8 *m_write_port[7]; +}; + + +class tms1025_device : public tms1024_device +{ +public: + tms1025_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); }; -// device type definition + + extern const device_type TMS1024; +extern const device_type TMS1025; #endif /* _TMS1024_H_ */ diff --git a/src/emu/machine/wd17xx.c b/src/emu/machine/wd17xx.c deleted file mode 100644 index c87c2911877..00000000000 --- a/src/emu/machine/wd17xx.c +++ /dev/null @@ -1,2107 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nathan Woods, Kevin Thacker, Phill Harvey-Smith, Robbbert, Curt Coder -/*************************************************************************** - - !!! DEPRECATED, USE src/emu/wd_fdc.h FOR NEW DRIVERS !!! - - wd17xx.c - - Implementations of the Western Digital 17xx and 27xx families of - floppy disk controllers - - - Models: - - DAL DD Side Clock Remark - --------------------------------------------------------- - FD1771 1 or 2 MHz First model - FD1781 x 1 or 2 MHz - FD1791 x 1 or 2 MHz - FD1792 1 or 2 MHz - FD1793 x x 1 or 2 MHz - FD1794 x 1 or 2 MHz - FD1795 x x 1 or 2 MHz - FD1797 x x x 1 or 2 MHz - FD1761 x 1 MHz - FD1762 1 MHz ? - FD1763 x x 1 MHz - FD1764 x 1 MHz ? - FD1765 x x 1 MHz - FD1767 x x x 1 MHz - WD2791 x 1 or 2 MHz Internal data separator - WD2793 x x 1 or 2 MHz Internal data separator - WD2795 x x 1 or 2 MHz Internal data separator - WD2797 x x x 1 or 2 MHz Internal data separator - WD1770 x x 8 MHz Motor On signal - WD1772 x x 8 MHz Motor On signal, Faster stepping rates - WD1773 x x 8 MHz Enable precomp line - - Notes: - In general, later models include all features of earlier models - - DAL: Data access lines, x = TRUE; otherwise inverted - - DD: Double density support - - Side: Has side select support - - ?: Unknown if it really exists - - Clones: - - - SMC FD179x - - Fujitsu MB8876 -> FD1791, MB8877 -> FD1793 - - VLSI VL177x - - - Changelog: - - Kevin Thacker - - Removed disk image code and replaced it with floppy drive functions. - Any disc image is now useable with this code. - - Fixed write protect - - 2005-Apr-16 P.Harvey-Smith: - - Increased the delay in wd17xx_timed_read_sector_request and - wd17xx_timed_write_sector_request, to 40us to more closely match - what happens on the real hardware, this has fixed the NitrOS9 boot - problems. - - 2007-Nov-01 Wilbert Pol: - Needed these changes to get the MB8877 for Osborne-1 to work: - - Added support for multiple record read - - Changed the wd17xx_read_id to not return after DATADONEDELAY, but - the host should read the id data through the data register. This - was accomplished by making this change in the wd17xx_read_id - function: - - wd17xx_complete_command(device, DELAY_DATADONE); - + wd17xx_set_data_request(); - - 2009-May-10 Robbbert: - Further change to get the Kaypro II to work - - When wd17xx_read_id has generated the 6 data bytes, it should make - an IRQ and turn off the busy status. The timing for Osborne is - critical, it must be between 300 and 700 usec, I've settled on 400. - The Kaypro doesn't care timewise, but the busy flag must turn off - sometime or it hangs. - - w->status |= STA_2_BUSY; - + wd17xx_set_busy(device, attotime::from_usec(400)); - - 2009-June-4 Roberto Lavarone: - - Initial support for wd1771 - - Added simulation of head loaded feedback from drive - - Bugfix: busy flag was cleared too early - - 2009-June-21 Robbbert: - - The Bugfix above, while valid, caused the Osborne1 to fail. This - is because the delay must not exceed 14usec (found by extensive testing). - - The minimum delay is 1usec, need by z80netf while formatting a disk. - - http://www.bannister.org/forums/ubbthreads.php?ubb=showflat&Number=50889#Post50889 - explains the problems, testing done, and the test procedure for the z80netf. - - Thus, the delay is set to 10usec, and all the disks I have (not many) - seem to work. - - Note to anyone who wants to change something: Make sure that the - Osborne1 boots up! It is extremely sensitive to timing! - - For testing only: The osborne1 rom can be patched to make it much - more stable, by changing the byte at 0x0da7 from 0x28 to 0x18. - - 2009-June-25 Robbbert: - - Turns out kayproii not working, 10usec is too short.. but 11usec is ok. - Setting it to 12usec. - Really, this whole thing needs a complete rewrite. - - 2009-July-08 Roberto Lavarone: - - Fixed a bug in head load flag handling: einstein and samcoupe now working again - - 2009-September-30 Robbbert: - - Modified what status flags are returned after a Forced Interrupt, - to allow Microbee to boot CP/M. - - 2010-Jan-31 Phill Harvey-Smith - - The above bugfixes for the Kaypro/Osborne1 have borked the booting on the Dragon - Alpha. The Alpha it seems needs a delay of ay least 17us or the NMI generated by - INTRQ happens too early and doen't break out of the read/write bytes loops. - - I have made the delay settable by calling wd17xx_set_complete_command_delay, and - let it default to 12us, as required above, so that the Dragon Alpha works again. - This hopefully should not break the other machines. - - This should probably be considdered a minor hack but it does seem to work ! - - 2010-02-04 Phill Harvey-Smith - - Added multiple sector write as the RM Nimbus needs it. - - 2010-March-22 Curt Coder: - - Implemented immediate and index pulse interrupts. - - 2010-Dec-31 Phill Harvey-Smith - - Copied multi-sector write code from r7263, for some reason this had been - silently removed, but is required for the rmnimbus driver. - - 2011-Mar-08 Phill Harvey-Smith - - Triggering intrq now clears the DRQ bit in the status as well as the busy bit. - Execution of the READ_DAM command now correctly sets w->command. - - 2011-Apr-01 Curt Coder - - Set complete command delay to 16 usec (DD) / 32 usec (SD) and removed - the external delay setting hack. - - 2011-Jun-24 Curt Coder - - Added device types for all known variants, and enforced inverted DAL lines. - - 2011-Sep-18 Curt Coder - - Connected Side Select Output for variants that support it. - - TODO: - - What happens if a track is read that doesn't have any id's on it? - (e.g. unformatted disc) - - Rewrite into a C++ device - -***************************************************************************/ - - -#include "emu.h" -#include "formats/imageutl.h" -#include "machine/wd17xx.h" - -/*************************************************************************** - CONSTANTS -***************************************************************************/ - -#define VERBOSE 0 /* General logging */ -#define VERBOSE_DATA 0 /* Logging of each byte during read and write */ - -#define DELAY_ERROR 3 -#define DELAY_NOTREADY 1 -#define DELAY_DATADONE 3 - -#define TYPE_I 1 -#define TYPE_II 2 -#define TYPE_III 3 -#define TYPE_IV 4 - -#define FDC_STEP_RATE 0x03 /* Type I additional flags */ -#define FDC_STEP_VERIFY 0x04 /* verify track number */ -#define FDC_STEP_HDLOAD 0x08 /* load head */ -#define FDC_STEP_UPDATE 0x10 /* update track register */ - -#define FDC_RESTORE 0x00 /* Type I commands */ -#define FDC_SEEK 0x10 -#define FDC_STEP 0x20 -#define FDC_STEP_IN 0x40 -#define FDC_STEP_OUT 0x60 - -#define FDC_MASK_TYPE_I (FDC_STEP_HDLOAD|FDC_STEP_VERIFY|FDC_STEP_RATE) - -/* Type I commands status */ -#define STA_1_BUSY 0x01 /* controller is busy */ -#define STA_1_IPL 0x02 /* index pulse */ -#define STA_1_TRACK0 0x04 /* track 0 detected */ -#define STA_1_CRC_ERR 0x08 /* CRC error */ -#define STA_1_SEEK_ERR 0x10 /* seek error */ -#define STA_1_HD_LOADED 0x20 /* head loaded */ -#define STA_1_WRITE_PRO 0x40 /* floppy is write protected */ -#define STA_1_NOT_READY 0x80 /* drive not ready */ -#define STA_1_MOTOR_ON 0x80 /* status of the Motor On output (WD1770 and WD1772 only) */ - -/* Type II and III additional flags */ -#define FDC_DELETED_AM 0x01 /* read/write deleted address mark */ -#define FDC_SIDE_CMP_T 0x02 /* side compare track data */ -#define FDC_15MS_DELAY 0x04 /* delay 15ms before command */ -#define FDC_SIDE_CMP_S 0x08 /* side compare sector data */ -#define FDC_MULTI_REC 0x10 /* only for type II commands */ - -/* Type II commands */ -#define FDC_READ_SEC 0x80 /* read sector */ -#define FDC_WRITE_SEC 0xA0 /* write sector */ - -#define FDC_MASK_TYPE_II (FDC_MULTI_REC|FDC_SIDE_CMP_S|FDC_15MS_DELAY|FDC_SIDE_CMP_T|FDC_DELETED_AM) - -/* Type II commands status */ -#define STA_2_BUSY 0x01 -#define STA_2_DRQ 0x02 -#define STA_2_LOST_DAT 0x04 -#define STA_2_CRC_ERR 0x08 -#define STA_2_REC_N_FND 0x10 -#define STA_2_REC_TYPE 0x20 -#define STA_2_WRITE_PRO 0x40 -#define STA_2_NOT_READY 0x80 - -#define FDC_MASK_TYPE_III (FDC_SIDE_CMP_S|FDC_15MS_DELAY|FDC_SIDE_CMP_T|FDC_DELETED_AM) - -/* Type III commands */ -#define FDC_READ_DAM 0xc0 /* read data address mark */ -#define FDC_READ_TRK 0xe0 /* read track */ -#define FDC_WRITE_TRK 0xf0 /* write track (format) */ - -/* Type IV additional flags */ -#define FDC_IM0 0x01 /* interrupt mode 0 */ -#define FDC_IM1 0x02 /* interrupt mode 1 */ -#define FDC_IM2 0x04 /* interrupt mode 2 */ -#define FDC_IM3 0x08 /* interrupt mode 3 */ - -#define FDC_MASK_TYPE_IV (FDC_IM3|FDC_IM2|FDC_IM1|FDC_IM0) - -/* Type IV commands */ -#define FDC_FORCE_INT 0xd0 /* force interrupt */ - -/* structure describing a double density track */ -#define TRKSIZE_DD 6144 -#if 0 -static const UINT8 track_DD[][2] = { - {16, 0x4e}, /* 16 * 4E (track lead in) */ - { 8, 0x00}, /* 8 * 00 (pre DAM) */ - { 3, 0xf5}, /* 3 * F5 (clear CRC) */ - - { 1, 0xfe}, /* *** sector *** FE (DAM) */ - { 1, 0x80}, /* 4 bytes track,head,sector,seclen */ - { 1, 0xf7}, /* 1 * F7 (CRC) */ - {22, 0x4e}, /* 22 * 4E (sector lead in) */ - {12, 0x00}, /* 12 * 00 (pre AM) */ - { 3, 0xf5}, /* 3 * F5 (clear CRC) */ - { 1, 0xfb}, /* 1 * FB (AM) */ - { 1, 0x81}, /* x bytes sector data */ - { 1, 0xf7}, /* 1 * F7 (CRC) */ - {16, 0x4e}, /* 16 * 4E (sector lead out) */ - { 8, 0x00}, /* 8 * 00 (post sector) */ - { 0, 0x00}, /* end of data */ -}; -#endif - -/* structure describing a single density track */ -#define TRKSIZE_SD 3172 -#if 0 -static const UINT8 track_SD[][2] = { - {16, 0xff}, /* 16 * FF (track lead in) */ - { 8, 0x00}, /* 8 * 00 (pre DAM) */ - { 1, 0xfc}, /* 1 * FC (clear CRC) */ - - {11, 0xff}, /* *** sector *** 11 * FF */ - { 6, 0x00}, /* 6 * 00 (pre DAM) */ - { 1, 0xfe}, /* 1 * FE (DAM) */ - { 1, 0x80}, /* 4 bytes track,head,sector,seclen */ - { 1, 0xf7}, /* 1 * F7 (CRC) */ - {10, 0xff}, /* 10 * FF (sector lead in) */ - { 4, 0x00}, /* 4 * 00 (pre AM) */ - { 1, 0xfb}, /* 1 * FB (AM) */ - { 1, 0x81}, /* x bytes sector data */ - { 1, 0xf7}, /* 1 * F7 (CRC) */ - { 0, 0x00}, /* end of data */ -}; -#endif - - -/*************************************************************************** - HELPER FUNCTIONS -***************************************************************************/ - -static int wd17xx_has_dal(device_t *device) -{ - return (device->type() == FD1793 || device->type() == FD1794 || device->type() == FD1797 || - device->type() == FD1763 || device->type() == FD1764 || device->type() == FD1767 || - device->type() == WD1770 || device->type() == WD1772 || device->type() == WD1773 || - device->type() == WD2793 || device->type() == WD2797 || - device->type() == MB8877); -} - -static int wd17xx_is_sd_only(device_t *device) -{ - return (device->type() == FD1771 || device->type() == FD1792 || device->type() == FD1794 || device->type() == FD1762 || device->type() == FD1764); -} - -static int wd17xx_has_side_select(device_t *device) -{ - return (device->type() == FD1795 || device->type() == FD1797 || - device->type() == FD1765 || device->type() == FD1767 || - device->type() == WD2795 || device->type() == WD2797); -} - -int wd1770_device::wd17xx_dden() -{ - if (!m_in_dden_func.isnull()) - return m_in_dden_func(); - else - return m_dden; -} - - -/*************************************************************************** - IMPLEMENTATION -***************************************************************************/ - -/* clear a data request */ -void wd1770_device::wd17xx_clear_drq() -{ - m_status &= ~STA_2_DRQ; - - m_drq = CLEAR_LINE; - m_out_drq_func(m_drq); -} - -/* set data request */ -void wd1770_device::wd17xx_set_drq() -{ - if (m_status & STA_2_DRQ) - m_status |= STA_2_LOST_DAT; - - m_status |= STA_2_DRQ; - - m_drq = ASSERT_LINE; - m_out_drq_func(m_drq); -} - -/* clear interrupt request */ -void wd1770_device::wd17xx_clear_intrq() -{ - m_intrq = CLEAR_LINE; - m_out_intrq_func(m_intrq); -} - -/* set interrupt request */ -void wd1770_device::wd17xx_set_intrq() -{ - m_status &= ~STA_2_BUSY; - m_status &= ~STA_2_DRQ; - - m_intrq = ASSERT_LINE; - m_out_intrq_func(m_intrq); -} - -/* set intrq after delay */ -TIMER_CALLBACK_MEMBER( wd1770_device::wd17xx_command_callback ) -{ - if (m_last_command_data != FDC_FORCE_INT) - { - wd17xx_set_intrq(); - } -} - -/* write next byte to data register and set drq */ -TIMER_CALLBACK_MEMBER( wd1770_device::wd17xx_data_callback ) -{ - /* check if this is a write command */ - if( (m_command_type == TYPE_II && m_command == FDC_WRITE_SEC) || - (m_command_type == TYPE_III && m_command == FDC_WRITE_TRK) ) - { - /* we are ready for new data */ - wd17xx_set_drq(); - - return; - } - - /* any bytes remaining? */ - if (m_data_count >= 1) - { - /* yes */ - m_data = m_buffer[m_data_offset++]; - - if (VERBOSE_DATA) - logerror("wd17xx_data_callback: $%02X (data_count %d)\n", m_data, m_data_count); - - wd17xx_set_drq(); - - /* any bytes remaining? */ - if (--m_data_count < 1) - { - /* no */ - m_data_offset = 0; - - /* clear ddam type */ - m_status &=~STA_2_REC_TYPE; - - /* read a sector with ddam set? */ - if (m_command_type == TYPE_II && m_ddam != 0) - { - /* set it */ - m_status |= STA_2_REC_TYPE; - } - - /* check if we should handle the next sector for a multi record read */ - if (m_command_type == TYPE_II && m_command == FDC_READ_SEC && (m_read_cmd & 0x10)) - { - if (VERBOSE) - logerror("wd17xx_data_callback: multi sector read\n"); - - if (m_sector == 0xff) - m_sector = 0x01; - else - m_sector++; - - wd17xx_timed_read_sector_request(); - } - else - { - /* Delay the INTRQ 3 byte times because we need to read two CRC bytes and - compare them with a calculated CRC */ - wd17xx_complete_command(DELAY_DATADONE); - - if (VERBOSE) - logerror("wd17xx_data_callback: data read completed\n"); - } - } - else - { - /* requeue us for more data */ - m_timer_data->adjust(attotime::from_usec(wd17xx_dden() ? 128 : 32)); - } - } - else - { - logerror("wd17xx_data_callback: (no new data) $%02X (data_count %d)\n", m_data, m_data_count); - } -} - - -void wd1770_device::wd17xx_set_busy(const attotime &duration) -{ - m_status |= STA_1_BUSY; - - m_timer_cmd->adjust(duration); -} - - -/* BUSY COUNT DOESN'T WORK PROPERLY! */ - -void wd1770_device::wd17xx_command_restore() -{ - UINT8 step_counter; - - if (m_drive == NULL) - return; - - step_counter = 255; - -#if 0 - m_status |= STA_1_BUSY; -#endif - - /* setup step direction */ - m_direction = -1; - - m_command_type = TYPE_I; - - /* reset busy count */ - m_busy_count = 0; - - if (1) // image_slotexists(m_drive) : FIXME - { - /* keep stepping until track 0 is received or 255 steps have been done */ - while (m_drive->floppy_tk00_r() && (step_counter != 0)) - { - /* update time to simulate seek time busy signal */ - m_busy_count++; - m_drive->floppy_drive_seek(m_direction); - step_counter--; - } - } - - /* update track reg */ - m_track = 0; -#if 0 - /* simulate seek time busy signal */ - m_busy_count = 0; //m_busy_count * ((m_data & FDC_STEP_RATE) + 1); - - /* when command completes set irq */ - wd17xx_set_intrq(); -#endif - wd17xx_set_busy(attotime::from_usec(100)); -} - -/* - Write an entire track. Formats which do not define a write_track - function pointer will cause a silent return. - What is written to the image depends on the selected format. Sector - dumps have to extract the sectors in the track, while track dumps - may directly write the bytes. - (The if-part below may thus be removed.) -*/ -void wd1770_device::write_track() -{ - floppy_image_legacy *floppy; -#if 0 - int i; - for (i=0;i+4<m_data_offset;) - { - if (m_buffer[i]==0xfe) - { - /* got address mark */ - int track = m_buffer[i+1]; - int side = m_buffer[i+2]; - int sector = m_buffer[i+3]; - //int len = m_buffer[i+4]; - int filler = 0xe5; /* IBM and Thomson */ - int density = m_density; - m_drive->floppy_drive_format_sector(side,sector,track, - m_hd,sector,density?1:0,filler); - i += 128; /* at least... */ - } - else - i++; - } -#endif - - /* Get the size in bytes of the current track. For real hardware this - may vary per system in small degree, and there even for each track - and head, so we should not assume a fixed value here. - As we are using a buffered track writing, we have to find out how long - the track will become. The only object which can tell us is the - selected format. - */ - m_data_count = 0; - floppy = m_drive->flopimg_get_image(); - if (floppy != NULL) - m_data_count = floppy_get_track_size(floppy, m_hd, m_track); - - if (m_data_count==0) - { - if (wd17xx_is_sd_only(this)) - m_data_count = TRKSIZE_SD; - else - m_data_count = wd17xx_dden() ? TRKSIZE_SD : TRKSIZE_DD; - } - - m_drive->floppy_drive_write_track_data_info_buffer( m_hd, (char *)m_buffer, &(m_data_count) ); - - m_data_offset = 0; - - wd17xx_set_drq(); - m_status |= STA_2_BUSY; - m_busy_count = 0; -} - -/* - Read an entire track. It is up to the format to deliver the data. Sector - dumps may be required to fantasize the missing track bytes, while track - dumps can directly deliver them. - (The if-part below may thus be removed.) -*/ -void wd1770_device::read_track() -{ - floppy_image_legacy *floppy; -#if 0 - UINT8 *psrc; /* pointer to track format structure */ - UINT8 *pdst; /* pointer to track buffer */ - int cnt; /* number of bytes to fill in */ - UINT16 crc; /* id or data CRC */ - UINT8 d; /* data */ - UINT8 t = m_track; /* track of DAM */ - UINT8 h = m_head; /* head of DAM */ - UINT8 s = m_sector_dam; /* sector of DAM */ - UINT16 l = m_sector_length; /* sector length of DAM */ - int i; - - for (i = 0; i < m_sec_per_track; i++) - { - m_dam_list[i][0] = t; - m_dam_list[i][1] = h; - m_dam_list[i][2] = i; - m_dam_list[i][3] = l >> 8; - } - - pdst = m_buffer; - - if (m_density) - { - psrc = track_DD[0]; /* double density track format */ - cnt = TRKSIZE_DD; - } - else - { - psrc = track_SD[0]; /* single density track format */ - cnt = TRKSIZE_SD; - } - - while (cnt > 0) - { - if (psrc[0] == 0) /* no more track format info ? */ - { - if (m_dam_cnt < m_sec_per_track) /* but more DAM info ? */ - { - if (m_density)/* DD track ? */ - psrc = track_DD[3]; - else - psrc = track_SD[3]; - } - } - - if (psrc[0] != 0) /* more track format info ? */ - { - cnt -= psrc[0]; /* subtract size */ - d = psrc[1]; - - if (d == 0xf5) /* clear CRC ? */ - { - crc = 0xffff; - d = 0xa1; /* store A1 */ - } - - for (i = 0; i < *psrc; i++) - *pdst++ = d; /* fill data */ - - if (d == 0xf7) /* store CRC ? */ - { - pdst--; /* go back one byte */ - *pdst++ = crc & 255; /* put CRC low */ - *pdst++ = crc / 256; /* put CRC high */ - cnt -= 1; /* count one more byte */ - } - else if (d == 0xfe)/* address mark ? */ - { - crc = 0xffff; /* reset CRC */ - } - else if (d == 0x80)/* sector ID ? */ - { - pdst--; /* go back one byte */ - t = *pdst++ = m_dam_list[m_dam_cnt][0]; /* track number */ - h = *pdst++ = m_dam_list[m_dam_cnt][1]; /* head number */ - s = *pdst++ = m_dam_list[m_dam_cnt][2]; /* sector number */ - l = *pdst++ = m_dam_list[m_dam_cnt][3]; /* sector length code */ - m_dam_cnt++; - crc = ccitt_crc16_one(crc, t); /* build CRC */ - crc = ccitt_crc16_one(crc, h); /* build CRC */ - crc = ccitt_crc16_one(crc, s); /* build CRC */ - crc = ccitt_crc16_one(crc, l); /* build CRC */ - l = (l == 0) ? 128 : l << 8; - } - else if (d == 0xfb)// data address mark ? - { - crc = 0xffff; // reset CRC - } - else if (d == 0x81)// sector DATA ? - { - pdst--; /* go back one byte */ - if (seek(w, t, h, s) == 0) - { - if (mame_fread(m_image_file, pdst, l) != l) - { - m_status = STA_2_CRC_ERR; - return; - } - } - else - { - m_status = STA_2_REC_N_FND; - return; - } - for (i = 0; i < l; i++) // build CRC of all data - crc = ccitt_crc16_one(crc, *pdst++); - cnt -= l; - } - psrc += 2; - } - else - { - *pdst++ = 0xff; /* fill track */ - cnt--; /* until end */ - } - } -#endif - /* Determine the track size. We cannot allow different sizes in this - design (see above, write_track). */ - m_data_count = 0; - floppy = m_drive->flopimg_get_image(); - if (floppy != NULL) - m_data_count = floppy_get_track_size(floppy, m_hd, m_track); - - if (m_data_count==0) - { - if (wd17xx_is_sd_only(this)) - m_data_count = TRKSIZE_SD; - else - m_data_count = wd17xx_dden() ? TRKSIZE_SD : TRKSIZE_DD; - } - - m_drive->floppy_drive_read_track_data_info_buffer( m_hd, (char *)m_buffer, &(m_data_count) ); - - m_data_offset = 0; - - wd17xx_set_drq(); - m_status |= STA_2_BUSY; - m_busy_count = 0; -} - - -/* read the next data address mark */ -void wd1770_device::wd17xx_read_id() -{ - chrn_id id; - m_status &= ~(STA_2_CRC_ERR | STA_2_REC_N_FND); - - /* get next id from disc */ - if (m_drive->floppy_drive_get_next_id(m_hd, &id)) - { - UINT16 crc = 0xffff; - - m_data_offset = 0; - m_data_count = 6; - - /* for MFM */ - /* crc includes 3x0x0a1, and 1x0x0fe (id mark) */ - crc = ccitt_crc16_one(crc,0x0a1); - crc = ccitt_crc16_one(crc,0x0a1); - crc = ccitt_crc16_one(crc,0x0a1); - crc = ccitt_crc16_one(crc,0x0fe); - - m_buffer[0] = id.C; - m_buffer[1] = id.H; - m_buffer[2] = id.R; - m_buffer[3] = id.N; - crc = ccitt_crc16_one(crc, m_buffer[0]); - crc = ccitt_crc16_one(crc, m_buffer[1]); - crc = ccitt_crc16_one(crc, m_buffer[2]); - crc = ccitt_crc16_one(crc, m_buffer[3]); - /* crc is stored hi-byte followed by lo-byte */ - m_buffer[4] = crc>>8; - m_buffer[5] = crc & 255; - - m_sector = id.C; - - if (VERBOSE) - logerror("wd17xx_read_id: read id succeeded.\n"); - - wd17xx_timed_data_request(); - } - else - { - /* record not found */ - m_status |= STA_2_REC_N_FND; - //m_sector = m_track; - if (VERBOSE) - logerror("wd17xx_read_id: read id failed\n"); - - wd17xx_complete_command(DELAY_ERROR); - } -} - - - -void wd1770_device::index_pulse_callback(device_t *img, int state) -{ - if (img != m_drive) - return; - - m_idx = state; - - if (!state && m_idx && BIT(m_interrupt, 2)) - wd17xx_set_intrq(); - - if (m_hld_count) - m_hld_count--; -} - - - -int wd1770_device::wd17xx_locate_sector() -{ - UINT8 revolution_count; - chrn_id id; - revolution_count = 0; - - m_status &= ~STA_2_REC_N_FND; - - while (revolution_count!=4) - { - if (m_drive->floppy_drive_get_next_id(m_hd, &id)) - { - /* compare track */ - if (id.C == m_track) - { - /* compare head, if we were asked to */ - if (!wd17xx_has_side_select(this) || (id.H == m_head) || (m_head == (UINT8) ~0)) - { - /* compare id */ - if (id.R == m_sector) - { - m_sector_length = 1<<(id.N+7); - m_sector_data_id = id.data_id; - /* get ddam status */ - m_ddam = id.flags & ID_FLAG_DELETED_DATA; - /* got record type here */ - if (VERBOSE) - logerror("sector found! C:$%02x H:$%02x R:$%02x N:$%02x%s\n", id.C, id.H, id.R, id.N, m_ddam ? " DDAM" : ""); - return 1; - } - } - } - } - - /* index set? */ - if (m_drive->floppy_drive_get_flag_state(FLOPPY_DRIVE_INDEX)) - { - /* update revolution count */ - revolution_count++; - } - } - return 0; -} - - -int wd1770_device::wd17xx_find_sector() -{ - if ( wd17xx_locate_sector() ) - { - return 1; - } - - /* record not found */ - m_status |= STA_2_REC_N_FND; - - if (VERBOSE) - logerror("track %d sector %d not found!\n", m_track, m_sector); - - wd17xx_complete_command(DELAY_ERROR); - - return 0; -} - -void wd1770_device::wd17xx_side_compare(UINT8 command) -{ - if (wd17xx_has_side_select(this)) - set_side((command & FDC_SIDE_CMP_T) ? 1 : 0); - - if (command & FDC_SIDE_CMP_T) - m_head = (command & FDC_SIDE_CMP_S) ? 1 : 0; - else - m_head = ~0; -} - -/* read a sector */ -void wd1770_device::wd17xx_read_sector() -{ - m_data_offset = 0; - - /* side compare? */ - wd17xx_side_compare(m_read_cmd); - - if (wd17xx_find_sector()) - { - m_data_count = m_sector_length; - - /* read data */ - m_drive->floppy_drive_read_sector_data(m_hd, m_sector_data_id, (char *)m_buffer, m_sector_length); - - wd17xx_timed_data_request(); - - m_status |= STA_2_BUSY; - m_busy_count = 0; - } -} - - -/* called on error, or when command is actually completed */ -/* KT - I have used a timer for systems that use interrupt driven transfers. -A interrupt occurs after the last byte has been read. If it occurs at the time -when the last byte has been read it causes problems - same byte read again -or bytes missed */ -/* TJL - I have add a parameter to allow the emulation to specify the delay -*/ -void wd1770_device::wd17xx_complete_command(int delay) -{ - m_data_count = 0; - - m_hld_count = 2; - - /* set new timer */ - int usecs = wd17xx_dden() ? 32 : 16; - m_timer_cmd->adjust(attotime::from_usec(usecs)); - - /* Kill onshot read/write sector timers */ - m_timer_rs->adjust(attotime::never); - m_timer_ws->adjust(attotime::never); -} - - - -void wd1770_device::wd17xx_write_sector() -{ - /* at this point, the disc is write enabled, and data - * has been transfered into our buffer - now write it to - * the disc image or to the real disc - */ - - /* side compare? */ - wd17xx_side_compare(m_write_cmd); - - /* find sector */ - if (wd17xx_find_sector()) - { - m_data_count = m_sector_length; - - /* write data */ - m_drive->floppy_drive_write_sector_data(m_hd, m_sector_data_id, (char *)m_buffer, m_sector_length, m_write_cmd & 0x01); - } -} - - - -/* verify the seek operation by looking for a id that has a matching track value */ -void wd1770_device::wd17xx_verify_seek() -{ - UINT8 revolution_count; - chrn_id id; - revolution_count = 0; - - if (VERBOSE) - logerror("doing seek verify\n"); - - m_status &= ~STA_1_SEEK_ERR; - - /* must be found within 5 revolutions otherwise error */ - while (revolution_count!=5) - { - if (m_drive->floppy_drive_get_next_id( m_hd, &id)) - { - /* compare track */ - if (id.C == m_track) - { - if (VERBOSE) - logerror("seek verify succeeded!\n"); - return; - } - } - - /* index set? */ - if (m_drive->floppy_drive_get_flag_state(FLOPPY_DRIVE_INDEX)) - { - /* update revolution count */ - revolution_count++; - } - } - - m_status |= STA_1_SEEK_ERR; - - if (VERBOSE) - logerror("failed seek verify!\n"); -} - - - -/* callback to initiate read sector */ -TIMER_CALLBACK_MEMBER( wd1770_device::wd17xx_read_sector_callback ) -{ - /* ok, start that read! */ - - if (VERBOSE) - logerror("wd179x: Read Sector callback.\n"); - - if (!m_drive->floppy_drive_get_flag_state(FLOPPY_DRIVE_READY)) - wd17xx_complete_command(DELAY_NOTREADY); - else - wd17xx_read_sector(); -} - - - -/* callback to initiate write sector */ -TIMER_CALLBACK_MEMBER( wd1770_device::wd17xx_write_sector_callback ) -{ - /* ok, start that write! */ - - if (VERBOSE) - logerror("wd179x: Write Sector callback.\n"); - - if (!m_drive->floppy_drive_get_flag_state(FLOPPY_DRIVE_READY)) - wd17xx_complete_command(DELAY_NOTREADY); - else - { - /* drive write protected? */ - if (m_drive->floppy_wpt_r() == CLEAR_LINE) - { - m_status |= STA_2_WRITE_PRO; - - wd17xx_complete_command(DELAY_ERROR); - } - else - { - /* side compare? */ - wd17xx_side_compare(m_write_cmd); - - /* attempt to find it first before getting data from cpu */ - if (wd17xx_find_sector()) - { - /* request data */ - m_data_offset = 0; - m_data_count = m_sector_length; - - wd17xx_set_drq(); - - m_status |= STA_2_BUSY; - m_busy_count = 0; - } - } - } -} - - - -/* setup a timed data request - data request will be triggered in a few usecs time */ -void wd1770_device::wd17xx_timed_data_request() -{ - /* set new timer */ - m_timer_data->adjust(attotime::from_usec(wd17xx_dden() ? 128 : 32)); -} - - - -/* setup a timed read sector - read sector will be triggered in a few usecs time */ -void wd1770_device::wd17xx_timed_read_sector_request() -{ - /* set new timer */ - m_timer_rs->adjust(attotime::from_usec(m_pause_time)); -} - - - -/* setup a timed write sector - write sector will be triggered in a few usecs time */ -void wd1770_device::wd17xx_timed_write_sector_request() -{ - /* set new timer */ - m_timer_ws->adjust(attotime::from_usec(m_pause_time)); -} - - -/*************************************************************************** - INTERFACE -***************************************************************************/ - -/* use this to determine which drive is controlled by WD */ -void wd1770_device::set_drive(UINT8 drive) -{ - if (VERBOSE) - logerror("wd17xx_set_drive: $%02x\n", drive); - - if (m_floppy_drive_tags[drive] != NULL) - { - m_drive = siblingdevice<legacy_floppy_image_device>(m_floppy_drive_tags[drive]); - } -} - -void wd1770_device::set_side(UINT8 head) -{ - if (VERBOSE) - { - if (head != m_hd) - logerror("wd17xx_set_side: $%02x\n", head); - } - - m_hd = head; -} - -void wd1770_device::set_pause_time(int usec) -{ - m_pause_time = usec; -} - - -/*************************************************************************** - DEVICE HANDLERS -***************************************************************************/ - -/* master reset */ -WRITE_LINE_MEMBER( wd1770_device::mr_w ) -{ - /* reset device when going from high to low */ - if (m_mr && state == CLEAR_LINE) - { - m_command = 0x03; - m_status &= ~STA_1_NOT_READY; /* ? */ - } - - /* execute restore command when going from low to high */ - if (m_mr == CLEAR_LINE && state) - { - wd17xx_command_restore(); - m_sector = 0x01; - } - - m_mr = state; -} - -/* ready and enable precomp (1773 only) */ -WRITE_LINE_MEMBER( wd1770_device::rdy_w ) -{ - m_rdy = state; -} - -/* motor on, 1770 and 1772 only */ -READ_LINE_MEMBER( wd1770_device::mo_r ) -{ - return m_mo; -} - -/* track zero */ -WRITE_LINE_MEMBER( wd1770_device::tr00_w ) -{ - m_tr00 = state; -} - -/* index pulse */ -WRITE_LINE_MEMBER( wd1770_device::idx_w ) -{ - m_idx = state; - - if (!state && m_idx && BIT(m_interrupt, 2)) - wd17xx_set_intrq(); -} - -/* write protect status */ -WRITE_LINE_MEMBER( wd1770_device::wprt_w ) -{ - m_wprt = state; -} - -/* double density enable */ -WRITE_LINE_MEMBER( wd1770_device::dden_w ) -{ - /* not supported on FD1771, FD1792, FD1794, FD1762 and FD1764 */ - if (wd17xx_is_sd_only(this)) - fatalerror("wd17xx_dden_w: double density input not supported on this model!\n"); - else if (!m_in_dden_func.isnull()) - logerror("wd17xx_dden_w: write has no effect because a read handler is already defined!\n"); - else - m_dden = state; -} - -/* data request */ -READ_LINE_MEMBER( wd1770_device::drq_r ) -{ - return m_drq; -} - -/* interrupt request */ -READ_LINE_MEMBER( wd1770_device::intrq_r ) -{ - return m_intrq; -} - -/* read the FDC status register. This clears IRQ line too */ -READ8_MEMBER( wd1770_device::status_r ) -{ - int result; - - if (!BIT(m_interrupt, 3)) - { - wd17xx_clear_intrq(); - } - - /* bit 7, 'not ready' or 'motor on' */ - if (type() == WD1770 || type() == WD1772) - { - m_status &= ~STA_1_MOTOR_ON; - m_status |= m_mo << 7; - } - else - { - m_status &= ~STA_1_NOT_READY; - if (!m_drive->floppy_drive_get_flag_state(FLOPPY_DRIVE_READY)) - m_status |= STA_1_NOT_READY; - } - - result = m_status; - - /* type 1 command or force int command? */ - if ((m_command_type==TYPE_I) || (m_command_type==TYPE_IV && ! m_was_busy)) - { - result &= ~(STA_1_IPL | STA_1_TRACK0); - - /* bit 1, index pulse */ - result |= m_idx << 1; - - /* bit 2, track 0 state, inverted */ - result |= !m_drive->floppy_tk00_r() << 2; - - if (m_command_type==TYPE_I) - { - if (m_hld_count) - m_status |= STA_1_HD_LOADED; - else - m_status &= ~ STA_1_HD_LOADED; - } - - /* bit 6, write protect, inverted */ - result |= !m_drive->floppy_wpt_r() << 6; - } - - /* eventually set data request bit */ -// m_status |= m_status_drq; - - if (VERBOSE) - { - if (m_data_count < 4) - logerror("%s: wd17xx_status_r: $%02X (data_count %d)\n", machine().describe_context(), result, m_data_count); - } - - return result ^ (wd17xx_has_dal(this) ? 0 : 0xff); -} - -/* read the FDC track register */ -READ8_MEMBER( wd1770_device::track_r ) -{ - if (VERBOSE) - logerror("%s: wd17xx_track_r: $%02X\n", machine().describe_context(), m_track); - - return m_track ^ (wd17xx_has_dal(this) ? 0 : 0xff); -} - -/* read the FDC sector register */ -READ8_MEMBER( wd1770_device::sector_r ) -{ - if (VERBOSE) - logerror("%s: wd17xx_sector_r: $%02X\n", machine().describe_context(), m_sector); - - return m_sector ^ (wd17xx_has_dal(this) ? 0 : 0xff); -} - -/* read the FDC data register */ -READ8_MEMBER( wd1770_device::data_r ) -{ - if (VERBOSE_DATA) - logerror("%s: wd17xx_data_r: %02x\n", machine().describe_context(), m_data); - - /* clear data request */ - wd17xx_clear_drq(); - - return m_data ^ (wd17xx_has_dal(this) ? 0 : 0xff); -} - -/* write the FDC command register */ -WRITE8_MEMBER( wd1770_device::command_w ) -{ - if (!wd17xx_has_dal(this)) data ^= 0xff; - - m_last_command_data = data; - - /* only the WD1770 and WD1772 have a 'motor on' line */ - if (type() == WD1770 || type() == WD1772) - { - m_mo = ASSERT_LINE; - m_drive->floppy_mon_w(CLEAR_LINE); - } - - m_drive->floppy_drive_set_ready_state(1,0); - - if (!BIT(m_interrupt, 3)) - { - wd17xx_clear_intrq(); - } - - /* clear write protected. On read sector, read track and read dam, write protected bit is clear */ - m_status &= ~((1<<6) | (1<<5) | (1<<4)); - - if ((data & ~FDC_MASK_TYPE_IV) == FDC_FORCE_INT) - { - if (VERBOSE) - logerror("%s: wd17xx_command_w $%02X FORCE_INT (data_count %d)\n", machine().describe_context(), data, m_data_count); - - m_data_count = 0; - m_data_offset = 0; - m_was_busy = m_status & STA_2_BUSY; - m_status &= ~STA_2_BUSY; - - wd17xx_clear_drq(); - - if (!BIT(m_interrupt, 3) && BIT(data, 3)) - { - /* set immediate interrupt */ - wd17xx_set_intrq(); - } - - if (BIT(m_interrupt, 3)) - { - if (data == FDC_FORCE_INT) - { - /* clear immediate interrupt */ - m_interrupt = data & 0x0f; - } - else - { - /* keep immediate interrupt */ - m_interrupt = 0x08 | (data & 0x07); - } - } - else - { - m_interrupt = data & 0x0f; - } - - /* terminate command */ - wd17xx_complete_command(DELAY_ERROR); - - m_busy_count = 0; - m_command_type = TYPE_IV; - return; - } - - if (data & 0x80) - { - /*m_status_ipl = 0;*/ - - if ((data & ~FDC_MASK_TYPE_II) == FDC_READ_SEC) - { - if (VERBOSE) - { - logerror("%s: wd17xx_command_w $%02X READ_SEC (", machine().describe_context(), data); - logerror("cmd=%02X, trk=%02X, sec=%02X, dat=%02X)\n",m_command,m_track,m_sector,m_data); - } - m_read_cmd = data; - m_command = data & ~FDC_MASK_TYPE_II; - m_command_type = TYPE_II; - m_status &= ~STA_2_LOST_DAT; - m_status |= STA_2_BUSY; - wd17xx_clear_drq(); - - wd17xx_timed_read_sector_request(); - - return; - } - - if ((data & ~FDC_MASK_TYPE_II) == FDC_WRITE_SEC) - { - if (VERBOSE) - { - logerror("%s: wd17xx_command_w $%02X WRITE_SEC (", machine().describe_context(), data); - logerror("cmd=%02X, trk=%02X, sec=%02X, dat=%02X)\n",m_command,m_track,m_sector,m_data); - } - - m_write_cmd = data; - m_command = data & ~FDC_MASK_TYPE_II; - m_command_type = TYPE_II; - m_status &= ~STA_2_LOST_DAT; - m_status |= STA_2_BUSY; - wd17xx_clear_drq(); - - wd17xx_timed_write_sector_request(); - - return; - } - - if ((data & ~FDC_MASK_TYPE_III) == FDC_READ_TRK) - { - if (VERBOSE) - logerror("%s: wd17xx_command_w $%02X READ_TRK\n", machine().describe_context(), data); - - m_command = data & ~FDC_MASK_TYPE_III; - m_command_type = TYPE_III; - m_status &= ~STA_2_LOST_DAT; - wd17xx_clear_drq(); -#if 1 -// m_status = seek(w, m_track, m_head, m_sector); - if (m_status == 0) - read_track(); -#endif - return; - } - - if ((data & ~FDC_MASK_TYPE_III) == FDC_WRITE_TRK) - { - if (VERBOSE) - logerror("%s: wd17xx_command_w $%02X WRITE_TRK\n", machine().describe_context(), data); - - m_command_type = TYPE_III; - m_status &= ~STA_2_LOST_DAT; - wd17xx_clear_drq(); - - if (!m_drive->floppy_drive_get_flag_state(FLOPPY_DRIVE_READY)) - { - wd17xx_complete_command(DELAY_NOTREADY); - } - else - { - /* drive write protected? */ - if (m_drive->floppy_wpt_r() == CLEAR_LINE) - { - /* yes */ - m_status |= STA_2_WRITE_PRO; - /* quit command */ - wd17xx_complete_command(DELAY_ERROR); - } - else - { - m_command = data & ~FDC_MASK_TYPE_III; - m_data_offset = 0; - if (wd17xx_is_sd_only(this)) - m_data_count = TRKSIZE_SD; - else - m_data_count = wd17xx_dden() ? TRKSIZE_SD : TRKSIZE_DD; - - wd17xx_set_drq(); - m_status |= STA_2_BUSY; - m_busy_count = 0; - } - } - return; - } - - if ((data & ~FDC_MASK_TYPE_III) == FDC_READ_DAM) - { - if (VERBOSE) - logerror("%s: wd17xx_command_w $%02X READ_DAM\n", machine().describe_context(), data); - - m_command_type = TYPE_III; - m_command = data & ~FDC_MASK_TYPE_III; - m_status &= ~STA_2_LOST_DAT; - m_status |= STA_2_BUSY; - - wd17xx_clear_drq(); - - if (m_drive->floppy_drive_get_flag_state(FLOPPY_DRIVE_READY)) - wd17xx_read_id(); - else - wd17xx_complete_command(DELAY_NOTREADY); - - return; - } - - if (VERBOSE) - logerror("%s: wd17xx_command_w $%02X unknown\n", machine().describe_context(), data); - - return; - } - - m_status |= STA_1_BUSY; - - /* clear CRC error */ - m_status &=~STA_1_CRC_ERR; - - if ((data & ~FDC_MASK_TYPE_I) == FDC_RESTORE) - { - if (VERBOSE) - logerror("%s: wd17xx_command_w $%02X RESTORE\n", machine().describe_context(), data); - - wd17xx_command_restore(); - } - - if ((data & ~FDC_MASK_TYPE_I) == FDC_SEEK) - { - UINT8 newtrack; - - if (VERBOSE) - logerror("old track: $%02x new track: $%02x\n", m_track, m_data); - m_command_type = TYPE_I; - - /* setup step direction */ - if (m_track < m_data) - { - if (VERBOSE) - logerror("direction: +1\n"); - - m_direction = 1; - } - else if (m_track > m_data) - { - if (VERBOSE) - logerror("direction: -1\n"); - - m_direction = -1; - } - - newtrack = m_data; - if (VERBOSE) - logerror("%s: wd17xx_command_w $%02X SEEK (data_reg is $%02X)\n", machine().describe_context(), data, newtrack); - - /* reset busy count */ - m_busy_count = 0; - - /* keep stepping until reached track programmed */ - while (m_track != newtrack) - { - /* update time to simulate seek time busy signal */ - m_busy_count++; - - /* update track reg */ - m_track += m_direction; - - m_drive->floppy_drive_seek(m_direction); - } - - /* simulate seek time busy signal */ - m_busy_count = 0; //m_busy_count * ((data & FDC_STEP_RATE) + 1); -#if 0 - wd17xx_set_intrq(); -#endif - wd17xx_set_busy(attotime::from_usec(100)); - - } - - if ((data & ~(FDC_STEP_UPDATE | FDC_MASK_TYPE_I)) == FDC_STEP) - { - if (VERBOSE) - logerror("%s: wd17xx_command_w $%02X STEP dir %+d\n", machine().describe_context(), data, m_direction); - - m_command_type = TYPE_I; - /* if it is a real floppy, issue a step command */ - /* simulate seek time busy signal */ - m_busy_count = 0; //((data & FDC_STEP_RATE) + 1); - - m_drive->floppy_drive_seek(m_direction); - - if (data & FDC_STEP_UPDATE) - m_track += m_direction; - -#if 0 - wd17xx_set_intrq(); -#endif - wd17xx_set_busy(attotime::from_usec(100)); - - - } - - if ((data & ~(FDC_STEP_UPDATE | FDC_MASK_TYPE_I)) == FDC_STEP_IN) - { - if (VERBOSE) - logerror("%s: wd17xx_command_w $%02X STEP_IN\n", machine().describe_context(), data); - - m_command_type = TYPE_I; - m_direction = +1; - /* simulate seek time busy signal */ - m_busy_count = 0; //((data & FDC_STEP_RATE) + 1); - - m_drive->floppy_drive_seek(m_direction); - - if (data & FDC_STEP_UPDATE) - m_track += m_direction; -#if 0 - wd17xx_set_intrq(); -#endif - wd17xx_set_busy(attotime::from_usec(100)); - - } - - if ((data & ~(FDC_STEP_UPDATE | FDC_MASK_TYPE_I)) == FDC_STEP_OUT) - { - if (VERBOSE) - logerror("%s: wd17xx_command_w $%02X STEP_OUT\n", machine().describe_context(), data); - - m_command_type = TYPE_I; - m_direction = -1; - /* simulate seek time busy signal */ - m_busy_count = 0; //((data & FDC_STEP_RATE) + 1); - - /* for now only allows a single drive to be selected */ - m_drive->floppy_drive_seek(m_direction); - - if (data & FDC_STEP_UPDATE) - m_track += m_direction; - -#if 0 - wd17xx_set_intrq(); -#endif - wd17xx_set_busy(attotime::from_usec(100)); - } - - if (m_command_type == TYPE_I) - { - /* 0 is enable spin up sequence, 1 is disable spin up sequence */ - if ((data & FDC_STEP_HDLOAD)==0) - { - m_status |= STA_1_HD_LOADED; - m_hld_count = 2; - } - else - m_status &= ~STA_1_HD_LOADED; - - if (data & FDC_STEP_VERIFY) - { - /* verify seek */ - wd17xx_verify_seek(); - } - } -} - -/* write the FDC track register */ -WRITE8_MEMBER( wd1770_device::track_w ) -{ - if (!wd17xx_has_dal(this)) data ^= 0xff; - - m_track = data; - - if (VERBOSE) - logerror("%s: wd17xx_track_w $%02X\n", machine().describe_context(), data); -} - -/* write the FDC sector register */ -WRITE8_MEMBER( wd1770_device::sector_w ) -{ - if (!wd17xx_has_dal(this)) data ^= 0xff; - - m_sector = data; - - if (VERBOSE) - logerror("%s: wd17xx_sector_w $%02X\n", machine().describe_context(), data); -} - -/* write the FDC data register */ -WRITE8_MEMBER( wd1770_device::data_w ) -{ - if (!wd17xx_has_dal(this)) data ^= 0xff; - - if (m_data_count > 0) - { - wd17xx_clear_drq(); - - /* put byte into buffer */ - if (VERBOSE_DATA) - logerror("wd17xx_info buffered data: $%02X at offset %d.\n", data, m_data_offset); - - m_buffer[m_data_offset++] = data; - - if (--m_data_count < 1) - { - if (m_command == FDC_WRITE_TRK) - write_track(); - else - wd17xx_write_sector(); - - m_data_offset = 0; - - /* Check we should handle the next sector for a multi record write */ - if ( m_command_type == TYPE_II && m_command == FDC_WRITE_SEC && ( m_write_cmd & FDC_MULTI_REC ) ) - { - m_sector++; - if (wd17xx_locate_sector()) - { - m_data_count = m_sector_length; - - m_status |= STA_2_BUSY; - m_busy_count = 0; - - wd17xx_timed_data_request(); - } - } - else - { - wd17xx_complete_command(DELAY_DATADONE); - if (VERBOSE) - logerror("wd17xx_data_w(): multi data write completed\n"); - } -// wd17xx_complete_command( DELAY_DATADONE); - } - else - { - if (m_command == FDC_WRITE_TRK) - { - /* Process special data values according to WD17xx specification. - Note that as CRC values take up two bytes which are written on - every 0xf7 byte, this will cause the actual image to - grow larger than what was written from the system. So we need - to take the value of data_offset when writing the track. - */ - if (wd17xx_dden()) - { - switch (data) - { - case 0xf5: - case 0xf6: - /* not allowed in FM. */ - /* Take back the last write. */ - m_data_offset--; - break; - case 0xf7: - /* Take back the last write. */ - m_data_offset--; - /* write two crc bytes */ - m_buffer[m_data_offset++] = (m_crc>>8)&0xff; - m_buffer[m_data_offset++] = (m_crc&0xff); - m_crc_active = FALSE; - break; - case 0xf8: - case 0xf9: - case 0xfa: - case 0xfb: - case 0xfe: - /* Preset crc */ - m_crc = 0xffff; - /* AM is included in the CRC */ - m_crc = ccitt_crc16_one(m_crc, data); - m_crc_active = TRUE; - break; - case 0xfc: - /* Write index mark. No effect here as we do not store clock patterns. - Maybe later. */ - break; - case 0xfd: - /* Just write, don't use for CRC. */ - break; - default: - /* Byte already written. */ - if (m_crc_active) - m_crc = ccitt_crc16_one(m_crc, data); - } - } - else /* MFM */ - { - switch (data) - { - case 0xf5: - /* Take back the last write. */ - m_data_offset--; - /* Write a1 */ - m_buffer[m_data_offset++] = 0xa1; - /* Preset CRC */ - m_crc = 0xffff; - m_crc_active = TRUE; - break; - case 0xf6: - /* Take back the last write. */ - m_data_offset--; - /* Write c2 */ - m_buffer[m_data_offset++] = 0xc2; - break; - case 0xf7: - /* Take back the last write. */ - m_data_offset--; - /* write two crc bytes */ - m_buffer[m_data_offset++] = (m_crc>>8)&0xff; - m_buffer[m_data_offset++] = (m_crc&0xff); - m_crc_active = FALSE; - break; - case 0xf8: - case 0xf9: - case 0xfa: - case 0xfb: - case 0xfc: - case 0xfd: - /* Just write, don't use for CRC. */ - break; - case 0xfe: - /* AM is included in the CRC */ - if (m_crc_active) - m_crc = ccitt_crc16_one(m_crc, data); - break; - default: - /* Byte already written. */ - if (m_crc_active) - m_crc = ccitt_crc16_one(m_crc, data); - } - } - } - /* yes... setup a timed data request */ - wd17xx_timed_data_request(); - } - } - else - { - if (VERBOSE) - logerror("%s: wd17xx_data_w $%02X\n", machine().describe_context(), data); - } - m_data = data; -} - -READ8_MEMBER( wd1770_device::read ) -{ - UINT8 data = 0; - - switch (offset & 0x03) - { - case 0: data = status_r(space, 0); break; - case 1: data = track_r(space, 0); break; - case 2: data = sector_r(space, 0); break; - case 3: data = data_r(space, 0); break; - } - - return data; -} - -WRITE8_MEMBER( wd1770_device::write ) -{ - switch (offset & 0x03) - { - case 0: command_w(space, 0, data); break; - case 1: track_w(space, 0, data); break; - case 2: sector_w(space, 0, data); break; - case 3: data_w(space, 0, data); break; - } -} - - -/*************************************************************************** - MAME DEVICE INTERFACE -***************************************************************************/ - -const device_type FD1771 = &device_creator<fd1771_device>; - -fd1771_device::fd1771_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, FD1771, "FD1771", tag, owner, clock, "fd1771", __FILE__) -{ -} - - -const device_type FD1781 = &device_creator<fd1781_device>; - -fd1781_device::fd1781_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, FD1781, "FD1781", tag, owner, clock, "fd1781", __FILE__) -{ -} - - -const device_type FD1791 = &device_creator<fd1791_device>; - -fd1791_device::fd1791_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, FD1791, "FD1791", tag, owner, clock, "fd1791", __FILE__) -{ -} - - -const device_type FD1792 = &device_creator<fd1792_device>; - -fd1792_device::fd1792_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, FD1792, "FD1792", tag, owner, clock, "fd1792", __FILE__) -{ -} - - -const device_type FD1793 = &device_creator<fd1793_device>; - -fd1793_device::fd1793_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, FD1793, "FD1793", tag, owner, clock, "fd1793", __FILE__) -{ -} - - -const device_type FD1794 = &device_creator<fd1794_device>; - -fd1794_device::fd1794_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, FD1794, "FD1794", tag, owner, clock, "fd1794", __FILE__) -{ -} - - -const device_type FD1795 = &device_creator<fd1795_device>; - -fd1795_device::fd1795_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, FD1795, "FD1795", tag, owner, clock, "fd1795", __FILE__) -{ -} - - -const device_type FD1797 = &device_creator<fd1797_device>; - -fd1797_device::fd1797_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, FD1797, "FD1797", tag, owner, clock, "fd1797", __FILE__) -{ -} - - -const device_type FD1761 = &device_creator<fd1761_device>; - -fd1761_device::fd1761_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, FD1761, "FD1761", tag, owner, clock, "fd1761", __FILE__) -{ -} - - -const device_type FD1762 = &device_creator<fd1762_device>; - -fd1762_device::fd1762_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, FD1762, "FD1762", tag, owner, clock, "fd1762", __FILE__) -{ -} - - -const device_type FD1763 = &device_creator<fd1763_device>; - -fd1763_device::fd1763_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, FD1763, "FD1763", tag, owner, clock, "fd1763", __FILE__) -{ -} - - -const device_type FD1764 = &device_creator<fd1764_device>; - -fd1764_device::fd1764_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, FD1764, "FD1764", tag, owner, clock, "fd1764", __FILE__) -{ -} - - -const device_type FD1765 = &device_creator<fd1765_device>; - -fd1765_device::fd1765_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, FD1765, "FD1765", tag, owner, clock, "fd1765", __FILE__) -{ -} - - -const device_type FD1767 = &device_creator<fd1767_device>; - -fd1767_device::fd1767_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, FD1767, "FD1767", tag, owner, clock, "fd1767", __FILE__) -{ -} - - -const device_type WD2791 = &device_creator<wd2791_device>; - -wd2791_device::wd2791_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, WD2791, "WD2791", tag, owner, clock, "wd2791", __FILE__) -{ -} - - -const device_type WD2793 = &device_creator<wd2793_device>; - -wd2793_device::wd2793_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, WD2793, "WD2793", tag, owner, clock, "wd2793", __FILE__) -{ -} - - -const device_type WD2795 = &device_creator<wd2795_device>; - -wd2795_device::wd2795_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, WD2795, "WD2795", tag, owner, clock, "wd2795", __FILE__) -{ -} - - -const device_type WD2797 = &device_creator<wd2797_device>; - -wd2797_device::wd2797_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, WD2797, "WD2797_LEGACY", tag, owner, clock, "wd2797_l", __FILE__) -{ -} - - -const device_type WD1770 = &device_creator<wd1770_device>; - -wd1770_device::wd1770_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : device_t(mconfig, WD1770, "WD1770_LEGACY", tag, owner, clock, "wd1770_l", __FILE__), - m_out_intrq_func(*this), - m_out_drq_func(*this), - m_in_dden_func(*this) -{ - for (int i = 0; i < 4; i++) - m_floppy_drive_tags[i] = NULL; -} - -wd1770_device::wd1770_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) - : device_t(mconfig, type, name, tag, owner, clock, shortname, source), - m_out_intrq_func(*this), - m_out_drq_func(*this), - m_in_dden_func(*this) -{ - for (int i = 0; i < 4; i++) - m_floppy_drive_tags[i] = NULL; -} - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void wd1770_device::device_start() -{ - m_status = STA_1_TRACK0; - m_pause_time = 1000; - - /* allocate timers */ - m_timer_cmd = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(wd1770_device::wd17xx_command_callback),this)); - m_timer_data = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(wd1770_device::wd17xx_data_callback),this)); - m_timer_rs = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(wd1770_device::wd17xx_read_sector_callback),this)); - m_timer_ws = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(wd1770_device::wd17xx_write_sector_callback),this)); - - /* resolve callbacks */ - m_in_dden_func.resolve(); - m_out_intrq_func.resolve_safe(); - m_out_drq_func.resolve_safe(); - - /* stepping rate depends on the clock */ - m_stepping_rate[0] = 6; - m_stepping_rate[1] = 12; - m_stepping_rate[2] = 20; - m_stepping_rate[3] = 30; - -} - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -static void wd17xx_index_pulse_callback(device_t *controller, device_t *img, int state) -{ - wd1770_device *wd = downcast<wd1770_device *>(controller); - wd->index_pulse_callback(img,state); -} - -void wd1770_device::device_reset() -{ - /* set the default state of some input lines */ - m_mr = ASSERT_LINE; - m_wprt = ASSERT_LINE; - m_dden = ASSERT_LINE; - - for (int i = 0; i < 4; i++) - { - if (m_floppy_drive_tags[i]) - { - legacy_floppy_image_device *img = siblingdevice<legacy_floppy_image_device>(m_floppy_drive_tags[i]); - - if (img) - { - img->floppy_drive_set_controller(this); - img->floppy_drive_set_index_pulse_callback(wd17xx_index_pulse_callback); - img->floppy_drive_set_rpm(300.); - } - } - } - - set_drive(0); - - m_hd = 0; - m_hld_count = 0; - m_sector = 1; - m_last_command_data = 0; - m_interrupt = 0; - m_data_count = 0; - m_idx = 0; - wd17xx_command_restore(); -} - - -const device_type WD1772 = &device_creator<wd1772_device>; - -wd1772_device::wd1772_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, WD1772, "WD1772_LEGACY", tag, owner, clock, "wd1772_l", __FILE__) -{ -} - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void wd1772_device::device_start() -{ - wd1770_device::device_start(); - - /* the 1772 has faster track stepping rates */ - m_stepping_rate[0] = 6; - m_stepping_rate[1] = 12; - m_stepping_rate[2] = 2; - m_stepping_rate[3] = 3; -} - - -const device_type WD1773 = &device_creator<wd1773_device>; - -wd1773_device::wd1773_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, WD1773, "WD1773_LEGACY", tag, owner, clock, "wd1773_l", __FILE__) -{ -} - - -const device_type MB8866 = &device_creator<mb8866_device>; - -mb8866_device::mb8866_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, MB8866, "MB8866", tag, owner, clock, "mb8866", __FILE__) -{ -} - - -const device_type MB8876 = &device_creator<mb8876_device>; - -mb8876_device::mb8876_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, MB8876, "MB8876", tag, owner, clock, "mb8876", __FILE__) -{ -} - - -const device_type MB8877 = &device_creator<mb8877_device>; - -mb8877_device::mb8877_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : wd1770_device(mconfig, MB8877, "MB8877_LEGACY", tag, owner, clock, "mb8877_l", __FILE__) -{ -} diff --git a/src/emu/machine/wd17xx.h b/src/emu/machine/wd17xx.h deleted file mode 100644 index 7fe3e48ea1f..00000000000 --- a/src/emu/machine/wd17xx.h +++ /dev/null @@ -1,401 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Nathan Woods, Kevin Thacker, Phill Harvey-Smith, Robbbert, Curt Coder -/********************************************************************* - - !!! DEPRECATED, USE src/emu/wd_fdc.h FOR NEW DRIVERS !!! - - wd17xx.h - - Implementations of the Western Digital 17xx and 27xx families of - floppy disk controllers - -*********************************************************************/ - -#ifndef __WD17XX_H__ -#define __WD17XX_H__ - -#include "imagedev/flopdrv.h" - - -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ - -#define MCFG_WD17XX_DRIVE_TAGS(_tag1, _tag2, _tag3, _tag4) \ - wd1770_device::set_drive_tags(*device, _tag1, _tag2, _tag3, _tag4); - -#define MCFG_WD17XX_DEFAULT_DRIVE4_TAGS \ - MCFG_WD17XX_DRIVE_TAGS(FLOPPY_0, FLOPPY_1, FLOPPY_2, FLOPPY_3) - -#define MCFG_WD17XX_DEFAULT_DRIVE2_TAGS \ - MCFG_WD17XX_DRIVE_TAGS(FLOPPY_0, FLOPPY_1, NULL, NULL) - -#define MCFG_WD17XX_DEFAULT_DRIVE1_TAGS \ - MCFG_WD17XX_DRIVE_TAGS(FLOPPY_0, NULL, NULL, NULL) - -#define MCFG_WD17XX_INTRQ_CALLBACK(_write) \ - devcb = &wd1770_device::set_intrq_wr_callback(*device, DEVCB_##_write); - -#define MCFG_WD17XX_DRQ_CALLBACK(_write) \ - devcb = &wd1770_device::set_drq_wr_callback(*device, DEVCB_##_write); - -#define MCFG_WD17XX_DDEN_CALLBACK(_write) \ - devcb = &wd1770_device::set_dden_rd_callback(*device, DEVCB_##_write); - - -/*************************************************************************** - MACROS -***************************************************************************/ - -class wd1770_device : public device_t -{ -public: - wd1770_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - wd1770_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); - - template<class _Object> static devcb_base &set_intrq_wr_callback(device_t &device, _Object object) { return downcast<wd1770_device &>(device).m_out_intrq_func.set_callback(object); } - template<class _Object> static devcb_base &set_drq_wr_callback(device_t &device, _Object object) { return downcast<wd1770_device &>(device).m_out_drq_func.set_callback(object); } - template<class _Object> static devcb_base &set_dden_rd_callback(device_t &device, _Object object) { return downcast<wd1770_device &>(device).m_in_dden_func.set_callback(object); } - - static void set_drive_tags(device_t &device, const char *tag1, const char *tag2, const char *tag3, const char *tag4) - { - wd1770_device &dev = downcast<wd1770_device &>(device); - dev.m_floppy_drive_tags[0] = tag1; - dev.m_floppy_drive_tags[1] = tag2; - dev.m_floppy_drive_tags[2] = tag3; - dev.m_floppy_drive_tags[3] = tag4; - } - - /* the following are not strictly part of the wd179x hardware/emulation - but will be put here for now until the flopdrv code has been finalised more */ - void set_drive(UINT8); /* set drive wd179x is accessing */ - void set_side(UINT8); /* set side wd179x is accessing */ - - void set_pause_time(int usec); /* default is 40 usec if not set */ - void index_pulse_callback(device_t *img, int state); - - DECLARE_READ8_MEMBER( status_r ); - DECLARE_READ8_MEMBER( track_r ); - DECLARE_READ8_MEMBER( sector_r ); - DECLARE_READ8_MEMBER( data_r ); - - DECLARE_WRITE8_MEMBER( command_w ); - DECLARE_WRITE8_MEMBER( track_w ); - DECLARE_WRITE8_MEMBER( sector_w ); - DECLARE_WRITE8_MEMBER( data_w ); - - DECLARE_READ8_MEMBER( read ); - DECLARE_WRITE8_MEMBER( write ); - - WRITE_LINE_MEMBER( mr_w ); - WRITE_LINE_MEMBER( rdy_w ); - READ_LINE_MEMBER( mo_r ); - WRITE_LINE_MEMBER( tr00_w ); - WRITE_LINE_MEMBER( idx_w ); - WRITE_LINE_MEMBER( wprt_w ); - WRITE_LINE_MEMBER( dden_w ); - READ_LINE_MEMBER( drq_r ); - READ_LINE_MEMBER( intrq_r ); -protected: - // device-level overrides - virtual void device_start(); - virtual void device_reset(); - -protected: - int wd17xx_dden(); - void wd17xx_clear_drq(); - void wd17xx_set_drq(); - void wd17xx_clear_intrq(); - void wd17xx_set_intrq(); - TIMER_CALLBACK_MEMBER( wd17xx_command_callback ); - TIMER_CALLBACK_MEMBER( wd17xx_data_callback ); - void wd17xx_set_busy(const attotime &duration); - void wd17xx_command_restore(); - void write_track(); - void read_track(); - void wd17xx_read_id(); - int wd17xx_locate_sector(); - int wd17xx_find_sector(); - void wd17xx_side_compare(UINT8 command); - void wd17xx_read_sector(); - void wd17xx_complete_command(int delay); - void wd17xx_write_sector(); - void wd17xx_verify_seek(); - TIMER_CALLBACK_MEMBER( wd17xx_read_sector_callback ); - TIMER_CALLBACK_MEMBER( wd17xx_write_sector_callback ); - void wd17xx_timed_data_request(); - void wd17xx_timed_read_sector_request(); - void wd17xx_timed_write_sector_request(); - - // internal state - /* callbacks */ - devcb_write_line m_out_intrq_func; - devcb_write_line m_out_drq_func; - devcb_read_line m_in_dden_func; - - const char *m_floppy_drive_tags[4]; - - /* input lines */ - int m_mr; /* master reset */ - int m_rdy; /* ready, enable precomp */ - int m_tr00; /* track 00 */ - int m_idx; /* index */ - int m_wprt; /* write protect */ - int m_dden; /* double density */ - - /* output lines */ - int m_mo; /* motor on */ - int m_dirc; /* direction */ - int m_drq; /* data request */ - int m_intrq; /* interrupt request */ - - /* register */ - UINT8 m_data_shift; - UINT8 m_data; - UINT8 m_track; - UINT8 m_sector; - UINT8 m_command; - UINT8 m_status; - UINT8 m_interrupt; - - int m_stepping_rate[4]; /* track stepping rate in ms */ - - unsigned short m_crc; /* Holds the current CRC value for write_track CRC calculation */ - int m_crc_active; /* Flag indicating that CRC calculation in write_track is active. */ - - UINT8 m_track_reg; /* value of track register */ - UINT8 m_command_type; /* last command type */ - UINT8 m_head; /* current head # */ - - UINT8 m_read_cmd; /* last read command issued */ - UINT8 m_write_cmd; /* last write command issued */ - INT8 m_direction; /* last step direction */ - UINT8 m_last_command_data; /* last command data */ - - UINT8 m_status_drq; /* status register data request bit */ - UINT8 m_busy_count; /* how long to keep busy bit set */ - - UINT8 m_buffer[6144]; /* I/O buffer (holds up to a whole track) */ - UINT32 m_data_offset; /* offset into I/O buffer */ - INT32 m_data_count; /* transfer count from/into I/O buffer */ - - UINT8 *m_fmt_sector_data[256]; /* pointer to data after formatting a track */ - - UINT8 m_dam_list[256][4]; /* list of data address marks while formatting */ - int m_dam_data[256]; /* offset to data inside buffer while formatting */ - int m_dam_cnt; /* valid number of entries in the dam_list */ - UINT16 m_sector_length; /* sector length (byte) */ - - UINT8 m_ddam; /* ddam of sector found - used when reading */ - UINT8 m_sector_data_id; - int m_data_direction; - - int m_hld_count; /* head loaded counter */ - - /* timers to delay execution/completion of commands */ - emu_timer *m_timer_cmd, *m_timer_data, *m_timer_rs, *m_timer_ws; - - /* this is the drive currently selected */ - legacy_floppy_image_device *m_drive; - - /* this is the head currently selected */ - UINT8 m_hd; - - /* pause time when writing/reading sector */ - int m_pause_time; - - /* Were we busy when we received a FORCE_INT command */ - UINT8 m_was_busy; -}; - -extern ATTR_DEPRECATED const device_type WD1770; - -class fd1771_device : public wd1770_device -{ -public: - fd1771_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type FD1771; - -class fd1781_device : public wd1770_device -{ -public: - fd1781_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type FD1781; - -class fd1791_device : public wd1770_device -{ -public: - fd1791_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type FD1791; - -class fd1792_device : public wd1770_device -{ -public: - fd1792_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type FD1792; - -class fd1793_device : public wd1770_device -{ -public: - fd1793_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type FD1793; - -class fd1794_device : public wd1770_device -{ -public: - fd1794_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type FD1794; - -class fd1795_device : public wd1770_device -{ -public: - fd1795_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type FD1795; - -class fd1797_device : public wd1770_device -{ -public: - fd1797_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type FD1797; - -class fd1761_device : public wd1770_device -{ -public: - fd1761_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type FD1761; - -class fd1762_device : public wd1770_device -{ -public: - fd1762_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type FD1762; - -class fd1763_device : public wd1770_device -{ -public: - fd1763_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type FD1763; - -class fd1764_device : public wd1770_device -{ -public: - fd1764_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type FD1764; - -class fd1765_device : public wd1770_device -{ -public: - fd1765_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type FD1765; - -class fd1767_device : public wd1770_device -{ -public: - fd1767_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type FD1767; - -class wd2791_device : public wd1770_device -{ -public: - wd2791_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type WD2791; - -class wd2793_device : public wd1770_device -{ -public: - wd2793_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type WD2793; - -class wd2795_device : public wd1770_device -{ -public: - wd2795_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type WD2795; - -class wd2797_device : public wd1770_device -{ -public: - wd2797_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type WD2797; - -class wd1772_device : public wd1770_device -{ -public: - wd1772_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -protected: - // device-level overrides - virtual void device_start(); -}; - -extern ATTR_DEPRECATED const device_type WD1772; - -class wd1773_device : public wd1770_device -{ -public: - wd1773_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type WD1773; - -class mb8866_device : public wd1770_device -{ -public: - mb8866_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type MB8866; - -class mb8876_device : public wd1770_device -{ -public: - mb8876_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type MB8876; - -class mb8877_device : public wd1770_device -{ -public: - mb8877_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); -}; - -extern ATTR_DEPRECATED const device_type MB8877; - - -#endif /* __WD17XX_H__ */ diff --git a/src/emu/machine/wd_fdc.c b/src/emu/machine/wd_fdc.c index 204c4c4281c..9052c033bef 100644 --- a/src/emu/machine/wd_fdc.c +++ b/src/emu/machine/wd_fdc.c @@ -9,6 +9,7 @@ const device_type FD1781x = &device_creator<fd1781_t>; const device_type FD1791x = &device_creator<fd1791_t>; const device_type FD1792x = &device_creator<fd1792_t>; const device_type FD1793x = &device_creator<fd1793_t>; +const device_type KR1818VG93x = &device_creator<kr1818vg93_t>; const device_type FD1794x = &device_creator<fd1794_t>; const device_type FD1795x = &device_creator<fd1795_t>; const device_type FD1797x = &device_creator<fd1797_t>; @@ -69,7 +70,8 @@ wd_fdc_t::wd_fdc_t(const machine_config &mconfig, device_type type, const char * intrq_cb(*this), drq_cb(*this), hld_cb(*this), - enp_cb(*this) + enp_cb(*this), + enmf_cb(*this) { force_ready = false; } @@ -85,12 +87,17 @@ void wd_fdc_t::device_start() drq_cb.resolve(); hld_cb.resolve(); enp_cb.resolve(); + enmf_cb.resolve(); + + if (!has_enmf && !enmf_cb.isnull()) + logerror("%s: Warning, this chip doesn't have an ENMF line.\n", tag()); t_gen = timer_alloc(TM_GEN); t_cmd = timer_alloc(TM_CMD); t_track = timer_alloc(TM_TRACK); t_sector = timer_alloc(TM_SECTOR); dden = disable_mfm; + enmf = false; floppy = 0; status = 0x00; @@ -128,6 +135,11 @@ void wd_fdc_t::soft_reset() counter = 0; status_type_1 = true; last_dir = 1; + + // gnd == enmf enabled, otherwise disabled (default) + if (!enmf_cb.isnull() && has_enmf) + enmf = enmf_cb() ? false : true; + intrq = false; if (!intrq_cb.isnull()) { @@ -233,7 +245,7 @@ void wd_fdc_t::seek_start(int state) { if (TRACE_COMMAND) logerror("%s: seek %d (track=%d)\n", tag(), data, track); main_state = state; - status = (status & ~(S_CRC|S_RNF|S_SPIN)) | S_BUSY; + status &= ~(S_CRC|S_RNF|S_SPIN); if(head_control) { // TODO get value from HLT callback if(command & 8) @@ -420,7 +432,7 @@ void wd_fdc_t::read_sector_start() } main_state = READ_SECTOR; - status = (status & ~(S_CRC|S_LOST|S_RNF|S_WP|S_DDM)) | S_BUSY; + status &= ~(S_CRC|S_LOST|S_RNF|S_WP|S_DDM); drop_drq(); if(side_control && floppy) floppy->ss_w((command & 0x02) ? 1 : 0); @@ -521,7 +533,7 @@ void wd_fdc_t::read_track_start() } main_state = READ_TRACK; - status = (status & ~(S_LOST|S_RNF)) | S_BUSY; + status &= ~(S_LOST|S_RNF); drop_drq(); if(side_control && floppy) floppy->ss_w((command & 0x02) ? 1 : 0); @@ -599,7 +611,7 @@ void wd_fdc_t::read_id_start() } main_state = READ_ID; - status = (status & ~(S_WP|S_DDM|S_LOST|S_RNF)) | S_BUSY; + status &= ~(S_WP|S_DDM|S_LOST|S_RNF); drop_drq(); if(side_control && floppy) floppy->ss_w((command & 0x02) ? 1 : 0); @@ -675,7 +687,7 @@ void wd_fdc_t::write_track_start() } main_state = WRITE_TRACK; - status = (status & ~(S_WP|S_DDM|S_LOST|S_RNF)) | S_BUSY; + status &= ~(S_WP|S_DDM|S_LOST|S_RNF); drop_drq(); if(side_control && floppy) floppy->ss_w((command & 0x02) ? 1 : 0); @@ -736,6 +748,7 @@ void wd_fdc_t::write_track_continue() if (TRACE_STATE) logerror("%s: DATA_LOAD_WAIT_DONE\n", tag()); if(drq) { status |= S_LOST; + drop_drq(); command_end(); return; } @@ -785,7 +798,7 @@ void wd_fdc_t::write_sector_start() } main_state = WRITE_SECTOR; - status = (status & ~(S_CRC|S_LOST|S_RNF|S_WP|S_DDM)) | S_BUSY; + status &= ~(S_CRC|S_LOST|S_RNF|S_WP|S_DDM); drop_drq(); if(side_control && floppy) floppy->ss_w((command & 0x02) ? 1 : 0); @@ -884,14 +897,27 @@ void wd_fdc_t::interrupt_start() drop_drq(); motor_timeout = 0; } + else + { + // when a force interrupt command is issued and there is no + // currently running command, return the status type 1 bits + status_type_1 = true; + } - if(!(command & 0x0f)) { - intrq_cond = 0; + int intcond = command & 0x0f; + if (!nonsticky_immint) { + if(intcond == 0) + intrq_cond = 0; + else + intrq_cond = (intrq_cond & I_IMM) | intcond; } else { - intrq_cond = (intrq_cond & I_IMM) | (command & 0x0f); + if (intcond < 8) + intrq_cond = intcond; + else + intrq_cond = 0; } - if(intrq_cond & I_IMM) { + if(command & I_IMM) { intrq = true; if(!intrq_cb.isnull()) intrq_cb(intrq); @@ -1041,7 +1067,17 @@ void wd_fdc_t::cmd_w(UINT8 val) cmd_buffer = val; - delay_cycles(t_cmd, dden ? delay_command_commit*2 : delay_command_commit); + if ((val & 0xf0) == 0xd0) + { + // force interrupt is executed instantly (?) + delay_cycles(t_cmd, 0); + } + else + { + // set busy, then set a timer to process the command + status |= S_BUSY; + delay_cycles(t_cmd, dden ? delay_command_commit*2 : delay_command_commit); + } } UINT8 wd_fdc_t::status_r() @@ -1130,7 +1166,11 @@ void wd_fdc_t::sector_w(UINT8 val) // return; sector_buffer = val; - delay_cycles(t_sector, dden ? delay_register_commit*2 : delay_register_commit); + + // set a timer to write the new value to the register, but only if we aren't in + // the middle of an already occurring update + if (!t_sector->enabled()) + delay_cycles(t_sector, dden ? delay_register_commit*2 : delay_register_commit); } UINT8 wd_fdc_t::sector_r() @@ -1201,6 +1241,10 @@ void wd_fdc_t::spinup() void wd_fdc_t::ready_callback(floppy_image_device *floppy, int state) { + // why is this even possible? + if (!floppy) + return; + live_sync(); if(!ready_hooked) return; @@ -1229,13 +1273,24 @@ void wd_fdc_t::index_callback(floppy_image_device *floppy, int state) switch(sub_state) { case IDLE: - if(motor_control) { + if(motor_control || head_control) { motor_timeout ++; - if(motor_timeout >= 5) { + if(motor_control && motor_timeout >= 5) { status &= ~S_MON; if(floppy) floppy->mon_w(1); } + + if (head_control && motor_timeout >= 3) + { + hld = false; + + // signal drive to unload head + if (!hld_cb.isnull()) + hld_cb(hld); + + status &= ~S_HLD; // todo: should get this value from the drive + } } break; @@ -1330,7 +1385,11 @@ void wd_fdc_t::live_start(int state) cur_live.previous_type = live_info::PT_NONE; cur_live.data_bit_context = false; cur_live.byte_counter = 0; - pll_reset(dden, cur_live.tm); + + if (!enmf_cb.isnull() && has_enmf) + enmf = enmf_cb() ? false : true; + + pll_reset(dden, enmf, cur_live.tm); checkpoint_live = cur_live; pll_save_checkpoint(); @@ -1645,6 +1704,10 @@ void wd_fdc_t::live_run(attotime limit) cur_live.shift_reg == 0xf56b ? 0x9fc6 : cur_live.shift_reg == 0xf56e ? 0xafa5 : 0xbf84; + + if((cur_live.data_reg & 0xfe) == 0xf8) + status |= S_DDM; + cur_live.data_separator_phase = false; cur_live.bit_counter = 0; cur_live.state = READ_SECTOR_DATA; @@ -2068,10 +2131,15 @@ wd_fdc_analog_t::wd_fdc_analog_t(const machine_config &mconfig, device_type type clock_ratio = 1; } -void wd_fdc_analog_t::pll_reset(bool fm, const attotime &when) +void wd_fdc_analog_t::pll_reset(bool fm, bool enmf, const attotime &when) { + int clocks = 2; + + if (fm) clocks *= 2; + if (enmf) clocks *= 2; + cur_pll.reset(when); - cur_pll.set_clock(clocks_to_attotime(fm ? 4 : 2)); + cur_pll.set_clock(clocks_to_attotime(clocks)); } void wd_fdc_analog_t::pll_start_writing(const attotime &tm) @@ -2117,10 +2185,15 @@ wd_fdc_digital_t::wd_fdc_digital_t(const machine_config &mconfig, device_type ty const int wd_fdc_digital_t::wd_digital_step_times[4] = { 12000, 24000, 40000, 60000 }; -void wd_fdc_digital_t::pll_reset(bool fm, const attotime &when) +void wd_fdc_digital_t::pll_reset(bool fm, bool enmf, const attotime &when) { + int clocks = 1; + + if (fm) clocks *= 2; + if (enmf) clocks *= 2; + cur_pll.reset(when); - cur_pll.set_clock(clocks_to_attotime(fm ? 2 : 1)); // HACK + cur_pll.set_clock(clocks_to_attotime(clocks)); } void wd_fdc_digital_t::pll_start_writing(const attotime &tm) @@ -2327,6 +2400,7 @@ fd1771_t::fd1771_t(const machine_config &mconfig, const char *tag, device_t *own head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } int fd1771_t::calc_sector_size(UINT8 size, UINT8 command) const @@ -2351,6 +2425,7 @@ fd1781_t::fd1781_t(const machine_config &mconfig, const char *tag, device_t *own head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } int fd1781_t::calc_sector_size(UINT8 size, UINT8 command) const @@ -2370,12 +2445,14 @@ fd1791_t::fd1791_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 4; delay_command_commit = 12; disable_mfm = false; + has_enmf = false; inverted_bus = true; side_control = false; side_compare = true; head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } fd1792_t::fd1792_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd_fdc_analog_t(mconfig, FD1792x, "FD1792", tag, owner, clock, "fd1792", __FILE__) @@ -2384,12 +2461,14 @@ fd1792_t::fd1792_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 4; delay_command_commit = 12; disable_mfm = true; + has_enmf = false; inverted_bus = true; side_control = false; side_compare = true; head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } fd1793_t::fd1793_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd_fdc_analog_t(mconfig, FD1793x, "FD1793", tag, owner, clock, "fd1793", __FILE__) @@ -2398,12 +2477,30 @@ fd1793_t::fd1793_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 4; delay_command_commit = 12; disable_mfm = false; + has_enmf = false; + inverted_bus = false; + side_control = false; + side_compare = true; + head_control = true; + motor_control = false; + ready_hooked = true; + nonsticky_immint = false; +} + +kr1818vg93_t::kr1818vg93_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd_fdc_analog_t(mconfig, KR1818VG93x, "KR1818VG93", tag, owner, clock, "kr1818vg93", __FILE__) +{ + step_times = fd179x_step_times; + delay_register_commit = 4; + delay_command_commit = 12; + disable_mfm = false; + has_enmf = false; inverted_bus = false; side_control = false; side_compare = true; head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = true; } fd1794_t::fd1794_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd_fdc_analog_t(mconfig, FD1794x, "FD1794", tag, owner, clock, "fd1794", __FILE__) @@ -2412,12 +2509,14 @@ fd1794_t::fd1794_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 4; delay_command_commit = 12; disable_mfm = true; + has_enmf = false; inverted_bus = false; side_control = false; side_compare = true; head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } fd1795_t::fd1795_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd_fdc_analog_t(mconfig, FD1795x, "FD1795", tag, owner, clock, "fd1795", __FILE__) @@ -2426,12 +2525,14 @@ fd1795_t::fd1795_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 4; delay_command_commit = 12; disable_mfm = false; + has_enmf = false; inverted_bus = true; side_control = true; side_compare = false; head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } int fd1795_t::calc_sector_size(UINT8 size, UINT8 command) const @@ -2448,12 +2549,14 @@ fd1797_t::fd1797_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 4; delay_command_commit = 12; disable_mfm = false; + has_enmf = false; inverted_bus = false; side_control = true; side_compare = false; head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } int fd1797_t::calc_sector_size(UINT8 size, UINT8 command) const @@ -2470,12 +2573,14 @@ mb8866_t::mb8866_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 4; delay_command_commit = 12; disable_mfm = false; + has_enmf = false; inverted_bus = true; side_control = false; side_compare = true; head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } mb8876_t::mb8876_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd_fdc_analog_t(mconfig, MB8876x, "MB8876", tag, owner, clock, "mb8876", __FILE__) @@ -2484,12 +2589,14 @@ mb8876_t::mb8876_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 4; delay_command_commit = 12; disable_mfm = false; + has_enmf = false; inverted_bus = true; side_control = false; side_compare = true; head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } mb8877_t::mb8877_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd_fdc_analog_t(mconfig, MB8877x, "MB8877", tag, owner, clock, "mb8877", __FILE__) @@ -2498,12 +2605,14 @@ mb8877_t::mb8877_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 4; delay_command_commit = 12; disable_mfm = false; + has_enmf = false; inverted_bus = false; side_control = false; side_compare = true; head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } fd1761_t::fd1761_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd_fdc_analog_t(mconfig, FD1761x, "FD1761", tag, owner, clock, "fd1761", __FILE__) @@ -2512,12 +2621,14 @@ fd1761_t::fd1761_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 16; delay_command_commit = 12; disable_mfm = false; + has_enmf = false; inverted_bus = true; side_control = false; side_compare = true; head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } fd1763_t::fd1763_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd_fdc_analog_t(mconfig, FD1763x, "FD1763", tag, owner, clock, "fd1763", __FILE__) @@ -2526,12 +2637,14 @@ fd1763_t::fd1763_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 16; delay_command_commit = 12; disable_mfm = false; + has_enmf = false; inverted_bus = false; side_control = false; side_compare = true; head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } fd1765_t::fd1765_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd_fdc_analog_t(mconfig, FD1765x, "FD1765", tag, owner, clock, "fd1765", __FILE__) @@ -2540,12 +2653,14 @@ fd1765_t::fd1765_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 16; delay_command_commit = 12; disable_mfm = false; + has_enmf = false; inverted_bus = true; side_control = true; side_compare = false; head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } int fd1765_t::calc_sector_size(UINT8 size, UINT8 command) const @@ -2562,12 +2677,14 @@ fd1767_t::fd1767_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 16; delay_command_commit = 12; disable_mfm = false; + has_enmf = false; inverted_bus = false; side_control = true; side_compare = false; head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } int fd1767_t::calc_sector_size(UINT8 size, UINT8 command) const @@ -2584,12 +2701,14 @@ wd2791_t::wd2791_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 16; delay_command_commit = 12; disable_mfm = false; + has_enmf = true; inverted_bus = true; side_control = false; side_compare = true; head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } wd2793_t::wd2793_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd_fdc_analog_t(mconfig, WD2793x, "WD2793", tag, owner, clock, "wd2793", __FILE__) @@ -2598,12 +2717,14 @@ wd2793_t::wd2793_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 16; delay_command_commit = 12; disable_mfm = false; + has_enmf = true; inverted_bus = false; side_control = false; side_compare = true; head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } wd2795_t::wd2795_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd_fdc_analog_t(mconfig, WD2795x, "WD2795", tag, owner, clock, "wd2795", __FILE__) @@ -2612,12 +2733,14 @@ wd2795_t::wd2795_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 16; delay_command_commit = 12; disable_mfm = false; + has_enmf = false; inverted_bus = true; side_control = true; side_compare = false; head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } int wd2795_t::calc_sector_size(UINT8 size, UINT8 command) const @@ -2634,12 +2757,14 @@ wd2797_t::wd2797_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 16; delay_command_commit = 12; disable_mfm = false; + has_enmf = false; inverted_bus = false; side_control = true; side_compare = false; head_control = true; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } int wd2797_t::calc_sector_size(UINT8 size, UINT8 command) const @@ -2656,12 +2781,14 @@ wd1770_t::wd1770_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 32; delay_command_commit = 36; // official 48 is too high for oric jasmin boot disable_mfm = false; + has_enmf = false; inverted_bus = false; side_control = false; side_compare = false; head_control = false; motor_control = true; ready_hooked = false; + nonsticky_immint = false; } wd1772_t::wd1772_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : wd_fdc_digital_t(mconfig, WD1772x, "WD1772", tag, owner, clock, "wd1772", __FILE__) @@ -2672,12 +2799,14 @@ wd1772_t::wd1772_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 32; delay_command_commit = 48; disable_mfm = false; + has_enmf = false; inverted_bus = false; side_control = false; side_compare = false; head_control = false; motor_control = true; ready_hooked = false; + nonsticky_immint = false; } int wd1772_t::settle_time() const @@ -2691,10 +2820,12 @@ wd1773_t::wd1773_t(const machine_config &mconfig, const char *tag, device_t *own delay_register_commit = 32; delay_command_commit = 48; disable_mfm = false; + has_enmf = false; inverted_bus = false; side_control = false; side_compare = true; head_control = false; motor_control = false; ready_hooked = true; + nonsticky_immint = false; } diff --git a/src/emu/machine/wd_fdc.h b/src/emu/machine/wd_fdc.h index c8527bc4096..8077ec2ec21 100644 --- a/src/emu/machine/wd_fdc.h +++ b/src/emu/machine/wd_fdc.h @@ -59,6 +59,9 @@ #define MCFG_FD1793x_ADD(_tag, _clock) \ MCFG_DEVICE_ADD(_tag, FD1793x, _clock) +#define MCFG_KR1818VG93x_ADD(_tag, _clock) \ + MCFG_DEVICE_ADD(_tag, KR1818VG93x, _clock) + #define MCFG_FD1794x_ADD(_tag, _clock) \ MCFG_DEVICE_ADD(_tag, FD1794x, _clock) @@ -125,6 +128,9 @@ #define MCFG_WD_FDC_ENP_CALLBACK(_write) \ devcb = &wd_fdc_t::set_enp_wr_callback(*device, DEVCB_##_write); +#define MCFG_WD_FDC_ENMF_CALLBACK(_read) \ + devcb = &wd_fdc_t::set_enmf_rd_callback(*device, DEVCB_##_read); + class wd_fdc_t : public device_t { public: wd_fdc_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); @@ -133,6 +139,7 @@ public: template<class _Object> static devcb_base &set_drq_wr_callback(device_t &device, _Object object) { return downcast<wd_fdc_t &>(device).drq_cb.set_callback(object); } template<class _Object> static devcb_base &set_hld_wr_callback(device_t &device, _Object object) { return downcast<wd_fdc_t &>(device).hld_cb.set_callback(object); } template<class _Object> static devcb_base &set_enp_wr_callback(device_t &device, _Object object) { return downcast<wd_fdc_t &>(device).enp_cb.set_callback(object); } + template<class _Object> static devcb_base &set_enmf_rd_callback(device_t &device, _Object object) { return downcast<wd_fdc_t &>(device).enmf_cb.set_callback(object); } void soft_reset(); @@ -176,12 +183,15 @@ public: protected: // Chip-specific configuration flags bool disable_mfm; + bool enmf; + bool has_enmf; bool inverted_bus; bool side_control; bool side_compare; bool head_control; bool motor_control; bool ready_hooked; + bool nonsticky_immint; int clock_ratio; const int *step_times; int delay_register_commit; @@ -197,7 +207,7 @@ protected: virtual int calc_sector_size(UINT8 size, UINT8 command) const; virtual int settle_time() const; - virtual void pll_reset(bool fm, const attotime &when) = 0; + virtual void pll_reset(bool fm, bool enmf, const attotime &when) = 0; virtual void pll_start_writing(const attotime &tm) = 0; virtual void pll_commit(floppy_image_device *floppy, const attotime &tm) = 0; virtual void pll_stop_writing(floppy_image_device *floppy, const attotime &tm) = 0; @@ -367,6 +377,7 @@ private: live_info cur_live, checkpoint_live; devcb_write_line intrq_cb, drq_cb, hld_cb, enp_cb; + devcb_read_line enmf_cb; UINT8 format_last_byte; int format_last_byte_count; @@ -437,7 +448,7 @@ public: wd_fdc_analog_t(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); protected: - virtual void pll_reset(bool fm, const attotime &when); + virtual void pll_reset(bool fm, bool enmf, const attotime &when); virtual void pll_start_writing(const attotime &tm); virtual void pll_commit(floppy_image_device *floppy, const attotime &tm); virtual void pll_stop_writing(floppy_image_device *floppy, const attotime &tm); @@ -457,7 +468,7 @@ public: protected: static const int wd_digital_step_times[4]; - virtual void pll_reset(bool fm, const attotime &when); + virtual void pll_reset(bool fm, bool enmf, const attotime &when); virtual void pll_start_writing(const attotime &tm); virtual void pll_commit(floppy_image_device *floppy, const attotime &tm); virtual void pll_stop_writing(floppy_image_device *floppy, const attotime &tm); @@ -525,6 +536,11 @@ public: fd1793_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); }; +class kr1818vg93_t : public wd_fdc_analog_t { +public: + kr1818vg93_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); +}; + class fd1794_t : public wd_fdc_analog_t { public: fd1794_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); @@ -590,11 +606,13 @@ protected: class wd2791_t : public wd_fdc_analog_t { public: wd2791_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + DECLARE_WRITE_LINE_MEMBER(enmf_w) { enmf = state ? false : true; } }; class wd2793_t : public wd_fdc_analog_t { public: wd2793_t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + DECLARE_WRITE_LINE_MEMBER(enmf_w) { enmf = state ? false : true; } }; class wd2795_t : public wd_fdc_analog_t { @@ -638,6 +656,7 @@ extern const device_type FD1781x; extern const device_type FD1791x; extern const device_type FD1792x; extern const device_type FD1793x; +extern const device_type KR1818VG93x; extern const device_type FD1795x; extern const device_type FD1797x; diff --git a/src/emu/machine/z80dart.h b/src/emu/machine/z80dart.h index 27df3dabb82..2674f84758a 100644 --- a/src/emu/machine/z80dart.h +++ b/src/emu/machine/z80dart.h @@ -500,6 +500,16 @@ public: DECLARE_READ8_MEMBER( ba_cd_r ); DECLARE_WRITE8_MEMBER( ba_cd_w ); + DECLARE_READ8_MEMBER( da_r ) { return m_chanA->data_read(); } + DECLARE_WRITE8_MEMBER( da_w ) { m_chanA->data_write(data); } + DECLARE_READ8_MEMBER( db_r ) { return m_chanB->data_read(); } + DECLARE_WRITE8_MEMBER( db_w ) { m_chanB->data_write(data); } + + DECLARE_READ8_MEMBER( ca_r ) { return m_chanA->control_read(); } + DECLARE_WRITE8_MEMBER( ca_w ) { m_chanA->control_write(data); } + DECLARE_READ8_MEMBER( cb_r ) { return m_chanB->control_read(); } + DECLARE_WRITE8_MEMBER( cb_w ) { m_chanB->control_write(data); } + // interrupt acknowledge int m1_r(); diff --git a/src/emu/netlist/analog/nld_bjt.c b/src/emu/netlist/analog/nld_bjt.c index fe9644ef052..04de16923e2 100644 --- a/src/emu/netlist/analog/nld_bjt.c +++ b/src/emu/netlist/analog/nld_bjt.c @@ -42,6 +42,15 @@ private: // nld_Q // ---------------------------------------------------------------------------------------- +NETLIB_NAME(Q)::NETLIB_NAME(Q)(const family_t afamily) +: netlist_device_t(afamily) +, m_qtype(BJT_NPN) { } + +NETLIB_NAME(Q)::~NETLIB_NAME(Q)() +{ +} + + NETLIB_START(Q) { register_param("model", m_model, ""); diff --git a/src/emu/netlist/analog/nld_bjt.h b/src/emu/netlist/analog/nld_bjt.h index eca05c423c7..b9bace5c032 100644 --- a/src/emu/netlist/analog/nld_bjt.h +++ b/src/emu/netlist/analog/nld_bjt.h @@ -38,16 +38,15 @@ public: BJT_PNP }; - ATTR_COLD NETLIB_NAME(Q)(const family_t afamily) - : netlist_device_t(afamily) - , m_qtype(BJT_NPN) { } + NETLIB_NAME(Q)(const family_t afamily); + virtual ~NETLIB_NAME(Q)(); inline q_type qtype() const { return m_qtype; } inline bool is_qtype(q_type atype) const { return m_qtype == atype; } inline void set_qtype(q_type atype) { m_qtype = atype; } protected: - /* ATTR_COLD */ virtual void start(); - /* ATTR_COLD */ virtual void reset(); + virtual void start(); + virtual void reset(); ATTR_HOT void update(); netlist_param_model_t m_model; @@ -59,9 +58,11 @@ class NETLIB_NAME(QBJT) : public NETLIB_NAME(Q) { public: - ATTR_COLD NETLIB_NAME(QBJT)(const family_t afamily) + NETLIB_NAME(QBJT)(const family_t afamily) : NETLIB_NAME(Q)(afamily) { } + virtual ~NETLIB_NAME(QBJT)() { } + protected: private: @@ -110,9 +111,9 @@ public: protected: - /* ATTR_COLD */ virtual void start(); + virtual void start(); ATTR_HOT virtual void update_param(); - /* ATTR_COLD */ virtual void reset(); + virtual void reset(); NETLIB_UPDATE_TERMINALSI(); nl_double m_gB; // base conductance / switch on @@ -142,8 +143,8 @@ public: protected: - /* ATTR_COLD */ virtual void start(); - /* ATTR_COLD */ virtual void reset(); + virtual void start(); + virtual void reset(); ATTR_HOT void update_param(); ATTR_HOT void virtual update(); NETLIB_UPDATE_TERMINALSI(); diff --git a/src/emu/netlist/analog/nld_fourterm.c b/src/emu/netlist/analog/nld_fourterm.c index e2457d8ee11..ad67ccbba4b 100644 --- a/src/emu/netlist/analog/nld_fourterm.c +++ b/src/emu/netlist/analog/nld_fourterm.c @@ -50,6 +50,7 @@ NETLIB_RESET(VCCS) const nl_double m_mult = m_G.Value() * m_gfac; // 1.0 ==> 1V ==> 1A const nl_double GI = NL_FCONST(1.0) / m_RI.Value(); + //printf("VCCS %s RI %f\n", name().cstr(), m_RI.Value()); m_IP.set(GI); m_IN.set(GI); diff --git a/src/emu/netlist/analog/nld_fourterm.h b/src/emu/netlist/analog/nld_fourterm.h index 13584babef5..e14a69a9944 100644 --- a/src/emu/netlist/analog/nld_fourterm.h +++ b/src/emu/netlist/analog/nld_fourterm.h @@ -56,9 +56,9 @@ public: : netlist_device_t(afamily), m_gfac(1.0) { } protected: - /* ATTR_COLD */ virtual void start(); - /* ATTR_COLD */ virtual void reset(); - /* ATTR_COLD */ virtual void update_param(); + virtual void start(); + virtual void reset(); + virtual void update_param(); ATTR_HOT void update(); ATTR_COLD void start_internal(const nl_double def_RI); @@ -112,9 +112,9 @@ public: //: netlist_device_t(afamily), m_gfac(1.0) { } protected: - /* ATTR_COLD */ virtual void start(); - /* ATTR_COLD */ virtual void reset(); - /* ATTR_COLD */ virtual void update_param(); + virtual void start(); + virtual void reset(); + virtual void update_param(); ATTR_HOT void update(); nl_double m_gfac; @@ -156,9 +156,9 @@ public: : NETLIB_NAME(VCCS)(VCVS) { } protected: - /* ATTR_COLD */ virtual void start(); - /* ATTR_COLD */ virtual void reset(); - /* ATTR_COLD */ virtual void update_param(); + virtual void start(); + virtual void reset(); + virtual void update_param(); //ATTR_HOT void update(); netlist_terminal_t m_OP2; diff --git a/src/emu/netlist/analog/nld_ms_direct.h b/src/emu/netlist/analog/nld_ms_direct.h index 08894933000..3c5d404d430 100644 --- a/src/emu/netlist/analog/nld_ms_direct.h +++ b/src/emu/netlist/analog/nld_ms_direct.h @@ -8,27 +8,29 @@ #ifndef NLD_MS_DIRECT_H_ #define NLD_MS_DIRECT_H_ +#include <algorithm> + #include "nld_solver.h" -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> class netlist_matrix_solver_direct_t: public netlist_matrix_solver_t { public: - netlist_matrix_solver_direct_t(const netlist_solver_parameters_t ¶ms, const int size); - netlist_matrix_solver_direct_t(const eSolverType type, const netlist_solver_parameters_t ¶ms, const int size); + netlist_matrix_solver_direct_t(const netlist_solver_parameters_t *params, const int size); + netlist_matrix_solver_direct_t(const eSolverType type, const netlist_solver_parameters_t *params, const int size); virtual ~netlist_matrix_solver_direct_t(); - /* ATTR_COLD */ virtual void vsetup(netlist_analog_net_t::list_t &nets); - /* ATTR_COLD */ virtual void reset() { netlist_matrix_solver_t::reset(); } + virtual void vsetup(netlist_analog_net_t::list_t &nets); + virtual void reset() { netlist_matrix_solver_t::reset(); } - ATTR_HOT inline int N() const { return (m_N == 0 ? m_dim : m_N); } + ATTR_HOT inline unsigned N() const { if (m_N == 0) return m_dim; else return m_N; } ATTR_HOT inline int vsolve_non_dynamic(const bool newton_raphson); protected: - /* ATTR_COLD */ virtual void add_term(int net_idx, netlist_terminal_t *term); + virtual void add_term(int net_idx, netlist_terminal_t *term); ATTR_HOT virtual nl_double vsolve(); @@ -56,7 +58,7 @@ protected: private: - const int m_dim; + const unsigned m_dim; nl_double m_lp_fact; }; @@ -64,10 +66,10 @@ private: // netlist_matrix_solver_direct // ---------------------------------------------------------------------------------------- -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> netlist_matrix_solver_direct_t<m_N, _storage_N>::~netlist_matrix_solver_direct_t() { - for (int k = 0; k < N(); k++) + for (unsigned k = 0; k < N(); k++) { pfree(m_terms[k]); } @@ -75,7 +77,7 @@ netlist_matrix_solver_direct_t<m_N, _storage_N>::~netlist_matrix_solver_direct_t pfree_array(m_rails_temp); } -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> ATTR_HOT nl_double netlist_matrix_solver_direct_t<m_N, _storage_N>::compute_next_timestep() { nl_double new_solver_timestep = m_params.m_max_timestep; @@ -86,7 +88,7 @@ ATTR_HOT nl_double netlist_matrix_solver_direct_t<m_N, _storage_N>::compute_next * FIXME: We should extend the logic to use either all nets or * only output nets. */ - for (int k = 0; k < N(); k++) + for (unsigned k = 0; k < N(); k++) { netlist_analog_net_t *n = m_nets[k]; @@ -114,7 +116,7 @@ ATTR_HOT nl_double netlist_matrix_solver_direct_t<m_N, _storage_N>::compute_next return new_solver_timestep; } -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::add_term(int k, netlist_terminal_t *term) { if (term->m_otherterm->net().isRailNet()) @@ -139,13 +141,13 @@ ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::add_term(int k, } -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::vsetup(netlist_analog_net_t::list_t &nets) { if (m_dim < nets.size()) netlist().error("Dimension %d less than %" SIZETFMT, m_dim, nets.size()); - for (int k = 0; k < N(); k++) + for (unsigned k = 0; k < N(); k++) { m_terms[k]->clear(); m_rails_temp[k].clear(); @@ -153,10 +155,10 @@ ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::vsetup(netlist_a netlist_matrix_solver_t::setup(nets); - for (int k = 0; k < N(); k++) + for (unsigned k = 0; k < N(); k++) { m_terms[k]->m_railstart = m_terms[k]->count(); - for (int i = 0; i < m_rails_temp[k].count(); i++) + for (unsigned i = 0; i < m_rails_temp[k].count(); i++) this->m_terms[k]->add(m_rails_temp[k].terms()[i], m_rails_temp[k].net_other()[i]); m_rails_temp[k].clear(); // no longer needed @@ -187,8 +189,8 @@ ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::vsetup(netlist_a int sort_order = (type() == GAUSS_SEIDEL ? 1 : -1); - for (int k = 0; k < N() / 2; k++) - for (int i = 0; i < N() - 1; i++) + for (unsigned k = 0; k < N() / 2; k++) + for (unsigned i = 0; i < N() - 1; i++) { if ((m_terms[i]->m_railstart - m_terms[i+1]->m_railstart) * sort_order < 0) { @@ -197,47 +199,62 @@ ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::vsetup(netlist_a } } - for (int k = 0; k < N(); k++) + for (unsigned k = 0; k < N(); k++) { int *other = m_terms[k]->net_other(); - for (int i = 0; i < m_terms[k]->count(); i++) + for (unsigned i = 0; i < m_terms[k]->count(); i++) if (other[i] != -1) other[i] = get_net_idx(&m_terms[k]->terms()[i]->m_otherterm->net()); } #endif + + //ATTR_ALIGN nl_double m_A[_storage_N][((_storage_N + 7) / 8) * 8]; + save(NLNAME(m_RHS)); + save(NLNAME(m_last_RHS)); + save(NLNAME(m_last_V)); + + for (unsigned k = 0; k < N(); k++) + { + pstring num = pstring::sprintf("%d", k); + + save(m_terms[k]->go(),"GO" + num, m_terms[k]->count()); + save(m_terms[k]->gt(),"GT" + num, m_terms[k]->count()); + save(m_terms[k]->Idr(),"IDR" + num , m_terms[k]->count()); + } + } -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::build_LE_A() { - for (int k = 0; k < N(); k++) + for (unsigned k = 0; k < N(); k++) { - for (int i=0; i < N(); i++) + for (unsigned i=0; i < N(); i++) m_A[k][i] = 0.0; nl_double akk = 0.0; - const int terms_count = m_terms[k]->count(); - const int railstart = m_terms[k]->m_railstart; + const unsigned terms_count = m_terms[k]->count(); + const unsigned railstart = m_terms[k]->m_railstart; const nl_double * RESTRICT gt = m_terms[k]->gt(); const nl_double * RESTRICT go = m_terms[k]->go(); const int * RESTRICT net_other = m_terms[k]->net_other(); - for (int i = 0; i < terms_count; i++) + for (unsigned i = 0; i < terms_count; i++) akk = akk + gt[i]; m_A[k][k] += akk; - for (int i = 0; i < railstart; i++) + for (unsigned i = 0; i < railstart; i++) m_A[k][net_other[i]] += -go[i]; } } -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::build_LE_RHS() { - for (int k = 0; k < N(); k++) + for (unsigned k = 0; k < N(); k++) { nl_double rhsk_a = 0.0; nl_double rhsk_b = 0.0; @@ -258,7 +275,7 @@ ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::build_LE_RHS() } } -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::LE_solve() { #if 0 @@ -271,15 +288,15 @@ ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::LE_solve() printf("\n"); #endif - const int kN = N(); + const unsigned kN = N(); - for (int i = 0; i < kN; i++) { + for (unsigned i = 0; i < kN; i++) { // FIXME: use a parameter to enable pivoting? if (USE_PIVOT_SEARCH) { /* Find the row with the largest first value */ - int maxrow = i; - for (int j = i + 1; j < kN; j++) + unsigned maxrow = i; + for (unsigned j = i + 1; j < kN; j++) { if (nl_math::abs(m_A[j][i]) > nl_math::abs(m_A[maxrow][i])) maxrow = j; @@ -288,7 +305,7 @@ ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::LE_solve() if (maxrow != i) { /* Swap the maxrow and ith row */ - for (int k = i; k < kN; k++) { + for (unsigned k = i; k < kN; k++) { std::swap(m_A[i][k], m_A[maxrow][k]); } std::swap(m_RHS[i], m_RHS[maxrow]); @@ -300,12 +317,12 @@ ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::LE_solve() /* Eliminate column i from row j */ - for (int j = i + 1; j < kN; j++) + for (unsigned j = i + 1; j < kN; j++) { const nl_double f1 = - m_A[j][i] * f; if (f1 != NL_FCONST(0.0)) { - for (int k = i + 1; k < kN; k++) + for (unsigned k = i + 1; k < kN; k++) m_A[j][k] += m_A[i][k] * f1; m_RHS[j] += m_RHS[i] * f1; } @@ -313,18 +330,18 @@ ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::LE_solve() } } -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::LE_back_subst( nl_double * RESTRICT x) { - const int kN = N(); + const unsigned kN = N(); /* back substitution */ for (int j = kN - 1; j >= 0; j--) { nl_double tmp = 0; - for (int k = j + 1; k < kN; k++) + for (unsigned k = j + 1; k < kN; k++) tmp += m_A[j][k] * x[k]; x[j] = (m_RHS[j] - tmp) / m_A[j][j]; @@ -342,13 +359,13 @@ ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::LE_back_subst( } -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> ATTR_HOT nl_double netlist_matrix_solver_direct_t<m_N, _storage_N>::delta( const nl_double * RESTRICT V) { nl_double cerr = 0; nl_double cerr2 = 0; - for (int i = 0; i < this->N(); i++) + for (unsigned i = 0; i < this->N(); i++) { const nl_double e = nl_math::abs(V[i] - this->m_nets[i]->m_cur_Analog); const nl_double e2 = nl_math::abs(m_RHS[i] - this->m_last_RHS[i]); @@ -359,24 +376,24 @@ ATTR_HOT nl_double netlist_matrix_solver_direct_t<m_N, _storage_N>::delta( return cerr + cerr2*NL_FCONST(100000.0); } -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> ATTR_HOT void netlist_matrix_solver_direct_t<m_N, _storage_N>::store( const nl_double * RESTRICT V, const bool store_RHS) { - for (int i = 0; i < this->N(); i++) + for (unsigned i = 0; i < this->N(); i++) { this->m_nets[i]->m_cur_Analog = V[i]; } if (store_RHS) { - for (int i = 0; i < this->N(); i++) + for (unsigned i = 0; i < this->N(); i++) { this->m_last_RHS[i] = m_RHS[i]; } } } -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> ATTR_HOT nl_double netlist_matrix_solver_direct_t<m_N, _storage_N>::vsolve() { solve_base<netlist_matrix_solver_direct_t>(this); @@ -384,7 +401,7 @@ ATTR_HOT nl_double netlist_matrix_solver_direct_t<m_N, _storage_N>::vsolve() } -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> ATTR_HOT int netlist_matrix_solver_direct_t<m_N, _storage_N>::solve_non_dynamic(ATTR_UNUSED const bool newton_raphson) { nl_double new_v[_storage_N]; // = { 0.0 }; @@ -406,7 +423,7 @@ ATTR_HOT int netlist_matrix_solver_direct_t<m_N, _storage_N>::solve_non_dynamic( } } -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> ATTR_HOT inline int netlist_matrix_solver_direct_t<m_N, _storage_N>::vsolve_non_dynamic(const bool newton_raphson) { this->build_LE_A(); @@ -416,8 +433,8 @@ ATTR_HOT inline int netlist_matrix_solver_direct_t<m_N, _storage_N>::vsolve_non_ return this->solve_non_dynamic(newton_raphson); } -template <int m_N, int _storage_N> -netlist_matrix_solver_direct_t<m_N, _storage_N>::netlist_matrix_solver_direct_t(const netlist_solver_parameters_t ¶ms, const int size) +template <unsigned m_N, unsigned _storage_N> +netlist_matrix_solver_direct_t<m_N, _storage_N>::netlist_matrix_solver_direct_t(const netlist_solver_parameters_t *params, const int size) : netlist_matrix_solver_t(GAUSSIAN_ELIMINATION, params) , m_dim(size) , m_lp_fact(0) @@ -425,7 +442,7 @@ netlist_matrix_solver_direct_t<m_N, _storage_N>::netlist_matrix_solver_direct_t( m_terms = palloc_array(terms_t *, N()); m_rails_temp = palloc_array(terms_t, N()); - for (int k = 0; k < N(); k++) + for (unsigned k = 0; k < N(); k++) { m_terms[k] = palloc(terms_t); m_last_RHS[k] = 0.0; @@ -433,8 +450,8 @@ netlist_matrix_solver_direct_t<m_N, _storage_N>::netlist_matrix_solver_direct_t( } } -template <int m_N, int _storage_N> -netlist_matrix_solver_direct_t<m_N, _storage_N>::netlist_matrix_solver_direct_t(const eSolverType type, const netlist_solver_parameters_t ¶ms, const int size) +template <unsigned m_N, unsigned _storage_N> +netlist_matrix_solver_direct_t<m_N, _storage_N>::netlist_matrix_solver_direct_t(const eSolverType type, const netlist_solver_parameters_t *params, const int size) : netlist_matrix_solver_t(type, params) , m_dim(size) , m_lp_fact(0) @@ -442,7 +459,7 @@ netlist_matrix_solver_direct_t<m_N, _storage_N>::netlist_matrix_solver_direct_t( m_terms = palloc_array(terms_t *, N()); m_rails_temp = palloc_array(terms_t, N()); - for (int k = 0; k < N(); k++) + for (unsigned k = 0; k < N(); k++) { m_terms[k] = palloc(terms_t); m_last_RHS[k] = 0.0; diff --git a/src/emu/netlist/analog/nld_ms_direct1.h b/src/emu/netlist/analog/nld_ms_direct1.h index 6b901417a0a..991da037591 100644 --- a/src/emu/netlist/analog/nld_ms_direct1.h +++ b/src/emu/netlist/analog/nld_ms_direct1.h @@ -15,7 +15,7 @@ class netlist_matrix_solver_direct1_t: public netlist_matrix_solver_direct_t<1,1 { public: - netlist_matrix_solver_direct1_t(const netlist_solver_parameters_t ¶ms) + netlist_matrix_solver_direct1_t(const netlist_solver_parameters_t *params) : netlist_matrix_solver_direct_t<1, 1>(params, 1) {} ATTR_HOT inline int vsolve_non_dynamic(const bool newton_raphson); diff --git a/src/emu/netlist/analog/nld_ms_direct2.h b/src/emu/netlist/analog/nld_ms_direct2.h index 2aa8d749aaa..69df8085c57 100644 --- a/src/emu/netlist/analog/nld_ms_direct2.h +++ b/src/emu/netlist/analog/nld_ms_direct2.h @@ -17,7 +17,7 @@ class netlist_matrix_solver_direct2_t: public netlist_matrix_solver_direct_t<2,2 { public: - netlist_matrix_solver_direct2_t(const netlist_solver_parameters_t ¶ms) + netlist_matrix_solver_direct2_t(const netlist_solver_parameters_t *params) : netlist_matrix_solver_direct_t<2, 2>(params, 2) {} ATTR_HOT inline int vsolve_non_dynamic(const bool newton_raphson); diff --git a/src/emu/netlist/analog/nld_ms_jakobi.h b/src/emu/netlist/analog/nld_ms_jakobi.h deleted file mode 100644 index 9376e54c9ef..00000000000 --- a/src/emu/netlist/analog/nld_ms_jakobi.h +++ /dev/null @@ -1,362 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * nld_ms_direct1.h - * - */ - -#ifndef NLD_MS_GAUSS_SEIDEL_H_ -#define NLD_MS_GAUSS_SEIDEL_H_ - -#include "nld_solver.h" -#include "nld_ms_direct.h" - -template <int m_N, int _storage_N> -class netlist_matrix_solver_SOR_t: public netlist_matrix_solver_direct_t<m_N, _storage_N> -{ -public: - - netlist_matrix_solver_SOR_t(const netlist_solver_parameters_t ¶ms, int size) - : netlist_matrix_solver_direct_t<m_N, _storage_N>(netlist_matrix_solver_t::GAUSS_SEIDEL, params, size) - , m_lp_fact(0) - , m_gs_fail(0) - , m_gs_total(0) - { - const char *p = osd_getenv("NL_STATS"); - if (p != NULL) - m_log_stats = (bool) atoi(p); - else - m_log_stats = false; - } - - virtual ~netlist_matrix_solver_SOR_t() {} - - /* ATTR_COLD */ virtual void log_stats(); - - ATTR_HOT inline int vsolve_non_dynamic(); -protected: - ATTR_HOT virtual nl_double vsolve(); - -private: - nl_double m_lp_fact; - int m_gs_fail; - int m_gs_total; - bool m_log_stats; - -}; - -// ---------------------------------------------------------------------------------------- -// netlist_matrix_solver - Gauss - Seidel -// ---------------------------------------------------------------------------------------- - -template <int m_N, int _storage_N> -void netlist_matrix_solver_SOR_t<m_N, _storage_N>::log_stats() -{ - if (this->m_stat_calculations != 0 && m_log_stats) - { - printf("==============================================\n"); - printf("Solver %s\n", this->name().cstr()); - printf(" ==> %d nets\n", this->N()); //, (*(*groups[i].first())->m_core_terms.first())->name().cstr()); - printf(" has %s elements\n", this->is_dynamic() ? "dynamic" : "no dynamic"); - printf(" has %s elements\n", this->is_timestep() ? "timestep" : "no timestep"); - printf(" %6.3f average newton raphson loops\n", (double) this->m_stat_newton_raphson / (double) this->m_stat_vsolver_calls); - printf(" %10d invocations (%6d Hz) %10d gs fails (%6.2f%%) %6.3f average\n", - this->m_stat_calculations, - this->m_stat_calculations * 10 / (int) (this->netlist().time().as_double() * 10.0), - this->m_gs_fail, - 100.0 * (double) this->m_gs_fail / (double) this->m_stat_calculations, - (double) this->m_gs_total / (double) this->m_stat_calculations); - } -} - -template <int m_N, int _storage_N> -ATTR_HOT nl_double netlist_matrix_solver_SOR_t<m_N, _storage_N>::vsolve() -{ - /* - * enable linear prediction on first newton pass - */ - - if (USE_LINEAR_PREDICTION) - for (int k = 0; k < this->N(); k++) - { - this->m_last_V[k] = this->m_nets[k]->m_cur_Analog; - this->m_nets[k]->m_cur_Analog = this->m_nets[k]->m_cur_Analog + this->m_Vdelta[k] * this->current_timestep() * m_lp_fact; - } - else - for (int k = 0; k < this->N(); k++) - { - this->m_last_V[k] = this->m_nets[k]->m_cur_Analog; - } - - this->solve_base(this); - - if (USE_LINEAR_PREDICTION) - { - nl_double sq = 0; - nl_double sqo = 0; - const nl_double rez_cts = 1.0 / this->current_timestep(); - for (int k = 0; k < this->N(); k++) - { - const netlist_analog_net_t *n = this->m_nets[k]; - const nl_double nv = (n->m_cur_Analog - this->m_last_V[k]) * rez_cts ; - sq += nv * nv; - sqo += this->m_Vdelta[k] * this->m_Vdelta[k]; - this->m_Vdelta[k] = nv; - } - if (sqo > 1e-90) - m_lp_fact = std::min(nl_math::sqrt(sq/sqo), 2.0); - else - m_lp_fact = 0.0; - } - - - return this->compute_next_timestep(); -} - -template <int m_N, int _storage_N> -ATTR_HOT inline int netlist_matrix_solver_SOR_t<m_N, _storage_N>::vsolve_non_dynamic() -{ - /* The matrix based code looks a lot nicer but actually is 30% slower than - * the optimized code which works directly on the data structures. - * Need something like that for gaussian elimination as well. - */ - -#if 0 || USE_MATRIX_GS - static nl_double ws = 1.0; - ATTR_ALIGN nl_double new_v[_storage_N] = { 0.0 }; - const int iN = this->N(); - - bool resched = false; - - int resched_cnt = 0; - - this->build_LE(); - - { - nl_double frob; - frob = 0; - nl_double rmin = 1e99, rmax = -1e99; - for (int k = 0; k < iN; k++) - { - new_v[k] = this->m_nets[k]->m_cur_Analog; - nl_double s=0.0; - for (int i = 0; i < iN; i++) - { - frob += this->m_A[k][i] * this->m_A[k][i]; - s = s + nl_math::abs(this->m_A[k][i]); - } - - if (s<rmin) - rmin = s; - if (s>rmax) - rmax = s; - } -#if 0 - nl_double frobA = nl_math::sqrt(frob /(iN)); - if (1 &&frobA < 1.0) - //ws = 2.0 / (1.0 + nl_math::sqrt(1.0-frobA)); - ws = 2.0 / (2.0 - frobA); - else - ws = 1.0; - ws = 0.9; -#else - // calculate an estimate for rho. - // This is based on the Perron???Frobenius theorem for positive matrices. - // No mathematical proof here. The following estimates the - // optimal relaxation parameter pretty well. Unfortunately, the - // overhead is bigger than the gain. Consequently the fast GS below - // uses a fixed GS. One can however use this here to determine a - // suitable parameter. - nl_double rm = (rmax + rmin) * 0.5; - if (rm < 1.0) - ws = 2.0 / (1.0 + nl_math::sqrt(1.0-rm)); - else - ws = 1.0; - if (ws > 1.02 && rmax > 1.001) - printf("rmin %f rmax %f ws %f\n", rmin, rmax, ws); -#endif - } - - // Frobenius norm for (D-L)^(-1)U - //nl_double frobU; - //nl_double frobL; - //nl_double norm; - do { - resched = false; - nl_double cerr = 0.0; - //frobU = 0; - //frobL = 0; - //norm = 0; - - for (int k = 0; k < iN; k++) - { - nl_double Idrive = 0; - //nl_double norm_t = 0; - // Reduction loops need -ffast-math - for (int i = 0; i < iN; i++) - Idrive += this->m_A[k][i] * new_v[i]; - - for (int i = 0; i < iN; i++) - { - //if (i < k) frobL += this->m_A[k][i] * this->m_A[k][i] / this->m_A[k][k] /this-> m_A[k][k]; - //if (i > k) frobU += this->m_A[k][i] * this->m_A[k][i] / this->m_A[k][k] / this->m_A[k][k]; - //norm_t += nl_math::abs(this->m_A[k][i]); - } - - //if (norm_t > norm) norm = norm_t; - const nl_double new_val = (1.0-ws) * new_v[k] + ws * (this->m_RHS[k] - Idrive + this->m_A[k][k] * new_v[k]) / this->m_A[k][k]; - - const nl_double e = nl_math::abs(new_val - new_v[k]); - cerr = (e > cerr ? e : cerr); - new_v[k] = new_val; - } - - if (cerr > this->m_params.m_accuracy) - { - resched = true; - } - resched_cnt++; - //ATTR_UNUSED nl_double frobUL = nl_math::sqrt((frobU + frobL) / (double) (iN) / (double) (iN)); - } while (resched && (resched_cnt < this->m_params.m_gs_loops)); - //printf("Frobenius %f %f %f %f %f\n", nl_math::sqrt(frobU), nl_math::sqrt(frobL), frobUL, frobA, norm); - //printf("Omega Estimate1 %f %f\n", 2.0 / (1.0 + nl_math::sqrt(1-frobUL)), 2.0 / (1.0 + nl_math::sqrt(1-frobA)) ); // printf("Frobenius %f\n", sqrt(frob / (double) (iN * iN) )); - //printf("Omega Estimate2 %f %f\n", 2.0 / (2.0 - frobUL), 2.0 / (2.0 - frobA) ); // printf("Frobenius %f\n", sqrt(frob / (double) (iN * iN) )); - - - this->store(new_v, false); - - this->m_gs_total += resched_cnt; - if (resched) - { - //this->netlist().warning("Falling back to direct solver .. Consider increasing RESCHED_LOOPS"); - this->m_gs_fail++; - int tmp = netlist_matrix_solver_direct_t<m_N, _storage_N>::solve_non_dynamic(); - this->m_calculations++; - return tmp; - } - else { - this->m_calculations++; - - return resched_cnt; - } - -#else - const int iN = this->N(); - bool resched = false; - int resched_cnt = 0; - - /* ideally, we could get an estimate for the spectral radius of - * Inv(D - L) * U - * - * and estimate using - * - * omega = 2.0 / (1.0 + nl_math::sqrt(1-rho)) - */ - - const nl_double ws = this->m_params.m_sor; //1.045; //2.0 / (1.0 + /*sin*/(3.14159 * 5.5 / (double) (m_nets.count()+1))); - //const nl_double ws = 2.0 / (1.0 + sin(3.14159 * 4 / (double) (this->N()))); - - ATTR_ALIGN nl_double w[_storage_N]; - ATTR_ALIGN nl_double one_m_w[_storage_N]; - ATTR_ALIGN nl_double RHS[_storage_N]; - ATTR_ALIGN nl_double new_V[_storage_N]; - ATTR_ALIGN nl_double old_V[_storage_N]; - - for (int k = 0; k < iN; k++) - { - nl_double gtot_t = 0.0; - nl_double gabs_t = 0.0; - nl_double RHS_t = 0.0; - - new_V[k] = this->m_nets[k]->m_cur_Analog; - - { - const int term_count = this->m_terms[k]->count(); - const nl_double * const RESTRICT gt = this->m_terms[k]->gt(); - const nl_double * const RESTRICT go = this->m_terms[k]->go(); - const nl_double * const RESTRICT Idr = this->m_terms[k]->Idr(); - const nl_double * const *other_cur_analog = this->m_terms[k]->other_curanalog(); - - for (int i = 0; i < term_count; i++) - { - gtot_t = gtot_t + gt[i]; - RHS_t = RHS_t + Idr[i]; - } - if (USE_GABS) - for (int i = 0; i < term_count; i++) - gabs_t = gabs_t + nl_math::abs(go[i]); - - for (int i = this->m_terms[k]->m_railstart; i < term_count; i++) - RHS_t = RHS_t + go[i] * *other_cur_analog[i]; - } - - RHS[k] = RHS_t; - - //if (nl_math::abs(gabs_t - nl_math::abs(gtot_t)) > 1e-20) - // printf("%d %e abs: %f tot: %f\n",k, gabs_t / gtot_t -1.0, gabs_t, gtot_t); - - gabs_t *= 0.95; // avoid rounding issues - if (!USE_GABS || gabs_t <= gtot_t) - { - w[k] = ws / gtot_t; - one_m_w[k] = 1.0 - ws; - } - else - { - //printf("abs: %f tot: %f\n", gabs_t, gtot_t); - w[k] = 1.0 / (gtot_t + gabs_t); - one_m_w[k] = 1.0 - 1.0 * gtot_t / (gtot_t + gabs_t); - } - - } - - const nl_double accuracy = this->m_params.m_accuracy; - - for (int k = 0; k < iN; k++) - old_V[k] = this->m_nets[k]->m_cur_Analog; - do { - resched = false; - - for (int k = 0; k < iN; k++) - { - const int * RESTRICT net_other = this->m_terms[k]->net_other(); - const int railstart = this->m_terms[k]->m_railstart; - const nl_double * RESTRICT go = this->m_terms[k]->go(); - - nl_double Idrive = 0.0; - for (int i = 0; i < railstart; i++) - //Idrive = Idrive + go[i] * new_V[net_other[i]]; - Idrive = Idrive + go[i] * old_V[net_other[i]]; - - //const nl_double new_val = new_V[k] * one_m_w[k] + (Idrive + RHS[k]) * w[k]; - //resched = resched || (nl_math::abs(new_val - new_V[k]) > accuracy); - const nl_double new_val = old_V[k] * one_m_w[k] + (Idrive + RHS[k]) * w[k]; - resched = resched || (nl_math::abs(new_val - old_V[k]) > accuracy); - new_V[k] = new_val; - } - for (int k = 0; k < iN; k++) - old_V[k] = new_V[k]; - - resched_cnt++; - } while (resched && (resched_cnt < this->m_params.m_gs_loops)); - - for (int k = 0; k < iN; k++) - this->m_nets[k]->m_cur_Analog = new_V[k]; - - this->m_gs_total += resched_cnt; - this->m_stat_calculations++; - - if (resched) - { - //this->netlist().warning("Falling back to direct solver .. Consider increasing RESCHED_LOOPS"); - this->m_gs_fail++; - return netlist_matrix_solver_direct_t<m_N, _storage_N>::vsolve_non_dynamic(); - } - else { - return resched_cnt; - } -#endif -} - - -#endif /* NLD_MS_GAUSS_SEIDEL_H_ */ diff --git a/src/emu/netlist/analog/nld_ms_sor.h b/src/emu/netlist/analog/nld_ms_sor.h index 11ee4273d62..4219363e229 100644 --- a/src/emu/netlist/analog/nld_ms_sor.h +++ b/src/emu/netlist/analog/nld_ms_sor.h @@ -12,15 +12,17 @@ #ifndef NLD_MS_SOR_H_ #define NLD_MS_SOR_H_ +#include <algorithm> + #include "nld_solver.h" #include "nld_ms_direct.h" -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> class netlist_matrix_solver_SOR_t: public netlist_matrix_solver_direct_t<m_N, _storage_N> { public: - netlist_matrix_solver_SOR_t(const netlist_solver_parameters_t ¶ms, int size) + netlist_matrix_solver_SOR_t(const netlist_solver_parameters_t *params, int size) : netlist_matrix_solver_direct_t<m_N, _storage_N>(netlist_matrix_solver_t::GAUSS_SEIDEL, params, size) , m_lp_fact(0) , m_gs_fail(0) @@ -30,8 +32,9 @@ public: virtual ~netlist_matrix_solver_SOR_t() {} - /* ATTR_COLD */ virtual void log_stats(); + virtual void log_stats(); + virtual void vsetup(netlist_analog_net_t::list_t &nets); ATTR_HOT virtual int vsolve_non_dynamic(const bool newton_raphson); protected: ATTR_HOT virtual nl_double vsolve(); @@ -46,7 +49,7 @@ private: // netlist_matrix_solver - Gauss - Seidel // ---------------------------------------------------------------------------------------- -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> void netlist_matrix_solver_SOR_t<m_N, _storage_N>::log_stats() { if (this->m_stat_calculations != 0 && this->m_params.m_log_stats) @@ -66,14 +69,23 @@ void netlist_matrix_solver_SOR_t<m_N, _storage_N>::log_stats() } } -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> +void netlist_matrix_solver_SOR_t<m_N, _storage_N>::vsetup(netlist_analog_net_t::list_t &nets) +{ + netlist_matrix_solver_direct_t<m_N, _storage_N>::vsetup(nets); + this->save(NLNAME(m_lp_fact)); + this->save(NLNAME(m_gs_fail)); + this->save(NLNAME(m_gs_total)); +} + +template <unsigned m_N, unsigned _storage_N> ATTR_HOT nl_double netlist_matrix_solver_SOR_t<m_N, _storage_N>::vsolve() { this->solve_base(this); return this->compute_next_timestep(); } -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> ATTR_HOT inline int netlist_matrix_solver_SOR_t<m_N, _storage_N>::vsolve_non_dynamic(const bool newton_raphson) { const int iN = this->N(); diff --git a/src/emu/netlist/analog/nld_ms_sor_mat.h b/src/emu/netlist/analog/nld_ms_sor_mat.h index 184df6313ff..4a788f8f403 100644 --- a/src/emu/netlist/analog/nld_ms_sor_mat.h +++ b/src/emu/netlist/analog/nld_ms_sor_mat.h @@ -12,17 +12,20 @@ #ifndef NLD_MS_SOR_MAT_H_ #define NLD_MS_SOR_MAT_H_ +#include <algorithm> + #include "nld_solver.h" #include "nld_ms_direct.h" -template <int m_N, int _storage_N> + +template <unsigned m_N, unsigned _storage_N> class netlist_matrix_solver_SOR_mat_t: public netlist_matrix_solver_direct_t<m_N, _storage_N> { public: - netlist_matrix_solver_SOR_mat_t(const netlist_solver_parameters_t ¶ms, int size) + netlist_matrix_solver_SOR_mat_t(const netlist_solver_parameters_t *params, int size) : netlist_matrix_solver_direct_t<m_N, _storage_N>(netlist_matrix_solver_t::GAUSS_SEIDEL, params, size) - , m_omega(params.m_sor) + , m_omega(params->m_sor) , m_lp_fact(0) , m_gs_fail(0) , m_gs_total(0) @@ -36,7 +39,8 @@ public: virtual ~netlist_matrix_solver_SOR_mat_t() {} - /* ATTR_COLD */ virtual void log_stats(); + virtual void log_stats(); + virtual void vsetup(netlist_analog_net_t::list_t &nets); ATTR_HOT inline int vsolve_non_dynamic(const bool newton_raphson); protected: @@ -57,7 +61,7 @@ private: // netlist_matrix_solver - Gauss - Seidel // ---------------------------------------------------------------------------------------- -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> void netlist_matrix_solver_SOR_mat_t<m_N, _storage_N>::log_stats() { if (this->m_stat_calculations != 0 && m_log_stats) @@ -77,7 +81,19 @@ void netlist_matrix_solver_SOR_mat_t<m_N, _storage_N>::log_stats() } } -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> +void netlist_matrix_solver_SOR_mat_t<m_N, _storage_N>::vsetup(netlist_analog_net_t::list_t &nets) +{ + netlist_matrix_solver_direct_t<m_N, _storage_N>::vsetup(nets); + this->save(NLNAME(m_omega)); + this->save(NLNAME(m_lp_fact)); + this->save(NLNAME(m_gs_fail)); + this->save(NLNAME(m_gs_total)); + this->save(NLNAME(m_Vdelta)); +} + + +template <unsigned m_N, unsigned _storage_N> ATTR_HOT nl_double netlist_matrix_solver_SOR_mat_t<m_N, _storage_N>::vsolve() { /* @@ -85,13 +101,13 @@ ATTR_HOT nl_double netlist_matrix_solver_SOR_mat_t<m_N, _storage_N>::vsolve() */ if (USE_LINEAR_PREDICTION) - for (int k = 0; k < this->N(); k++) + for (unsigned k = 0; k < this->N(); k++) { this->m_last_V[k] = this->m_nets[k]->m_cur_Analog; this->m_nets[k]->m_cur_Analog = this->m_nets[k]->m_cur_Analog + this->m_Vdelta[k] * this->current_timestep() * m_lp_fact; } else - for (int k = 0; k < this->N(); k++) + for (unsigned k = 0; k < this->N(); k++) { this->m_last_V[k] = this->m_nets[k]->m_cur_Analog; } @@ -103,7 +119,7 @@ ATTR_HOT nl_double netlist_matrix_solver_SOR_mat_t<m_N, _storage_N>::vsolve() nl_double sq = 0; nl_double sqo = 0; const nl_double rez_cts = 1.0 / this->current_timestep(); - for (int k = 0; k < this->N(); k++) + for (unsigned k = 0; k < this->N(); k++) { const netlist_analog_net_t *n = this->m_nets[k]; const nl_double nv = (n->m_cur_Analog - this->m_last_V[k]) * rez_cts ; @@ -123,7 +139,7 @@ ATTR_HOT nl_double netlist_matrix_solver_SOR_mat_t<m_N, _storage_N>::vsolve() return this->compute_next_timestep(); } -template <int m_N, int _storage_N> +template <unsigned m_N, unsigned _storage_N> ATTR_HOT inline int netlist_matrix_solver_SOR_mat_t<m_N, _storage_N>::vsolve_non_dynamic(const bool newton_raphson) { /* The matrix based code looks a lot nicer but actually is 30% slower than diff --git a/src/emu/netlist/analog/nld_opamps.h b/src/emu/netlist/analog/nld_opamps.h index 4433114a18c..722212b1763 100644 --- a/src/emu/netlist/analog/nld_opamps.h +++ b/src/emu/netlist/analog/nld_opamps.h @@ -19,7 +19,7 @@ // ---------------------------------------------------------------------------------------- #define LM3900(_name) \ - SUBMODEL(_name, opamp_lm3900) + SUBMODEL(opamp_lm3900, name) // ---------------------------------------------------------------------------------------- // Devices ... diff --git a/src/emu/netlist/analog/nld_solver.c b/src/emu/netlist/analog/nld_solver.c index 703f6f35770..c7d4ac1cddc 100644 --- a/src/emu/netlist/analog/nld_solver.c +++ b/src/emu/netlist/analog/nld_solver.c @@ -51,7 +51,7 @@ ATTR_COLD void terms_t::add(netlist_terminal_t *term, int net_other) ATTR_COLD void terms_t::set_pointers() { - for (int i = 0; i < count(); i++) + for (unsigned i = 0; i < count(); i++) { m_term[i]->m_gt1 = &m_gt[i]; m_term[i]->m_go1 = &m_go[i]; @@ -64,11 +64,11 @@ ATTR_COLD void terms_t::set_pointers() // netlist_matrix_solver // ---------------------------------------------------------------------------------------- -ATTR_COLD netlist_matrix_solver_t::netlist_matrix_solver_t(const eSolverType type, const netlist_solver_parameters_t ¶ms) +ATTR_COLD netlist_matrix_solver_t::netlist_matrix_solver_t(const eSolverType type, const netlist_solver_parameters_t *params) : m_stat_calculations(0), m_stat_newton_raphson(0), m_stat_vsolver_calls(0), - m_params(params), + m_params(*params), m_cur_ts(0), m_type(type) { @@ -156,7 +156,7 @@ ATTR_COLD void netlist_matrix_solver_t::setup(netlist_analog_net_t::list_t &nets break; } } - NL_VERBOSE_OUT(("added net with %d populated connections\n", net->m_core_terms.size())); + NL_VERBOSE_OUT(("added net with %" SIZETFMT " populated connections\n", net->m_core_terms.size())); } } @@ -173,15 +173,7 @@ ATTR_HOT void netlist_matrix_solver_t::update_dynamic() { /* update all non-linear devices */ for (std::size_t i=0; i < m_dynamic_devices.size(); i++) - switch (m_dynamic_devices[i]->family()) - { - case netlist_device_t::DIODE: - static_cast<NETLIB_NAME(D) *>(m_dynamic_devices[i])->update_terminals(); - break; - default: - m_dynamic_devices[i]->update_terminals(); - break; - } + m_dynamic_devices[i]->update_terminals(); } ATTR_COLD void netlist_matrix_solver_t::start() @@ -189,6 +181,10 @@ ATTR_COLD void netlist_matrix_solver_t::start() register_output("Q_sync", m_Q_sync); register_input("FB_sync", m_fb_sync); connect(m_fb_sync, m_Q_sync); + + save(NLNAME(m_last_step)); + save(NLNAME(m_cur_ts)); + } ATTR_COLD void netlist_matrix_solver_t::reset() @@ -399,9 +395,9 @@ template <int m_N, int _storage_N> netlist_matrix_solver_t * NETLIB_NAME(solver)::create_solver(int size, const int gs_threshold, const bool use_specific) { if (use_specific && m_N == 1) - return palloc(netlist_matrix_solver_direct1_t, m_params); + return palloc(netlist_matrix_solver_direct1_t, &m_params); else if (use_specific && m_N == 2) - return palloc(netlist_matrix_solver_direct2_t, m_params); + return palloc(netlist_matrix_solver_direct2_t, &m_params); else { if (size >= gs_threshold) @@ -409,18 +405,18 @@ netlist_matrix_solver_t * NETLIB_NAME(solver)::create_solver(int size, const int if (USE_MATRIX_GS) { typedef netlist_matrix_solver_SOR_mat_t<m_N,_storage_N> solver_mat; - return palloc(solver_mat, m_params, size); + return palloc(solver_mat, &m_params, size); } else { typedef netlist_matrix_solver_SOR_t<m_N,_storage_N> solver_GS; - return palloc(solver_GS, m_params, size); + return palloc(solver_GS, &m_params, size); } } else { typedef netlist_matrix_solver_direct_t<m_N,_storage_N> solver_D; - return palloc(solver_D, m_params, size); + return palloc(solver_D, &m_params, size); } } } @@ -512,6 +508,9 @@ ATTR_COLD void NETLIB_NAME(solver)::post_start() case 12: ms = create_solver<12,12>(12, gs_threshold, use_specific); break; + case 87: + ms = create_solver<87,87>(87, gs_threshold, use_specific); + break; default: if (net_count <= 16) { @@ -525,9 +524,13 @@ ATTR_COLD void NETLIB_NAME(solver)::post_start() { ms = create_solver<0,64>(net_count, gs_threshold, use_specific); } + else if (net_count <= 128) + { + ms = create_solver<0,128>(net_count, gs_threshold, use_specific); + } else { - netlist().error("Encountered netgroup with > 64 nets"); + netlist().error("Encountered netgroup with > 128 nets"); ms = NULL; /* tease compilers */ } diff --git a/src/emu/netlist/analog/nld_solver.h b/src/emu/netlist/analog/nld_solver.h index 874c8dc7e1d..a774912ac00 100644 --- a/src/emu/netlist/analog/nld_solver.h +++ b/src/emu/netlist/analog/nld_solver.h @@ -61,11 +61,14 @@ class terms_t m_term.clear(); m_net_other.clear(); m_gt.clear(); + m_go.clear(); + m_Idr.clear(); + m_other_curanalog.clear(); } ATTR_COLD void add(netlist_terminal_t *term, int net_other); - ATTR_HOT inline int count() { return m_term.size(); } + ATTR_HOT inline unsigned count() { return m_term.size(); } ATTR_HOT inline netlist_terminal_t **terms() { return m_term.data(); } ATTR_HOT inline int *net_other() { return m_net_other.data(); } @@ -76,7 +79,7 @@ class terms_t ATTR_COLD void set_pointers(); - int m_railstart; + unsigned m_railstart; private: plist_t<netlist_terminal_t *> m_term; @@ -99,10 +102,10 @@ public: GAUSS_SEIDEL }; - ATTR_COLD netlist_matrix_solver_t(const eSolverType type, const netlist_solver_parameters_t ¶ms); - /* ATTR_COLD */ virtual ~netlist_matrix_solver_t(); + ATTR_COLD netlist_matrix_solver_t(const eSolverType type, const netlist_solver_parameters_t *params); + virtual ~netlist_matrix_solver_t(); - /* ATTR_COLD */ virtual void vsetup(netlist_analog_net_t::list_t &nets) = 0; + virtual void vsetup(netlist_analog_net_t::list_t &nets) = 0; template<class C> void solve_base(C *p); @@ -120,11 +123,11 @@ public: /* netdevice functions */ ATTR_HOT virtual void update(); - /* ATTR_COLD */ virtual void start(); - /* ATTR_COLD */ virtual void reset(); + virtual void start(); + virtual void reset(); ATTR_COLD int get_net_idx(netlist_net_t *net); - /* ATTR_COLD */ virtual void log_stats() {}; + virtual void log_stats() {}; inline eSolverType type() const { return m_type; } @@ -136,7 +139,7 @@ protected: // should return next time step ATTR_HOT virtual nl_double vsolve() = 0; - /* ATTR_COLD */ virtual void add_term(int net_idx, netlist_terminal_t *term) = 0; + virtual void add_term(int net_idx, netlist_terminal_t *term) = 0; plist_t<netlist_analog_net_t *> m_nets; plist_t<netlist_analog_output_t *> m_inps; @@ -173,7 +176,7 @@ public: NETLIB_NAME(solver)() : netlist_device_t() { } - /* ATTR_COLD */ virtual ~NETLIB_NAME(solver)(); + virtual ~NETLIB_NAME(solver)(); ATTR_COLD void post_start(); ATTR_COLD void stop(); diff --git a/src/emu/netlist/analog/nld_twoterm.c b/src/emu/netlist/analog/nld_twoterm.c index 02ec7fa9c29..958ad33ab51 100644 --- a/src/emu/netlist/analog/nld_twoterm.c +++ b/src/emu/netlist/analog/nld_twoterm.c @@ -5,6 +5,8 @@ * */ +#include <algorithm> + #include "nld_twoterm.h" #include "nld_solver.h" @@ -20,7 +22,7 @@ ATTR_COLD netlist_generic_diode::netlist_generic_diode() ATTR_COLD void netlist_generic_diode::set_param(const nl_double Is, const nl_double n, nl_double gmin) { - static const int csqrt2 = nl_math::sqrt(2.0); + static const double csqrt2 = nl_math::sqrt(2.0); m_Is = Is; m_n = n; m_gmin = gmin; diff --git a/src/emu/netlist/analog/nld_twoterm.h b/src/emu/netlist/analog/nld_twoterm.h index fed3b148db5..8088b684902 100644 --- a/src/emu/netlist/analog/nld_twoterm.h +++ b/src/emu/netlist/analog/nld_twoterm.h @@ -102,14 +102,14 @@ public: { } - ATTR_HOT inline void set(const nl_double G, const nl_double V, const nl_double I) + ATTR_HOT /* inline */ void set(const nl_double G, const nl_double V, const nl_double I) { /* GO, GT, I */ m_P.set( G, G, ( V) * G - I); m_N.set( G, G, ( -V) * G + I); } - ATTR_HOT inline nl_double deltaV() const + ATTR_HOT /* inline */ nl_double deltaV() const { return m_P.net().as_analog().Q_Analog() - m_N.net().as_analog().Q_Analog(); } @@ -122,8 +122,8 @@ public: } protected: - /* ATTR_COLD */ virtual void start(); - /* ATTR_COLD */ virtual void reset(); + virtual void start(); + virtual void reset(); ATTR_HOT void update(); private: @@ -144,8 +144,8 @@ public: } protected: - /* ATTR_COLD */ virtual void start(); - /* ATTR_COLD */ virtual void reset(); + virtual void start(); + virtual void reset(); ATTR_HOT void update(); }; @@ -193,9 +193,9 @@ public: } protected: - /* ATTR_COLD */ virtual void start(); - /* ATTR_COLD */ virtual void reset(); - /* ATTR_COLD */ virtual void update_param(); + virtual void start(); + virtual void reset(); + virtual void update_param(); ATTR_HOT void update(); netlist_param_double_t m_C; @@ -282,8 +282,8 @@ public: NETLIB_UPDATE_TERMINALSI(); protected: - /* ATTR_COLD */ virtual void start(); - /* ATTR_COLD */ virtual void update_param(); + virtual void start(); + virtual void update_param(); ATTR_HOT void update(); netlist_param_model_t m_model; diff --git a/src/emu/netlist/devices/net_lib.c b/src/emu/netlist/devices/net_lib.c index f17b638c6e1..37eaf082493 100644 --- a/src/emu/netlist/devices/net_lib.c +++ b/src/emu/netlist/devices/net_lib.c @@ -41,7 +41,7 @@ NETLIST_END() #define ENTRY1(_nic, _name, _defparam) factory.register_device<_nic>( # _name, xstr(_nic), _defparam ); #define ENTRY(_nic, _name, _defparam) ENTRY1(NETLIB_NAME(_nic), _name, _defparam) -void nl_initialize_factory(netlist_factory_t &factory) +void nl_initialize_factory(netlist_factory_list_t &factory) { ENTRY(R, RES, "R") ENTRY(POT, POT, "R") @@ -52,7 +52,7 @@ void nl_initialize_factory(netlist_factory_t &factory) ENTRY(VCCS, VCCS, "-") ENTRY(CCCS, CCCS, "-") ENTRY(dummy_input, DUMMY_INPUT, "-") - ENTRY(frontier, FRONTIER, "+I,Q") + ENTRY(frontier, FRONTIER_DEV, "+I,G,Q") // not intended to be used directly ENTRY(QBJT_EB, QBJT_EB, "model") ENTRY(QBJT_switch, QBJT_SW, "model") ENTRY(ttl_input, TTL_INPUT, "IN") diff --git a/src/emu/netlist/devices/net_lib.h b/src/emu/netlist/devices/net_lib.h index c6ab75fe522..1ae4336f62e 100644 --- a/src/emu/netlist/devices/net_lib.h +++ b/src/emu/netlist/devices/net_lib.h @@ -67,6 +67,6 @@ NETLIST_EXTERNAL(diode_models); NETLIST_EXTERNAL(bjt_models); -void nl_initialize_factory(netlist_factory_t &factory); +void nl_initialize_factory(netlist_factory_list_t &factory); #endif diff --git a/src/emu/netlist/devices/nld_4020.c b/src/emu/netlist/devices/nld_4020.c index f0e160de8d3..93166b11fc4 100644 --- a/src/emu/netlist/devices/nld_4020.c +++ b/src/emu/netlist/devices/nld_4020.c @@ -76,7 +76,7 @@ NETLIB_UPDATE(4020) { sub.m_cnt = 0; sub.m_IP.inactivate(); - static const netlist_time reset_time = netlist_time::from_nsec(140); + /* static */ const netlist_time reset_time = netlist_time::from_nsec(140); OUTLOGIC(sub.m_Q[0], 0, reset_time); for (int i=3; i<14; i++) OUTLOGIC(sub.m_Q[i], 0, reset_time); @@ -87,7 +87,7 @@ NETLIB_UPDATE(4020) inline NETLIB_FUNC_VOID(4020_sub, update_outputs, (const UINT16 cnt)) { - static const netlist_time out_delayQn[14] = { + /* static */ const netlist_time out_delayQn[14] = { NLTIME_FROM_NS(180), NLTIME_FROM_NS(280), NLTIME_FROM_NS(380), NLTIME_FROM_NS(480), NLTIME_FROM_NS(580), NLTIME_FROM_NS(680), diff --git a/src/emu/netlist/devices/nld_7400.c b/src/emu/netlist/devices/nld_7400.c index 758d5d1b667..91a1bfbf472 100644 --- a/src/emu/netlist/devices/nld_7400.c +++ b/src/emu/netlist/devices/nld_7400.c @@ -26,20 +26,20 @@ NETLIB_START(7400_dip) register_sub("3", m_3); register_sub("4", m_4); - register_subalias("1", m_1.m_i[0]); - register_subalias("2", m_1.m_i[1]); + register_subalias("1", m_1.m_I[0]); + register_subalias("2", m_1.m_I[1]); register_subalias("3", m_1.m_Q[0]); - register_subalias("4", m_2.m_i[0]); - register_subalias("5", m_2.m_i[1]); + register_subalias("4", m_2.m_I[0]); + register_subalias("5", m_2.m_I[1]); register_subalias("6", m_2.m_Q[0]); - register_subalias("9", m_3.m_i[0]); - register_subalias("10", m_3.m_i[1]); + register_subalias("9", m_3.m_I[0]); + register_subalias("10", m_3.m_I[1]); register_subalias("8", m_3.m_Q[0]); - register_subalias("12", m_4.m_i[0]); - register_subalias("13", m_4.m_i[1]); + register_subalias("12", m_4.m_I[0]); + register_subalias("13", m_4.m_I[1]); register_subalias("11", m_4.m_Q[0]); } diff --git a/src/emu/netlist/devices/nld_7402.c b/src/emu/netlist/devices/nld_7402.c index 708dab04fcf..f64f5e4ba96 100644 --- a/src/emu/netlist/devices/nld_7402.c +++ b/src/emu/netlist/devices/nld_7402.c @@ -27,19 +27,19 @@ NETLIB_START(7402_dip) register_sub("4", m_4); register_subalias("1", m_1.m_Q[0]); - register_subalias("2", m_1.m_i[0]); - register_subalias("3", m_1.m_i[1]); + register_subalias("2", m_1.m_I[0]); + register_subalias("3", m_1.m_I[1]); register_subalias("4", m_2.m_Q[0]); - register_subalias("5", m_2.m_i[0]); - register_subalias("6", m_2.m_i[1]); + register_subalias("5", m_2.m_I[0]); + register_subalias("6", m_2.m_I[1]); - register_subalias("8", m_3.m_i[0]); - register_subalias("9", m_3.m_i[1]); + register_subalias("8", m_3.m_I[0]); + register_subalias("9", m_3.m_I[1]); register_subalias("10", m_3.m_Q[0]); - register_subalias("11", m_4.m_i[0]); - register_subalias("12", m_4.m_i[1]); + register_subalias("11", m_4.m_I[0]); + register_subalias("12", m_4.m_I[1]); register_subalias("13", m_4.m_Q[0]); } diff --git a/src/emu/netlist/devices/nld_7404.c b/src/emu/netlist/devices/nld_7404.c index 57050ac8cd8..8637da2fec6 100644 --- a/src/emu/netlist/devices/nld_7404.c +++ b/src/emu/netlist/devices/nld_7404.c @@ -7,10 +7,20 @@ #include "nld_7404.h" +#if 1 && (USE_TRUTHTABLE) +nld_7404::truthtable_t nld_7404::m_ttbl; +const char *nld_7404::m_desc[] = { + "A | Q ", + "0 | 1|22", + "1 | 0|15", + "" +}; +#else + NETLIB_START(7404) { - register_input("A", m_I); - register_output("Q", m_Q); + register_input("A", m_I[0]); + register_output("Q", m_Q[0]); } NETLIB_RESET(7404) @@ -19,10 +29,11 @@ NETLIB_RESET(7404) NETLIB_UPDATE(7404) { - static const netlist_time delay[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) }; - UINT8 t = (INPLOGIC(m_I)) ^ 1; - OUTLOGIC(m_Q, t, delay[t]); + /* static */ const netlist_time delay[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) }; + UINT8 t = (INPLOGIC(m_I[0])) ^ 1; + OUTLOGIC(m_Q[0], t, delay[t]); } +#endif NETLIB_START(7404_dip) { @@ -33,23 +44,23 @@ NETLIB_START(7404_dip) register_sub("5", m_5); register_sub("6", m_6); - register_subalias("1", m_1.m_I); - register_subalias("2", m_1.m_Q); + register_subalias("1", m_1.m_I[0]); + register_subalias("2", m_1.m_Q[0]); - register_subalias("3", m_2.m_I); - register_subalias("4", m_2.m_Q); + register_subalias("3", m_2.m_I[0]); + register_subalias("4", m_2.m_Q[0]); - register_subalias("5", m_3.m_I); - register_subalias("6", m_3.m_Q); + register_subalias("5", m_3.m_I[0]); + register_subalias("6", m_3.m_Q[0]); - register_subalias("8", m_4.m_Q); - register_subalias("9", m_4.m_I); + register_subalias("8", m_4.m_Q[0]); + register_subalias("9", m_4.m_I[0]); - register_subalias("10", m_5.m_Q); - register_subalias("11", m_5.m_I); + register_subalias("10", m_5.m_Q[0]); + register_subalias("11", m_5.m_I[0]); - register_subalias("12", m_6.m_Q); - register_subalias("13", m_6.m_I); + register_subalias("12", m_6.m_Q[0]); + register_subalias("13", m_6.m_I[0]); } NETLIB_UPDATE(7404_dip) diff --git a/src/emu/netlist/devices/nld_7404.h b/src/emu/netlist/devices/nld_7404.h index f74210bc958..0988d1d1e7c 100644 --- a/src/emu/netlist/devices/nld_7404.h +++ b/src/emu/netlist/devices/nld_7404.h @@ -32,11 +32,16 @@ #include "nld_signal.h" +#if 1 && (USE_TRUTHTABLE) +#include "nld_truthtable.h" +NETLIB_TRUTHTABLE(7404, 1, 1, 0); +#else NETLIB_DEVICE(7404, public: - netlist_logic_input_t m_I; - netlist_logic_output_t m_Q; + netlist_logic_input_t m_I[1]; + netlist_logic_output_t m_Q[1]; ); +#endif #define TTL_7404_INVERT(_name, _A) \ NET_REGISTER_DEV(7404, _name) \ diff --git a/src/emu/netlist/devices/nld_7408.c b/src/emu/netlist/devices/nld_7408.c index 4ecdc78469b..70cc8006f67 100644 --- a/src/emu/netlist/devices/nld_7408.c +++ b/src/emu/netlist/devices/nld_7408.c @@ -26,20 +26,20 @@ NETLIB_START(7408_dip) register_sub("3", m_3); register_sub("4", m_4); - register_subalias("1", m_1.m_i[0]); - register_subalias("2", m_1.m_i[1]); + register_subalias("1", m_1.m_I[0]); + register_subalias("2", m_1.m_I[1]); register_subalias("3", m_1.m_Q[0]); - register_subalias("4", m_2.m_i[0]); - register_subalias("5", m_2.m_i[1]); + register_subalias("4", m_2.m_I[0]); + register_subalias("5", m_2.m_I[1]); register_subalias("6", m_2.m_Q[0]); - register_subalias("9", m_3.m_i[0]); - register_subalias("10", m_3.m_i[1]); + register_subalias("9", m_3.m_I[0]); + register_subalias("10", m_3.m_I[1]); register_subalias("8", m_3.m_Q[0]); - register_subalias("12", m_4.m_i[0]); - register_subalias("13", m_4.m_i[1]); + register_subalias("12", m_4.m_I[0]); + register_subalias("13", m_4.m_I[1]); register_subalias("11", m_4.m_Q[0]); } diff --git a/src/emu/netlist/devices/nld_7410.c b/src/emu/netlist/devices/nld_7410.c index d920398c68b..05ad04f2b1c 100644 --- a/src/emu/netlist/devices/nld_7410.c +++ b/src/emu/netlist/devices/nld_7410.c @@ -27,20 +27,20 @@ NETLIB_START(7410_dip) register_sub("2", m_2); register_sub("3", m_3); - register_subalias("1", m_1.m_i[0]); - register_subalias("2", m_1.m_i[1]); - register_subalias("3", m_2.m_i[0]); - register_subalias("4", m_2.m_i[1]); - register_subalias("5", m_2.m_i[2]); + register_subalias("1", m_1.m_I[0]); + register_subalias("2", m_1.m_I[1]); + register_subalias("3", m_2.m_I[0]); + register_subalias("4", m_2.m_I[1]); + register_subalias("5", m_2.m_I[2]); register_subalias("6", m_2.m_Q[0]); register_subalias("8", m_3.m_Q[0]); - register_subalias("9", m_3.m_i[0]); - register_subalias("10", m_3.m_i[1]); - register_subalias("11", m_3.m_i[2]); + register_subalias("9", m_3.m_I[0]); + register_subalias("10", m_3.m_I[1]); + register_subalias("11", m_3.m_I[2]); register_subalias("12", m_1.m_Q[0]); - register_subalias("13", m_1.m_i[2]); + register_subalias("13", m_1.m_I[2]); } NETLIB_UPDATE(7410_dip) diff --git a/src/emu/netlist/devices/nld_7411.c b/src/emu/netlist/devices/nld_7411.c index 0664bd10c5c..3ac56fc11ef 100644 --- a/src/emu/netlist/devices/nld_7411.c +++ b/src/emu/netlist/devices/nld_7411.c @@ -25,20 +25,20 @@ NETLIB_START(7411_dip) register_sub("2", m_2); register_sub("3", m_3); - register_subalias("1", m_1.m_i[0]); - register_subalias("2", m_1.m_i[1]); - register_subalias("3", m_2.m_i[0]); - register_subalias("4", m_2.m_i[1]); - register_subalias("5", m_2.m_i[2]); + register_subalias("1", m_1.m_I[0]); + register_subalias("2", m_1.m_I[1]); + register_subalias("3", m_2.m_I[0]); + register_subalias("4", m_2.m_I[1]); + register_subalias("5", m_2.m_I[2]); register_subalias("6", m_2.m_Q[0]); register_subalias("8", m_3.m_Q[0]); - register_subalias("9", m_3.m_i[0]); - register_subalias("10", m_3.m_i[1]); - register_subalias("11", m_3.m_i[2]); + register_subalias("9", m_3.m_I[0]); + register_subalias("10", m_3.m_I[1]); + register_subalias("11", m_3.m_I[2]); register_subalias("12", m_1.m_Q[0]); - register_subalias("13", m_1.m_i[2]); + register_subalias("13", m_1.m_I[2]); } NETLIB_UPDATE(7411_dip) diff --git a/src/emu/netlist/devices/nld_74123.c b/src/emu/netlist/devices/nld_74123.c index 5d301558c2d..618f4735e26 100644 --- a/src/emu/netlist/devices/nld_74123.c +++ b/src/emu/netlist/devices/nld_74123.c @@ -42,11 +42,12 @@ NETLIB_START(74123) connect(m_RN.m_R.m_P, m_RP.m_R.m_N); connect(m_CV, m_RN.m_R.m_P); + m_KP = 1.0 / (1.0 + exp(m_K.Value())); + save(NLNAME(m_last_trig)); save(NLNAME(m_state)); save(NLNAME(m_KP)); - m_KP = 1.0 / (1.0 + exp(m_K.Value())); } NETLIB_UPDATE(74123) diff --git a/src/emu/netlist/devices/nld_74192.c b/src/emu/netlist/devices/nld_74192.c index 785b0d48094..2343ff2055b 100644 --- a/src/emu/netlist/devices/nld_74192.c +++ b/src/emu/netlist/devices/nld_74192.c @@ -42,7 +42,7 @@ NETLIB_RESET(74192) } // FIXME: Timing -static const netlist_time delay[4] = +/* static */ const netlist_time delay[4] = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(40), diff --git a/src/emu/netlist/devices/nld_7420.c b/src/emu/netlist/devices/nld_7420.c index 59e649fc6f6..e45b91397bc 100644 --- a/src/emu/netlist/devices/nld_7420.c +++ b/src/emu/netlist/devices/nld_7420.c @@ -25,19 +25,19 @@ NETLIB_START(7420_dip) register_sub("1", m_1); register_sub("2", m_2); - register_subalias("1", m_1.m_i[0]); - register_subalias("2", m_1.m_i[1]); + register_subalias("1", m_1.m_I[0]); + register_subalias("2", m_1.m_I[1]); - register_subalias("4", m_1.m_i[2]); - register_subalias("5", m_1.m_i[3]); + register_subalias("4", m_1.m_I[2]); + register_subalias("5", m_1.m_I[3]); register_subalias("6", m_1.m_Q[0]); register_subalias("8", m_2.m_Q[0]); - register_subalias("9", m_2.m_i[0]); - register_subalias("10", m_2.m_i[1]); + register_subalias("9", m_2.m_I[0]); + register_subalias("10", m_2.m_I[1]); - register_subalias("12", m_2.m_i[2]); - register_subalias("13", m_2.m_i[3]); + register_subalias("12", m_2.m_I[2]); + register_subalias("13", m_2.m_I[3]); } diff --git a/src/emu/netlist/devices/nld_7425.c b/src/emu/netlist/devices/nld_7425.c index 59bb899c56b..a46f544297e 100644 --- a/src/emu/netlist/devices/nld_7425.c +++ b/src/emu/netlist/devices/nld_7425.c @@ -12,23 +12,23 @@ NETLIB_START(7425_dip) register_sub("1", m_1); register_sub("2", m_2); - register_subalias("1", m_1.m_i[0]); - register_subalias("2", m_1.m_i[1]); + register_subalias("1", m_1.m_I[0]); + register_subalias("2", m_1.m_I[1]); //register_subalias("3", ); X1 ==> NC - register_subalias("4", m_1.m_i[2]); - register_subalias("5", m_1.m_i[3]); + register_subalias("4", m_1.m_I[2]); + register_subalias("5", m_1.m_I[3]); register_subalias("6", m_1.m_Q[0]); register_subalias("8", m_2.m_Q[0]); - register_subalias("9", m_2.m_i[0]); - register_subalias("10", m_2.m_i[1]); + register_subalias("9", m_2.m_I[0]); + register_subalias("10", m_2.m_I[1]); //register_subalias("11", ); X2 ==> NC - register_subalias("12", m_2.m_i[2]); - register_subalias("13", m_2.m_i[3]); + register_subalias("12", m_2.m_I[2]); + register_subalias("13", m_2.m_I[3]); } diff --git a/src/emu/netlist/devices/nld_7427.c b/src/emu/netlist/devices/nld_7427.c index a363ddd5f3c..6551ee1840b 100644 --- a/src/emu/netlist/devices/nld_7427.c +++ b/src/emu/netlist/devices/nld_7427.c @@ -27,20 +27,20 @@ NETLIB_START(7427_dip) register_sub("2", m_2); register_sub("3", m_3); - register_subalias("1", m_1.m_i[0]); - register_subalias("2", m_1.m_i[1]); - register_subalias("3", m_2.m_i[0]); - register_subalias("4", m_2.m_i[1]); - register_subalias("5", m_2.m_i[2]); + register_subalias("1", m_1.m_I[0]); + register_subalias("2", m_1.m_I[1]); + register_subalias("3", m_2.m_I[0]); + register_subalias("4", m_2.m_I[1]); + register_subalias("5", m_2.m_I[2]); register_subalias("6", m_2.m_Q[0]); register_subalias("8", m_3.m_Q[0]); - register_subalias("9", m_3.m_i[0]); - register_subalias("10", m_3.m_i[1]); - register_subalias("11", m_3.m_i[2]); + register_subalias("9", m_3.m_I[0]); + register_subalias("10", m_3.m_I[1]); + register_subalias("11", m_3.m_I[2]); register_subalias("12", m_1.m_Q[0]); - register_subalias("13", m_1.m_i[2]); + register_subalias("13", m_1.m_I[2]); } NETLIB_UPDATE(7427_dip) diff --git a/src/emu/netlist/devices/nld_74279.c b/src/emu/netlist/devices/nld_74279.c index 17fbc2e8b22..5740b59c6ed 100644 --- a/src/emu/netlist/devices/nld_74279.c +++ b/src/emu/netlist/devices/nld_74279.c @@ -125,23 +125,23 @@ NETLIB_START(74279_dip) register_sub("3", m_3); register_sub("4", m_4); - register_subalias("1", m_1.m_i[2]); //R - register_subalias("2", m_1.m_i[0]); - register_subalias("3", m_1.m_i[1]); + register_subalias("1", m_1.m_I[2]); //R + register_subalias("2", m_1.m_I[0]); + register_subalias("3", m_1.m_I[1]); register_subalias("4", m_1.m_Q[0]); - register_subalias("5", m_2.m_i[1]); //R - register_subalias("6", m_2.m_i[0]); + register_subalias("5", m_2.m_I[1]); //R + register_subalias("6", m_2.m_I[0]); register_subalias("7", m_2.m_Q[0]); register_subalias("9", m_3.m_Q[0]); - register_subalias("10", m_3.m_i[2]); //R - register_subalias("11", m_3.m_i[0]); - register_subalias("12", m_3.m_i[1]); + register_subalias("10", m_3.m_I[2]); //R + register_subalias("11", m_3.m_I[0]); + register_subalias("12", m_3.m_I[1]); register_subalias("13", m_4.m_Q[0]); - register_subalias("14", m_4.m_i[1]); //R - register_subalias("15", m_4.m_i[0]); + register_subalias("14", m_4.m_I[1]); //R + register_subalias("15", m_4.m_I[0]); } NETLIB_UPDATE(74279_dip) diff --git a/src/emu/netlist/devices/nld_7430.c b/src/emu/netlist/devices/nld_7430.c index 06d73997ad5..24d61d7b8ac 100644 --- a/src/emu/netlist/devices/nld_7430.c +++ b/src/emu/netlist/devices/nld_7430.c @@ -30,17 +30,17 @@ NETLIB_START(7430_dip) { register_sub("1", m_1); - register_subalias("1", m_1.m_i[0]); - register_subalias("2", m_1.m_i[1]); - register_subalias("3", m_1.m_i[2]); - register_subalias("4", m_1.m_i[3]); - register_subalias("5", m_1.m_i[4]); - register_subalias("6", m_1.m_i[5]); + register_subalias("1", m_1.m_I[0]); + register_subalias("2", m_1.m_I[1]); + register_subalias("3", m_1.m_I[2]); + register_subalias("4", m_1.m_I[3]); + register_subalias("5", m_1.m_I[4]); + register_subalias("6", m_1.m_I[5]); register_subalias("8", m_1.m_Q[0]); - register_subalias("11", m_1.m_i[6]); - register_subalias("12", m_1.m_i[7]); + register_subalias("11", m_1.m_I[6]); + register_subalias("12", m_1.m_I[7]); } NETLIB_UPDATE(7430_dip) diff --git a/src/emu/netlist/devices/nld_7432.c b/src/emu/netlist/devices/nld_7432.c index e3dda241be7..0e176a323fc 100644 --- a/src/emu/netlist/devices/nld_7432.c +++ b/src/emu/netlist/devices/nld_7432.c @@ -27,19 +27,19 @@ NETLIB_START(7432_dip) register_sub("4", m_4); register_subalias("3", m_1.m_Q[0]); - register_subalias("1", m_1.m_i[0]); - register_subalias("2", m_1.m_i[1]); + register_subalias("1", m_1.m_I[0]); + register_subalias("2", m_1.m_I[1]); register_subalias("6", m_2.m_Q[0]); - register_subalias("4", m_2.m_i[0]); - register_subalias("5", m_2.m_i[1]); + register_subalias("4", m_2.m_I[0]); + register_subalias("5", m_2.m_I[1]); - register_subalias("9", m_3.m_i[0]); - register_subalias("10", m_3.m_i[1]); + register_subalias("9", m_3.m_I[0]); + register_subalias("10", m_3.m_I[1]); register_subalias("8", m_3.m_Q[0]); - register_subalias("12", m_4.m_i[0]); - register_subalias("13", m_4.m_i[1]); + register_subalias("12", m_4.m_I[0]); + register_subalias("13", m_4.m_I[1]); register_subalias("11", m_4.m_Q[0]); } diff --git a/src/emu/netlist/devices/nld_7437.c b/src/emu/netlist/devices/nld_7437.c index ba078f81d11..f65c9fd016b 100644 --- a/src/emu/netlist/devices/nld_7437.c +++ b/src/emu/netlist/devices/nld_7437.c @@ -26,20 +26,20 @@ NETLIB_START(7437_dip) register_sub("3", m_3); register_sub("4", m_4); - register_subalias("1", m_1.m_i[0]); - register_subalias("2", m_1.m_i[1]); + register_subalias("1", m_1.m_I[0]); + register_subalias("2", m_1.m_I[1]); register_subalias("3", m_1.m_Q[0]); - register_subalias("4", m_2.m_i[0]); - register_subalias("5", m_2.m_i[1]); + register_subalias("4", m_2.m_I[0]); + register_subalias("5", m_2.m_I[1]); register_subalias("6", m_2.m_Q[0]); - register_subalias("9", m_3.m_i[0]); - register_subalias("10", m_3.m_i[1]); + register_subalias("9", m_3.m_I[0]); + register_subalias("10", m_3.m_I[1]); register_subalias("8", m_3.m_Q[0]); - register_subalias("12", m_4.m_i[0]); - register_subalias("13", m_4.m_i[1]); + register_subalias("12", m_4.m_I[0]); + register_subalias("13", m_4.m_I[1]); register_subalias("11", m_4.m_Q[0]); } diff --git a/src/emu/netlist/devices/nld_7448.c b/src/emu/netlist/devices/nld_7448.c index 7533449e8c5..3ee68f46c91 100644 --- a/src/emu/netlist/devices/nld_7448.c +++ b/src/emu/netlist/devices/nld_7448.c @@ -135,13 +135,11 @@ NETLIB_START(7448_sub) register_output("g", m_Q[6]); save(NLNAME(m_state)); - save(NLNAME(m_active)); } NETLIB_RESET(7448_sub) { m_state = 0; - m_active = 1; } NETLIB_UPDATE(7448_sub) diff --git a/src/emu/netlist/devices/nld_7448.h b/src/emu/netlist/devices/nld_7448.h index 676da1ac184..4cc3f346809 100644 --- a/src/emu/netlist/devices/nld_7448.h +++ b/src/emu/netlist/devices/nld_7448.h @@ -59,7 +59,6 @@ NETLIB_SUBDEVICE(7448_sub, netlist_logic_input_t m_RBIQ; UINT8 m_state; - int m_active; netlist_logic_output_t m_Q[7]; /* a .. g */ diff --git a/src/emu/netlist/devices/nld_7486.c b/src/emu/netlist/devices/nld_7486.c index e4009b22180..1e8de4bf744 100644 --- a/src/emu/netlist/devices/nld_7486.c +++ b/src/emu/netlist/devices/nld_7486.c @@ -7,11 +7,22 @@ #include "nld_7486.h" +#if (USE_TRUTHTABLE) +nld_7486::truthtable_t nld_7486::m_ttbl; +const char *nld_7486::m_desc[] = { + "A , B | Q ", + "0,0|0|15", + "0,1|1|22", + "1,0|1|22", + "1,1|0|15", + "" +}; +#else NETLIB_START(7486) { - register_input("A", m_A); - register_input("B", m_B); - register_output("Q", m_Q); + register_input("A", m_I[0]); + register_input("B", m_I[1]); + register_output("Q", m_Q[0]); save(NLNAME(m_active)); } @@ -25,10 +36,41 @@ NETLIB_UPDATE(7486) { const netlist_time delay[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) }; - UINT8 t = INPLOGIC(m_A) ^ INPLOGIC(m_B); - OUTLOGIC(m_Q, t, delay[t]); + UINT8 t = INPLOGIC(m_I[0]) ^ INPLOGIC(m_I[1]); + OUTLOGIC(m_Q[0], t, delay[t]); } +ATTR_HOT void NETLIB_NAME(7486)::inc_active() +{ + const netlist_time delay[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) }; + nl_assert(netlist().use_deactivate()); + if (++m_active == 1) + { + m_I[0].activate(); + m_I[1].activate(); + + netlist_time mt = this->m_I[0].net().time(); + if (this->m_I[1].net().time() > mt) + mt = this->m_I[1].net().time(); + + UINT8 t = INPLOGIC(m_I[0]) ^ INPLOGIC(m_I[1]); + m_Q[0].net().set_Q_time(t, mt + delay[t]); + } +} + +ATTR_HOT void NETLIB_NAME(7486)::dec_active() +{ +#if 1 + nl_assert(netlist().use_deactivate()); + if (--m_active == 0) + { + m_I[0].inactivate(); + m_I[1].inactivate(); + } +#endif +} +#endif + NETLIB_START(7486_dip) { register_sub("1", m_1); @@ -36,21 +78,21 @@ NETLIB_START(7486_dip) register_sub("3", m_3); register_sub("4", m_4); - register_subalias("1", m_1.m_A); - register_subalias("2", m_1.m_B); - register_subalias("3", m_1.m_Q); + register_subalias("1", m_1.m_I[0]); + register_subalias("2", m_1.m_I[1]); + register_subalias("3", m_1.m_Q[0]); - register_subalias("4", m_2.m_A); - register_subalias("5", m_2.m_B); - register_subalias("6", m_2.m_Q); + register_subalias("4", m_2.m_I[0]); + register_subalias("5", m_2.m_I[1]); + register_subalias("6", m_2.m_Q[0]); - register_subalias("9", m_3.m_A); - register_subalias("10", m_3.m_B); - register_subalias("8", m_3.m_Q); + register_subalias("9", m_3.m_I[0]); + register_subalias("10", m_3.m_I[1]); + register_subalias("8", m_3.m_Q[0]); - register_subalias("12", m_4.m_A); - register_subalias("13", m_4.m_B); - register_subalias("11", m_4.m_Q); + register_subalias("12", m_4.m_I[0]); + register_subalias("13", m_4.m_I[1]); + register_subalias("11", m_4.m_Q[0]); } NETLIB_UPDATE(7486_dip) @@ -70,32 +112,3 @@ NETLIB_RESET(7486_dip) m_4.do_reset(); } -ATTR_HOT void NETLIB_NAME(7486)::inc_active() -{ - const netlist_time delay[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) }; - nl_assert(netlist().use_deactivate()); - if (++m_active == 1) - { - m_A.activate(); - m_B.activate(); - - netlist_time mt = this->m_A.net().time(); - if (this->m_B.net().time() > mt) - mt = this->m_B.net().time(); - - UINT8 t = INPLOGIC(m_A) ^ INPLOGIC(m_B); - m_Q.net().set_Q_time(t, mt + delay[t]); - } -} - -ATTR_HOT void NETLIB_NAME(7486)::dec_active() -{ -#if 1 - nl_assert(netlist().use_deactivate()); - if (--m_active == 0) - { - m_A.inactivate(); - m_B.inactivate(); - } -#endif -} diff --git a/src/emu/netlist/devices/nld_7486.h b/src/emu/netlist/devices/nld_7486.h index 5febda494f9..e5ad2cb3be7 100644 --- a/src/emu/netlist/devices/nld_7486.h +++ b/src/emu/netlist/devices/nld_7486.h @@ -39,16 +39,20 @@ NET_CONNECT(_name, A, _A) \ NET_CONNECT(_name, B, _B) +#if (USE_TRUTHTABLE) +#include "nld_truthtable.h" +NETLIB_TRUTHTABLE(7486, 2, 1, 0); +#else NETLIB_DEVICE(7486, public: - netlist_logic_input_t m_A; - netlist_logic_input_t m_B; - netlist_logic_output_t m_Q; + netlist_logic_input_t m_I[2]; + netlist_logic_output_t m_Q[1]; ATTR_HOT void inc_active(); ATTR_HOT void dec_active(); int m_active; ); +#endif #define TTL_7486_DIP(_name) \ NET_REGISTER_DEV(7486_dip, _name) diff --git a/src/emu/netlist/devices/nld_7490.c b/src/emu/netlist/devices/nld_7490.c index 03317c96040..ec149da7fce 100644 --- a/src/emu/netlist/devices/nld_7490.c +++ b/src/emu/netlist/devices/nld_7490.c @@ -43,6 +43,9 @@ static const netlist_time delay[4] = NETLIB_UPDATE(7490) { + const netlist_sig_t new_A = INPLOGIC(m_A); + const netlist_sig_t new_B = INPLOGIC(m_B); + if (INPLOGIC(m_R91) & INPLOGIC(m_R92)) { m_cnt = 9; @@ -53,20 +56,23 @@ NETLIB_UPDATE(7490) m_cnt = 0; update_outputs(); } - else if (m_last_A && !INPLOGIC(m_A)) // High - Low - { - m_cnt ^= 1; - OUTLOGIC(m_Q[0], m_cnt & 1, delay[0]); - } - else if (m_last_B && !INPLOGIC(m_B)) // High - Low + else { - m_cnt += 2; - if (m_cnt >= 10) - m_cnt = 0; - update_outputs(); + if (m_last_A && !new_A) // High - Low + { + m_cnt ^= 1; + OUTLOGIC(m_Q[0], m_cnt & 1, delay[0]); + } + if (m_last_B && !new_B) // High - Low + { + m_cnt += 2; + if (m_cnt >= 10) + m_cnt &= 1; /* Output A is not reset! */ + update_outputs(); + } } - m_last_A = INPLOGIC(m_A); - m_last_B = INPLOGIC(m_B); + m_last_A = new_A; + m_last_B = new_B; } NETLIB_FUNC_VOID(7490, update_outputs, (void)) @@ -85,7 +91,7 @@ NETLIB_START(7490_dip) // register_subalias("4", ); --> NC // register_subalias("5", ); --> VCC register_subalias("6", m_R91); - register_subalias("7", m_R92); + register_subalias("7", m_R92); register_subalias("8", m_Q[2]); register_subalias("9", m_Q[1]); diff --git a/src/emu/netlist/devices/nld_7493.c b/src/emu/netlist/devices/nld_7493.c index 7f5be72fd6a..b558410d828 100644 --- a/src/emu/netlist/devices/nld_7493.c +++ b/src/emu/netlist/devices/nld_7493.c @@ -43,19 +43,24 @@ NETLIB_START(7493ff) register_output("Q", m_Q); save(NLNAME(m_reset)); + save(NLNAME(m_state)); } NETLIB_RESET(7493ff) { m_reset = 1; + m_state = 0; m_I.set_state(netlist_logic_t::STATE_INP_HL); } NETLIB_UPDATE(7493ff) { const netlist_time out_delay = NLTIME_FROM_NS(18); - //if (m_reset == 0) - OUTLOGIC(m_Q, (!m_Q.net().as_logic().new_Q()) & m_reset, out_delay); + if (m_reset != 0) + { + m_state ^= 1; + OUTLOGIC(m_Q, m_state, out_delay); + } } NETLIB_UPDATE(7493) @@ -71,6 +76,7 @@ NETLIB_UPDATE(7493) OUTLOGIC(C.m_Q, 0, NLTIME_FROM_NS(40)); OUTLOGIC(D.m_Q, 0, NLTIME_FROM_NS(40)); A.m_reset = B.m_reset = C.m_reset = D.m_reset = 0; + A.m_state = B.m_state = C.m_state = D.m_state = 0; } else { diff --git a/src/emu/netlist/devices/nld_7493.h b/src/emu/netlist/devices/nld_7493.h index 1cdb1594076..c78b7dce4dc 100644 --- a/src/emu/netlist/devices/nld_7493.h +++ b/src/emu/netlist/devices/nld_7493.h @@ -74,6 +74,7 @@ NETLIB_SUBDEVICE(7493ff, netlist_logic_output_t m_Q; UINT8 m_reset; + UINT8 m_state; ); NETLIB_DEVICE(7493, diff --git a/src/emu/netlist/devices/nld_82S16.c b/src/emu/netlist/devices/nld_82S16.c index a9f7b7c9072..1cf8d8e8182 100644 --- a/src/emu/netlist/devices/nld_82S16.c +++ b/src/emu/netlist/devices/nld_82S16.c @@ -7,8 +7,6 @@ #include "nld_82S16.h" -//static const netlist_time delay[2] = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(25) }; - // FIXME: timing! // FIXME: optimize device (separate address decoder!) NETLIB_UPDATE(82S16) diff --git a/src/emu/netlist/devices/nld_9310.c b/src/emu/netlist/devices/nld_9310.c index 42787be9157..29b941d4417 100644 --- a/src/emu/netlist/devices/nld_9310.c +++ b/src/emu/netlist/devices/nld_9310.c @@ -156,7 +156,7 @@ inline NETLIB_FUNC_VOID(9310_sub, update_outputs_all, (const UINT8 cnt, const ne inline NETLIB_FUNC_VOID(9310_sub, update_outputs, (const UINT8 cnt)) { - static const netlist_time out_delay = NLTIME_FROM_NS(20); + /* static */ const netlist_time out_delay = NLTIME_FROM_NS(20); #if 0 // for (int i=0; i<4; i++) // OUTLOGIC(m_Q[i], (cnt >> i) & 1, delay[i]); diff --git a/src/emu/netlist/devices/nld_9312.c b/src/emu/netlist/devices/nld_9312.c index a867ef6d986..06b6c3c5f62 100644 --- a/src/emu/netlist/devices/nld_9312.c +++ b/src/emu/netlist/devices/nld_9312.c @@ -59,7 +59,7 @@ NETLIB_UPDATE(9312) const UINT8 G = INPLOGIC(m_G); if (G) { - static const netlist_time delay[2] = { NLTIME_FROM_NS(33), NLTIME_FROM_NS(19) }; + /* static */ const netlist_time delay[2] = { NLTIME_FROM_NS(33), NLTIME_FROM_NS(19) }; OUTLOGIC(m_Y, 0, delay[0]); OUTLOGIC(m_YQ, 1, delay[1]); @@ -77,7 +77,7 @@ NETLIB_UPDATE(9312) m_B.activate(); m_C.activate(); } - static const netlist_time delay[2] = { NLTIME_FROM_NS(33), NLTIME_FROM_NS(28) }; + /* static */ const netlist_time delay[2] = { NLTIME_FROM_NS(33), NLTIME_FROM_NS(28) }; const UINT8 chan = INPLOGIC(m_A) | (INPLOGIC(m_B)<<1) | (INPLOGIC(m_C)<<2); if (m_last_chan != chan) { @@ -128,19 +128,19 @@ NETLIB_START(9312_dip) #if (1 && USE_TRUTHTABLE) - register_subalias("13", m_sub.m_i[0]); - register_subalias("12", m_sub.m_i[1]); - register_subalias("11", m_sub.m_i[2]); - register_subalias("10", m_sub.m_i[3]); - - register_subalias("1", m_sub.m_i[4]); - register_subalias("2", m_sub.m_i[5]); - register_subalias("3", m_sub.m_i[6]); - register_subalias("4", m_sub.m_i[7]); - register_subalias("5", m_sub.m_i[8]); - register_subalias("6", m_sub.m_i[9]); - register_subalias("7", m_sub.m_i[10]); - register_subalias("9", m_sub.m_i[11]); + register_subalias("13", m_sub.m_I[0]); + register_subalias("12", m_sub.m_I[1]); + register_subalias("11", m_sub.m_I[2]); + register_subalias("10", m_sub.m_I[3]); + + register_subalias("1", m_sub.m_I[4]); + register_subalias("2", m_sub.m_I[5]); + register_subalias("3", m_sub.m_I[6]); + register_subalias("4", m_sub.m_I[7]); + register_subalias("5", m_sub.m_I[8]); + register_subalias("6", m_sub.m_I[9]); + register_subalias("7", m_sub.m_I[10]); + register_subalias("9", m_sub.m_I[11]); register_subalias("15", m_sub.m_Q[0]); // Y register_subalias("14", m_sub.m_Q[1]); // YQ diff --git a/src/emu/netlist/devices/nld_9316.c b/src/emu/netlist/devices/nld_9316.c index ce5b05cfbf0..dd922af52e3 100644 --- a/src/emu/netlist/devices/nld_9316.c +++ b/src/emu/netlist/devices/nld_9316.c @@ -151,7 +151,7 @@ inline NETLIB_FUNC_VOID(9316_sub, update_outputs_all, (const UINT8 cnt, const ne inline NETLIB_FUNC_VOID(9316_sub, update_outputs, (const UINT8 cnt)) { - static const netlist_time out_delay = NLTIME_FROM_NS(20); + /* static */ const netlist_time out_delay = NLTIME_FROM_NS(20); #if 0 // for (int i=0; i<4; i++) // OUTLOGIC(m_Q[i], (cnt >> i) & 1, delay[i]); diff --git a/src/emu/netlist/devices/nld_legacy.c b/src/emu/netlist/devices/nld_legacy.c index 6eadf46ad64..ed4e384bc2a 100644 --- a/src/emu/netlist/devices/nld_legacy.c +++ b/src/emu/netlist/devices/nld_legacy.c @@ -59,15 +59,16 @@ NETLIB_UPDATE_PARAM(nicDelay) NETLIB_UPDATE(nicDelay) { - if (INPLOGIC(m_I) && !m_last) + netlist_sig_t nval = INPLOGIC(m_I); + if (nval && !m_last) { // L_to_H OUTLOGIC(m_Q, 1, NLTIME_FROM_NS(m_L_to_H.Value())); } - else if (!INPLOGIC(m_I) && m_last) + else if (!nval && m_last) { // H_to_L OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(m_H_to_L.Value())); } - m_last = INPLOGIC(m_I); + m_last = nval; } diff --git a/src/emu/netlist/devices/nld_signal.h b/src/emu/netlist/devices/nld_signal.h index 3f4bb331741..0dc84e7e549 100644 --- a/src/emu/netlist/devices/nld_signal.h +++ b/src/emu/netlist/devices/nld_signal.h @@ -18,7 +18,7 @@ class NETLIB_NAME(_name) : public net_signal_t<_num_input, _check, _invert> \ { \ public: \ - ATTR_COLD NETLIB_NAME(_name) () \ + NETLIB_NAME(_name) () \ : net_signal_t<_num_input, _check, _invert>() { } \ } @@ -35,19 +35,19 @@ public: { } - ATTR_COLD void start() + void start() { const char *sIN[8] = { "A", "B", "C", "D", "E", "F", "G", "H" }; register_output("Q", m_Q[0]); for (int i=0; i < _numdev; i++) { - register_input(sIN[i], m_i[i]); + register_input(sIN[i], m_I[i]); } save(NLNAME(m_active)); } - ATTR_COLD void reset() + void reset() { m_Q[0].initial(0); m_active = 1; @@ -57,13 +57,13 @@ public: { for (int i = 0; i< _numdev; i++) { - this->m_i[i].activate(); - if (INPLOGIC(this->m_i[i]) == _check) + this->m_I[i].activate(); + if (INPLOGIC(this->m_I[i]) == _check) { for (int j = 0; j < i; j++) - this->m_i[j].inactivate(); + this->m_I[j].inactivate(); for (int j = i + 1; j < _numdev; j++) - this->m_i[j].inactivate(); + this->m_I[j].inactivate(); return _check ^ (1 ^ _invert); } } @@ -80,8 +80,8 @@ public: netlist_time mt = netlist_time::zero; for (int i = 0; i< _numdev; i++) { - if (this->m_i[i].net().time() > mt) - mt = this->m_i[i].net().time(); + if (this->m_I[i].net().time() > mt) + mt = this->m_I[i].net().time(); } netlist_sig_t r = process(); m_Q[0].net().set_Q_time(r, mt + times[r]); @@ -94,7 +94,7 @@ public: if (--m_active == 0) { for (int i = 0; i< _numdev; i++) - m_i[i].inactivate(); + m_I[i].inactivate(); } } @@ -107,7 +107,7 @@ public: } public: - netlist_logic_input_t m_i[_numdev]; + netlist_logic_input_t m_I[_numdev]; netlist_logic_output_t m_Q[1]; INT32 m_active; }; diff --git a/src/emu/netlist/devices/nld_system.c b/src/emu/netlist/devices/nld_system.c index f97a0e14147..68057768bad 100644 --- a/src/emu/netlist/devices/nld_system.c +++ b/src/emu/netlist/devices/nld_system.c @@ -76,7 +76,7 @@ NETLIB_START(extclock) connect(m_feedback, m_Q); { netlist_time base = netlist_time::from_hz(m_freq.Value()*2); - nl_util::pstring_list pat = nl_util::split(m_pattern.Value(),","); + pstring_list_t pat(m_pattern.Value(),","); m_off = netlist_time::from_double(m_offset.Value()); int pati[256]; @@ -177,7 +177,7 @@ NETLIB_UPDATE_PARAM(analog_input) // nld_d_to_a_proxy // ---------------------------------------------------------------------------------------- -ATTR_COLD void nld_d_to_a_proxy::start() +void nld_d_to_a_proxy::start() { nld_base_d_to_a_proxy::start(); @@ -190,9 +190,11 @@ ATTR_COLD void nld_d_to_a_proxy::start() connect(m_RV.m_N, m_Q); m_Q.initial(0.0); + + save(NLNAME(m_last_state)); } -ATTR_COLD void nld_d_to_a_proxy::reset() +void nld_d_to_a_proxy::reset() { m_RV.do_reset(); m_is_timestep = m_RV.m_P.net().as_analog().solver()->is_timestep(); diff --git a/src/emu/netlist/devices/nld_system.h b/src/emu/netlist/devices/nld_system.h index f764f0027e6..2552ebe018b 100644 --- a/src/emu/netlist/devices/nld_system.h +++ b/src/emu/netlist/devices/nld_system.h @@ -44,19 +44,26 @@ #define DUMMY_INPUT(_name) \ NET_REGISTER_DEV(dummy_input, _name) -#define FRONTIER(_name, _IN, _OUT) \ +//FIXME: Usage discouraged, use OPTIMIZE_FRONTIER instead +#define FRONTIER_DEV(_name, _IN, _G, _OUT) \ NET_REGISTER_DEV(frontier, _name) \ NET_C(_IN, _name.I) \ + NET_C(_G, _name.G) \ NET_C(_OUT, _name.Q) +#define OPTIMIZE_FRONTIER(_attach, _r_in, _r_out) \ + setup.register_frontier(# _attach, _r_in, _r_out); + #define RES_SWITCH(_name, _IN, _P1, _P2) \ NET_REGISTER_DEV(res_sw, _name) \ NET_C(_IN, _name.I) \ NET_C(_P1, _name.1) \ NET_C(_P2, _name.2) + /* Default device to hold netlist parameters */ #define PARAMETERS(_name) \ NET_REGISTER_DEV(netlistparams, _name) + // ----------------------------------------------------------------------------- // mainclock // ----------------------------------------------------------------------------- @@ -133,23 +140,23 @@ NETLIB_DEVICE_WITH_PARAMS(analog_input, class NETLIB_NAME(gnd) : public netlist_device_t { public: - ATTR_COLD NETLIB_NAME(gnd)() + NETLIB_NAME(gnd)() : netlist_device_t(GND) { } - /* ATTR_COLD */ virtual ~NETLIB_NAME(gnd)() {} + virtual ~NETLIB_NAME(gnd)() {} protected: - ATTR_COLD void start() + void start() { register_output("Q", m_Q); } - ATTR_COLD void reset() + void reset() { } - ATTR_HOT void update() + void update() { OUTANALOG(m_Q, 0.0); } @@ -166,23 +173,23 @@ private: class NETLIB_NAME(dummy_input) : public netlist_device_t { public: - ATTR_COLD NETLIB_NAME(dummy_input)() + NETLIB_NAME(dummy_input)() : netlist_device_t(DUMMY) { } - /* ATTR_COLD */ virtual ~NETLIB_NAME(dummy_input)() {} + virtual ~NETLIB_NAME(dummy_input)() {} protected: - ATTR_COLD void start() + void start() { register_input("I", m_I); } - ATTR_COLD void reset() + void reset() { } - ATTR_HOT void update() + void update() { } @@ -198,32 +205,48 @@ private: class NETLIB_NAME(frontier) : public netlist_device_t { public: - ATTR_COLD NETLIB_NAME(frontier)() + NETLIB_NAME(frontier)() : netlist_device_t(DUMMY) { } - /* ATTR_COLD */ virtual ~NETLIB_NAME(frontier)() {} + virtual ~NETLIB_NAME(frontier)() {} protected: - ATTR_COLD void start() + void start() { - register_input("I", m_I); - register_output("Q", m_Q); + register_param("RIN", m_p_RIN, 1.0e6); + register_param("ROUT", m_p_ROUT, 50.0); + + register_input("_I", m_I); + register_terminal("I",m_RIN.m_P); + register_terminal("G",m_RIN.m_N); + connect(m_I, m_RIN.m_P); + + register_output("_Q", m_Q); + register_terminal("_OP",m_ROUT.m_P); + register_terminal("Q",m_ROUT.m_N); + connect(m_Q, m_ROUT.m_P); } - ATTR_COLD void reset() + void reset() { + m_RIN.set(1.0 / m_p_RIN.Value(),0,0); + m_ROUT.set(1.0 / m_p_ROUT.Value(),0,0); } - ATTR_HOT void update() + void update() { OUTANALOG(m_Q, INPANALOG(m_I)); } private: + NETLIB_NAME(twoterm) m_RIN; + NETLIB_NAME(twoterm) m_ROUT; netlist_analog_input_t m_I; netlist_analog_output_t m_Q; + netlist_param_double_t m_p_RIN; + netlist_param_double_t m_p_ROUT; }; // ----------------------------------------------------------------------------- @@ -233,10 +256,10 @@ private: class NETLIB_NAME(res_sw) : public netlist_device_t { public: - ATTR_COLD NETLIB_NAME(res_sw)() + NETLIB_NAME(res_sw)() : netlist_device_t() { } - /* ATTR_COLD */ virtual ~NETLIB_NAME(res_sw)() {} + virtual ~NETLIB_NAME(res_sw)() {} netlist_param_double_t m_RON; netlist_param_double_t m_ROFF; @@ -245,8 +268,8 @@ public: protected: - ATTR_COLD void start(); - ATTR_COLD void reset(); + void start(); + void reset(); ATTR_HOT void update(); ATTR_HOT void update_param(); @@ -261,22 +284,22 @@ private: class nld_base_proxy : public netlist_device_t { public: - ATTR_COLD nld_base_proxy(netlist_logic_t &inout_proxied, netlist_core_terminal_t &proxy_inout) + nld_base_proxy(netlist_logic_t *inout_proxied, netlist_core_terminal_t *proxy_inout) : netlist_device_t() { - m_logic_family = inout_proxied.logic_family(); - m_term_proxied = &inout_proxied; - m_proxy_term = &proxy_inout; + m_logic_family = inout_proxied->logic_family(); + m_term_proxied = inout_proxied; + m_proxy_term = proxy_inout; } - /* ATTR_COLD */ virtual ~nld_base_proxy() {} + virtual ~nld_base_proxy() {} - ATTR_COLD netlist_logic_t &term_proxied() const { return *m_term_proxied; } - ATTR_COLD netlist_core_terminal_t &proxy_term() const { return *m_proxy_term; } + netlist_logic_t &term_proxied() const { return *m_term_proxied; } + netlist_core_terminal_t &proxy_term() const { return *m_proxy_term; } protected: - /* ATTR_COLD */ virtual const netlist_logic_family_desc_t &logic_family() const + virtual const netlist_logic_family_desc_t &logic_family() const { return *m_logic_family; } @@ -294,24 +317,24 @@ private: class nld_a_to_d_proxy : public nld_base_proxy { public: - ATTR_COLD nld_a_to_d_proxy(netlist_logic_input_t &in_proxied) - : nld_base_proxy(in_proxied, m_I) + nld_a_to_d_proxy(netlist_logic_input_t *in_proxied) + : nld_base_proxy(in_proxied, &m_I) { } - /* ATTR_COLD */ virtual ~nld_a_to_d_proxy() {} + virtual ~nld_a_to_d_proxy() {} netlist_analog_input_t m_I; netlist_logic_output_t m_Q; protected: - ATTR_COLD void start() + void start() { register_input("I", m_I); register_output("Q", m_Q); } - ATTR_COLD void reset() + void reset() { } @@ -336,17 +359,17 @@ private: class nld_base_d_to_a_proxy : public nld_base_proxy { public: - ATTR_COLD nld_base_d_to_a_proxy(netlist_logic_output_t &out_proxied, netlist_core_terminal_t &proxy_out) - : nld_base_proxy(out_proxied, proxy_out) - { - } - - /* ATTR_COLD */ virtual ~nld_base_d_to_a_proxy() {} + virtual ~nld_base_d_to_a_proxy() {} - /* ATTR_COLD */ virtual netlist_logic_input_t &in() { return m_I; } + virtual netlist_logic_input_t &in() { return m_I; } protected: - /* ATTR_COLD */ virtual void start() + nld_base_d_to_a_proxy(netlist_logic_output_t *out_proxied, netlist_core_terminal_t &proxy_out) + : nld_base_proxy(out_proxied, &proxy_out) + { + } + + virtual void start() { register_input("I", m_I); } @@ -359,7 +382,7 @@ private: class nld_d_to_a_proxy : public nld_base_d_to_a_proxy { public: - ATTR_COLD nld_d_to_a_proxy(netlist_logic_output_t &out_proxied) + nld_d_to_a_proxy(netlist_logic_output_t *out_proxied) : nld_base_d_to_a_proxy(out_proxied, m_RV.m_P) , m_RV(TWOTERM) , m_last_state(-1) @@ -367,12 +390,12 @@ public: { } - /* ATTR_COLD */ virtual ~nld_d_to_a_proxy() {} + virtual ~nld_d_to_a_proxy() {} protected: - /* ATTR_COLD */ virtual void start(); + virtual void start(); - /* ATTR_COLD */ virtual void reset(); + virtual void reset(); ATTR_HOT void update(); diff --git a/src/emu/netlist/devices/nld_truthtable.c b/src/emu/netlist/devices/nld_truthtable.c index 85fc56ac34b..24c3e88285e 100644 --- a/src/emu/netlist/devices/nld_truthtable.c +++ b/src/emu/netlist/devices/nld_truthtable.c @@ -6,7 +6,7 @@ */ #include "nld_truthtable.h" -#include "../plists.h" +#include "../plib/plists.h" unsigned truthtable_desc_t::count_bits(UINT32 v) { @@ -97,7 +97,7 @@ UINT32 truthtable_desc_t::get_ignored_extended(UINT32 i) // desc // ---------------------------------------------------------------------------------------- -ATTR_COLD void truthtable_desc_t::help(unsigned cur, nl_util::pstring_list list, +void truthtable_desc_t::help(unsigned cur, pstring_list_t list, UINT64 state,UINT16 val, UINT8 *timing_index) { pstring elem = list[cur].trim(); @@ -142,15 +142,17 @@ ATTR_COLD void truthtable_desc_t::help(unsigned cur, nl_util::pstring_list list, } } -ATTR_COLD void truthtable_desc_t::setup(const char **truthtable, UINT32 disabled_ignore) +void truthtable_desc_t::setup(const pstring_list_t &truthtable, UINT32 disabled_ignore) { + unsigned line = 0; + if (*m_initialized) return; - pstring ttline = pstring(truthtable[0]); - truthtable++; - ttline = pstring(truthtable[0]); - truthtable++; + pstring ttline = truthtable[line]; + line++; + ttline = truthtable[line]; + line++; for (unsigned j=0; j < m_size; j++) m_outs[j] = ~0L; @@ -160,14 +162,14 @@ ATTR_COLD void truthtable_desc_t::setup(const char **truthtable, UINT32 disabled while (!ttline.equals("")) { - nl_util::pstring_list io = nl_util::split(ttline,"|"); + pstring_list_t io(ttline,"|"); // checks nl_assert_always(io.size() == 3, "io.count mismatch"); - nl_util::pstring_list inout = nl_util::split(io[0], ","); + pstring_list_t inout(io[0], ","); nl_assert_always(inout.size() == m_num_bits, "number of bits not matching"); - nl_util::pstring_list out = nl_util::split(io[1], ","); + pstring_list_t out(io[1], ","); nl_assert_always(out.size() == m_NO, "output count not matching"); - nl_util::pstring_list times = nl_util::split(io[2], ","); + pstring_list_t times(io[2], ","); nl_assert_always(times.size() == m_NO, "timing count not matching"); UINT16 val = 0; @@ -189,8 +191,8 @@ ATTR_COLD void truthtable_desc_t::setup(const char **truthtable, UINT32 disabled } help(0, inout, 0 , val, tindex.data()); - ttline = pstring(truthtable[0]); - truthtable++; + ttline = truthtable[line]; + line++; } // determine ignore @@ -233,3 +235,35 @@ ATTR_COLD void truthtable_desc_t::setup(const char **truthtable, UINT32 disabled *m_initialized = true; } + +#define ENTRYX(_n,_m,_h) case (_n * 1000 + _m * 10 + _h): \ + { typedef netlist_factory_truthtable_t<_n,_m,_h> xtype; \ + return palloc(xtype,name,classname,def_param); } break + +#define ENTRYY(_n,_m) ENTRYX(_n,_m,0); ENTRYX(_n,_m,1) + +#define ENTRY(_n) ENTRYY(_n, 1); ENTRYY(_n, 2); ENTRYY(_n, 3); ENTRYY(_n, 4); ENTRYY(_n, 5); ENTRYY(_n, 6) + +netlist_base_factory_truthtable_t *nl_tt_factory_create(const unsigned ni, const unsigned no, + const unsigned has_state, + const pstring &name, const pstring &classname, + const pstring &def_param) +{ + switch (ni * 1000 + no * 10 + has_state) + { + ENTRY(1); + ENTRY(2); + ENTRY(3); + ENTRY(4); + ENTRY(5); + ENTRY(6); + ENTRY(7); + ENTRY(8); + ENTRY(9); + ENTRY(10); + default: + pstring msg = pstring::sprintf("unable to create truthtable<%d,%d,%d>", ni, no, has_state); + nl_assert_always(false, msg.cstr()); + } + return NULL; +} diff --git a/src/emu/netlist/devices/nld_truthtable.h b/src/emu/netlist/devices/nld_truthtable.h index d12dd3c578b..615f8d6b9b6 100644 --- a/src/emu/netlist/devices/nld_truthtable.h +++ b/src/emu/netlist/devices/nld_truthtable.h @@ -11,6 +11,7 @@ #define NLD_TRUTHTABLE_H_ #include "../nl_base.h" +#include "../nl_factory.h" #define NETLIB_TRUTHTABLE(_name, _nIN, _nOUT, _state) \ class NETLIB_NAME(_name) : public nld_truthtable_t<_nIN, _nOUT, _state> \ @@ -44,10 +45,10 @@ struct truthtable_desc_t { } - ATTR_COLD void setup(const char **truthtable, UINT32 disabled_ignore); + void setup(const pstring_list_t &desc, UINT32 disabled_ignore); private: - ATTR_COLD void help(unsigned cur, nl_util::pstring_list list, + void help(unsigned cur, pstring_list_t list, UINT64 state,UINT16 val, UINT8 *timing_index); static unsigned count_bits(UINT32 v); static UINT32 set_bits(UINT32 v, UINT32 b); @@ -89,28 +90,40 @@ public: }; nld_truthtable_t(truthtable_t *ttbl, const char *desc[]) - : netlist_device_t(), m_last_state(0), m_ign(0), m_active(1), m_ttp(ttbl), m_desc(desc) + : netlist_device_t(), m_last_state(0), m_ign(0), m_active(1), m_ttp(ttbl) { + while (*desc != NULL && **desc != 0 ) + { + m_desc.add(*desc); + desc++; + } + + } + + nld_truthtable_t(truthtable_t *ttbl, const pstring_list_t &desc) + : netlist_device_t(), m_last_state(0), m_ign(0), m_active(1), m_ttp(ttbl) + { + m_desc = desc; } - /* ATTR_COLD */ virtual void start() + virtual void start() { - pstring ttline = pstring(m_desc[0]); + pstring header = m_desc[0]; - nl_util::pstring_list io = nl_util::split(ttline,"|"); + pstring_list_t io(header,"|"); // checks nl_assert_always(io.size() == 2, "too many '|'"); - nl_util::pstring_list inout = nl_util::split(io[0], ","); + pstring_list_t inout(io[0], ","); nl_assert_always(inout.size() == m_num_bits, "bitcount wrong"); - nl_util::pstring_list out = nl_util::split(io[1], ","); + pstring_list_t out(io[1], ","); nl_assert_always(out.size() == m_NO, "output count wrong"); - for (int i=0; i < m_NI; i++) + for (unsigned i=0; i < m_NI; i++) { inout[i] = inout[i].trim(); - register_input(inout[i], m_i[i]); + register_input(inout[i], m_I[i]); } - for (int i=0; i < m_NO; i++) + for (unsigned i=0; i < m_NO; i++) { out[i] = out[i].trim(); register_output(out[i], m_Q[i]); @@ -118,14 +131,14 @@ public: // Connect output "Q" to input "_Q" if this exists // This enables timed state without having explicit state .... UINT32 disabled_ignore = 0; - for (int i=0; i < m_NO; i++) + for (unsigned i=0; i < m_NO; i++) { pstring tmp = "_" + out[i]; const int idx = inout.indexof(tmp); if (idx>=0) { //printf("connecting %s %d\n", out[i].cstr(), idx); - connect(m_Q[i], m_i[idx]); + connect(m_Q[i], m_I[idx]); // disable ignore for this inputs altogether. // FIXME: This shouldn't be necessary disabled_ignore |= (1<<idx); @@ -144,66 +157,70 @@ public: for (int k=0; m_ttp->m_timing_nt[k] != netlist_time::zero; k++) printf("%d %f\n", k, m_ttp->m_timing_nt[k].as_double() * 1000000.0); #endif - // FIXME: save state save(NLNAME(m_last_state)); save(NLNAME(m_ign)); save(NLNAME(m_active)); - } - ATTR_COLD void reset() + void reset() { m_active = 0; - for (int i=0; i<m_NO;i++) + m_ign = 0; + for (unsigned i = 0; i < m_NI; i++) + m_I[i].activate(); + for (unsigned i=0; i<m_NO;i++) if (this->m_Q[i].net().num_cons()>0) m_active++; m_last_state = 0; } template<bool doOUT> - ATTR_HOT inline void process() + inline void process() { netlist_time mt = netlist_time::zero; UINT32 state = 0; for (unsigned i = 0; i < m_NI; i++) { - if (!doOUT || (m_ign & (1<<i)) != 0) - m_i[i].activate(); + if (!doOUT || (m_ign & (1<<i))) + m_I[i].activate(); } for (unsigned i = 0; i < m_NI; i++) { - state |= (INPLOGIC(m_i[i]) << i); + state |= (INPLOGIC(m_I[i]) << i); if (!doOUT) - if (this->m_i[i].net().time() > mt) - mt = this->m_i[i].net().time(); + if (this->m_I[i].net().time() > mt) + mt = this->m_I[i].net().time(); } const UINT32 nstate = state | (has_state ? (m_last_state << m_NI) : 0); - const UINT32 out = m_ttp->m_outs[nstate] & ((1 << m_NO) - 1); - m_ign = m_ttp->m_outs[nstate] >> m_NO; + const UINT32 outstate = m_ttp->m_outs[nstate]; + const UINT32 out = outstate & ((1 << m_NO) - 1); + m_ign = outstate >> m_NO; if (has_state) m_last_state = (state << m_NO) | out; #if 0 for (int i = 0; i < m_NI; i++) if (m_ign & (1 << i)) - m_i[i].inactivate(); + m_I[i].inactivate(); #endif const UINT32 timebase = nstate * m_NO; if (doOUT) { - for (int i = 0; i < m_NO; i++) + for (unsigned i = 0; i < m_NO; i++) OUTLOGIC(m_Q[i], (out >> i) & 1, m_ttp->m_timing_nt[m_ttp->m_timing[timebase + i]]); } else - for (int i = 0; i < m_NO; i++) + for (unsigned i = 0; i < m_NO; i++) m_Q[i].net().set_Q_time((out >> i) & 1, mt + m_ttp->m_timing_nt[m_ttp->m_timing[timebase + i]]); - for (int i = 0; i < m_NI; i++) - if (m_ign & (1 << i)) - m_i[i].inactivate(); - + if (m_NI > 1 || has_state) + { + for (unsigned i = 0; i < m_NI; i++) + if (m_ign & (1 << i)) + m_I[i].inactivate(); + } } ATTR_HOT void update() @@ -224,15 +241,24 @@ public: ATTR_HOT void dec_active() { nl_assert(netlist().use_deactivate()); + /* FIXME: + * Based on current measurements there is no point to disable + * 1 input devices. This should actually be a parameter so that we + * can decide for each individual gate whether it is benefitial to + * ignore deactivation. + */ + if (m_NI < 2) + return; if (has_state == 0) if (--m_active == 0) { - for (int i = 0; i< m_NI; i++) - m_i[i].inactivate(); + for (unsigned i = 0; i< m_NI; i++) + m_I[i].inactivate(); + m_ign = (1<<m_NI)-1; } } - netlist_logic_input_t m_i[m_NI]; + netlist_logic_input_t m_I[m_NI]; netlist_logic_output_t m_Q[m_NO]; private: @@ -242,10 +268,60 @@ private: INT32 m_active; truthtable_t *m_ttp; - const char **m_desc; + pstring_list_t m_desc; +}; + +class netlist_base_factory_truthtable_t : public netlist_base_factory_t +{ + NETLIST_PREVENT_COPYING(netlist_base_factory_truthtable_t) +public: + netlist_base_factory_truthtable_t(const pstring &name, const pstring &classname, + const pstring &def_param) + : netlist_base_factory_t(name, classname, def_param) + {} + pstring_list_t m_desc; +}; + + +template<unsigned m_NI, unsigned m_NO, int has_state> +class netlist_factory_truthtable_t : public netlist_base_factory_truthtable_t +{ + NETLIST_PREVENT_COPYING(netlist_factory_truthtable_t) +public: + netlist_factory_truthtable_t(const pstring &name, const pstring &classname, + const pstring &def_param) + : netlist_base_factory_truthtable_t(name, classname, def_param) { } + + netlist_device_t *Create() + { + typedef nld_truthtable_t<m_NI, m_NO, has_state> tt_type; + netlist_device_t *r = palloc(tt_type, &m_ttbl, m_desc); + //r->init(setup, name); + return r; + } +private: + typename nld_truthtable_t<m_NI, m_NO, has_state>::truthtable_t m_ttbl; }; +netlist_base_factory_truthtable_t *nl_tt_factory_create(const unsigned ni, const unsigned no, + const unsigned has_state, + const pstring &name, const pstring &classname, + const pstring &def_param); +#define TRUTHTABLE_START(_name, _in, _out, _has_state, _def_params) \ + { \ + netlist_base_factory_truthtable_t *ttd = nl_tt_factory_create(_in, _out, _has_state, \ + # _name, # _name, "+" _def_params); + +#define TT_HEAD(_x) \ + ttd->m_desc.add(_x); + +#define TT_LINE(_x) \ + ttd->m_desc.add(_x); + +#define TRUTHTABLE_END() \ + setup.factory().register_device(ttd); \ + } #endif /* NLD_TRUTHTABLE_H_ */ diff --git a/src/emu/netlist/nl_base.c b/src/emu/netlist/nl_base.c index 0a8da9fda8b..c8c59c37b7b 100644 --- a/src/emu/netlist/nl_base.c +++ b/src/emu/netlist/nl_base.c @@ -6,13 +6,13 @@ */ #include <cstring> +#include <algorithm> -#include "palloc.h" +#include "plib/palloc.h" #include "nl_base.h" #include "devices/nld_system.h" #include "analog/nld_solver.h" -#include "pstring.h" #include "nl_util.h" const netlist_time netlist_time::zero = netlist_time::from_raw(0); @@ -27,6 +27,7 @@ nl_fatalerror::nl_fatalerror(const char *format, ...) va_list ap; va_start(ap, format); m_text = pstring(format).vprintf(ap); + fprintf(stderr, "%s\n", m_text.cstr()); va_end(ap); } @@ -52,7 +53,7 @@ public: m_R_low = 1.0; m_R_high = 130.0; } - virtual nld_base_d_to_a_proxy *create_d_a_proxy(netlist_logic_output_t &proxied) const + virtual nld_base_d_to_a_proxy *create_d_a_proxy(netlist_logic_output_t *proxied) const { return palloc(nld_d_to_a_proxy , proxied); } @@ -72,7 +73,7 @@ public: m_R_low = 1.0; m_R_high = 130.0; } - virtual nld_base_d_to_a_proxy *create_d_a_proxy(netlist_logic_output_t &proxied) const + virtual nld_base_d_to_a_proxy *create_d_a_proxy(netlist_logic_output_t *proxied) const { return palloc(nld_d_to_a_proxy , proxied); } @@ -86,10 +87,12 @@ const netlist_logic_family_desc_t &netlist_family_CD4000 = netlist_logic_family_ // ---------------------------------------------------------------------------------------- netlist_queue_t::netlist_queue_t(netlist_base_t &nl) - : netlist_timed_queue<netlist_net_t *, netlist_time, 512>() + : netlist_timed_queue<netlist_net_t *, netlist_time>(512) , netlist_object_t(QUEUE, GENERIC) , pstate_callback_t() , m_qsize(0) + , m_times(512) + , m_names(512) { this->init_object(nl, "QUEUE"); } @@ -98,8 +101,8 @@ void netlist_queue_t::register_state(pstate_manager_t &manager, const pstring &m { NL_VERBOSE_OUT(("register_state\n")); manager.save_item(m_qsize, this, module + "." + "qsize"); - manager.save_item(m_times, this, module + "." + "times"); - manager.save_item(&(m_name[0][0]), this, module + "." + "names", sizeof(m_name)); + manager.save_item(&m_times[0], this, module + "." + "times", m_times.size()); + manager.save_item(&(m_names[0][0]), this, module + "." + "names", m_names.size() * 64); } void netlist_queue_t::on_pre_save() @@ -113,8 +116,8 @@ void netlist_queue_t::on_pre_save() pstring p = this->listptr()[i].object()->name(); int n = p.len(); n = std::min(63, n); - std::strncpy(&(m_name[i][0]), p, n); - m_name[i][n] = 0; + std::strncpy(&(m_names[i][0]), p, n); + m_names[i][n] = 0; } } @@ -125,9 +128,9 @@ void netlist_queue_t::on_post_load() NL_VERBOSE_OUT(("current time %f qsize %d\n", netlist().time().as_double(), m_qsize)); for (int i = 0; i < m_qsize; i++ ) { - netlist_net_t *n = netlist().find_net(&(m_name[i][0])); + netlist_net_t *n = netlist().find_net(&(m_names[i][0])); //NL_VERBOSE_OUT(("Got %s ==> %p\n", qtemp[i].m_name, n)); - //NL_VERBOSE_OUT(("schedule time %f (%f)\n", n->time().as_double(), qtemp[i].m_time.as_double())); + //NL_VERBOSE_OUT(("schedule time %f (%f)\n", n->time().as_double(), netlist_time::from_raw(m_times[i]).as_double())); this->push(netlist_queue_t::entry_t(netlist_time::from_raw(m_times[i]), n)); } } @@ -186,11 +189,11 @@ netlist_base_t::netlist_base_t() : netlist_object_t(NETLIST, GENERIC), pstate_manager_t(), m_stop(netlist_time::zero), m_time(netlist_time::zero), + m_use_deactivate(0), m_queue(*this), m_mainclock(NULL), m_solver(NULL), m_gnd(NULL), - m_use_deactivate(0), m_setup(NULL) { } @@ -282,6 +285,7 @@ ATTR_COLD netlist_net_t *netlist_base_t::find_net(const pstring &name) ATTR_COLD void netlist_base_t::rebuild_lists() { + //printf("Rebuild Lists\n"); for (std::size_t i = 0; i < m_nets.size(); i++) m_nets[i]->rebuild_list(); } @@ -420,15 +424,15 @@ ATTR_COLD void netlist_core_device_t::init(netlist_base_t &anetlist, const pstri set_logic_family(this->default_logic_family()); init_object(anetlist, name); -#if USE_PMFDELEGATES +#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF) void (netlist_core_device_t::* pFunc)() = &netlist_core_device_t::update; -#if NO_USE_PMFCONVERSION - static_update = pFunc; -#else - static_update = reinterpret_cast<net_update_delegate>((this->*pFunc)); -#endif + m_static_update = pFunc; +#elif (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) + void (netlist_core_device_t::* pFunc)() = &netlist_core_device_t::update; + m_static_update = reinterpret_cast<net_update_delegate>((this->*pFunc)); +#elif (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL) + m_static_update = pmfp::get_mfp<net_update_delegate>(&netlist_core_device_t::update, this); #endif - } ATTR_COLD netlist_core_device_t::~netlist_core_device_t() @@ -606,6 +610,7 @@ ATTR_HOT void netlist_net_t::inc_active(netlist_core_terminal_t &term) { m_active++; m_list_active.insert(term); + nl_assert(m_active <= num_cons()); if (m_active == 1) { if (netlist().use_deactivate()) @@ -634,6 +639,7 @@ ATTR_HOT void netlist_net_t::inc_active(netlist_core_terminal_t &term) ATTR_HOT void netlist_net_t::dec_active(netlist_core_terminal_t &term) { m_active--; + nl_assert(m_active >= 0); m_list_active.remove(term); if (m_active == 0 && netlist().use_deactivate()) railterminal().netdev().dec_active(); @@ -649,10 +655,17 @@ ATTR_COLD void netlist_net_t::rebuild_list() { /* rebuild m_list */ + unsigned cnt = 0; m_list_active.clear(); for (std::size_t i=0; i < m_core_terms.size(); i++) if (m_core_terms[i]->state() != netlist_logic_t::STATE_INP_PASSIVE) + { m_list_active.add(*m_core_terms[i]); + cnt++; + } + //if (cnt != m_active) + //printf("ARgh %s ==> %d != %d\n", name().cstr(), cnt, m_active); + m_active = cnt; } ATTR_COLD void netlist_net_t::save_register() @@ -666,7 +679,7 @@ ATTR_COLD void netlist_net_t::save_register() netlist_object_t::save_register(); } -ATTR_HOT inline void netlist_core_terminal_t::update_dev(const UINT32 mask) +ATTR_HOT /* inline */ void netlist_core_terminal_t::update_dev(const UINT32 mask) { inc_stat(netdev().stat_call_count); if ((state() & mask) != 0) @@ -675,17 +688,29 @@ ATTR_HOT inline void netlist_core_terminal_t::update_dev(const UINT32 mask) } } -ATTR_HOT inline void netlist_net_t::update_devs() +ATTR_HOT /* inline */ void netlist_net_t::update_devs() { //assert(m_num_cons != 0); nl_assert(this->isRailNet()); - const int masks[4] = { 1, 5, 3, 1 }; + const UINT32 masks[4] = { 1, 5, 3, 1 }; const UINT32 mask = masks[ (m_cur_Q << 1) | m_new_Q ]; m_in_queue = 2; /* mark as taken ... */ m_cur_Q = m_new_Q; +#if 0 + netlist_core_terminal_t * t[256]; + netlist_core_terminal_t *p = m_list_active.first(); + int cnt = 0; + while (p != NULL) + { + if ((p->state() & mask) != 0) + t[cnt++] = p; + p = m_list_active.next(p); + } + for (int i=0; i<cnt; i++) + t[i]->netdev().update_dev(); netlist_core_terminal_t *p = m_list_active.first(); while (p != NULL) @@ -693,6 +718,16 @@ ATTR_HOT inline void netlist_net_t::update_devs() p->update_dev(mask); p = m_list_active.next(p); } + +#else + netlist_core_terminal_t *p = m_list_active.first(); + + while (p != NULL) + { + p->update_dev(mask); + p = p->m_next; + } +#endif } ATTR_COLD void netlist_net_t::reset() @@ -737,6 +772,7 @@ ATTR_COLD void netlist_net_t::move_connections(netlist_net_t *dest_net) dest_net->register_con(*p); } m_core_terms.clear(); // FIXME: othernet needs to be free'd from memory + m_active = 0; } ATTR_COLD void netlist_net_t::merge_net(netlist_net_t *othernet) @@ -1057,7 +1093,7 @@ ATTR_COLD nl_double netlist_param_model_t::model_value(const pstring &entity, co // mainclock // ---------------------------------------------------------------------------------------- -ATTR_HOT inline void NETLIB_NAME(mainclock)::mc_update(netlist_logic_net_t &net) +ATTR_HOT /* inline */ void NETLIB_NAME(mainclock)::mc_update(netlist_logic_net_t &net) { net.toggle_new_Q(); net.update_devs(); @@ -1089,12 +1125,3 @@ NETLIB_UPDATE(mainclock) net.set_time(netlist().time() + m_inc); } -ATTR_HOT void netlist_base_t::push_to_queue(netlist_net_t &out, const netlist_time &attime) -{ - m_queue.push(netlist_queue_t::entry_t(attime, &out)); -} - -ATTR_HOT void netlist_base_t::remove_from_queue(netlist_net_t &out) -{ - m_queue.remove(&out); -} diff --git a/src/emu/netlist/nl_base.h b/src/emu/netlist/nl_base.h index a293ec95dd4..9b7059efb10 100644 --- a/src/emu/netlist/nl_base.h +++ b/src/emu/netlist/nl_base.h @@ -158,8 +158,7 @@ #include "nl_lists.h" #include "nl_time.h" #include "nl_util.h" -#include "pstring.h" -#include "pstate.h" +#include "plib/pstate.h" // ---------------------------------------------------------------------------------------- // Type definitions @@ -169,16 +168,6 @@ #define netlist_sig_t UINT8 -class netlist_core_device_t; - -#if USE_PMFDELEGATES -#if NO_USE_PMFCONVERSION -typedef void (netlist_core_device_t::*net_update_delegate)(); -#else -typedef void (*net_update_delegate)(netlist_core_device_t *); -#endif -#endif - //============================================================ // MACROS / netlist devices //============================================================ @@ -251,7 +240,7 @@ typedef void (*net_update_delegate)(netlist_core_device_t *); , _priv) #define NETLIB_LOGIC_FAMILY(_fam) \ -/* ATTR_COLD */ virtual const netlist_logic_family_desc_t *default_logic_family() \ +virtual const netlist_logic_family_desc_t *default_logic_family() \ { \ return &netlist_family_ ## _fam; \ } @@ -267,7 +256,7 @@ public: nl_fatalerror(const char *format, va_list ap); virtual ~nl_fatalerror() throw() {} - /* inline */ const pstring &text() { return m_text; } + const pstring &text() { return m_text; } private: pstring m_text; }; @@ -276,7 +265,7 @@ private: // Asserts //============================================================ -#ifdef MAME_DEBUG +#if defined(MAME_DEBUG) #define nl_assert(x) do { if (!(x)) throw nl_fatalerror("assert: %s:%d: %s", __FILE__, __LINE__, #x); } while (0) #else #define nl_assert(x) do { if (0) if (!(x)) throw nl_fatalerror("assert: %s:%d: %s", __FILE__, __LINE__, #x); } while (0) @@ -292,10 +281,10 @@ class netlist_logic_output_t; class netlist_analog_net_t; class netlist_logic_net_t; class netlist_net_t; -class netlist_param_t; class netlist_setup_t; class netlist_base_t; class netlist_matrix_solver_t; +class netlist_core_device_t; class NETLIB_NAME(gnd); class NETLIB_NAME(solver); @@ -313,7 +302,7 @@ class netlist_logic_family_desc_t { public: virtual ~netlist_logic_family_desc_t() {} - virtual nld_base_d_to_a_proxy *create_d_a_proxy(netlist_logic_output_t &proxied) const = 0; + virtual nld_base_d_to_a_proxy *create_d_a_proxy(netlist_logic_output_t *proxied) const = 0; nl_double m_low_thresh_V; nl_double m_high_thresh_V; @@ -329,7 +318,7 @@ public: netlist_logic_family_t() : m_logic_family(NULL) {} - ATTR_HOT /* inline */ const netlist_logic_family_desc_t *logic_family() const { return m_logic_family; } + ATTR_HOT const netlist_logic_family_desc_t *logic_family() const { return m_logic_family; } ATTR_COLD void set_logic_family(const netlist_logic_family_desc_t *fam) { m_logic_family = fam; } private: @@ -396,25 +385,25 @@ public: PSTATE_INTERFACE_DECL() - ATTR_HOT /* inline */ type_t type() const { return m_objtype; } - ATTR_HOT /* inline */ family_t family() const { return m_family; } + ATTR_HOT type_t type() const { return m_objtype; } + ATTR_HOT family_t family() const { return m_family; } - ATTR_HOT /* inline */ bool isType(const type_t atype) const { return (m_objtype == atype); } - ATTR_HOT /* inline */ bool isFamily(const family_t afamily) const { return (m_family == afamily); } + ATTR_HOT bool isType(const type_t atype) const { return (m_objtype == atype); } + ATTR_HOT bool isFamily(const family_t afamily) const { return (m_family == afamily); } - ATTR_HOT /* inline */ netlist_base_t & netlist() { return *m_netlist; } - ATTR_HOT /* inline */ const netlist_base_t & netlist() const { return *m_netlist; } + ATTR_HOT netlist_base_t & netlist() { return *m_netlist; } + ATTR_HOT const netlist_base_t & netlist() const { return *m_netlist; } - ATTR_COLD void /* inline */ do_reset() + ATTR_COLD void do_reset() { reset(); } protected: - /* ATTR_COLD */ virtual void reset() = 0; + virtual void reset() = 0; // must call parent save_register ! - /* ATTR_COLD */ virtual void save_register() { }; + virtual void save_register() { }; private: pstring m_name; @@ -435,7 +424,7 @@ public: ATTR_COLD void init_object(netlist_core_device_t &dev, const pstring &aname); - ATTR_HOT /* inline */ netlist_core_device_t &netdev() const { return *m_netdev; } + ATTR_HOT netlist_core_device_t &netdev() const { return *m_netdev; } private: netlist_core_device_t * m_netdev; }; @@ -468,25 +457,25 @@ public: //ATTR_COLD void init_object(netlist_core_device_t &dev, const pstring &aname); ATTR_COLD void set_net(netlist_net_t &anet); - ATTR_COLD /* inline */ void clear_net() { m_net = NULL; } - ATTR_HOT /* inline */ bool has_net() const { return (m_net != NULL); } + ATTR_COLD void clear_net() { m_net = NULL; } + ATTR_HOT bool has_net() const { return (m_net != NULL); } - ATTR_HOT /* inline */ const netlist_net_t & net() const { return *m_net;} - ATTR_HOT /* inline */ netlist_net_t & net() { return *m_net;} + ATTR_HOT const netlist_net_t & net() const { return *m_net;} + ATTR_HOT netlist_net_t & net() { return *m_net;} - ATTR_HOT /* inline */ bool is_state(const state_e astate) const { return (m_state == astate); } - ATTR_HOT /* inline */ state_e state() const { return m_state; } - ATTR_HOT /* inline */ void set_state(const state_e astate) + ATTR_HOT bool is_state(const state_e astate) const { return (m_state == astate); } + ATTR_HOT state_e state() const { return m_state; } + ATTR_HOT void set_state(const state_e astate) { nl_assert(astate != STATE_NONEX); m_state = astate; } - /* inline only intended to be called from nl_base.c */ + ATTR_HOT /* inline */ void update_dev(const UINT32 mask); protected: - /* ATTR_COLD */ virtual void save_register() + virtual void save_register() { save(NLNAME(m_state)); netlist_owned_object_t::save_register(); @@ -513,21 +502,21 @@ public: nl_double *m_go1; // conductance for Voltage from other term nl_double *m_gt1; // conductance for total conductance - ATTR_HOT /* inline */ void set(const nl_double G) + ATTR_HOT void set(const nl_double G) { set_ptr(m_Idr1, 0); set_ptr(m_go1, G); set_ptr(m_gt1, G); } - ATTR_HOT /* inline */ void set(const nl_double GO, const nl_double GT) + ATTR_HOT void set(const nl_double GO, const nl_double GT) { set_ptr(m_Idr1, 0); set_ptr(m_go1, GO); set_ptr(m_gt1, GT); } - ATTR_HOT /* inline */ void set(const nl_double GO, const nl_double GT, const nl_double I) + ATTR_HOT void set(const nl_double GO, const nl_double GT, const nl_double I) { set_ptr(m_Idr1, I); set_ptr(m_go1, GO); @@ -540,11 +529,11 @@ public: netlist_terminal_t *m_otherterm; protected: - /* ATTR_COLD */ virtual void save_register(); + virtual void save_register(); - /* ATTR_COLD */ virtual void reset(); + virtual void reset(); private: - ATTR_HOT /* inline */ void set_ptr(nl_double *ptr, const nl_double val) + ATTR_HOT void set_ptr(nl_double *ptr, const nl_double val) { if (ptr != NULL && *ptr != val) { @@ -607,16 +596,16 @@ public: set_state(STATE_INP_ACTIVE); } - ATTR_HOT /* inline */ netlist_sig_t Q() const; - ATTR_HOT /* inline */ netlist_sig_t last_Q() const; + ATTR_HOT netlist_sig_t Q() const; + ATTR_HOT netlist_sig_t last_Q() const; - ATTR_HOT /* inline */ void inactivate(); - ATTR_HOT /* inline */ void activate(); - ATTR_HOT /* inline */ void activate_hl(); - ATTR_HOT /* inline */ void activate_lh(); + ATTR_HOT void inactivate(); + ATTR_HOT void activate(); + ATTR_HOT void activate_hl(); + ATTR_HOT void activate_lh(); protected: - /* ATTR_COLD */ virtual void reset() + virtual void reset() { //netlist_core_terminal_t::reset(); set_state(STATE_INP_ACTIVE); @@ -637,10 +626,10 @@ public: set_state(STATE_INP_ACTIVE); } - ATTR_HOT /* inline */ nl_double Q_Analog() const; + ATTR_HOT nl_double Q_Analog() const; protected: - /* ATTR_COLD */ virtual void reset() + virtual void reset() { //netlist_core_terminal_t::reset(); set_state(STATE_INP_ACTIVE); @@ -659,7 +648,7 @@ public: typedef plist_t<netlist_net_t *> list_t; ATTR_COLD netlist_net_t(const family_t afamily); - /* ATTR_COLD */ virtual ~netlist_net_t(); + virtual ~netlist_net_t(); ATTR_COLD void init_object(netlist_base_t &nl, const pstring &aname); @@ -667,25 +656,25 @@ public: ATTR_COLD void merge_net(netlist_net_t *othernet); ATTR_COLD void register_railterminal(netlist_core_terminal_t &mr); - ATTR_HOT /* inline */ netlist_logic_net_t & as_logic(); - ATTR_HOT /* inline */ const netlist_logic_net_t & as_logic() const; + ATTR_HOT netlist_logic_net_t & as_logic(); + ATTR_HOT const netlist_logic_net_t & as_logic() const; - ATTR_HOT /* inline */ netlist_analog_net_t & as_analog(); - ATTR_HOT /* inline */ const netlist_analog_net_t & as_analog() const; + ATTR_HOT netlist_analog_net_t & as_analog(); + ATTR_HOT const netlist_analog_net_t & as_analog() const; ATTR_HOT void update_devs(); - ATTR_HOT /* inline */ const netlist_time &time() const { return m_time; } - ATTR_HOT /* inline */ void set_time(const netlist_time &ntime) { m_time = ntime; } + ATTR_HOT const netlist_time &time() const { return m_time; } + ATTR_HOT void set_time(const netlist_time &ntime) { m_time = ntime; } - ATTR_HOT /* inline */ bool isRailNet() const { return !(m_railterminal == NULL); } - ATTR_HOT /* inline */ netlist_core_terminal_t & railterminal() const { return *m_railterminal; } + ATTR_HOT bool isRailNet() const { return !(m_railterminal == NULL); } + ATTR_HOT netlist_core_terminal_t & railterminal() const { return *m_railterminal; } - ATTR_HOT /* inline */ void push_to_queue(const netlist_time &delay); - ATTR_HOT /* inline */ void reschedule_in_queue(const netlist_time &delay); - ATTR_HOT bool /* inline */ is_queued() const { return m_in_queue == 1; } + ATTR_HOT void push_to_queue(const netlist_time &delay); + ATTR_HOT void reschedule_in_queue(const netlist_time &delay); + ATTR_HOT bool is_queued() const { return m_in_queue == 1; } - ATTR_HOT /* inline */ int num_cons() const { return m_core_terms.size(); } + ATTR_HOT int num_cons() const { return m_core_terms.size(); } ATTR_HOT void inc_active(netlist_core_terminal_t &term); ATTR_HOT void dec_active(netlist_core_terminal_t &term); @@ -696,7 +685,7 @@ public: plist_t<netlist_core_terminal_t *> m_core_terms; // save post-start m_list ... - ATTR_HOT /* inline */ void set_Q_time(const netlist_sig_t &newQ, const netlist_time &at) + ATTR_HOT void set_Q_time(const netlist_sig_t &newQ, const netlist_time &at) { if (newQ != m_new_Q) { @@ -708,8 +697,8 @@ public: protected: //FIXME: needed by current solver code - /* ATTR_COLD */ virtual void save_register(); - /* ATTR_COLD */ virtual void reset(); + virtual void save_register(); + virtual void reset(); netlist_sig_t m_new_Q; netlist_sig_t m_cur_Q; @@ -739,19 +728,19 @@ public: typedef plist_t<netlist_logic_net_t *> list_t; ATTR_COLD netlist_logic_net_t(); - /* ATTR_COLD */ virtual ~netlist_logic_net_t() { }; + virtual ~netlist_logic_net_t() { }; - ATTR_HOT /* inline */ netlist_sig_t Q() const + ATTR_HOT netlist_sig_t Q() const { return m_cur_Q; } - ATTR_HOT /* inline */ netlist_sig_t new_Q() const + ATTR_HOT netlist_sig_t new_Q() const { return m_new_Q; } - ATTR_HOT /* inline */ void set_Q(const netlist_sig_t &newQ, const netlist_time &delay) + ATTR_HOT void set_Q(const netlist_sig_t &newQ, const netlist_time &delay) { if (newQ != m_new_Q) { @@ -760,7 +749,7 @@ public: } } - ATTR_HOT /* inline */ void toggle_new_Q() + ATTR_HOT void toggle_new_Q() { m_new_Q ^= 1; } @@ -774,15 +763,15 @@ public: /* internal state support * FIXME: get rid of this and implement export/import in MAME */ - ATTR_COLD /* inline */ netlist_sig_t &Q_state_ptr() + ATTR_COLD netlist_sig_t &Q_state_ptr() { return m_cur_Q; } protected: //FIXME: needed by current solver code - /* ATTR_COLD */ virtual void save_register(); - /* ATTR_COLD */ virtual void reset(); + virtual void save_register(); + virtual void reset(); private: @@ -799,27 +788,27 @@ public: typedef plist_t<netlist_analog_net_t *> list_t; ATTR_COLD netlist_analog_net_t(); - /* ATTR_COLD */ virtual ~netlist_analog_net_t() { }; + virtual ~netlist_analog_net_t() { }; - ATTR_HOT /* inline */ nl_double Q_Analog() const + ATTR_HOT nl_double Q_Analog() const { return m_cur_Analog; } - ATTR_COLD /* inline */ nl_double &Q_Analog_state_ptr() + ATTR_COLD nl_double &Q_Analog_state_ptr() { return m_cur_Analog; } - ATTR_HOT /* inline */ netlist_matrix_solver_t *solver() { return m_solver; } + ATTR_HOT netlist_matrix_solver_t *solver() { return m_solver; } ATTR_COLD bool already_processed(list_t *groups, int cur_group); ATTR_COLD void process_net(list_t *groups, int &cur_group); protected: - /* ATTR_COLD */ virtual void save_register(); - /* ATTR_COLD */ virtual void reset(); + virtual void save_register(); + virtual void reset(); private: @@ -844,14 +833,14 @@ public: ATTR_COLD netlist_logic_output_t(); ATTR_COLD void init_object(netlist_core_device_t &dev, const pstring &aname); - /* ATTR_COLD */ virtual void reset() + virtual void reset() { set_state(STATE_OUT); } ATTR_COLD void initial(const netlist_sig_t val); - ATTR_HOT /* inline */ void set_Q(const netlist_sig_t newQ, const netlist_time &delay) + ATTR_HOT void set_Q(const netlist_sig_t newQ, const netlist_time &delay) { net().as_logic().set_Q(newQ, delay); } @@ -868,14 +857,14 @@ public: ATTR_COLD netlist_analog_output_t(); ATTR_COLD void init_object(netlist_core_device_t &dev, const pstring &aname); - /* ATTR_COLD */ virtual void reset() + virtual void reset() { set_state(STATE_OUT); } ATTR_COLD void initial(const nl_double val); - ATTR_HOT /* inline */ void set_Q(const nl_double newQ); + ATTR_HOT void set_Q(const nl_double newQ); netlist_analog_net_t *m_proxied_net; // only for proxy nets in analog input logic @@ -902,11 +891,11 @@ public: ATTR_COLD netlist_param_t(const param_type_t atype); - ATTR_HOT /* inline */ param_type_t param_type() const { return m_param_type; } + ATTR_HOT param_type_t param_type() const { return m_param_type; } protected: - /* ATTR_COLD */ virtual void reset() { } + virtual void reset() { } private: const param_type_t m_param_type; @@ -918,12 +907,12 @@ class netlist_param_double_t : public netlist_param_t public: ATTR_COLD netlist_param_double_t(); - ATTR_HOT /* inline */ void setTo(const nl_double param); - ATTR_COLD /* inline */ void initial(const nl_double val) { m_param = val; } - ATTR_HOT /* inline */ nl_double Value() const { return m_param; } + ATTR_HOT void setTo(const nl_double param); + ATTR_COLD void initial(const nl_double val) { m_param = val; } + ATTR_HOT nl_double Value() const { return m_param; } protected: - /* ATTR_COLD */ virtual void save_register() + virtual void save_register() { save(NLNAME(m_param)); netlist_param_t::save_register(); @@ -939,13 +928,13 @@ class netlist_param_int_t : public netlist_param_t public: ATTR_COLD netlist_param_int_t(); - ATTR_HOT /* inline */ void setTo(const int param); - ATTR_COLD /* inline */ void initial(const int val) { m_param = val; } + ATTR_HOT void setTo(const int param); + ATTR_COLD void initial(const int val) { m_param = val; } - ATTR_HOT /* inline */ int Value() const { return m_param; } + ATTR_HOT int Value() const { return m_param; } protected: - /* ATTR_COLD */ virtual void save_register() + virtual void save_register() { save(NLNAME(m_param)); netlist_param_t::save_register(); @@ -968,10 +957,10 @@ class netlist_param_str_t : public netlist_param_t public: ATTR_COLD netlist_param_str_t(); - ATTR_HOT /* inline */ void setTo(const pstring ¶m); - ATTR_COLD /* inline */ void initial(const pstring &val) { m_param = val; } + ATTR_HOT void setTo(const pstring ¶m); + ATTR_COLD void initial(const pstring &val) { m_param = val; } - ATTR_HOT /* inline */ const pstring &Value() const { return m_param; } + ATTR_HOT const pstring &Value() const { return m_param; } private: pstring m_param; @@ -983,9 +972,9 @@ class netlist_param_model_t : public netlist_param_t public: ATTR_COLD netlist_param_model_t(); - ATTR_COLD /* inline */ void initial(const pstring &val) { m_param = val; } + ATTR_COLD void initial(const pstring &val) { m_param = val; } - ATTR_HOT /* inline */ const pstring &Value() const { return m_param; } + ATTR_HOT const pstring &Value() const { return m_param; } /* these should be cached! */ ATTR_COLD nl_double model_value(const pstring &entity, const nl_double defval = 0.0) const; @@ -1008,21 +997,20 @@ public: ATTR_COLD netlist_core_device_t(const family_t afamily); - /* ATTR_COLD */ virtual ~netlist_core_device_t(); + virtual ~netlist_core_device_t(); - /* ATTR_COLD */ virtual void init(netlist_base_t &anetlist, const pstring &name); + virtual void init(netlist_base_t &anetlist, const pstring &name); ATTR_HOT virtual void update_param() {} - ATTR_HOT /* inline */ void update_dev() + ATTR_HOT void update_dev() { begin_timing(stat_total_time); inc_stat(stat_update_count); -#if USE_PMFDELEGATES -#if NO_USE_PMFCONVERSION - (this->*static_update)(); -#else - static_update(this); -#endif + +#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF) + (this->*m_static_update)(); +#elif ((NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) || (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL)) + m_static_update(this); #else update(); #endif @@ -1033,22 +1021,23 @@ public: ATTR_HOT netlist_sig_t INPLOGIC_PASSIVE(netlist_logic_input_t &inp); - ATTR_HOT /* inline */ netlist_sig_t INPLOGIC(const netlist_logic_input_t &inp) const + ATTR_HOT netlist_sig_t INPLOGIC(const netlist_logic_input_t &inp) const { + //printf("%s %d\n", inp.name().cstr(), inp.state()); nl_assert(inp.state() != netlist_logic_t::STATE_INP_PASSIVE); return inp.Q(); } - ATTR_HOT /* inline */ void OUTLOGIC(netlist_logic_output_t &out, const netlist_sig_t val, const netlist_time &delay) + ATTR_HOT void OUTLOGIC(netlist_logic_output_t &out, const netlist_sig_t val, const netlist_time &delay) { out.set_Q(val, delay); } - ATTR_HOT /* inline */ nl_double INPANALOG(const netlist_analog_input_t &inp) const { return inp.Q_Analog(); } + ATTR_HOT nl_double INPANALOG(const netlist_analog_input_t &inp) const { return inp.Q_Analog(); } - ATTR_HOT /* inline */ nl_double TERMANALOG(const netlist_terminal_t &term) const { return term.net().as_analog().Q_Analog(); } + ATTR_HOT nl_double TERMANALOG(const netlist_terminal_t &term) const { return term.net().as_analog().Q_Analog(); } - ATTR_HOT /* inline */ void OUTANALOG(netlist_analog_output_t &out, const nl_double val) + ATTR_HOT void OUTANALOG(netlist_analog_output_t &out, const nl_double val) { out.set_Q(val); } @@ -1060,8 +1049,6 @@ public: ATTR_HOT virtual void step_time(ATTR_UNUSED const nl_double st) { } ATTR_HOT virtual void update_terminals() { } - - #if (NL_KEEP_STATISTICS) /* stats */ osd_ticks_t stat_total_time; @@ -1069,21 +1056,27 @@ public: INT32 stat_call_count; #endif -#if USE_PMFDELEGATES - net_update_delegate static_update; -#endif - protected: ATTR_HOT virtual void update() { } - /* ATTR_COLD */ virtual void start() { } - /* ATTR_COLD */ virtual void stop() { } \ - /* ATTR_COLD */ virtual const netlist_logic_family_desc_t *default_logic_family() + virtual void start() { } + virtual void stop() { } \ + virtual const netlist_logic_family_desc_t *default_logic_family() { return &netlist_family_TTL; } private: + + #if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF) + typedef void (netlist_core_device_t::*net_update_delegate)(); + #elif ((NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) || (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL)) + typedef MEMBER_ABI void (*net_update_delegate)(netlist_core_device_t *); + #endif + +#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL) + net_update_delegate m_static_update; +#endif }; @@ -1095,9 +1088,9 @@ public: ATTR_COLD netlist_device_t(); ATTR_COLD netlist_device_t(const family_t afamily); - /* ATTR_COLD */ virtual ~netlist_device_t(); + virtual ~netlist_device_t(); - /* ATTR_COLD */ virtual void init(netlist_base_t &anetlist, const pstring &name); + virtual void init(netlist_base_t &anetlist, const pstring &name); ATTR_COLD netlist_setup_t &setup(); @@ -1130,7 +1123,7 @@ private: // netlist_queue_t // ----------------------------------------------------------------------------- -class netlist_queue_t : public netlist_timed_queue<netlist_net_t *, netlist_time, 512>, +class netlist_queue_t : public netlist_timed_queue<netlist_net_t *, netlist_time>, public netlist_object_t, public pstate_callback_t { @@ -1147,8 +1140,8 @@ protected: private: int m_qsize; - netlist_time::INTERNALTYPE m_times[512]; - char m_name[512][64]; + parray_t<netlist_time::INTERNALTYPE> m_times; + parray_t<char[64]> m_names; }; // ----------------------------------------------------------------------------- @@ -1167,20 +1160,20 @@ public: ATTR_COLD void start(); ATTR_COLD void stop(); - ATTR_HOT /* inline */ const netlist_queue_t &queue() const { return m_queue; } - ATTR_HOT /* inline */ netlist_queue_t &queue() { return m_queue; } - ATTR_HOT /* inline */ const netlist_time &time() const { return m_time; } - ATTR_HOT /* inline */ NETLIB_NAME(solver) *solver() const { return m_solver; } - ATTR_HOT /* inline */ NETLIB_NAME(gnd) *gnd() const { return m_gnd; } + ATTR_HOT const netlist_queue_t &queue() const { return m_queue; } + ATTR_HOT netlist_queue_t &queue() { return m_queue; } + ATTR_HOT const netlist_time &time() const { return m_time; } + ATTR_HOT NETLIB_NAME(solver) *solver() const { return m_solver; } + ATTR_HOT NETLIB_NAME(gnd) *gnd() const { return m_gnd; } ATTR_HOT nl_double gmin() const; ATTR_HOT void push_to_queue(netlist_net_t &out, const netlist_time &attime); ATTR_HOT void remove_from_queue(netlist_net_t &out); ATTR_HOT void process_queue(const netlist_time &delta); - ATTR_HOT /* inline */ void abort_current_queue_slice() { m_stop = netlist_time::zero; } + ATTR_HOT void abort_current_queue_slice() { m_stop = netlist_time::zero; } - ATTR_HOT /* inline */ const bool &use_deactivate() const { return m_use_deactivate; } + ATTR_HOT const bool &use_deactivate() const { return m_use_deactivate; } ATTR_COLD void rebuild_lists(); /* must be called after post_load ! */ @@ -1197,7 +1190,7 @@ public: plist_t<_C *> get_device_list() { plist_t<_C *> tmp; - for (int i = 0; i < m_devices.size(); i++) + for (std::size_t i = 0; i < m_devices.size(); i++) { _C *dev = dynamic_cast<_C *>(m_devices[i]); if (dev != NULL) @@ -1209,7 +1202,7 @@ public: template<class _C> _C *get_first_device() { - for (int i = 0; i < m_devices.size(); i++) + for (std::size_t i = 0; i < m_devices.size(); i++) { _C *dev = dynamic_cast<_C *>(m_devices[i]); if (dev != NULL) @@ -1222,7 +1215,7 @@ public: _C *get_single_device(const char *classname) { _C *ret = NULL; - for (int i = 0; i < m_devices.size(); i++) + for (std::size_t i = 0; i < m_devices.size(); i++) { _C *dev = dynamic_cast<_C *>(m_devices[i]); if (dev != NULL) @@ -1252,12 +1245,12 @@ protected: }; // any derived netlist must override this ... - /* ATTR_COLD */ virtual void verror(const loglevel_e level, + virtual void verror(const loglevel_e level, const char *format, va_list ap) const = 0; /* from netlist_object */ - /* ATTR_COLD */ virtual void reset(); - /* ATTR_COLD */ virtual void save_register(); + virtual void reset(); + virtual void save_register(); #if (NL_KEEP_STATISTICS) // performance @@ -1270,20 +1263,21 @@ private: netlist_time m_stop; // target time for current queue processing netlist_time m_time; + bool m_use_deactivate; netlist_queue_t m_queue; + NETLIB_NAME(mainclock) * m_mainclock; NETLIB_NAME(solver) * m_solver; NETLIB_NAME(gnd) * m_gnd; - bool m_use_deactivate; NETLIB_NAME(netlistparams) *m_params; netlist_setup_t *m_setup; }; // ----------------------------------------------------------------------------- -// /* inline */ implementations +// inline implementations // ----------------------------------------------------------------------------- PSTATE_INTERFACE(netlist_object_t, m_netlist, name()) @@ -1341,6 +1335,7 @@ ATTR_HOT inline void netlist_logic_input_t::inactivate() { if (EXPECTED(!is_state(STATE_INP_PASSIVE))) { + //printf("inactivate %s\n", name().cstr()); set_state(STATE_INP_PASSIVE); net().as_logic().dec_active(*this); } @@ -1420,4 +1415,14 @@ ATTR_HOT inline void netlist_analog_output_t::set_Q(const nl_double newQ) } } +ATTR_HOT inline void netlist_base_t::push_to_queue(netlist_net_t &out, const netlist_time &attime) +{ + m_queue.push(netlist_queue_t::entry_t(attime, &out)); +} + +ATTR_HOT inline void netlist_base_t::remove_from_queue(netlist_net_t &out) +{ + m_queue.remove(&out); +} + #endif /* NLBASE_H_ */ diff --git a/src/emu/netlist/nl_config.h b/src/emu/netlist/nl_config.h index d01f6154e92..439e779b1ce 100644 --- a/src/emu/netlist/nl_config.h +++ b/src/emu/netlist/nl_config.h @@ -8,39 +8,62 @@ #ifndef NLCONFIG_H_ #define NLCONFIG_H_ -#include "pconfig.h" +#include "plib/pconfig.h" //============================================================ // SETUP //============================================================ /* - * The next options needs -Wno-pmf-conversions to compile and gcc - * There is quite some significant speed-up of up to 20% involved. - * NO_USE_PMFCONVERSION is for illustrative purposes only. Using PMFs - * has some overhead in comparison to calling a virtual function. + * The following options determine how object::update is called. + * NL_PMF_TYPE_VIRTUAL + * Use stock virtual call * - * To get a performance increase we need the GCC extension. + * NL_PMF_TYPE_GNUC_PMF + * Use standard pointer to member function syntax * - * Todo: This doesn't work with current (4.8+) mingw 32bit builds. - * Therefore disabled for now for i386 builds. + * NL_PMF_TYPE_GNUC_PMF_CONV + * Use gnu extension and convert the pmf to a function pointer. + * This is not standard compliant and needs + * -Wno-pmf-conversions to compile. * + * NL_PMF_TYPE_INTERNAL + * Use the same approach as MAME for deriving the function pointer. + * This is compiler-dependant as well + * + * Benchmarks for ./nltool -c run -f src/mame/drivers/nl_pong.c -t 10 -n pong_fast + * + * NL_PMF_TYPE_INTERNAL: 215% + * NL_PMF_TYPE_GNUC_PMF: 163% + * NL_PMF_TYPE_GNUC_PMF_CONV: 215% + * NL_PMF_TYPE_VIRTUAL: 213% + * + * The whole exercise was done to avoid virtual calls. In prior versions of + * netlist, the INTERNAL and GNUC_PMF_CONV approach provided significant improvement. + * Since than, ATTR_COLD was removed from functions declared as virtual. + * This may explain that the recent benchmarks show no difference at all. + * + * Disappointing is the GNUC_PMF performance. */ -#ifndef USE_PMFDELEGATES -#if defined(__clang__) || (defined(__GNUC__) && defined(__i386__)) - #define USE_PMFDELEGATES (0) - #define NO_USE_PMFCONVERSION (1) -#else - #if defined(__GNUC__) - #define USE_PMFDELEGATES (1) - #define NO_USE_PMFCONVERSION (0) - #pragma GCC diagnostic ignored "-Wpmf-conversions" +// This will be autodetected +//#define NL_PMF_TYPE 3 + +#define NL_PMF_TYPE_VIRTUAL 0 +#define NL_PMF_TYPE_GNUC_PMF 1 +#define NL_PMF_TYPE_GNUC_PMF_CONV 2 +#define NL_PMF_TYPE_INTERNAL 3 + +#ifndef NL_PMF_TYPE + #if PHAS_PMF_INTERNAL + #define NL_PMF_TYPE NL_PMF_TYPE_INTERNAL #else - #define USE_PMFDELEGATES (0) - #define NO_USE_PMFCONVERSION (1) + #define NL_PMF_TYPE NL_PMF_TYPE_VIRTUAL #endif #endif + +#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) +#pragma GCC diagnostic ignored "-Wpmf-conversions" #endif /* @@ -71,7 +94,6 @@ #define NETLIST_GMIN_DEFAULT (1e-9) - //#define nl_double float //#define NL_FCONST(x) (x ## f) @@ -99,9 +121,9 @@ #define NL_KEEP_STATISTICS (0) #if (NL_VERBOSE) - #define NL_VERBOSE_OUT(x) printf x + #define NL_VERBOSE_OUT(x) netlist().log x #else - #define NL_VERBOSE_OUT(x) do { } while (0) + #define NL_VERBOSE_OUT(x) do { if(0) netlist().log x ; } while (0) #endif //============================================================ @@ -125,6 +147,7 @@ //============================================================ #if NL_KEEP_STATISTICS +#include "eminline.h" #define add_to_stat(v,x) do { v += (x); } while (0) #define inc_stat(v) add_to_stat(v, 1) #define begin_timing(v) do { v -= get_profile_ticks(); } while (0) diff --git a/src/emu/netlist/nl_factory.c b/src/emu/netlist/nl_factory.c index 4c611af4c18..15ccbc62b5e 100644 --- a/src/emu/netlist/nl_factory.c +++ b/src/emu/netlist/nl_factory.c @@ -15,42 +15,42 @@ // net_device_t_base_factory // ---------------------------------------------------------------------------------------- -ATTR_COLD const nl_util::pstring_list net_device_t_base_factory::term_param_list() +ATTR_COLD const pstring_list_t netlist_base_factory_t::term_param_list() { if (m_def_param.startsWith("+")) - return nl_util::split(m_def_param.substr(1), ","); + return pstring_list_t(m_def_param.substr(1), ","); else - return nl_util::pstring_list(); + return pstring_list_t(); } -ATTR_COLD const nl_util::pstring_list net_device_t_base_factory::def_params() +ATTR_COLD const pstring_list_t netlist_base_factory_t::def_params() { if (m_def_param.startsWith("+") || m_def_param.equals("-")) - return nl_util::pstring_list(); + return pstring_list_t(); else - return nl_util::split(m_def_param, ","); + return pstring_list_t(m_def_param, ","); } -netlist_factory_t::netlist_factory_t() +netlist_factory_list_t::netlist_factory_list_t() { } -netlist_factory_t::~netlist_factory_t() +netlist_factory_list_t::~netlist_factory_list_t() { for (std::size_t i=0; i < m_list.size(); i++) { - net_device_t_base_factory *p = m_list[i]; + netlist_base_factory_t *p = m_list[i]; pfree(p); } m_list.clear(); } -netlist_device_t *netlist_factory_t::new_device_by_classname(const pstring &classname) const +netlist_device_t *netlist_factory_list_t::new_device_by_classname(const pstring &classname) const { for (std::size_t i=0; i < m_list.size(); i++) { - net_device_t_base_factory *p = m_list[i]; + netlist_base_factory_t *p = m_list[i]; if (p->classname() == classname) { netlist_device_t *ret = p->Create(); @@ -61,17 +61,17 @@ netlist_device_t *netlist_factory_t::new_device_by_classname(const pstring &clas return NULL; // appease code analysis } -netlist_device_t *netlist_factory_t::new_device_by_name(const pstring &name, netlist_setup_t &setup) const +netlist_device_t *netlist_factory_list_t::new_device_by_name(const pstring &name, netlist_setup_t &setup) const { - net_device_t_base_factory *f = factory_by_name(name, setup); + netlist_base_factory_t *f = factory_by_name(name, setup); return f->Create(); } -net_device_t_base_factory * netlist_factory_t::factory_by_name(const pstring &name, netlist_setup_t &setup) const +netlist_base_factory_t * netlist_factory_list_t::factory_by_name(const pstring &name, netlist_setup_t &setup) const { for (std::size_t i=0; i < m_list.size(); i++) { - net_device_t_base_factory *p = m_list[i]; + netlist_base_factory_t *p = m_list[i]; if (p->name() == name) { return p; diff --git a/src/emu/netlist/nl_factory.h b/src/emu/netlist/nl_factory.h index 970a5024c5a..c0379caced4 100644 --- a/src/emu/netlist/nl_factory.h +++ b/src/emu/netlist/nl_factory.h @@ -10,33 +10,32 @@ #define NLFACTORY_H_ #include "nl_config.h" -#include "palloc.h" -#include "plists.h" +#include "plib/palloc.h" +#include "plib/plists.h" #include "nl_base.h" -#include "pstring.h" // ----------------------------------------------------------------------------- // net_dev class factory // ----------------------------------------------------------------------------- -class net_device_t_base_factory +class netlist_base_factory_t { - NETLIST_PREVENT_COPYING(net_device_t_base_factory) + NETLIST_PREVENT_COPYING(netlist_base_factory_t) public: - ATTR_COLD net_device_t_base_factory(const pstring &name, const pstring &classname, + ATTR_COLD netlist_base_factory_t(const pstring &name, const pstring &classname, const pstring &def_param) : m_name(name), m_classname(classname), m_def_param(def_param) {} - /* ATTR_COLD */ virtual ~net_device_t_base_factory() {} + virtual ~netlist_base_factory_t() {} - /* ATTR_COLD */ virtual netlist_device_t *Create() const = 0; + virtual netlist_device_t *Create() = 0; ATTR_COLD const pstring &name() const { return m_name; } ATTR_COLD const pstring &classname() const { return m_classname; } ATTR_COLD const pstring ¶m_desc() const { return m_def_param; } - ATTR_COLD const nl_util::pstring_list term_param_list(); - ATTR_COLD const nl_util::pstring_list def_params(); + ATTR_COLD const pstring_list_t term_param_list(); + ATTR_COLD const pstring_list_t def_params(); protected: pstring m_name; /* device name */ @@ -45,15 +44,15 @@ protected: }; template <class C> -class net_device_t_factory : public net_device_t_base_factory +class net_list_factory_t : public netlist_base_factory_t { - NETLIST_PREVENT_COPYING(net_device_t_factory) + NETLIST_PREVENT_COPYING(net_list_factory_t) public: - ATTR_COLD net_device_t_factory(const pstring &name, const pstring &classname, + ATTR_COLD net_list_factory_t(const pstring &name, const pstring &classname, const pstring &def_param) - : net_device_t_base_factory(name, classname, def_param) { } + : netlist_base_factory_t(name, classname, def_param) { } - ATTR_COLD netlist_device_t *Create() const + ATTR_COLD netlist_device_t *Create() { netlist_device_t *r = palloc(C); //r->init(setup, name); @@ -61,24 +60,29 @@ public: } }; -class netlist_factory_t +class netlist_factory_list_t { public: - typedef plist_t<net_device_t_base_factory *> list_t; + typedef plist_t<netlist_base_factory_t *> list_t; - netlist_factory_t(); - ~netlist_factory_t(); + netlist_factory_list_t(); + ~netlist_factory_list_t(); template<class _C> ATTR_COLD void register_device(const pstring &name, const pstring &classname, const pstring &def_param) { - m_list.add(palloc(net_device_t_factory< _C >, name, classname, def_param)); + m_list.add(palloc(net_list_factory_t< _C >, name, classname, def_param)); + } + + ATTR_COLD void register_device(netlist_base_factory_t *factory) + { + m_list.add(factory); } ATTR_COLD netlist_device_t *new_device_by_classname(const pstring &classname) const; ATTR_COLD netlist_device_t *new_device_by_name(const pstring &name, netlist_setup_t &setup) const; - ATTR_COLD net_device_t_base_factory * factory_by_name(const pstring &name, netlist_setup_t &setup) const; + ATTR_COLD netlist_base_factory_t * factory_by_name(const pstring &name, netlist_setup_t &setup) const; const list_t &list() { return m_list; } diff --git a/src/emu/netlist/nl_lists.h b/src/emu/netlist/nl_lists.h index 88570dc1269..bb47c3137f6 100644 --- a/src/emu/netlist/nl_lists.h +++ b/src/emu/netlist/nl_lists.h @@ -11,13 +11,13 @@ #define NLLISTS_H_ #include "nl_config.h" - +#include "plib/plists.h" // ---------------------------------------------------------------------------------------- // timed queue // ---------------------------------------------------------------------------------------- -template <class _Element, class _Time, int _Size> +template <class _Element, class _Time> class netlist_timed_queue { NETLIST_PREVENT_COPYING(netlist_timed_queue) @@ -26,58 +26,74 @@ public: class entry_t { public: - ATTR_HOT /* inline */ entry_t() - : m_object(), m_exec_time() {} - ATTR_HOT /* inline */ entry_t(const _Time &atime, const _Element &elem) : m_object(elem), m_exec_time(atime) {} - ATTR_HOT /* inline */ const _Time exec_time() const { return m_exec_time; } - ATTR_HOT /* inline */ const _Element object() const { return m_object; } + ATTR_HOT entry_t() + : m_exec_time(), m_object() {} + ATTR_HOT entry_t(const _Time &atime, const _Element &elem) : m_exec_time(atime), m_object(elem) {} + ATTR_HOT const _Time &exec_time() const { return m_exec_time; } + ATTR_HOT const _Element &object() const { return m_object; } - ATTR_HOT /* inline */ entry_t &operator=(const entry_t &right) { - m_object = right.m_object; + ATTR_HOT entry_t &operator=(const entry_t &right) { m_exec_time = right.m_exec_time; + m_object = right.m_object; return *this; } private: - _Element m_object; _Time m_exec_time; + _Element m_object; }; - netlist_timed_queue() + netlist_timed_queue(unsigned list_size) + : m_list(list_size) { +#if HAS_OPENMP && USE_OPENMP + m_lock = 0; +#endif clear(); } - ATTR_HOT /* inline */ int capacity() const { return _Size; } - ATTR_HOT /* inline */ bool is_empty() const { return (m_end == &m_list[0]); } - ATTR_HOT /* inline */ bool is_not_empty() const { return (m_end > &m_list[0]); } + ATTR_HOT std::size_t capacity() const { return m_list.size(); } + ATTR_HOT bool is_empty() const { return (m_end == &m_list[1]); } + ATTR_HOT bool is_not_empty() const { return (m_end > &m_list[1]); } ATTR_HOT void push(const entry_t &e) { +#if HAS_OPENMP && USE_OPENMP + /* Lock */ + while (atomic_exchange32(&m_lock, 1)) { } +#endif + const _Time t = e.exec_time(); entry_t * i = m_end++; - while ((i > &m_list[0]) && (e.exec_time() > (i - 1)->exec_time()) ) + while (t > (i - 1)->exec_time()) { *(i) = *(i-1); i--; inc_stat(m_prof_sortmove); } *i = e; - inc_stat(m_prof_sort); + inc_stat(m_prof_call); +#if HAS_OPENMP && USE_OPENMP + m_lock = 0; +#endif //nl_assert(m_end - m_list < _Size); } - ATTR_HOT /* inline */ const entry_t *pop() + ATTR_HOT const entry_t *pop() { return --m_end; } - ATTR_HOT /* inline */ const entry_t *peek() const + ATTR_HOT const entry_t *peek() const { return (m_end-1); } - ATTR_HOT /* inline */ void remove(const _Element &elem) + ATTR_HOT void remove(const _Element &elem) { + /* Lock */ +#if HAS_OPENMP && USE_OPENMP + while (atomic_exchange32(&m_lock, 1)) { } +#endif entry_t * i = m_end - 1; while (i > &m_list[0]) { @@ -89,35 +105,49 @@ public: *i = *(i+1); i++; } +#if HAS_OPENMP && USE_OPENMP + m_lock = 0; +#endif return; } i--; } +#if HAS_OPENMP && USE_OPENMP + m_lock = 0; +#endif } ATTR_COLD void clear() { m_end = &m_list[0]; + /* put an empty element with maximum time into the queue. + * the insert algo above will run into this element and doesn't + * need a comparison with queue start. + */ + m_list[0] = entry_t(_Time::from_raw(~0), _Element(0)); + m_end++; } // save state support & mame disasm - ATTR_COLD /* inline */ const entry_t *listptr() const { return &m_list[0]; } - ATTR_HOT /* inline */ int count() const { return m_end - m_list; } - ATTR_HOT /* inline */ const entry_t & operator[](const int & index) const { return m_list[index]; } + ATTR_COLD const entry_t *listptr() const { return &m_list[1]; } + ATTR_HOT int count() const { return m_end - &m_list[1]; } + ATTR_HOT const entry_t & operator[](const int & index) const { return m_list[1+index]; } #if (NL_KEEP_STATISTICS) // profiling - INT32 m_prof_start; - INT32 m_prof_end; INT32 m_prof_sortmove; - INT32 m_prof_sort; + INT32 m_prof_call; #endif private: +#if HAS_OPENMP && USE_OPENMP + volatile INT32 m_lock; +#endif entry_t * m_end; - entry_t m_list[_Size]; + //entry_t m_list[_Size]; + parray_t<entry_t> m_list; }; diff --git a/src/emu/netlist/nl_parser.c b/src/emu/netlist/nl_parser.c index 7d7b29733be..bf52363df83 100644 --- a/src/emu/netlist/nl_parser.c +++ b/src/emu/netlist/nl_parser.c @@ -7,6 +7,7 @@ #include "nl_parser.h" #include "nl_factory.h" +#include "devices/nld_truthtable.h" //#undef NL_VERBOSE_OUT //#define NL_VERBOSE_OUT(x) printf x @@ -33,7 +34,7 @@ bool netlist_parser::parse(const char *buf, const pstring nlname) reset(m_buf); set_identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-"); - set_number_chars("01234567890eE-."); //FIXME: processing of numbers + set_number_chars(".0123456789", "0123456789eE-."); //FIXME: processing of numbers char ws[5]; ws[0] = ' '; ws[1] = 9; @@ -48,12 +49,18 @@ bool netlist_parser::parse(const char *buf, const pstring nlname) m_tok_ALIAS = register_token("ALIAS"); m_tok_NET_C = register_token("NET_C"); + m_tok_FRONTIER = register_token("OPTIMIZE_FRONTIER"); m_tok_PARAM = register_token("PARAM"); m_tok_NET_MODEL = register_token("NET_MODEL"); m_tok_INCLUDE = register_token("INCLUDE"); + m_tok_LOCAL_SOURCE = register_token("LOCAL_SOURCE"); m_tok_SUBMODEL = register_token("SUBMODEL"); m_tok_NETLIST_START = register_token("NETLIST_START"); m_tok_NETLIST_END = register_token("NETLIST_END"); + m_tok_TRUTHTABLE_START = register_token("TRUTHTABLE_START"); + m_tok_TRUTHTABLE_END = register_token("TRUTHTABLE_END"); + m_tok_TT_HEAD = register_token("TT_HEAD"); + m_tok_TT_LINE = register_token("TT_LINE"); bool in_nl = false; @@ -111,6 +118,8 @@ void netlist_parser::parse_netlist(ATTR_UNUSED const pstring &nlname) net_alias(); else if (token.is(m_tok_NET_C)) net_c(); + else if (token.is(m_tok_FRONTIER)) + frontier(); else if (token.is(m_tok_PARAM)) netdev_param(); else if (token.is(m_tok_NET_MODEL)) @@ -119,6 +128,10 @@ void netlist_parser::parse_netlist(ATTR_UNUSED const pstring &nlname) net_submodel(); else if (token.is(m_tok_INCLUDE)) net_include(); + else if (token.is(m_tok_LOCAL_SOURCE)) + net_local_source(); + else if (token.is(m_tok_TRUTHTABLE_START)) + net_truthtable_start(); else if (token.is(m_tok_NETLIST_END)) { netdev_netlist_end(); @@ -129,6 +142,49 @@ void netlist_parser::parse_netlist(ATTR_UNUSED const pstring &nlname) } } +void netlist_parser::net_truthtable_start() +{ + pstring name = get_identifier(); + require_token(m_tok_comma); + unsigned ni = get_number_long(); + require_token(m_tok_comma); + unsigned no = get_number_long(); + require_token(m_tok_comma); + unsigned hs = get_number_long(); + require_token(m_tok_comma); + pstring def_param = get_string(); + require_token(m_tok_param_right); + + netlist_base_factory_truthtable_t *ttd = nl_tt_factory_create(ni, no, hs, + name, name, "+" + def_param); + + while (true) + { + token_t token = get_token(); + + if (token.is(m_tok_TT_HEAD)) + { + require_token(m_tok_param_left); + ttd->m_desc.add(get_string()); + require_token(m_tok_param_right); + } + else if (token.is(m_tok_TT_LINE)) + { + require_token(m_tok_param_left); + ttd->m_desc.add(get_string()); + require_token(m_tok_param_right); + } + else + { + require_token(token, m_tok_TRUTHTABLE_END); + require_token(m_tok_param_left); + require_token(m_tok_param_right); + m_setup.factory().register_device(ttd); + return; + } + } +} + void netlist_parser::netdev_netlist_start() { @@ -154,30 +210,49 @@ void netlist_parser::net_model() void netlist_parser::net_submodel() { // don't do much - pstring name = get_identifier(); - require_token(m_tok_comma); pstring model = get_identifier(); + require_token(m_tok_comma); + pstring name = get_identifier(); require_token(m_tok_param_right); m_setup.namespace_push(name); - netlist_parser subparser(m_setup); - subparser.parse(m_buf, model); + m_setup.include(model); m_setup.namespace_pop(); } +void netlist_parser::frontier() +{ + // don't do much + pstring attachat = get_identifier(); + require_token(m_tok_comma); + double r_IN = eval_param(get_token()); + require_token(m_tok_comma); + double r_OUT = eval_param(get_token()); + require_token(m_tok_param_right); + + m_setup.register_frontier(attachat, r_IN, r_OUT); +} + void netlist_parser::net_include() { // don't do much pstring name = get_identifier(); require_token(m_tok_param_right); - netlist_parser subparser(m_setup); - subparser.parse(m_buf, name); + m_setup.include(name); +} + +void netlist_parser::net_local_source() +{ + // This directive is only for hardcoded netlists. Ignore it here. + pstring name = get_identifier(); + require_token(m_tok_param_right); + } void netlist_parser::net_alias() { - pstring alias = get_identifier(); + pstring alias = get_identifier_or_number(); require_token(m_tok_comma); @@ -198,7 +273,7 @@ void netlist_parser::net_c() { pstring t1 = get_identifier(); m_setup.register_link(first , t1); - NL_VERBOSE_OUT(("Parser: Connect: %s %s\n", last.cstr(), t1.cstr())); + NL_VERBOSE_OUT(("Parser: Connect: %s %s\n", first.cstr(), t1.cstr())); token_t n = get_token(); if (n.is(m_tok_param_right)) break; @@ -223,10 +298,10 @@ void netlist_parser::netdev_param() void netlist_parser::device(const pstring &dev_type) { pstring devname; - net_device_t_base_factory *f = m_setup.factory().factory_by_name(dev_type, m_setup); + netlist_base_factory_t *f = m_setup.factory().factory_by_name(dev_type, m_setup); netlist_device_t *dev; - nl_util::pstring_list termlist = f->term_param_list(); - nl_util::pstring_list def_params = f->def_params(); + pstring_list_t termlist = f->term_param_list(); + pstring_list_t def_params = f->def_params(); std::size_t cnt; @@ -293,6 +368,23 @@ nl_double netlist_parser::eval_param(const token_t tok) for (i=1; i<6;i++) if (tok.str().equals(macs[i])) f = i; +#if 1 + if (f>0) + { + require_token(m_tok_param_left); + ret = get_number_double(); + require_token(m_tok_param_right); + } + else + { + val = tok.str(); + ret = val.as_double(&e); + if (e) + error("Error with parameter ...\n"); + } + return ret * facs[f]; + +#else if (f>0) { require_token(m_tok_param_left); @@ -308,4 +400,5 @@ nl_double netlist_parser::eval_param(const token_t tok) if (f>0) require_token(m_tok_param_right); return ret * facs[f]; +#endif } diff --git a/src/emu/netlist/nl_parser.h b/src/emu/netlist/nl_parser.h index 582aad49de7..2f44ef9992d 100644 --- a/src/emu/netlist/nl_parser.h +++ b/src/emu/netlist/nl_parser.h @@ -10,7 +10,7 @@ #include "nl_setup.h" #include "nl_util.h" -#include "pparser.h" +#include "plib/pparser.h" class netlist_parser : public ptokenizer { @@ -25,14 +25,20 @@ public: void net_alias(); void netdev_param(); void net_c(); + void frontier(); void device(const pstring &dev_type); void netdev_netlist_start(); void netdev_netlist_end(); void net_model(); void net_submodel(); void net_include(); + void net_local_source(); + void net_truthtable_start(); protected: + /* for debugging messages */ + netlist_base_t &netlist() { return m_setup.netlist(); } + virtual void verror(pstring msg, int line_num, pstring line); private: @@ -43,117 +49,23 @@ private: token_id_t m_tok_comma; token_id_t m_tok_ALIAS; token_id_t m_tok_NET_C; + token_id_t m_tok_FRONTIER; token_id_t m_tok_PARAM; token_id_t m_tok_NET_MODEL; token_id_t m_tok_NETLIST_START; token_id_t m_tok_NETLIST_END; token_id_t m_tok_SUBMODEL; token_id_t m_tok_INCLUDE; + token_id_t m_tok_LOCAL_SOURCE; + token_id_t m_tok_TRUTHTABLE_START; + token_id_t m_tok_TRUTHTABLE_END; + token_id_t m_tok_TT_HEAD; + token_id_t m_tok_TT_LINE; netlist_setup_t &m_setup; const char *m_buf; }; -class netlist_source_t -{ -public: - typedef plist_t<netlist_source_t> list_t; - - enum source_e - { - EMPTY, - STRING, - PROC, - MEMORY - }; - - netlist_source_t() - : m_type(EMPTY), - m_setup_func(NULL), - m_setup_func_name(""), - m_mem(NULL) - { - } - - netlist_source_t(pstring name, void (*setup_func)(netlist_setup_t &)) - : m_type(PROC), - m_setup_func(setup_func), - m_setup_func_name(name), - m_mem(NULL) - { - } - - netlist_source_t(const char *mem) - : m_type(MEMORY), - m_setup_func(NULL), - m_setup_func_name(""), - m_mem(mem) - { - } - - ~netlist_source_t() { } - - bool parse(netlist_setup_t &setup, const pstring name) - { - switch (m_type) - { - case PROC: - if (name == m_setup_func_name) - { - m_setup_func(setup); - return true; - } - break; - case MEMORY: - { - netlist_parser p(setup); - return p.parse(m_mem, name); - } - break; - case STRING: - case EMPTY: - break; - } - return false; - } -private: - source_e m_type; - - void (*m_setup_func)(netlist_setup_t &); - pstring m_setup_func_name; - const char *m_mem; - -}; - -class netlist_sources_t -{ -public: - - netlist_sources_t() { } - - ~netlist_sources_t() - { - m_list.clear(); - } - - void add(netlist_source_t src) - { - m_list.add(src); - } - - void parse(netlist_setup_t &setup, const pstring name) - { - for (std::size_t i=0; i < m_list.size(); i++) - { - if (m_list[i].parse(setup, name)) - return; - } - setup.netlist().error("unable to find %s in source collection", name.cstr()); - } - -private: - netlist_source_t::list_t m_list; -}; #endif /* NL_PARSER_H_ */ diff --git a/src/emu/netlist/nl_setup.c b/src/emu/netlist/nl_setup.c index 6b98f14d452..a22c94519e6 100644 --- a/src/emu/netlist/nl_setup.c +++ b/src/emu/netlist/nl_setup.c @@ -7,7 +7,7 @@ #include <cstdio> -#include "palloc.h" +#include "plib/palloc.h" #include "nl_base.h" #include "nl_setup.h" #include "nl_parser.h" @@ -24,6 +24,9 @@ static NETLIST_START(base) NET_REGISTER_DEV(gnd, GND) NET_REGISTER_DEV(netlistparams, NETLIST) + LOCAL_SOURCE(diode_models) + LOCAL_SOURCE(bjt_models) + INCLUDE(diode_models); INCLUDE(bjt_models); @@ -34,12 +37,12 @@ NETLIST_END() // netlist_setup_t // ---------------------------------------------------------------------------------------- -netlist_setup_t::netlist_setup_t(netlist_base_t &netlist) +netlist_setup_t::netlist_setup_t(netlist_base_t *netlist) : m_netlist(netlist) , m_proxy_cnt(0) { - netlist.set_setup(this); - m_factory = palloc(netlist_factory_t); + netlist->set_setup(this); + m_factory = palloc(netlist_factory_list_t); } void netlist_setup_t::init() @@ -59,6 +62,7 @@ netlist_setup_t::~netlist_setup_t() netlist().set_setup(NULL); pfree(m_factory); + m_sources.clear_and_free(); pstring::resetmem(); } @@ -104,23 +108,9 @@ netlist_device_t *netlist_setup_t::register_dev(const pstring &classname, const return register_dev(dev, name); } -template <class T> -static void remove_start_with(T &hm, pstring &sw) -{ - for (std::size_t i = hm.size() - 1; i >= 0; i--) - { - pstring x = hm[i]->name(); - if (sw.equals(x.substr(0, sw.len()))) - { - NL_VERBOSE_OUT(("removing %s\n", hm[i]->name().cstr())); - hm.remove(hm[i]); - } - } -} - void netlist_setup_t::remove_dev(const pstring &name) { - netlist_device_t *dev = netlist().m_devices.find(name); + netlist_device_t *dev = netlist().m_devices.find_by_name(name); pstring temp = name + "."; if (dev == NULL) netlist().error("Device %s does not exist\n", name.cstr()); @@ -215,7 +205,7 @@ void netlist_setup_t::register_object(netlist_device_t &dev, const pstring &name { netlist_param_t ¶m = dynamic_cast<netlist_param_t &>(obj); //printf("name: %s\n", name.cstr()); - const pstring val = m_params_temp.find(name).e2; + const pstring val = m_params_temp.find_by_name(name).e2; if (val != "") { switch (param.param_type()) @@ -286,7 +276,7 @@ void netlist_setup_t::register_object(netlist_device_t &dev, const pstring &name void netlist_setup_t::register_link_arr(const pstring &terms) { - nl_util::pstring_list list = nl_util::split(terms,", "); + pstring_list_t list(terms,", "); if (list.size() < 2) netlist().error("You must pass at least 2 terminals to NET_C"); for (std::size_t i = 1; i < list.size(); i++) @@ -305,6 +295,36 @@ void netlist_setup_t::register_link(const pstring &sin, const pstring &sout) // fatalerror("Error adding link %s<==%s to link list\n", sin.cstr(), sout.cstr()); } +void netlist_setup_t::register_frontier(const pstring attach, const double r_IN, const double r_OUT) +{ + static int frontier_cnt = 0; + pstring frontier_name = pstring::sprintf("frontier_%d", frontier_cnt); + frontier_cnt++; + netlist_device_t *front = register_dev("nld_frontier", frontier_name); + register_param(frontier_name + ".RIN", r_IN); + register_param(frontier_name + ".ROUT", r_OUT); + register_link(frontier_name + ".G", "GND"); + pstring attfn = build_fqn(attach); + bool found = false; + for (std::size_t i = 0; i < m_links.size(); i++) + { + if (m_links[i].e1 == attfn) + { + m_links[i].e1 = front->name() + ".I"; + found = true; + } + else if (m_links[i].e2 == attfn) + { + m_links[i].e2 = front->name() + ".I"; + found = true; + } + } + if (!found) + netlist().error("Frontier setup: found no occurrence of %s\n", attach.cstr()); + register_link(attach, frontier_name + ".Q"); +} + + void netlist_setup_t::register_param(const pstring ¶m, const double value) { // FIXME: there should be a better way @@ -327,7 +347,7 @@ const pstring netlist_setup_t::resolve_alias(const pstring &name) const /* FIXME: Detect endless loop */ do { ret = temp; - temp = m_alias.find(ret).e2; + temp = m_alias.find_by_name(ret).e2; } while (temp != ""); NL_VERBOSE_OUT(("%s==>%s\n", name.cstr(), ret.cstr())); @@ -339,13 +359,13 @@ netlist_core_terminal_t *netlist_setup_t::find_terminal(const pstring &terminal_ const pstring &tname = resolve_alias(terminal_in); netlist_core_terminal_t *ret; - ret = m_terminals.find(tname); + ret = m_terminals.find_by_name(tname); /* look for default */ if (ret == NULL) { /* look for ".Q" std output */ pstring s = tname + ".Q"; - ret = m_terminals.find(s); + ret = m_terminals.find_by_name(s); } if (ret == NULL && required) netlist().error("terminal %s(%s) not found!\n", terminal_in.cstr(), tname.cstr()); @@ -359,13 +379,13 @@ netlist_core_terminal_t *netlist_setup_t::find_terminal(const pstring &terminal_ const pstring &tname = resolve_alias(terminal_in); netlist_core_terminal_t *ret; - ret = m_terminals.find(tname); + ret = m_terminals.find_by_name(tname); /* look for default */ if (ret == NULL && atype == netlist_object_t::OUTPUT) { /* look for ".Q" std output */ pstring s = tname + ".Q"; - ret = m_terminals.find(s); + ret = m_terminals.find_by_name(s); } if (ret == NULL && required) netlist().error("terminal %s(%s) not found!\n", terminal_in.cstr(), tname.cstr()); @@ -388,7 +408,7 @@ netlist_param_t *netlist_setup_t::find_param(const pstring ¶m_in, bool requi const pstring &outname = resolve_alias(param_in_fqn); netlist_param_t *ret; - ret = m_params.find(outname); + ret = m_params.find_by_name(outname); if (ret == NULL && required) netlist().error("parameter %s(%s) not found!\n", param_in_fqn.cstr(), outname.cstr()); if (ret != NULL) @@ -408,7 +428,7 @@ nld_base_proxy *netlist_setup_t::get_d_a_proxy(netlist_core_terminal_t &out) if (proxy == NULL) { // create a new one ... - nld_base_d_to_a_proxy *new_proxy = out_cast.logic_family()->create_d_a_proxy(out_cast); + nld_base_d_to_a_proxy *new_proxy = out_cast.logic_family()->create_d_a_proxy(&out_cast); pstring x = pstring::sprintf("proxy_da_%s_%d", out.name().cstr(), m_proxy_cnt); m_proxy_cnt++; @@ -439,7 +459,7 @@ void netlist_setup_t::connect_input_output(netlist_core_terminal_t &in, netlist_ if (out.isFamily(netlist_terminal_t::ANALOG) && in.isFamily(netlist_terminal_t::LOGIC)) { netlist_logic_input_t &incast = dynamic_cast<netlist_logic_input_t &>(in); - nld_a_to_d_proxy *proxy = palloc(nld_a_to_d_proxy, incast); + nld_a_to_d_proxy *proxy = palloc(nld_a_to_d_proxy, &incast); incast.set_proxy(proxy); pstring x = pstring::sprintf("proxy_ad_%s_%d", in.name().cstr(), m_proxy_cnt); m_proxy_cnt++; @@ -478,7 +498,7 @@ void netlist_setup_t::connect_terminal_input(netlist_terminal_t &term, netlist_c { netlist_logic_input_t &incast = dynamic_cast<netlist_logic_input_t &>(inp); NL_VERBOSE_OUT(("connect_terminal_input: connecting proxy\n")); - nld_a_to_d_proxy *proxy = palloc(nld_a_to_d_proxy, incast); + nld_a_to_d_proxy *proxy = palloc(nld_a_to_d_proxy, &incast); incast.set_proxy(proxy); pstring x = pstring::sprintf("proxy_ad_%s_%d", inp.name().cstr(), m_proxy_cnt); m_proxy_cnt++; @@ -759,13 +779,13 @@ void netlist_setup_t::resolve_inputs() netlist().log("initialize solver ...\n"); - if (m_netlist.solver() == NULL) + if (netlist().solver() == NULL) { if (has_twoterms) netlist().error("No solver found for this net although analog elements are present\n"); } else - m_netlist.solver()->post_start(); + netlist().solver()->post_start(); } @@ -776,8 +796,8 @@ void netlist_setup_t::start_devices() if (env != "") { NL_VERBOSE_OUT(("Creating dynamic logs ...\n")); - nl_util::pstring_list ll = nl_util::split(env, ":"); - for (std::size_t i=0; i < ll.size(); i++) + pstring_list_t ll(env, ":"); + for (unsigned i=0; i < ll.size(); i++) { NL_VERBOSE_OUT(("%d: <%s>\n",i, ll[i].cstr())); NL_VERBOSE_OUT(("%d: <%s>\n",i, ll[i].cstr())); @@ -791,25 +811,47 @@ void netlist_setup_t::start_devices() netlist().start(); } -void netlist_setup_t::parse(const char *buf) -{ - netlist_parser parser(*this); - parser.parse(buf); -} - void netlist_setup_t::print_stats() const { #if (NL_KEEP_STATISTICS) { - for (netlist_core_device_t * const *entry = netlist().m_started_devices.first(); entry != NULL; entry = netlist().m_started_devices.next(entry)) + for (std::size_t i = 0; i < netlist().m_started_devices.size(); i++) { - //entry->object()->s - printf("Device %20s : %12d %12d %15ld\n", (*entry)->name().cstr(), (*entry)->stat_call_count, (*entry)->stat_update_count, (long int) (*entry)->stat_total_time / ((*entry)->stat_update_count + 1)); + netlist_core_device_t *entry = netlist().m_started_devices[i]; + printf("Device %20s : %12d %12d %15ld\n", entry->name().cstr(), entry->stat_call_count, entry->stat_update_count, (long int) entry->stat_total_time / (entry->stat_update_count + 1)); } - printf("Queue Start %15d\n", m_netlist.queue().m_prof_start); - printf("Queue End %15d\n", m_netlist.queue().m_prof_end); - printf("Queue Sort %15d\n", m_netlist.queue().m_prof_sort); - printf("Queue Move %15d\n", m_netlist.queue().m_prof_sortmove); + printf("Queue Pushes %15d\n", m_netlist.queue().m_prof_call); + printf("Queue Moves %15d\n", m_netlist.queue().m_prof_sortmove); } #endif } + +// ---------------------------------------------------------------------------------------- +// Sources +// ---------------------------------------------------------------------------------------- + +void netlist_setup_t::include(const pstring &netlist_name) +{ + for (std::size_t i=0; i < m_sources.size(); i++) + { + if (m_sources[i]->parse(this, netlist_name)) + return; + } + netlist().error("unable to find %s in source collection", netlist_name.cstr()); +} + +// ---------------------------------------------------------------------------------------- +// base sources +// ---------------------------------------------------------------------------------------- + +bool netlist_source_string_t::parse(netlist_setup_t *setup, const pstring name) +{ + netlist_parser p(*setup); + return p.parse(m_str, name); +} + +bool netlist_source_mem_t::parse(netlist_setup_t *setup, const pstring name) +{ + netlist_parser p(*setup); + return p.parse(m_str, name); +} diff --git a/src/emu/netlist/nl_setup.h b/src/emu/netlist/nl_setup.h index 311ca0bfa63..6cd5afc36f0 100644 --- a/src/emu/netlist/nl_setup.h +++ b/src/emu/netlist/nl_setup.h @@ -25,6 +25,10 @@ #define NET_REGISTER_DEV(_type, _name) \ setup.register_dev(NETLIB_NAME_STR(_type), # _name); +/* to be used to reference new library truthtable devices */ +#define NET_REGISTER_DEV_X(_type, _name) \ + setup.register_dev(# _type, # _name); + #define NET_REMOVE_DEV(_name) \ setup.remove_dev(# _name); @@ -53,26 +57,49 @@ ATTR_COLD void NETLIST_NAME(_name)(netlist_setup_t &setup) { #define NETLIST_END() } +#define LOCAL_SOURCE(_name) \ + setup.register_source(palloc(netlist_source_proc_t, # _name, &NETLIST_NAME(_name))); + #define INCLUDE(_name) \ - NETLIST_NAME(_name)(setup); + setup.include(# _name); -#define SUBMODEL(_name, _model) \ +#define SUBMODEL(_model, _name) \ setup.namespace_push(# _name); \ NETLIST_NAME(_model)(setup); \ setup.namespace_pop(); +class netlist_setup_t; + // ---------------------------------------------------------------------------------------- // netlist_setup_t // ---------------------------------------------------------------------------------------- // Forward definition so we keep nl_factory.h out of the public -class netlist_factory_t; +class netlist_factory_list_t; class netlist_setup_t { NETLIST_PREVENT_COPYING(netlist_setup_t) public: + // ---------------------------------------------------------------------------------------- + // A Generic netlist sources implementation + // ---------------------------------------------------------------------------------------- + + class source_t + { + public: + typedef plist_t<source_t *> list_t; + + source_t() + {} + + virtual ~source_t() { } + + virtual bool parse(netlist_setup_t *setup, const pstring name) = 0; + private: + }; + struct link_t { link_t() { } @@ -103,13 +130,13 @@ public: typedef pnamedlist_t<netlist_core_terminal_t *> tagmap_terminal_t; typedef plist_t<link_t> tagmap_link_t; - netlist_setup_t(netlist_base_t &netlist); + netlist_setup_t(netlist_base_t *netlist); ~netlist_setup_t(); void init(); - netlist_base_t &netlist() { return m_netlist; } - const netlist_base_t &netlist() const { return m_netlist; } + netlist_base_t &netlist() { return *m_netlist; } + const netlist_base_t &netlist() const { return *m_netlist; } pstring build_fqn(const pstring &obj_name) const; @@ -124,6 +151,7 @@ public: void register_link(const pstring &sin, const pstring &sout); void register_param(const pstring ¶m, const pstring &value); void register_param(const pstring ¶m, const double value); + void register_frontier(const pstring attach, const double r_IN, const double r_OUT); void register_object(netlist_device_t &dev, const pstring &name, netlist_object_t &obj); bool connect(netlist_core_terminal_t &t1, netlist_core_terminal_t &t2); @@ -133,8 +161,6 @@ public: netlist_param_t *find_param(const pstring ¶m_in, bool required = true); - void parse(const char *buf); - void start_devices(); void resolve_inputs(); @@ -143,8 +169,16 @@ public: void namespace_push(const pstring &aname); void namespace_pop(); - netlist_factory_t &factory() { return *m_factory; } - const netlist_factory_t &factory() const { return *m_factory; } + /* parse a source */ + + void include(const pstring &netlist_name); + + /* register a source */ + + void register_source(source_t *src) { m_sources.add(src); } + + netlist_factory_list_t &factory() { return *m_factory; } + const netlist_factory_list_t &factory() const { return *m_factory; } /* not ideal, but needed for save_state */ tagmap_terminal_t m_terminals; @@ -155,20 +189,21 @@ protected: private: - netlist_base_t &m_netlist; + netlist_base_t *m_netlist; tagmap_nstring_t m_alias; tagmap_param_t m_params; tagmap_link_t m_links; tagmap_nstring_t m_params_temp; - netlist_factory_t *m_factory; + netlist_factory_list_t *m_factory; plist_t<pstring> m_models; int m_proxy_cnt; pstack_t<pstring> m_stack; + source_t::list_t m_sources; void connect_terminals(netlist_core_terminal_t &in, netlist_core_terminal_t &out); @@ -182,6 +217,80 @@ private: const pstring resolve_alias(const pstring &name) const; nld_base_proxy *get_d_a_proxy(netlist_core_terminal_t &out); + + template <class T> + void remove_start_with(T &hm, pstring &sw) + { + for (std::size_t i = hm.size() - 1; i >= 0; i--) + { + pstring x = hm[i]->name(); + if (sw.equals(x.substr(0, sw.len()))) + { + NL_VERBOSE_OUT(("removing %s\n", hm[i]->name().cstr())); + hm.remove(hm[i]); + } + } + } }; +// ---------------------------------------------------------------------------------------- +// base sources +// ---------------------------------------------------------------------------------------- + + +class netlist_source_string_t : public netlist_setup_t::source_t +{ +public: + + netlist_source_string_t(pstring source) + : netlist_setup_t::source_t(), m_str(source) + { + } + + bool parse(netlist_setup_t *setup, const pstring name); + +private: + pstring m_str; +}; + + +class netlist_source_mem_t : public netlist_setup_t::source_t +{ +public: + netlist_source_mem_t(const char *mem) + : netlist_setup_t::source_t(), m_str(mem) + { + } + + bool parse(netlist_setup_t *setup, const pstring name); +private: + pstring m_str; +}; + +class netlist_source_proc_t : public netlist_setup_t::source_t +{ +public: + netlist_source_proc_t(pstring name, void (*setup_func)(netlist_setup_t &)) + : netlist_setup_t::source_t(), + m_setup_func(setup_func), + m_setup_func_name(name) + { + } + + bool parse(netlist_setup_t *setup, const pstring name) + { + if (name == m_setup_func_name) + { + m_setup_func(*setup); + return true; + } + else + return false; + } +private: + void (*m_setup_func)(netlist_setup_t &); + pstring m_setup_func_name; +}; + + #endif /* NLSETUP_H_ */ diff --git a/src/emu/netlist/nl_time.h b/src/emu/netlist/nl_time.h index 457f7622307..f5005af40fd 100644 --- a/src/emu/netlist/nl_time.h +++ b/src/emu/netlist/nl_time.h @@ -8,7 +8,7 @@ #define NLTIME_H_ #include "nl_config.h" -#include "pstate.h" +#include "plib/pstate.h" //============================================================ // MACROS @@ -23,56 +23,59 @@ // net_list_time // ---------------------------------------------------------------------------------------- +#define RESOLUTION NETLIST_INTERNAL_RES + struct netlist_time { public: typedef UINT64 INTERNALTYPE; - static const INTERNALTYPE RESOLUTION = NETLIST_INTERNAL_RES; - - ATTR_HOT inline netlist_time() : m_time(0) {} + ATTR_HOT /* inline */ netlist_time() : m_time(0) {} - ATTR_HOT friend inline const netlist_time operator-(const netlist_time &left, const netlist_time &right); - ATTR_HOT friend inline const netlist_time operator+(const netlist_time &left, const netlist_time &right); - ATTR_HOT friend inline const netlist_time operator*(const netlist_time &left, const UINT32 factor); - ATTR_HOT friend inline UINT32 operator/(const netlist_time &left, const netlist_time &right); - ATTR_HOT friend inline bool operator>(const netlist_time &left, const netlist_time &right); - ATTR_HOT friend inline bool operator<(const netlist_time &left, const netlist_time &right); - ATTR_HOT friend inline bool operator>=(const netlist_time &left, const netlist_time &right); - ATTR_HOT friend inline bool operator<=(const netlist_time &left, const netlist_time &right); - ATTR_HOT friend inline bool operator!=(const netlist_time &left, const netlist_time &right); + ATTR_HOT friend /* inline */ const netlist_time operator-(const netlist_time &left, const netlist_time &right); + ATTR_HOT friend /* inline */ const netlist_time operator+(const netlist_time &left, const netlist_time &right); + ATTR_HOT friend /* inline */ const netlist_time operator*(const netlist_time &left, const UINT32 factor); + ATTR_HOT friend /* inline */ UINT32 operator/(const netlist_time &left, const netlist_time &right); + ATTR_HOT friend /* inline */ bool operator>(const netlist_time &left, const netlist_time &right); + ATTR_HOT friend /* inline */ bool operator<(const netlist_time &left, const netlist_time &right); + ATTR_HOT friend /* inline */ bool operator>=(const netlist_time &left, const netlist_time &right); + ATTR_HOT friend /* inline */ bool operator<=(const netlist_time &left, const netlist_time &right); + ATTR_HOT friend /* inline */ bool operator!=(const netlist_time &left, const netlist_time &right); - ATTR_HOT inline const netlist_time &operator=(const netlist_time &right) { m_time = right.m_time; return *this; } - ATTR_HOT inline const netlist_time &operator=(const double &right) { m_time = (INTERNALTYPE) ( right * (double) RESOLUTION); return *this; } + ATTR_HOT /* inline */ const netlist_time &operator=(const netlist_time &right) { m_time = right.m_time; return *this; } + ATTR_HOT /* inline */ const netlist_time &operator=(const double &right) { m_time = (INTERNALTYPE) ( right * (double) RESOLUTION); return *this; } // issues with ISO C++ standard - //ATTR_HOT inline operator double() const { return as_double(); } + //ATTR_HOT /* inline */ operator double() const { return as_double(); } - ATTR_HOT inline const netlist_time &operator+=(const netlist_time &right) { m_time += right.m_time; return *this; } + ATTR_HOT /* inline */ const netlist_time &operator+=(const netlist_time &right) { m_time += right.m_time; return *this; } - ATTR_HOT inline INTERNALTYPE as_raw() const { return m_time; } - ATTR_HOT inline double as_double() const { return (double) m_time / (double) RESOLUTION; } + ATTR_HOT /* inline */ INTERNALTYPE as_raw() const { return m_time; } + ATTR_HOT /* inline */ double as_double() const { return (double) m_time / (double) RESOLUTION; } // for save states .... - ATTR_HOT inline INTERNALTYPE *get_internaltype_ptr() { return &m_time; } + ATTR_HOT /* inline */ INTERNALTYPE *get_internaltype_ptr() { return &m_time; } - ATTR_HOT static inline const netlist_time from_nsec(const int ns) { return netlist_time((UINT64) ns * (RESOLUTION / U64(1000000000))); } - ATTR_HOT static inline const netlist_time from_usec(const int us) { return netlist_time((UINT64) us * (RESOLUTION / U64(1000000))); } - ATTR_HOT static inline const netlist_time from_msec(const int ms) { return netlist_time((UINT64) ms * (RESOLUTION / U64(1000))); } - ATTR_HOT static inline const netlist_time from_hz(const UINT64 hz) { return netlist_time(RESOLUTION / hz); } - ATTR_HOT static inline const netlist_time from_double(const double t) { return netlist_time((INTERNALTYPE) ( t * (double) RESOLUTION)); } - ATTR_HOT static inline const netlist_time from_raw(const INTERNALTYPE raw) { return netlist_time(raw); } + ATTR_HOT static /* inline */ const netlist_time from_nsec(const int ns) { return netlist_time((UINT64) ns * (RESOLUTION / U64(1000000000))); } + ATTR_HOT static /* inline */ const netlist_time from_usec(const int us) { return netlist_time((UINT64) us * (RESOLUTION / U64(1000000))); } + ATTR_HOT static /* inline */ const netlist_time from_msec(const int ms) { return netlist_time((UINT64) ms * (RESOLUTION / U64(1000))); } + ATTR_HOT static /* inline */ const netlist_time from_hz(const UINT64 hz) { return netlist_time(RESOLUTION / hz); } + ATTR_HOT static /* inline */ const netlist_time from_double(const double t) { return netlist_time((INTERNALTYPE) ( t * (double) RESOLUTION)); } + ATTR_HOT static /* inline */ const netlist_time from_raw(const INTERNALTYPE raw) { return netlist_time(raw); } static const netlist_time zero; protected: - ATTR_HOT inline netlist_time(const INTERNALTYPE val) : m_time(val) {} + ATTR_HOT /* inline */ netlist_time(const INTERNALTYPE val) : m_time(val) {} +private: INTERNALTYPE m_time; }; +#undef RESOLUTION + template<> ATTR_COLD inline void pstate_manager_t::save_item(netlist_time &nlt, const void *owner, const pstring &stname) { save_state_ptr(stname, DT_INT64, owner, sizeof(netlist_time::INTERNALTYPE), 1, nlt.get_internaltype_ptr(), false); diff --git a/src/emu/netlist/nl_util.h b/src/emu/netlist/nl_util.h index cf5ee6a3a7b..bb5a564dd74 100644 --- a/src/emu/netlist/nl_util.h +++ b/src/emu/netlist/nl_util.h @@ -8,10 +8,12 @@ #ifndef NL_UTIL_H_ #define NL_UTIL_H_ -#include "pstring.h" -#include "plists.h" #include <cmath> #include <cstring> +#include <cstdlib> + +#include "plib/pstring.h" +#include "plib/plists.h" class nl_util { @@ -20,68 +22,7 @@ private: nl_util() {}; public: - typedef plist_t<pstring> pstring_list; - static pstring_list split(const pstring &str, const pstring &onstr, bool ignore_empty = false) - { - pstring_list temp; - - int p = 0; - int pn; - - pn = str.find(onstr, p); - while (pn>=0) - { - pstring t = str.substr(p, pn - p); - if (!ignore_empty || t.len() != 0) - temp.add(t); - p = pn + onstr.len(); - pn = str.find(onstr, p); - } - if (p<str.len()) - { - pstring t = str.substr(p); - if (!ignore_empty || t.len() != 0) - temp.add(t); - } - return temp; - } - - static pstring_list splitexpr(const pstring &str, const pstring_list &onstrl) - { - pstring_list temp; - pstring col = ""; - - int i = 0; - while (i<str.len()) - { - int p = -1; - for (std::size_t j=0; j < onstrl.size(); j++) - { - if (std::strncmp(onstrl[j].cstr(), &(str.cstr()[i]), onstrl[j].len())==0) - { - p = j; - break; - } - } - if (p>=0) - { - if (col != "") - temp.add(col); - col = ""; - temp.add(onstrl[p]); - i += onstrl[p].len(); - } - else - { - col += str.cstr()[i]; - i++; - } - } - if (col != "") - temp.add(col); - return temp; - } static const pstring environment(const pstring &var, const pstring &default_val = "") { @@ -120,17 +61,22 @@ public: #if 0 inline static double fastexp_h(const double x) { - static const double ln2r = 1.442695040888963387; - static const double ln2 = 0.693147180559945286; - static const double c3 = 0.166666666666666667; + /* static */ const double ln2r = 1.442695040888963387; + /* static */ const double ln2 = 0.693147180559945286; + /* static */ const double c3 = 0.166666666666666667; + /* static */ const double c4 = 1.0 / 24.0; + /* static */ const double c5 = 1.0 / 120.0; const double y = x * ln2r; - const unsigned int t = y; + const UINT32 t = y; const double z = (x - ln2 * (double) t); - const double zz = z * z; - const double zzz = zz * z; + const double e = (1.0 + z * (1.0 + z * (0.5 + z * (c3 + z * (c4 + c5*z))))); - return (double)(1 << t)*(1.0 + z + 0.5 * zz + c3 * zzz); + if (t < 63) + //return (double)((UINT64) 1 << t)*(1.0 + z + 0.5 * zz + c3 * zzz+c4*zzzz+c5*zzzzz); + return (double)((UINT64) 1 << t) * e; + else + return pow(2.0, t)*e; } ATTR_HOT inline static double exp(const double x) diff --git a/src/emu/netlist/pconfig.h b/src/emu/netlist/pconfig.h deleted file mode 100644 index b05292b26e4..00000000000 --- a/src/emu/netlist/pconfig.h +++ /dev/null @@ -1,82 +0,0 @@ -// license:GPL-2.0+ -// copyright-holders:Couriersud -/* - * pconfig.h - * - */ - -#ifndef PCONFIG_H_ -#define PCONFIG_H_ - -#ifndef PSTANDALONE - #define PSTANDALONE (0) -#endif - -//============================================================ -// Compiling standalone -//============================================================ - -// Compiling without mame ? - -#include <algorithm> -#include <cstdarg> - -#if !(PSTANDALONE) -#include "osdcore.h" - -#undef ATTR_COLD -#define ATTR_COLD - -#else -#include <stdint.h> - -/* not supported in GCC prior to 4.4.x */ -/* ATTR_HOT and ATTR_COLD cause performance degration in 5.1 */ -//#define ATTR_HOT -//#define ATTR_COLD -#define ATTR_HOT __attribute__((hot)) -#define ATTR_COLD __attribute__((cold)) - -#define RESTRICT -#define EXPECTED(x) (x) -#define UNEXPECTED(x) (x) -#define ATTR_PRINTF(x,y) __attribute__((format(printf, x, y))) -#define ATTR_UNUSED __attribute__((__unused__)) - -/* 8-bit values */ -typedef unsigned char UINT8; -typedef signed char INT8; - -/* 16-bit values */ -typedef unsigned short UINT16; -typedef signed short INT16; - -/* 32-bit values */ -#ifndef _WINDOWS_H -typedef unsigned int UINT32; -typedef signed int INT32; -#endif - -/* 64-bit values */ -#ifndef _WINDOWS_H -#ifdef _MSC_VER -typedef signed __int64 INT64; -typedef unsigned __int64 UINT64; -#else -typedef uint64_t UINT64; -typedef int64_t INT64; -#endif -#endif - -/* U64 and S64 are used to wrap long integer constants. */ -#if defined(__GNUC__) || defined(_MSC_VER) -#define U64(val) val##ULL -#define S64(val) val##LL -#else -#define U64(val) val -#define S64(val) val -#endif - -#endif - -#endif /* PCONFIG_H_ */ diff --git a/src/emu/netlist/palloc.c b/src/emu/netlist/plib/palloc.c index 5f9dbc5fee7..5f9dbc5fee7 100644 --- a/src/emu/netlist/palloc.c +++ b/src/emu/netlist/plib/palloc.c diff --git a/src/emu/netlist/palloc.h b/src/emu/netlist/plib/palloc.h index e78bbc6e3ab..c5d060196f1 100644 --- a/src/emu/netlist/palloc.h +++ b/src/emu/netlist/plib/palloc.h @@ -40,28 +40,28 @@ inline T *palloc_t() } template<typename T, typename P1> -inline T *palloc_t(P1 &p1) +inline T *palloc_t(P1 p1) { void *p = palloc_raw(sizeof(T)); return new (p) T(p1); } template<typename T, typename P1, typename P2> -inline T *palloc_t(P1 &p1, P2 &p2) +inline T *palloc_t(P1 p1, P2 p2) { void *p = palloc_raw(sizeof(T)); return new (p) T(p1, p2); } template<typename T, typename P1, typename P2, typename P3> -inline T *palloc_t(P1 &p1, P2 &p2, P3 &p3) +inline T *palloc_t(P1 p1, P2 p2, P3 p3) { void *p = palloc_raw(sizeof(T)); return new (p) T(p1, p2, p3); } template<typename T, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7> -inline T *palloc_t(P1 &p1, P2 &p2, P3 &p3, P4 &p4, P5 &p5, P6 &p6, P7 &p7) +inline T *palloc_t(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { void *p = palloc_raw(sizeof(T)); return new (p) T(p1, p2, p3, p4, p5, p6, p7); @@ -87,9 +87,13 @@ inline void pfree_array_t(T *p) delete[] p; } +#if 1 #define palloc(T, ...) palloc_t<T>(__VA_ARGS__) #define pfree(_ptr) pfree_t(_ptr) - +#else +#define palloc(T, ...) new T(__VA_ARGS__) +#define pfree(_ptr) delete(_ptr) +#endif #define palloc_array(T, N) palloc_array_t<T>(N) #define pfree_array(_ptr) pfree_array_t(_ptr) diff --git a/src/emu/netlist/plib/pconfig.h b/src/emu/netlist/plib/pconfig.h new file mode 100644 index 00000000000..cfb4fe8fb60 --- /dev/null +++ b/src/emu/netlist/plib/pconfig.h @@ -0,0 +1,198 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud +/* + * pconfig.h + * + */ + +#ifndef PCONFIG_H_ +#define PCONFIG_H_ + +#ifndef PSTANDALONE + #define PSTANDALONE (0) +#endif + +#if !(PSTANDALONE) +#include "osdcore.h" +#include "eminline.h" + +#ifndef assert +#define assert(x) do {} while (0) +#endif + +#include "delegate.h" + +#else +#include <stdint.h> +#include <cstddef> +#endif + +//============================================================ +// Compiling standalone +//============================================================ + +#if !(PSTANDALONE) + +#undef ATTR_COLD +#define ATTR_COLD + +/* use MAME */ +#if (USE_DELEGATE_TYPE == DELEGATE_TYPE_INTERNAL) +#define PHAS_PMF_INTERNAL 1 +#else +#define PHAS_PMF_INTERNAL 0 +#endif + +#else + +/* determine PMF approach */ + +#if defined(__GNUC__) + /* does not work in versions over 4.7.x of 32bit MINGW */ + #if defined(__MINGW32__) && !defined(__x86_64) && defined(__i386__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7))) + #define PHAS_PMF_INTERNAL 1 + #define MEMBER_ABI __thiscall + #elif defined(EMSCRIPTEN) + #define PHAS_PMF_INTERNAL 0 + #elif defined(__arm__) || defined(__ARMEL__) + #define PHAS_PMF_INTERNAL 0 + #else + #define PHAS_PMF_INTERNAL 1 + #endif +#else +#define USE_DELEGATE_TYPE PHAS_PMF_INTERNAL 0 +#endif + +#ifndef MEMBER_ABI + #define MEMBER_ABI +#endif + +/* not supported in GCC prior to 4.4.x */ +/* ATTR_HOT and ATTR_COLD cause performance degration in 5.1 */ +//#define ATTR_HOT +//#define ATTR_COLD +#define ATTR_HOT __attribute__((hot)) +#define ATTR_COLD __attribute__((cold)) + +#define RESTRICT +#define EXPECTED(x) (x) +#define UNEXPECTED(x) (x) +#define ATTR_PRINTF(x,y) __attribute__((format(printf, x, y))) +#define ATTR_UNUSED __attribute__((__unused__)) + +/* 8-bit values */ +typedef unsigned char UINT8; +typedef signed char INT8; + +/* 16-bit values */ +typedef unsigned short UINT16; +typedef signed short INT16; + +/* 32-bit values */ +#ifndef _WINDOWS_H +typedef unsigned int UINT32; +typedef signed int INT32; +#endif + +/* 64-bit values */ +#ifndef _WINDOWS_H +#ifdef _MSC_VER +typedef signed __int64 INT64; +typedef unsigned __int64 UINT64; +#else +typedef uint64_t UINT64; +typedef int64_t INT64; +#endif +#endif + +/* U64 and S64 are used to wrap long integer constants. */ +#if defined(__GNUC__) || defined(_MSC_VER) +#define U64(val) val##ULL +#define S64(val) val##LL +#else +#define U64(val) val +#define S64(val) val +#endif + +/* MINGW has adopted the MSVC formatting for 64-bit ints as of gcc 4.4 */ +#if (defined(__MINGW32__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))) || defined(_MSC_VER) +#define I64FMT "I64" +#else +#define I64FMT "ll" +#endif + +#if defined(_MSC_VER) || defined(__MINGW32__) +#ifdef PTR64 +#define SIZETFMT "I64u" +#else +#define SIZETFMT "u" +#endif +#else +#define SIZETFMT "zu" +#endif + +#endif + +/* + * The following class was derived from the MAME delegate.h code. + * It derives a pointer to a member function. + */ + +#if (PHAS_PMF_INTERNAL) +class pmfp +{ +public: + // construct from any member function pointer + class generic_class; + typedef void (*generic_function)(); + + #if (PSTANDALONE) + typedef std::size_t FPTR; + #endif + + template<typename _MemberFunctionType> + pmfp(_MemberFunctionType mfp) + : m_function(0), m_this_delta(0) + { + *reinterpret_cast<_MemberFunctionType *>(this) = mfp; + } + + // binding helper + template<typename _FunctionType, typename _ObjectType> + _FunctionType update_after_bind(_ObjectType *object) + { + return reinterpret_cast<_FunctionType>( + convert_to_generic(reinterpret_cast<generic_class *>(object))); + } + template<typename _FunctionType, typename _MemberFunctionType, typename _ObjectType> + static _FunctionType get_mfp(_MemberFunctionType mfp, _ObjectType *object) + { + pmfp mfpo(mfp); + return mfpo.update_after_bind<_FunctionType>(object); + } + +private: + // extract the generic function and adjust the object pointer + generic_function convert_to_generic(generic_class * object) const + { + // apply the "this" delta to the object first + generic_class * o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<UINT8 *>(object) + m_this_delta); + + // if the low bit of the vtable index is clear, then it is just a raw function pointer + if (!(m_function & 1)) + return reinterpret_cast<generic_function>(m_function); + + // otherwise, it is the byte index into the vtable where the actual function lives + UINT8 *vtable_base = *reinterpret_cast<UINT8 **>(o_p_delta); + return *reinterpret_cast<generic_function *>(vtable_base + m_function - 1); + } + + // actual state + FPTR m_function; // first item can be one of two things: + // if even, it's a pointer to the function + // if odd, it's the byte offset into the vtable + int m_this_delta; // delta to apply to the 'this' pointer +}; +#endif + +#endif /* PCONFIG_H_ */ diff --git a/src/emu/netlist/plists.h b/src/emu/netlist/plib/plists.h index 25ded23fe83..4c223ab9150 100644 --- a/src/emu/netlist/plists.h +++ b/src/emu/netlist/plib/plists.h @@ -10,6 +10,8 @@ #ifndef PLISTS_H_ #define PLISTS_H_ +#include <cstring> + #include "palloc.h" #include "pstring.h" @@ -56,12 +58,12 @@ public: * array works around this. */ - ATTR_HOT /* inline */ _ListClass *data() { return m_list; } + ATTR_HOT _ListClass *data() { return m_list; } - ATTR_HOT /* inline */ _ListClass& operator[](std::size_t index) { return m_list[index]; } - ATTR_HOT /* inline */ const _ListClass& operator[](std::size_t index) const { return m_list[index]; } + ATTR_HOT _ListClass& operator[](std::size_t index) { return m_list[index]; } + ATTR_HOT const _ListClass& operator[](std::size_t index) const { return m_list[index]; } - ATTR_HOT /* inline */ std::size_t size() const { return m_capacity; } + ATTR_HOT std::size_t size() const { return m_capacity; } protected: ATTR_COLD void set_capacity(const std::size_t new_capacity) @@ -94,7 +96,7 @@ public: plist_t() : std::vector<_ListClass>() {} plist_t(const int numElements) : std::vector<_ListClass>(numElements) {} - /* inline */ void add(const _ListClass &elem) { this->push_back(elem); } + void add(const _ListClass &elem) { this->push_back(elem); } void clear_and_free() { for (_ListClass *i = this->data(); i < this->data() + this->size(); i++) @@ -103,7 +105,7 @@ public: } this->clear(); } - /* inline */ bool contains(const _ListClass &elem) const + bool contains(const _ListClass &elem) const { for (const _ListClass *i = this->data(); i < this->data() + this->size(); i++) { @@ -113,7 +115,7 @@ public: return false; } - /* inline */ void remove(const _ListClass &elem) + void remove(const _ListClass &elem) { for (int i = 0; i < this->size(); i++) { @@ -124,12 +126,12 @@ public: } } } - /* inline */ void remove_at(const int pos) + void remove_at(const int pos) { this->erase(this->begin() + pos); } - /* inline */ int indexof(const _ListClass &elem) const + int indexof(const _ListClass &elem) const { for (int i = 0; i < this->size(); i++) { @@ -139,7 +141,7 @@ public: return -1; } - ATTR_HOT /* inline */ void swap(const int pos1, const int pos2) + ATTR_HOT void swap(const int pos1, const int pos2) { //nl_assert((pos1>=0) && (pos1<m_count)); //nl_assert((pos2>=0) && (pos2<m_count)); @@ -198,12 +200,12 @@ public: m_list = NULL; } - ATTR_HOT /* inline */ _ListClass *data() { return m_list; } + ATTR_HOT _ListClass *data() { return m_list; } - ATTR_HOT /* inline */ _ListClass& operator[](std::size_t index) { return *(m_list + index); } - ATTR_HOT /* inline */ const _ListClass& operator[](std::size_t index) const { return *(m_list + index); } + ATTR_HOT _ListClass& operator[](std::size_t index) { return *(m_list + index); } + ATTR_HOT const _ListClass& operator[](std::size_t index) const { return *(m_list + index); } - ATTR_HOT /* inline */ void add(const _ListClass &elem) + ATTR_HOT void add(const _ListClass &elem) { if (m_count >= m_capacity){ std::size_t new_size = m_capacity * 2; @@ -215,7 +217,7 @@ public: m_list[m_count++] = elem; } - ATTR_HOT /* inline */ void remove(const _ListClass &elem) + ATTR_HOT void remove(const _ListClass &elem) { for (std::size_t i = 0; i < m_count; i++) { @@ -232,17 +234,17 @@ public: } } - ATTR_HOT /* inline */ void remove_at(const std::size_t pos) + ATTR_HOT void remove_at(const std::size_t pos) { //nl_assert((pos>=0) && (pos<m_count)); m_count--; - for (int i = pos; i < m_count; i++) + for (std::size_t i = pos; i < m_count; i++) { m_list[i] = m_list[i+1]; } } - ATTR_HOT /* inline */ void swap(const std::size_t pos1, const std::size_t pos2) + ATTR_HOT void swap(const std::size_t pos1, const std::size_t pos2) { //nl_assert((pos1>=0) && (pos1<m_count)); //nl_assert((pos2>=0) && (pos2<m_count)); @@ -251,7 +253,7 @@ public: m_list[pos2] =tmp; } - ATTR_HOT /* inline */ bool contains(const _ListClass &elem) const + ATTR_HOT bool contains(const _ListClass &elem) const { for (_ListClass *i = m_list; i < m_list + m_count; i++) { @@ -261,7 +263,7 @@ public: return false; } - ATTR_HOT /* inline */ int indexof(const _ListClass &elem) const + ATTR_HOT int indexof(const _ListClass &elem) const { for (std::size_t i = 0; i < m_count; i++) { @@ -271,10 +273,10 @@ public: return -1; } - ATTR_HOT /* inline */ std::size_t size() const { return m_count; } - ATTR_HOT /* inline */ bool is_empty() const { return (m_count == 0); } - ATTR_HOT /* inline */ void clear() { m_count = 0; } - ATTR_HOT /* inline */ std::size_t capacity() const { return m_capacity; } + ATTR_HOT std::size_t size() const { return m_count; } + ATTR_HOT bool is_empty() const { return (m_count == 0); } + ATTR_HOT void clear() { m_count = 0; } + ATTR_HOT std::size_t capacity() const { return m_capacity; } ATTR_COLD void clear_and_free() { @@ -337,9 +339,9 @@ template <class _ListClass> class pnamedlist_t : public plist_t<_ListClass> { public: - _ListClass find(const pstring &name) const + _ListClass find_by_name(const pstring &name) const { - for (int i=0; i < this->size(); i++) + for (std::size_t i=0; i < this->size(); i++) if (get_name((*this)[i]) == name) return (*this)[i]; return _ListClass(NULL); @@ -347,7 +349,7 @@ public: void remove_by_name(const pstring &name) { - plist_t<_ListClass>::remove(find(name)); + plist_t<_ListClass>::remove(find_by_name(name)); } bool add(_ListClass dev, bool allow_duplicate) @@ -356,7 +358,7 @@ public: plist_t<_ListClass>::add(dev); else { - if (!(this->find(get_name(dev)) == _ListClass(NULL))) + if (!(this->find_by_name(get_name(dev)) == _ListClass(NULL))) return false; plist_t<_ListClass>::add(dev); } @@ -364,9 +366,9 @@ public: } private: - template <typename T> static const pstring get_name(const T *elem) { return elem->name(); } - template <typename T> static const pstring get_name(T *elem) { return elem->name(); } - template <typename T> static const pstring get_name(const T &elem) { return elem.name(); } + template <typename T> const pstring &get_name(const T *elem) const { return elem->name(); } + template <typename T> const pstring &get_name(T *elem) const { return elem->name(); } + template <typename T> const pstring &get_name(const T &elem) const { return elem.name(); } }; @@ -401,27 +403,27 @@ public: { } - ATTR_HOT /* inline */ void push(const _StackClass &elem) + ATTR_HOT void push(const _StackClass &elem) { m_list.add(elem); } - ATTR_HOT /* inline */ _StackClass peek() const + ATTR_HOT _StackClass peek() const { return m_list[m_list.size() - 1]; } - ATTR_HOT /* inline */ _StackClass pop() + ATTR_HOT _StackClass pop() { _StackClass ret = peek(); m_list.remove_at(m_list.size() - 1); return ret; } - ATTR_HOT /* inline */ int count() const { return m_list.size(); } - ATTR_HOT /* inline */ bool empty() const { return (m_list.size() == 0); } - ATTR_HOT /* inline */ void reset() { m_list.reset(); } - ATTR_HOT /* inline */ int capacity() const { return m_list.capacity(); } + ATTR_HOT int count() const { return m_list.size(); } + ATTR_HOT bool empty() const { return (m_list.size() == 0); } + ATTR_HOT void reset() { m_list.reset(); } + ATTR_HOT int capacity() const { return m_list.capacity(); } private: plist_t<_StackClass> m_list; @@ -446,7 +448,7 @@ public: plinkedlist_t() : m_head(NULL) {} - ATTR_HOT /* inline */ void insert(const _ListClass &before, _ListClass &elem) + ATTR_HOT void insert(const _ListClass &before, _ListClass &elem) { if (m_head == &before) { @@ -471,13 +473,13 @@ public: } } - ATTR_HOT /* inline */ void insert(_ListClass &elem) + ATTR_HOT void insert(_ListClass &elem) { elem.m_next = m_head; m_head = &elem; } - ATTR_HOT /* inline */ void add(_ListClass &elem) + ATTR_HOT void add(_ListClass &elem) { _ListClass **p = &m_head; while (*p != NULL) @@ -488,7 +490,7 @@ public: elem.m_next = NULL; } - ATTR_HOT /* inline */ void remove(const _ListClass &elem) + ATTR_HOT void remove(const _ListClass &elem) { _ListClass **p = &m_head; while (*p != &elem) @@ -500,14 +502,84 @@ public: } - ATTR_HOT static /* inline */ _ListClass *next(const _ListClass &elem) { return elem.m_next; } - ATTR_HOT static /* inline */ _ListClass *next(const _ListClass *elem) { return elem->m_next; } - ATTR_HOT /* inline */ _ListClass *first() const { return m_head; } - ATTR_HOT /* inline */ void clear() { m_head = NULL; } - ATTR_HOT /* inline */ bool is_empty() const { return (m_head == NULL); } + ATTR_HOT static _ListClass *next(const _ListClass &elem) { return elem.m_next; } + ATTR_HOT static _ListClass *next(const _ListClass *elem) { return elem->m_next; } + ATTR_HOT _ListClass *first() const { return m_head; } + ATTR_HOT void clear() { m_head = NULL; } + ATTR_HOT bool is_empty() const { return (m_head == NULL); } private: _ListClass *m_head; }; +// ---------------------------------------------------------------------------------------- +// string list +// ---------------------------------------------------------------------------------------- + +class pstring_list_t : public plist_t<pstring> +{ +public: + pstring_list_t() : plist_t<pstring>() { } + + pstring_list_t(const pstring &str, const pstring &onstr, bool ignore_empty = false) + : plist_t<pstring>() + { + + int p = 0; + int pn; + + pn = str.find(onstr, p); + while (pn>=0) + { + pstring t = str.substr(p, pn - p); + if (!ignore_empty || t.len() != 0) + this->add(t); + p = pn + onstr.len(); + pn = str.find(onstr, p); + } + if (p<str.len()) + { + pstring t = str.substr(p); + if (!ignore_empty || t.len() != 0) + this->add(t); + } + } + + static pstring_list_t splitexpr(const pstring &str, const pstring_list_t &onstrl) + { + pstring_list_t temp; + pstring col = ""; + + int i = 0; + while (i<str.len()) + { + int p = -1; + for (std::size_t j=0; j < onstrl.size(); j++) + { + if (std::strncmp(onstrl[j].cstr(), &(str.cstr()[i]), onstrl[j].len())==0) + { + p = j; + break; + } + } + if (p>=0) + { + if (col != "") + temp.add(col); + col = ""; + temp.add(onstrl[p]); + i += onstrl[p].len(); + } + else + { + col += str.cstr()[i]; + i++; + } + } + if (col != "") + temp.add(col); + return temp; + } +}; + #endif /* PLISTS_H_ */ diff --git a/src/emu/netlist/poptions.h b/src/emu/netlist/plib/poptions.h index 7803a315d94..b082504930d 100644 --- a/src/emu/netlist/poptions.h +++ b/src/emu/netlist/plib/poptions.h @@ -59,6 +59,30 @@ private: pstring m_val; }; +class poption_str_limit : public poption +{ +public: + poption_str_limit(pstring ashort, pstring along, pstring defval, pstring limit, pstring help, poptions *parent = NULL) + : poption(ashort, along, help, true, parent), m_val(defval), m_limit(limit, ":") + {} + + virtual int parse(pstring argument) + { + if (m_limit.contains(argument)) + { + m_val = argument; + return 0; + } + else + return 1; + } + + pstring operator ()() { return m_val; } +private: + pstring m_val; + pstring_list_t m_limit; +}; + class poption_bool : public poption { public: diff --git a/src/emu/netlist/pparser.c b/src/emu/netlist/plib/pparser.c index 8e58f0dcae7..a6e633f22bb 100644 --- a/src/emu/netlist/pparser.c +++ b/src/emu/netlist/plib/pparser.c @@ -6,6 +6,7 @@ */ #include <cstdio> +#include <cstdarg> #include "pparser.h" @@ -96,6 +97,44 @@ pstring ptokenizer::get_identifier() return tok.str(); } +pstring ptokenizer::get_identifier_or_number() +{ + token_t tok = get_token(); + if (!(tok.is_type(IDENTIFIER) || tok.is_type(NUMBER))) + { + error("Error: expected an identifier, got <%s>\n", tok.str().cstr()); + } + return tok.str(); +} + +double ptokenizer::get_number_double() +{ + token_t tok = get_token(); + if (!tok.is_type(NUMBER)) + { + error("Error: expected a number, got <%s>\n", tok.str().cstr()); + } + bool err = false; + double ret = tok.str().as_double(&err); + if (err) + error("Error: expected a number, got <%s>\n", tok.str().cstr()); + return ret; +} + +long ptokenizer::get_number_long() +{ + token_t tok = get_token(); + if (!tok.is_type(NUMBER)) + { + error("Error: expected a long int, got <%s>\n", tok.str().cstr()); + } + bool err = false; + long ret = tok.str().as_long(&err); + if (err) + error("Error: expected a long int, got <%s>\n", tok.str().cstr()); + return ret; +} + ptokenizer::token_t ptokenizer::get_token() { while (true) @@ -135,7 +174,26 @@ ptokenizer::token_t ptokenizer::get_token_internal() return token_t(ENDOFFILE); } } - if (m_identifier_chars.find(c)>=0) + if (m_number_chars_start.find(c)>=0) + { + /* read number while we receive number or identifier chars + * treat it as an identifier when there are identifier chars in it + * + */ + token_type ret = NUMBER; + pstring tokstr = ""; + while (true) { + if (m_identifier_chars.find(c)>=0 && m_number_chars.find(c)<0) + ret = IDENTIFIER; + else if (m_number_chars.find(c)<0) + break; + tokstr += c; + c = getc(); + } + ungetc(); + return token_t(ret, tokstr); + } + else if (m_identifier_chars.find(c)>=0) { /* read identifier till non identifier char */ pstring tokstr = ""; @@ -209,6 +267,7 @@ ATTR_COLD void ptokenizer::error(const char *format, ...) ppreprocessor::ppreprocessor() { + m_expr_sep.add("!"); m_expr_sep.add("("); m_expr_sep.add(")"); m_expr_sep.add("+"); @@ -218,6 +277,8 @@ ppreprocessor::ppreprocessor() m_expr_sep.add("=="); m_expr_sep.add(" "); m_expr_sep.add("\t"); + + m_defines.add(define_t("__PLIB_PREPROCESSOR__", "1")); } void ppreprocessor::error(const pstring &err) @@ -227,18 +288,27 @@ void ppreprocessor::error(const pstring &err) -double ppreprocessor::expr(const nl_util::pstring_list &sexpr, std::size_t &start, int prio) +double ppreprocessor::expr(const pstring_list_t &sexpr, std::size_t &start, int prio) { double val; pstring tok=sexpr[start]; if (tok == "(") { start++; - val = expr(sexpr, start, prio); + val = expr(sexpr, start, /*prio*/ 0); if (sexpr[start] != ")") error("parsing error!"); start++; } + else if (tok == "!") + { + start++; + val = expr(sexpr, start, 90); + if (val != 0) + val = 0; + else + val = 1; + } else { tok=sexpr[start]; @@ -300,7 +370,7 @@ ppreprocessor::define_t *ppreprocessor::get_define(const pstring &name) pstring ppreprocessor::replace_macros(const pstring &line) { - nl_util::pstring_list elems = nl_util::splitexpr(line, m_expr_sep); + pstring_list_t elems = pstring_list_t::splitexpr(line, m_expr_sep); pstringbuffer ret = ""; for (std::size_t i=0; i<elems.size(); i++) { @@ -313,7 +383,7 @@ pstring ppreprocessor::replace_macros(const pstring &line) return pstring(ret.cstr()); } -static pstring catremainder(const nl_util::pstring_list &elems, std::size_t start, pstring sep) +static pstring catremainder(const pstring_list_t &elems, std::size_t start, pstring sep) { pstringbuffer ret = ""; for (std::size_t i=start; i<elems.size(); i++) @@ -327,7 +397,7 @@ static pstring catremainder(const nl_util::pstring_list &elems, std::size_t star pstring ppreprocessor::process(const pstring &contents) { pstringbuffer ret = ""; - nl_util::pstring_list lines = nl_util::split(contents,"\n", false); + pstring_list_t lines(contents,"\n", false); UINT32 ifflag = 0; // 31 if levels int level = 0; @@ -336,15 +406,16 @@ pstring ppreprocessor::process(const pstring &contents) { pstring line = lines[i]; pstring lt = line.replace("\t"," ").trim(); - lt = replace_macros(lt); + // FIXME ... revise and extend macro handling if (lt.startsWith("#")) { - nl_util::pstring_list lti = nl_util::split(lt, " ", true); + pstring_list_t lti(lt, " ", true); if (lti[0].equals("#if")) { level++; std::size_t start = 0; - nl_util::pstring_list t = nl_util::splitexpr(lt.substr(3).replace(" ",""), m_expr_sep); + lt = replace_macros(lt); + pstring_list_t t = pstring_list_t::splitexpr(lt.substr(3).replace(" ",""), m_expr_sep); int val = expr(t, start, 0); if (val == 0) ifflag |= (1 << level); @@ -376,7 +447,7 @@ pstring ppreprocessor::process(const pstring &contents) } else if (lti[0].equals("#pragma")) { - if (lti.size() > 3 && lti[1].equals("NETLIST")) + if (ifflag == 0 && lti.size() > 3 && lti[1].equals("NETLIST")) { if (lti[2].equals("warning")) error("NETLIST: " + catremainder(lti, 3, " ")); @@ -384,9 +455,12 @@ pstring ppreprocessor::process(const pstring &contents) } else if (lti[0].equals("#define")) { - if (lti.size() != 3) - error(pstring::sprintf("PREPRO: only simple defines allowed: %s", line.cstr())); - m_defines.add(define_t(lti[1], lti[2])); + if (ifflag == 0) + { + if (lti.size() != 3) + error(pstring::sprintf("PREPRO: only simple defines allowed: %s", line.cstr())); + m_defines.add(define_t(lti[1], lti[2])); + } } else error(pstring::sprintf("unknown directive on line %" SIZETFMT ": %s\n", i, line.cstr())); @@ -395,9 +469,10 @@ pstring ppreprocessor::process(const pstring &contents) { //if (ifflag == 0 && level > 0) // fprintf(stderr, "conditional: %s\n", line.cstr()); + lt = replace_macros(lt); if (ifflag == 0) { - ret.cat(line); + ret.cat(lt); ret.cat("\n"); } } diff --git a/src/emu/netlist/pparser.h b/src/emu/netlist/plib/pparser.h index b44e83f649c..f4f8cff2171 100644 --- a/src/emu/netlist/pparser.h +++ b/src/emu/netlist/plib/pparser.h @@ -9,8 +9,8 @@ #define PPARSER_H_ #include "pconfig.h" -#include "nl_config.h" // FIXME -#include "nl_util.h" +#include "../nl_config.h" // FIXME +#include "../nl_util.h" class ptokenizer { @@ -51,13 +51,13 @@ public: m_id = token_id_t(-1); m_token =""; } - token_t(token_type type, const pstring str) + token_t(token_type type, const pstring &str) { m_type = type; m_id = token_id_t(-1); m_token = str; } - token_t(const token_id_t id, const pstring str) + token_t(const token_id_t id, const pstring &str) { m_type = TOKEN; m_id = id; @@ -86,6 +86,9 @@ public: token_t get_token(); pstring get_string(); pstring get_identifier(); + pstring get_identifier_or_number(); + double get_number_double(); + long get_number_long(); void require_token(const token_id_t &token_num); void require_token(const token_t tok, const token_id_t &token_num); @@ -97,21 +100,22 @@ public: } void set_identifier_chars(pstring s) { m_identifier_chars = s; } - void set_number_chars(pstring s) { m_number_chars = s; } + void set_number_chars(pstring st, pstring rem) { m_number_chars_start = st; m_number_chars = rem; } + void set_string_char(char c) { m_string = c; } void set_whitespace(pstring s) { m_whitespace = s; } void set_comment(pstring start, pstring end, pstring line) { m_tok_comment_start = register_token(start); m_tok_comment_end = register_token(end); m_tok_line_comment = register_token(line); - m_string = '"'; } token_t get_token_internal(); void error(const char *format, ...) ATTR_PRINTF(2,3); -protected: void reset(const char *p) { m_px = p; m_line = 1; m_line_ptr = p; } + +protected: virtual void verror(pstring msg, int line_num, pstring line) = 0; private: @@ -129,6 +133,7 @@ private: pstring m_identifier_chars; pstring m_number_chars; + pstring m_number_chars_start; plist_t<pstring> m_tokens; pstring m_whitespace; char m_string; @@ -161,7 +166,7 @@ public: protected: - double expr(const nl_util::pstring_list &sexpr, std::size_t &start, int prio); + double expr(const pstring_list_t &sexpr, std::size_t &start, int prio); define_t *get_define(const pstring &name); @@ -172,7 +177,7 @@ protected: private: plist_t<define_t> m_defines; - nl_util::pstring_list m_expr_sep; + pstring_list_t m_expr_sep; }; #endif /* PPARSER_H_ */ diff --git a/src/emu/netlist/pstate.c b/src/emu/netlist/plib/pstate.c index 07532032405..07532032405 100644 --- a/src/emu/netlist/pstate.c +++ b/src/emu/netlist/plib/pstate.c diff --git a/src/emu/netlist/pstate.h b/src/emu/netlist/plib/pstate.h index 73b83e65a00..27e0ea08ebb 100644 --- a/src/emu/netlist/pstate.h +++ b/src/emu/netlist/plib/pstate.h @@ -71,6 +71,7 @@ NETLIST_SAVE_TYPE(INT32, DT_INT); NETLIST_SAVE_TYPE(UINT16, DT_INT16); NETLIST_SAVE_TYPE(INT16, DT_INT16); //NETLIST_SAVE_TYPE(netlist_time::INTERNALTYPE, DT_INT64); +//NETLIST_SAVE_TYPE(std::size_t, DT_INT64); class pstate_manager_t; diff --git a/src/emu/netlist/pstring.c b/src/emu/netlist/plib/pstring.c index ec930808e7b..e5f73ffa17b 100644 --- a/src/emu/netlist/pstring.c +++ b/src/emu/netlist/plib/pstring.c @@ -5,12 +5,12 @@ * */ -#include <new> #include <cstdio> #include <cstring> //FIXME:: pstring should be locale free #include <cctype> #include <cstdlib> +#include <algorithm> #include "pstring.h" #include "palloc.h" @@ -73,7 +73,7 @@ void pstring::pcopy(const char *from, int size) m_ptr = n; } -pstring pstring::substr(unsigned int start, int count) const +const pstring pstring::substr(unsigned int start, int count) const { pstring ret; unsigned alen = len(); @@ -85,7 +85,7 @@ pstring pstring::substr(unsigned int start, int count) const return ret; } -pstring pstring::ucase() const +const pstring pstring::ucase() const { pstring ret = *this; ret.pcopy(cstr(), len()); @@ -94,7 +94,7 @@ pstring pstring::ucase() const return ret; } -int pstring::find_first_not_of(const pstring no) const +int pstring::find_first_not_of(const pstring &no) const { for (int i=0; i < len(); i++) { @@ -108,7 +108,7 @@ int pstring::find_first_not_of(const pstring no) const return -1; } -int pstring::find_last_not_of(const pstring no) const +int pstring::find_last_not_of(const pstring &no) const { for (int i=len() - 1; i >= 0; i--) { @@ -144,7 +144,7 @@ pstring pstring::replace(const pstring &search, const pstring &replace) const } return ret; } -pstring pstring::ltrim(const pstring ws) const +const pstring pstring::ltrim(const pstring &ws) const { int f = find_first_not_of(ws); if (f>=0) @@ -153,7 +153,7 @@ pstring pstring::ltrim(const pstring ws) const return ""; } -pstring pstring::rtrim(const pstring ws) const +const pstring pstring::rtrim(const pstring &ws) const { int f = find_last_not_of(ws); if (f>=0) @@ -218,7 +218,7 @@ long pstring::as_long(bool *error) const return ret; } -pstring pstring::vprintf(va_list args) const +const pstring pstring::vprintf(va_list args) const { // sprintf into the temporary buffer char tempbuf[4096]; @@ -259,7 +259,7 @@ void pstring::resetmem() // pstring ... // ---------------------------------------------------------------------------------------- -pstring pstring::sprintf(const char *format, ...) +const pstring pstring::sprintf(const char *format, ...) { va_list ap; va_start(ap, format); diff --git a/src/emu/netlist/pstring.h b/src/emu/netlist/plib/pstring.h index 7cfb936472c..88a8922e98b 100644 --- a/src/emu/netlist/pstring.h +++ b/src/emu/netlist/plib/pstring.h @@ -7,6 +7,9 @@ #ifndef _PSTRING_H_ #define _PSTRING_H_ +#include <cstdarg> +#include <cstddef> + #include "pconfig.h" // ---------------------------------------------------------------------------------------- @@ -36,7 +39,7 @@ public: // C string conversion operators and helpers operator const char *() const { return m_ptr->str(); } - inline const char *cstr() const { return m_ptr->str(); } + const char *cstr() const { return m_ptr->str(); } // concatenation operators pstring& operator+=(const char c) { char buf[2] = { c, 0 }; pcat(buf); return *this; } @@ -61,13 +64,13 @@ public: bool operator>=(const char *string) const { return (pcmp(string) >= 0); } bool operator>=(const pstring &string) const { return (pcmp(string.cstr()) >= 0); } - inline int len() const { return m_ptr->len(); } + int len() const { return m_ptr->len(); } - inline bool equals(const pstring &string) const { return (pcmp(string.cstr(), m_ptr->str()) == 0); } - inline bool iequals(const pstring &string) const { return (pcmpi(string.cstr(), m_ptr->str()) == 0); } + bool equals(const pstring &string) const { return (pcmp(string.cstr(), m_ptr->str()) == 0); } + bool iequals(const pstring &string) const { return (pcmpi(string.cstr(), m_ptr->str()) == 0); } - inline int cmp(const pstring &string) const { return pcmp(string.cstr()); } - inline int cmpi(const pstring &string) const { return pcmpi(cstr(), string.cstr()); } + int cmp(const pstring &string) const { return pcmp(string.cstr()); } + int cmpi(const pstring &string) const { return pcmpi(cstr(), string.cstr()); } int find(const char *search, int start = 0) const; @@ -75,28 +78,28 @@ public: // various - inline bool startsWith(const pstring &arg) const { return (pcmp(cstr(), arg.cstr(), arg.len()) == 0); } + bool startsWith(const pstring &arg) const { return (pcmp(cstr(), arg.cstr(), arg.len()) == 0); } bool startsWith(const char *arg) const; pstring replace(const pstring &search, const pstring &replace) const; // these return nstring ... - inline pstring cat(const pstring &s) const { return *this + s; } - inline pstring cat(const char *s) const { return *this + s; } + const pstring cat(const pstring &s) const { return *this + s; } + const pstring cat(const char *s) const { return *this + s; } - pstring substr(unsigned int start, int count = -1) const ; + const pstring substr(unsigned int start, int count = -1) const ; - inline pstring left(unsigned int count) const { return substr(0, count); } - inline pstring right(unsigned int count) const { return substr(len() - count, count); } + const pstring left(unsigned int count) const { return substr(0, count); } + const pstring right(unsigned int count) const { return substr(len() - count, count); } - int find_first_not_of(const pstring no) const; - int find_last_not_of(const pstring no) const; + int find_first_not_of(const pstring &no) const; + int find_last_not_of(const pstring &no) const; - pstring ltrim(const pstring ws = " \t\n\r") const; - pstring rtrim(const pstring ws = " \t\n\r") const; - inline pstring trim(const pstring ws = " \t\n\r") const { return this->ltrim(ws).rtrim(ws); } + const pstring ltrim(const pstring &ws = " \t\n\r") const; + const pstring rtrim(const pstring &ws = " \t\n\r") const; + const pstring trim(const pstring &ws = " \t\n\r") const { return this->ltrim(ws).rtrim(ws); } - pstring rpad(const pstring ws, const int cnt) const + const pstring rpad(const pstring &ws, const int cnt) const { // FIXME: slow! pstring ret = *this; @@ -105,7 +108,7 @@ public: return ret.substr(0, cnt); } - pstring ucase() const; + const pstring ucase() const; // conversions @@ -115,10 +118,10 @@ public: // printf using string as format ... - pstring vprintf(va_list args) const; + const pstring vprintf(va_list args) const; // static - static pstring sprintf(const char *format, ...) ATTR_PRINTF(1,2); + static const pstring sprintf(const char *format, ...) ATTR_PRINTF(1,2); static void resetmem(); protected: @@ -147,13 +150,13 @@ protected: str_t *m_ptr; private: - inline void init() + void init() { m_ptr = &m_zero; m_ptr->m_ref_count++; } - inline int pcmp(const char *right) const + int pcmp(const char *right) const { return pcmp(m_ptr->str(), right); } @@ -166,7 +169,7 @@ private: void pcopy(const char *from); - inline void pcopy(const pstring &from) + void pcopy(const pstring &from) { sfree(m_ptr); m_ptr = from.m_ptr; @@ -212,7 +215,7 @@ public: // C string conversion operators and helpers operator const char *() const { return m_ptr; } - inline const char *cstr() const { return m_ptr; } + const char *cstr() const { return m_ptr; } operator pstring() const { return pstring(m_ptr); } @@ -220,10 +223,10 @@ public: pstringbuffer& operator+=(const char c) { char buf[2] = { c, 0 }; pcat(buf); return *this; } pstringbuffer& operator+=(const pstring &string) { pcat(string.cstr()); return *this; } - inline std::size_t len() const { return m_len; } + std::size_t len() const { return m_len; } - inline void cat(const pstring &s) { pcat(s); } - inline void cat(const char *s) { pcat(s); } + void cat(const pstring &s) { pcat(s); } + void cat(const char *s) { pcat(s); } pstring substr(unsigned int start, int count = -1) { @@ -232,7 +235,7 @@ public: private: - inline void init() + void init() { m_ptr = NULL; m_size = 0; diff --git a/src/emu/netlist/tools/nl_convert.c b/src/emu/netlist/tools/nl_convert.c new file mode 100644 index 00000000000..698bb6a5a4d --- /dev/null +++ b/src/emu/netlist/tools/nl_convert.c @@ -0,0 +1,458 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud +/* + * nl_convert.c + * + */ + +#include <algorithm> + +#include "nl_convert.h" + +template<typename Class> +static plist_t<int> bubble(const pnamedlist_t<Class *> &sl) +{ + plist_t<int> ret(sl.size()); + for (int i=0; i<sl.size(); i++) + ret[i] = i; + + for(int i=0; i < sl.size()-1;i++) + { + for(int j=i+1; j < sl.size(); j++) + { + if(sl[ret[i]]->name() > sl[ret[j]]->name()) + { + std::swap(ret[i], ret[j]); + } + } + } + return ret; +} + +/*------------------------------------------------- + convert - convert a spice netlist +-------------------------------------------------*/ + + +void nl_convert_base_t::out(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + m_buf += pstring(format).vprintf(ap); + va_end(ap); +} + +void nl_convert_base_t::add_pin_alias(const pstring &devname, const pstring &name, const pstring &alias) +{ + m_pins.add(palloc(pin_alias_t, devname + "." + name, devname + "." + alias), false); +} + +void nl_convert_base_t::add_ext_alias(const pstring &alias) +{ + m_ext_alias.add(alias); +} + +void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname, const pstring &amodel) +{ + m_devs.add(palloc(dev_t, atype, aname, amodel), false); +} +void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname, double aval) +{ + m_devs.add(palloc(dev_t, atype, aname, aval), false); +} +void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname) +{ + m_devs.add(palloc(dev_t, atype, aname), false); +} + +void nl_convert_base_t::add_term(pstring netname, pstring termname) +{ + net_t * net = m_nets.find_by_name(netname); + if (net == NULL) + { + net = palloc(net_t, netname); + m_nets.add(net, false); + } + + /* if there is a pin alias, translate ... */ + pin_alias_t *alias = m_pins.find_by_name(termname); + + if (alias != NULL) + net->terminals().add(alias->alias()); + else + net->terminals().add(termname); +} + +void nl_convert_base_t::dump_nl() +{ + for (std::size_t i=0; i<m_ext_alias.size(); i++) + { + net_t *net = m_nets.find_by_name(m_ext_alias[i]); + // use the first terminal ... + out("ALIAS(%s, %s)\n", m_ext_alias[i].cstr(), net->terminals()[0].cstr()); + // if the aliased net only has this one terminal connected ==> don't dump + if (net->terminals().size() == 1) + net->set_no_export(); + } + plist_t<int> sorted = bubble(m_devs); + for (std::size_t i=0; i<m_devs.size(); i++) + { + std::size_t j = sorted[i]; + + if (m_devs[j]->has_value()) + out("%s(%s, %s)\n", m_devs[j]->type().cstr(), + m_devs[j]->name().cstr(), get_nl_val(m_devs[j]->value()).cstr()); + else if (m_devs[j]->has_model()) + out("%s(%s, \"%s\")\n", m_devs[j]->type().cstr(), + m_devs[j]->name().cstr(), m_devs[j]->model().cstr()); + else + out("%s(%s)\n", m_devs[j]->type().cstr(), + m_devs[j]->name().cstr()); + } + // print nets + for (std::size_t i=0; i<m_nets.size(); i++) + { + net_t * net = m_nets[i]; + if (!net->is_no_export()) + { + //printf("Net %s\n", net->name().cstr()); + out("NET_C(%s", net->terminals()[0].cstr() ); + for (std::size_t j=1; j<net->terminals().size(); j++) + { + out(", %s", net->terminals()[j].cstr() ); + } + out(")\n"); + } + } + m_devs.clear_and_free(); + m_nets.clear_and_free(); + m_pins.clear_and_free(); + m_ext_alias.clear(); +} + +const pstring nl_convert_base_t::get_nl_val(const double val) +{ + { + int i = 0; + while (m_units[i].m_unit != "-" ) + { + if (m_units[i].m_mult <= nl_math::abs(val)) + break; + i++; + } + return pstring::sprintf(m_units[i].m_func.cstr(), val / m_units[i].m_mult); + } +} +double nl_convert_base_t::get_sp_unit(const pstring &unit) +{ + int i = 0; + while (m_units[i].m_unit != "-") + { + if (m_units[i].m_unit == unit) + return m_units[i].m_mult; + i++; + } + fprintf(stderr, "Unit %s unknown\n", unit.cstr()); + return 0.0; +} + +double nl_convert_base_t::get_sp_val(const pstring &sin) +{ + int p = sin.len() - 1; + while (p>=0 && (sin.substr(p,1) < "0" || sin.substr(p,1) > "9")) + p--; + pstring val = sin.substr(0,p + 1); + pstring unit = sin.substr(p + 1); + + double ret = get_sp_unit(unit) * val.as_double(); + //printf("<%s> %s %d ==> %f\n", sin.cstr(), unit.cstr(), p, ret); + return ret; +} + +nl_convert_base_t::unit_t nl_convert_base_t::m_units[] = { + {"T", "", 1.0e12 }, + {"G", "", 1.0e9 }, + {"MEG", "RES_M(%g)", 1.0e6 }, + {"k", "RES_K(%g)", 1.0e3 }, /* eagle */ + {"K", "RES_K(%g)", 1.0e3 }, + {"", "%g", 1.0e0 }, + {"M", "CAP_M(%g)", 1.0e-3 }, + {"u", "CAP_U(%g)", 1.0e-6 }, /* eagle */ + {"U", "CAP_U(%g)", 1.0e-6 }, + {"µ", "CAP_U(%g)", 1.0e-6 }, + {"N", "CAP_N(%g)", 1.0e-9 }, + {"P", "CAP_P(%g)", 1.0e-12}, + {"F", "%ge-15", 1.0e-15}, + + {"MIL", "%e", 25.4e-6}, + + {"-", "%g", 1.0 } +}; + + +void nl_convert_spice_t::convert(const pstring &contents) +{ + pstring_list_t spnl(contents, "\n"); + + // Add gnd net + + // FIXME: Parameter + out("NETLIST_START(dummy)\n"); + add_term("0", "GND"); + + pstring line = ""; + + for (std::size_t i=0; i < spnl.size(); i++) + { + // Basic preprocessing + pstring inl = spnl[i].trim().ucase(); + if (inl.startsWith("+")) + line = line + inl.substr(1); + else + { + process_line(line); + line = inl; + } + } + process_line(line); + dump_nl(); + // FIXME: Parameter + out("NETLIST_END()\n"); +} + +void nl_convert_spice_t::process_line(const pstring &line) +{ + if (line != "") + { + pstring_list_t tt(line, " ", true); + double val = 0.0; + switch (tt[0].cstr()[0]) + { + case ';': + out("// %s\n", line.substr(1).cstr()); + break; + case '*': + out("// %s\n", line.substr(1).cstr()); + break; + case '.': + if (tt[0].equals(".SUBCKT")) + { + out("NETLIST_START(%s)\n", tt[1].cstr()); + for (std::size_t i=2; i<tt.size(); i++) + add_ext_alias(tt[i]); + } + else if (tt[0].equals(".ENDS")) + { + dump_nl(); + out("NETLIST_END()\n"); + } + else + out("// %s\n", line.cstr()); + break; + case 'Q': + { + bool cerr = false; + /* check for fourth terminal ... should be numeric net + * including "0" or start with "N" (ltspice) + */ + ATTR_UNUSED int nval =tt[4].as_long(&cerr); + pstring model; + pstring pins ="CBE"; + + if ((!cerr || tt[4].startsWith("N")) && tt.size() > 5) + model = tt[5]; + else + model = tt[4]; + pstring_list_t m(model,"{"); + if (m.size() == 2) + { + if (m[1].len() != 4) + fprintf(stderr, "error with model desc %s\n", model.cstr()); + pins = m[1].left(3); + } + add_device("QBJT_EB", tt[0], m[0]); + add_term(tt[1], tt[0] + "." + pins[0]); + add_term(tt[2], tt[0] + "." + pins[1]); + add_term(tt[3], tt[0] + "." + pins[2]); + } + break; + case 'R': + if (tt[0].startsWith("RV")) + { + val = get_sp_val(tt[4]); + add_device("POT", tt[0], val); + add_term(tt[1], tt[0] + ".1"); + add_term(tt[2], tt[0] + ".2"); + add_term(tt[3], tt[0] + ".3"); + } + else + { + val = get_sp_val(tt[3]); + add_device("RES", tt[0], val); + add_term(tt[1], tt[0] + ".1"); + add_term(tt[2], tt[0] + ".2"); + } + break; + case 'C': + val = get_sp_val(tt[3]); + add_device("CAP", tt[0], val); + add_term(tt[1], tt[0] + ".1"); + add_term(tt[2], tt[0] + ".2"); + break; + case 'V': + // just simple Voltage sources .... + if (tt[2].equals("0")) + { + val = get_sp_val(tt[3]); + add_device("ANALOG_INPUT", tt[0], val); + add_term(tt[1], tt[0] + ".Q"); + //add_term(tt[2], tt[0] + ".2"); + } + else + fprintf(stderr, "Voltage Source %s not connected to GND\n", tt[0].cstr()); + break; + case 'I': // Input pin special notation + { + val = get_sp_val(tt[2]); + add_device("ANALOG_INPUT", tt[0], val); + add_term(tt[1], tt[0] + ".Q"); + } + break; + case 'D': + add_device("DIODE", tt[0], tt[3]); + /* FIXME ==> does Kicad use different notation from LTSPICE */ + add_term(tt[1], tt[0] + ".K"); + add_term(tt[2], tt[0] + ".A"); + break; + case 'U': + case 'X': + { + // FIXME: specific code for KICAD exports + // last element is component type + // FIXME: Parameter + + pstring xname = tt[0].replace(".", "_"); + pstring tname = "TTL_" + tt[tt.size()-1] + "_DIP"; + add_device(tname, xname); + for (std::size_t i=1; i < tt.size() - 1; i++) + { + pstring term = pstring::sprintf("%s.%" SIZETFMT, xname.cstr(), i); + add_term(tt[i], term); + } + break; + } + default: + out("// IGNORED %s: %s\n", tt[0].cstr(), line.cstr()); + } + } +} + + +void nl_convert_eagle_t::convert(const pstring &contents) +{ + eagle_tokenizer tok(*this); + tok.reset(contents.cstr()); + + out("NETLIST_START(dummy)\n"); + add_term("GND", "GND"); + add_term("VCC", "VCC"); + eagle_tokenizer::token_t token = tok.get_token(); + while (true) + { + if (token.is_type(eagle_tokenizer::ENDOFFILE)) + { + dump_nl(); + // FIXME: Parameter + out("NETLIST_END()\n"); + return; + } + else if (token.is(tok.m_tok_SEMICOLON)) + { + /* ignore empty statements */ + token = tok.get_token(); + } + else if (token.is(tok.m_tok_ADD)) + { + pstring name = tok.get_string(); + /* skip to semicolon */ + do + { + token = tok.get_token(); + } while (!token.is(tok.m_tok_SEMICOLON)); + token = tok.get_token(); + pstring sval = ""; + if (token.is(tok.m_tok_VALUE)) + { + pstring vname = tok.get_string(); + sval = tok.get_string(); + tok.require_token(tok.m_tok_SEMICOLON); + token = tok.get_token(); + } + switch (name.cstr()[0]) + { + case 'Q': + { + add_device("QBJT", name, sval); + } + break; + case 'R': + { + double val = get_sp_val(sval); + add_device("RES", name, val); + } + break; + case 'C': + { + double val = get_sp_val(sval); + add_device("CAP", name, val); + } + break; + case 'P': + if (sval.ucase() == "HIGH") + add_device("TTL_INPUT", name, 1); + else if (sval.ucase() == "LOW") + add_device("TTL_INPUT", name, 0); + else + add_device("ANALOG_INPUT", name, sval.as_double()); + add_pin_alias(name, "1", "Q"); + break; + case 'D': + /* Pin 1 = Anode, Pin 2 = Cathode */ + add_device("DIODE", name, sval); + add_pin_alias(name, "1", "A"); + add_pin_alias(name, "2", "K"); + break; + case 'U': + case 'X': + { + pstring tname = "TTL_" + sval + "_DIP"; + add_device(tname, name); + break; + } + default: + tok.error("// IGNORED %s\n", name.cstr()); + } + + } + else if (token.is(tok.m_tok_SIGNAL)) + { + pstring netname = tok.get_string(); + token = tok.get_token(); + while (!token.is(tok.m_tok_SEMICOLON)) + { + /* fixme: should check for string */ + pstring devname = token.str(); + pstring pin = tok.get_string(); + add_term(netname, devname + "." + pin); + token = tok.get_token(); } + } + else + { + out("Unexpected %s\n", token.str().cstr()); + return; + } + } + +} + + diff --git a/src/emu/netlist/tools/nl_convert.h b/src/emu/netlist/tools/nl_convert.h new file mode 100644 index 00000000000..4a0efd020a7 --- /dev/null +++ b/src/emu/netlist/tools/nl_convert.h @@ -0,0 +1,219 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud +/* + * nl_convert.h + * + */ + +#pragma once + +#ifndef NL_CONVERT_H_ +#define NL_CONVERT_H_ + +#include "plib/pstring.h" +#include "plib/plists.h" +#include "plib/pparser.h" + +/*------------------------------------------------- + convert - convert a spice netlist +-------------------------------------------------*/ + +class nl_convert_base_t +{ +public: + + nl_convert_base_t() {}; + virtual ~nl_convert_base_t() + { + m_nets.clear_and_free(); + m_devs.clear_and_free(); + m_pins.clear_and_free(); + } + + const pstringbuffer &result() { return m_buf; } + virtual void convert(const pstring &contents) = 0; + +protected: + + void out(const char *format, ...) ATTR_PRINTF(2,3); + void add_pin_alias(const pstring &devname, const pstring &name, const pstring &alias); + + void add_ext_alias(const pstring &alias); + + void add_device(const pstring &atype, const pstring &aname, const pstring &amodel); + void add_device(const pstring &atype, const pstring &aname, double aval); + void add_device(const pstring &atype, const pstring &aname); + + void add_term(pstring netname, pstring termname); + + void dump_nl(); + + const pstring get_nl_val(const double val); + double get_sp_unit(const pstring &unit); + + double get_sp_val(const pstring &sin); + +private: + struct net_t + { + public: + net_t(const pstring &aname) + : m_name(aname), m_no_export(false) {} + + const pstring &name() { return m_name;} + pstring_list_t &terminals() { return m_terminals; } + void set_no_export() { m_no_export = true; } + bool is_no_export() { return m_no_export; } + + private: + pstring m_name; + bool m_no_export; + pstring_list_t m_terminals; + }; + + struct dev_t + { + public: + dev_t(const pstring &atype, const pstring &aname, const pstring &amodel) + : m_type(atype), m_name(aname), m_model(amodel), m_val(0), m_has_val(false) + {} + + dev_t(const pstring &atype, const pstring &aname, double aval) + : m_type(atype), m_name(aname), m_model(""), m_val(aval), m_has_val(true) + {} + + dev_t(const pstring &atype, const pstring &aname) + : m_type(atype), m_name(aname), m_model(""), m_val(0.0), m_has_val(false) + {} + + const pstring &name() { return m_name;} + const pstring &type() { return m_type;} + const pstring &model() { return m_model;} + const double &value() { return m_val;} + + bool has_model() { return m_model != ""; } + bool has_value() { return m_has_val; } + + private: + pstring m_type; + pstring m_name; + pstring m_model; + double m_val; + bool m_has_val; + }; + + struct unit_t { + pstring m_unit; + pstring m_func; + double m_mult; + }; + + struct pin_alias_t + { + public: + pin_alias_t(const pstring &name, const pstring &alias) + : m_name(name), m_alias(alias) + {} + const pstring &name() { return m_name; } + const pstring &alias() { return m_alias; } + private: + pstring m_name; + pstring m_alias; + }; + +private: + + pstringbuffer m_buf; + + pnamedlist_t<dev_t *> m_devs; + pnamedlist_t<net_t *> m_nets; + plist_t<pstring> m_ext_alias; + pnamedlist_t<pin_alias_t *> m_pins; + + static unit_t m_units[]; + +}; + +class nl_convert_spice_t : public nl_convert_base_t +{ +public: + + nl_convert_spice_t() : nl_convert_base_t() {}; + ~nl_convert_spice_t() + { + } + + void convert(const pstring &contents); + +protected: + + void process_line(const pstring &line); + +private: + +}; + +class nl_convert_eagle_t : public nl_convert_base_t +{ +public: + + nl_convert_eagle_t() : nl_convert_base_t() {}; + ~nl_convert_eagle_t() + { + } + + class eagle_tokenizer : public ptokenizer + { + + public: + eagle_tokenizer(nl_convert_eagle_t &convert) + : ptokenizer(), m_convert(convert) + { + set_identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-"); + set_number_chars(".0123456789", "0123456789eE-."); //FIXME: processing of numbers + char ws[5]; + ws[0] = ' '; + ws[1] = 9; + ws[2] = 10; + ws[3] = 13; + ws[4] = 0; + set_whitespace(ws); + /* FIXME: gnetlist doesn't print comments */ + set_comment("/*", "*/", "//"); + set_string_char('\''); + m_tok_ADD = register_token("ADD"); + m_tok_VALUE = register_token("VALUE"); + m_tok_SIGNAL = register_token("SIGNAL"); + m_tok_SEMICOLON = register_token(";"); + /* currently not used, but required for parsing */ + register_token(")"); + register_token("("); + } + + token_id_t m_tok_ADD; + token_id_t m_tok_VALUE; + token_id_t m_tok_SIGNAL; + token_id_t m_tok_SEMICOLON; + + protected: + + void verror(pstring msg, int line_num, pstring line) + { + m_convert.out("%s (line %d): %s\n", msg.cstr(), line_num, line.cstr()); + } + + + private: + nl_convert_eagle_t &m_convert; + }; + + void convert(const pstring &contents); + +protected: + + +private: + +}; + +#endif /* NL_CONVERT_H_ */ diff --git a/src/emu/schedule.h b/src/emu/schedule.h index 36ae83d2929..a2d8660ef4f 100644 --- a/src/emu/schedule.h +++ b/src/emu/schedule.h @@ -144,10 +144,12 @@ public: void synchronize(timer_expired_delegate callback = timer_expired_delegate(), int param = 0, void *ptr = NULL) { timer_set(attotime::zero, callback, param, ptr); } // timers with old-skool callbacks +#ifdef USE_STATIC_DELEGATE emu_timer *timer_alloc(timer_expired_func callback, const char *name, void *ptr = NULL) { return timer_alloc(timer_expired_delegate(callback, name, &machine()), ptr); } void timer_set(const attotime &duration, timer_expired_func callback, const char *name, int param = 0, void *ptr = NULL) { timer_set(duration, timer_expired_delegate(callback, name, &machine()), param, ptr); } void timer_pulse(const attotime &period, timer_expired_func callback, const char *name, int param = 0, void *ptr = NULL) { timer_pulse(period, timer_expired_delegate(callback, name, &machine()), param, ptr); } void synchronize(timer_expired_func callback, const char *name = NULL, int param = 0, void *ptr = NULL) { timer_set(attotime::zero, callback, name, param, ptr); } +#endif // timers, specified by device/id; generally devices should use the device_t methods instead emu_timer *timer_alloc(device_t &device, device_timer_id id = 0, void *ptr = NULL); diff --git a/src/emu/softlist.c b/src/emu/softlist.c index 9f6fd339b8b..b9719d29a33 100644 --- a/src/emu/softlist.c +++ b/src/emu/softlist.c @@ -557,6 +557,13 @@ void software_list_device::internal_validity_check(validity_checker &valid) break; } + // Did we lost the software parts? + if (swinfo->num_parts() == 0) + { + osd_printf_error("%s: %s has no part\n", filename(), swinfo->shortname()); + break; + } + // Second, since the xml is fine, run additional checks: // check for duplicate names diff --git a/src/emu/sound/aica.c b/src/emu/sound/aica.c index 225d3e396e1..e788b4fda34 100644 --- a/src/emu/sound/aica.c +++ b/src/emu/sound/aica.c @@ -1,4 +1,4 @@ -// license:BSD-3-Clause +// license:??? // copyright-holders:ElSemi, kingshriek, Deunan Knute, R. Belmont /* Sega/Yamaha AICA emulation diff --git a/src/emu/sound/aica.h b/src/emu/sound/aica.h index 25c6cb54fd1..0c7d5caf4f4 100644 --- a/src/emu/sound/aica.h +++ b/src/emu/sound/aica.h @@ -1,4 +1,4 @@ -// license:BSD-3-Clause +// license:??? // copyright-holders:ElSemi, kingshriek, Deunan Knute, R. Belmont /* diff --git a/src/emu/sound/aicadsp.c b/src/emu/sound/aicadsp.c index 7e8d4914171..4f533125825 100644 --- a/src/emu/sound/aicadsp.c +++ b/src/emu/sound/aicadsp.c @@ -1,4 +1,4 @@ -// license:BSD-3-Clause +// license:??? // copyright-holders:ElSemi, kingshriek, Deunan Knute, R. Belmont #include "emu.h" #include "aicadsp.h" diff --git a/src/emu/sound/aicadsp.h b/src/emu/sound/aicadsp.h index f5672e3dbd3..e28301a6100 100644 --- a/src/emu/sound/aicadsp.h +++ b/src/emu/sound/aicadsp.h @@ -1,4 +1,4 @@ -// license:BSD-3-Clause +// license:??? // copyright-holders:ElSemi, kingshriek, Deunan Knute, R. Belmont #pragma once diff --git a/src/emu/sound/c352.c b/src/emu/sound/c352.c index aab4fdbb3d3..c164bc53413 100644 --- a/src/emu/sound/c352.c +++ b/src/emu/sound/c352.c @@ -46,6 +46,17 @@ c352_device::c352_device(const machine_config &mconfig, const char *tag, device_ } //------------------------------------------------- +// static_set_dividder - configuration helper to +// set the divider setting +//------------------------------------------------- + +void c352_device::static_set_divider(device_t &device, int setting) +{ + c352_device &c352 = downcast<c352_device &>(device); + c352.m_divider = setting; +} + +//------------------------------------------------- // memory_space_config - return a description of // any address spaces owned by this device //------------------------------------------------- @@ -457,7 +468,7 @@ void c352_device::write_reg16(unsigned long address, unsigned short val) void c352_device::device_start() { - int i; + int i, divider; double x_max = 32752.0; double y_max = 127.0; double u = 10.0; @@ -465,7 +476,21 @@ void c352_device::device_start() // find our direct access m_direct = &space().direct(); - m_sample_rate_base = clock() / 288; + switch(m_divider) + { + case C352_DIVIDER_228: + divider=228; + break; + case C352_DIVIDER_288: + default: + divider=288; + break; + case C352_DIVIDER_332: + divider=332; + break; + } + + m_sample_rate_base = clock() / divider; m_stream = machine().sound().stream_alloc(*this, 0, 4, m_sample_rate_base); diff --git a/src/emu/sound/c352.h b/src/emu/sound/c352.h index e6998f81b9f..0717fd133df 100644 --- a/src/emu/sound/c352.h +++ b/src/emu/sound/c352.h @@ -6,12 +6,27 @@ #define __C352_H__ //************************************************************************** +// CONSTANTS +//************************************************************************** + +enum +{ + C352_DIVIDER_228 = 0, + C352_DIVIDER_288 = 1, + C352_DIVIDER_332 = 2 +}; + +//************************************************************************** // INTERFACE CONFIGURATION MACROS //************************************************************************** -#define MCFG_C352_ADD(_tag, _clock) \ - MCFG_DEVICE_ADD(_tag, C352, _clock) +#define MCFG_C352_ADD(_tag, _clock, _setting) \ + MCFG_DEVICE_ADD(_tag, C352, _clock) \ + MCFG_C352_DIVIDER(_setting) +#define MCFG_C352_DIVIDER(_setting) \ + c352_device::static_set_divider(*device, _setting); + //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -26,6 +41,9 @@ public: // construction/destruction c352_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + // inline configuration helpers + static void static_set_divider(device_t &device, int setting); + DECLARE_READ16_MEMBER(read); DECLARE_WRITE16_MEMBER(write); @@ -89,7 +107,8 @@ private: c352_ch_t m_c352_ch[32]; int m_sample_rate_base; - + int m_divider; + long m_channel_l[2048*2]; long m_channel_r[2048*2]; long m_channel_l2[2048*2]; diff --git a/src/emu/sound/disc_cls.h b/src/emu/sound/disc_cls.h index c03592a9f08..255b0958c15 100644 --- a/src/emu/sound/disc_cls.h +++ b/src/emu/sound/disc_cls.h @@ -1,4 +1,4 @@ -// license:BSD-3-Clause +// license:??? // copyright-holders:K.Wilkins, Derrick Renaud, F.Palazzolo, Couriersud #pragma once diff --git a/src/emu/sound/discrete.c b/src/emu/sound/discrete.c index d9bf63180db..61f3ea35242 100644 --- a/src/emu/sound/discrete.c +++ b/src/emu/sound/discrete.c @@ -1,4 +1,4 @@ -// license:BSD-3-Clause +// license:??? // copyright-holders:K.Wilkins, Derrick Renaud, Frank Palazzolo, Couriersud /************************************************************************ * diff --git a/src/emu/sound/discrete.h b/src/emu/sound/discrete.h index 921974193ab..a7dff7c7ff7 100644 --- a/src/emu/sound/discrete.h +++ b/src/emu/sound/discrete.h @@ -1,4 +1,4 @@ -// license:BSD-3-Clause +// license:??? // copyright-holders:K.Wilkins, Derrick Renaud, Frank Palazzolo, Couriersud #pragma once diff --git a/src/emu/sound/es5503.c b/src/emu/sound/es5503.c index fd2d52c4545..9364aa8065d 100644 --- a/src/emu/sound/es5503.c +++ b/src/emu/sound/es5503.c @@ -128,9 +128,10 @@ void es5503_device::halt_osc(int onum, int type, UINT32 *accumulator, int resshi *accumulator = altram << resshift; } + int omode = (pPartner->control>>1) & 3; // if swap mode, start the partner - if (mode == MODE_SWAP) + if ((mode == MODE_SWAP) || (omode == MODE_SWAP)) { pPartner->control &= ~1; // clear the halt bit pPartner->accumulator = 0; // and make sure it starts from the top (does this also need phase preservation?) diff --git a/src/emu/sound/fmopl.c b/src/emu/sound/fmopl.c index 98eda602c10..4932cde31fa 100644 --- a/src/emu/sound/fmopl.c +++ b/src/emu/sound/fmopl.c @@ -513,8 +513,8 @@ O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), #define ML 2 static const UINT8 mul_tab[16]= { /* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */ - 0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML, - 8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML + ML/2, 1*ML, 2*ML, 3*ML, 4*ML, 5*ML, 6*ML, 7*ML, + 8*ML, 9*ML,10*ML,10*ML,12*ML,12*ML,15*ML,15*ML }; #undef ML diff --git a/src/emu/sound/ics2115.c b/src/emu/sound/ics2115.c index 92affac6f30..d77410ad74b 100644 --- a/src/emu/sound/ics2115.c +++ b/src/emu/sound/ics2115.c @@ -1,5 +1,5 @@ -// license:BSD-3-Clause -// copyright-holders:Alex Marshal,nimitz,austere +// license:??? +// copyright-holders:Alex Marshall,nimitz,austere //ICS2115 by Raiden II team (c) 2010 //members: austere, nimitz, Alex Marshal // diff --git a/src/emu/sound/ics2115.h b/src/emu/sound/ics2115.h index 5ea25a1e768..16d571fd997 100644 --- a/src/emu/sound/ics2115.h +++ b/src/emu/sound/ics2115.h @@ -1,5 +1,5 @@ -// license:BSD-3-Clause -// copyright-holders:Alex Marshal,nimitz,austere +// license:??? +// copyright-holders:Alex Marshall,nimitz,austere #pragma once #ifndef __ICS2115_H__ diff --git a/src/emu/sound/n63701x.c b/src/emu/sound/n63701x.c index e76db1e1fc4..db90445f0cf 100644 --- a/src/emu/sound/n63701x.c +++ b/src/emu/sound/n63701x.c @@ -47,6 +47,16 @@ namco_63701x_device::namco_63701x_device(const machine_config &mconfig, const ch void namco_63701x_device::device_start() { m_stream = stream_alloc(0, 2, clock()/1000); + + for (int i = 0; i < 2; i++) + { + save_item(NAME(m_voices[i].select), i); + save_item(NAME(m_voices[i].playing), i); + save_item(NAME(m_voices[i].base_addr), i); + save_item(NAME(m_voices[i].position), i); + save_item(NAME(m_voices[i].volume), i); + save_item(NAME(m_voices[i].silence_counter), i); + } } diff --git a/src/emu/sound/okim9810.c b/src/emu/sound/okim9810.c index 311138e8df7..54e53fe55d0 100644 --- a/src/emu/sound/okim9810.c +++ b/src/emu/sound/okim9810.c @@ -4,7 +4,7 @@ okim9810.h - OKI MSM9810 ADCPM(2) sound chip. + OKI MSM9810 ADPCM(2) sound chip. ***************************************************************************/ diff --git a/src/emu/sound/okim9810.h b/src/emu/sound/okim9810.h index 665c9a9fdee..6d3595c59b2 100644 --- a/src/emu/sound/okim9810.h +++ b/src/emu/sound/okim9810.h @@ -4,7 +4,7 @@ okim9810.h - OKI MSM9810 ADCPM(2) sound chip. + OKI MSM9810 ADPCM(2) sound chip. Notes: The master clock frequency for this chip can range from 3.5MHz to 4.5Mhz. diff --git a/src/emu/sound/qsound.c b/src/emu/sound/qsound.c index a3bbb1210f6..c519da454a5 100644 --- a/src/emu/sound/qsound.c +++ b/src/emu/sound/qsound.c @@ -1,4 +1,4 @@ -// license:BSD-3-Clause +// license:??? // copyright-holders:Paul Leaman, Miguel Angel Horna /*************************************************************************** diff --git a/src/emu/sound/qsound.h b/src/emu/sound/qsound.h index 9d0697f406a..208fdac41e9 100644 --- a/src/emu/sound/qsound.h +++ b/src/emu/sound/qsound.h @@ -1,4 +1,4 @@ -// license:BSD-3-Clause +// license:??? // copyright-holders:Paul Leaman, Miguel Angel Horna /********************************************************* diff --git a/src/emu/sound/st0016.c b/src/emu/sound/st0016.c index 4c75f3f7b02..d62332496cb 100644 --- a/src/emu/sound/st0016.c +++ b/src/emu/sound/st0016.c @@ -45,6 +45,11 @@ void st0016_device::device_start() { m_stream = stream_alloc(0, 2, 44100); m_ram_read_cb.resolve_safe(0); + + save_item(NAME(m_vpos)); + save_item(NAME(m_frac)); + save_item(NAME(m_lponce)); + save_item(NAME(m_regs)); } diff --git a/src/emu/sound/tms5110.c b/src/emu/sound/tms5110.c index c1595b1caa7..03729598737 100644 --- a/src/emu/sound/tms5110.c +++ b/src/emu/sound/tms5110.c @@ -1,4 +1,4 @@ -// license:BSD-3-Clause +// license:??? // copyright-holders:Frank Palazzolo, Jarek Burczynski, Aaron Giles, Jonathan Gevaryahu, Couriersud /********************************************************************************************** diff --git a/src/emu/sound/tms5110.h b/src/emu/sound/tms5110.h index 5addc3d967e..6196834a24a 100644 --- a/src/emu/sound/tms5110.h +++ b/src/emu/sound/tms5110.h @@ -1,4 +1,4 @@ -// license:BSD-3-Clause +// license:??? // copyright-holders:Frank Palazzolo, Jarek Burczynski, Aaron Giles, Jonathan Gevaryahu, Couriersud #pragma once diff --git a/src/emu/sound/ym2413.c b/src/emu/sound/ym2413.c index 3e33f478a41..631560912b0 100644 --- a/src/emu/sound/ym2413.c +++ b/src/emu/sound/ym2413.c @@ -449,8 +449,8 @@ O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), #define ML 2 static const UINT8 mul_tab[16]= { /* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */ - 0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML, - 8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML + ML/2, 1*ML, 2*ML, 3*ML, 4*ML, 5*ML, 6*ML, 7*ML, + 8*ML, 9*ML,10*ML,10*ML,12*ML,12*ML,15*ML,15*ML }; #undef ML diff --git a/src/emu/sound/ymf262.c b/src/emu/sound/ymf262.c index aeb5df4c682..0982ae266e8 100644 --- a/src/emu/sound/ymf262.c +++ b/src/emu/sound/ymf262.c @@ -466,8 +466,8 @@ O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0), #define ML 2 static const UINT8 mul_tab[16]= { /* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */ - 0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML, - 8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML + ML/2, 1*ML, 2*ML, 3*ML, 4*ML, 5*ML, 6*ML, 7*ML, + 8*ML, 9*ML,10*ML,10*ML,12*ML,12*ML,15*ML,15*ML }; #undef ML diff --git a/src/emu/sound/zsg2.c b/src/emu/sound/zsg2.c index e6b9f6af450..4f3f1a42ca9 100644 --- a/src/emu/sound/zsg2.c +++ b/src/emu/sound/zsg2.c @@ -47,7 +47,6 @@ TODO: - volume/panning is linear? volume slides are too steep - most music sounds tinny, probably due to missing DSP? - what is reg 0xa/0xc? seems related to volume -- chip should running at 31khz (divider of 768 instead of 192) - identify sample flags * bassdrum in shikigam level 1 music is a good hint: it should be one octave lower, indicating possible stereo sample, or base octave(like in ymf278) @@ -86,10 +85,9 @@ void zsg2_device::device_start() memset(&m_chan, 0, sizeof(m_chan)); - m_stream = stream_alloc(0, 2, clock() / 192); + m_stream = stream_alloc(0, 2, clock() / 768); m_mem_blocks = m_mem_base.length(); - m_mem_copy = auto_alloc_array_clear(machine(), UINT32, m_mem_blocks); m_full_samples = auto_alloc_array_clear(machine(), INT16, m_mem_blocks * 4 + 4); // +4 is for empty block @@ -214,7 +212,7 @@ void zsg2_device::sound_stream_update(sound_stream &stream, stream_sample_t **in continue; m_chan[ch].step_ptr += m_chan[ch].step; - if (m_chan[ch].step_ptr & 0x40000) + if (m_chan[ch].step_ptr & 0x10000) { m_chan[ch].step_ptr &= 0xffff; if (++m_chan[ch].cur_pos >= m_chan[ch].end_pos) @@ -231,7 +229,7 @@ void zsg2_device::sound_stream_update(sound_stream &stream, stream_sample_t **in m_chan[ch].samples = prepare_samples(m_chan[ch].page | m_chan[ch].cur_pos); } - INT32 sample = (m_chan[ch].samples[m_chan[ch].step_ptr >> 16 & 3] * m_chan[ch].vol) >> 16; + INT32 sample = (m_chan[ch].samples[m_chan[ch].step_ptr >> 14 & 3] * m_chan[ch].vol) >> 16; mix_l += (sample * m_chan[ch].panl + sample * (0x1f - m_chan[ch].panr)) >> 5; mix_r += (sample * m_chan[ch].panr + sample * (0x1f - m_chan[ch].panl)) >> 5; diff --git a/src/emu/ui/filesel.c b/src/emu/ui/filesel.c index 294e58c76fb..141d2f9e7b9 100644 --- a/src/emu/ui/filesel.c +++ b/src/emu/ui/filesel.c @@ -566,7 +566,8 @@ void ui_menu_file_selector::populate() if (m_has_softlist) { // add the "[software list]" entry - append_entry(SELECTOR_ENTRY_TYPE_SOFTWARE_LIST, NULL, NULL); + entry = append_entry(SELECTOR_ENTRY_TYPE_SOFTWARE_LIST, NULL, NULL); + selected_entry = entry; } // add the drives diff --git a/src/emu/ui/imgcntrl.c b/src/emu/ui/imgcntrl.c index 15f487c4c2e..f1166bb3a8a 100644 --- a/src/emu/ui/imgcntrl.c +++ b/src/emu/ui/imgcntrl.c @@ -134,6 +134,7 @@ void ui_menu_control_device_image::load_software_part() std::string temp_name = std::string(sld->list_name()).append(":").append(swi->shortname()).append(":").append(swp->name()); driver_enumerator drivlist(machine().options(), machine().options().system_name()); + drivlist.next(); media_auditor auditor(drivlist); media_auditor::summary summary = auditor.audit_software(sld->list_name(), (software_info *)swi, AUDIT_VALIDATE_FAST); // if everything looks good, load software diff --git a/src/emu/ui/ui.c b/src/emu/ui/ui.c index b9b9da66643..91f3f4825b1 100644 --- a/src/emu/ui/ui.c +++ b/src/emu/ui/ui.c @@ -92,6 +92,7 @@ static const input_item_id non_char_keys[] = // messagebox buffer static std::string messagebox_text; +static std::string messagebox_poptext; static rgb_t messagebox_backcolor; // slider info @@ -441,7 +442,7 @@ void ui_manager::update_and_render(render_container *container) // display any popup messages if (osd_ticks() < m_popup_text_end) - draw_text_box(container, messagebox_text.c_str(), JUSTIFY_CENTER, 0.5f, 0.9f, messagebox_backcolor); + draw_text_box(container, messagebox_poptext.c_str(), JUSTIFY_CENTER, 0.5f, 0.9f, messagebox_backcolor); else m_popup_text_end = 0; @@ -868,7 +869,7 @@ void CLIB_DECL ui_manager::popup_time(int seconds, const char *text, ...) // extract the text va_start(arg,text); - strvprintf(messagebox_text, text, arg); + strvprintf(messagebox_poptext, text, arg); messagebox_backcolor = UI_BACKGROUND_COLOR; va_end(arg); diff --git a/src/emu/video/clgd542x.c b/src/emu/video/clgd542x.c index 84a7c0b33cf..aee97491ef1 100644 --- a/src/emu/video/clgd542x.c +++ b/src/emu/video/clgd542x.c @@ -233,13 +233,12 @@ void cirrus_gd5428_device::cirrus_define_video_mode() if (!gc_locked && (vga.sequencer.data[0x07] & 0x01)) { - switch(vga.sequencer.data[0x07] & 0x0E) + switch(vga.sequencer.data[0x07] & 0x06) // bit 3 is reserved on GD542x { case 0x00: svga.rgb8_en = 1; break; - case 0x02: svga.rgb16_en = 1; divisor = 2; break; //double VCLK - case 0x04: svga.rgb24_en = 1; divisor = 3; break; - case 0x06: svga.rgb16_en = 1; break; - case 0x08: svga.rgb32_en = 1; break; + case 0x02: svga.rgb16_en = 1; clock /= 2; break; // Clock / 2 for 16-bit data + case 0x04: svga.rgb24_en = 1; clock /= 3; break; // Clock / 3 for 24-bit data + case 0x06: svga.rgb16_en = 1; divisor = 2; break; // Clock rate for 16-bit data } } recompute_params_clock(divisor, (int)clock); @@ -251,6 +250,12 @@ UINT16 cirrus_gd5428_device::offset() if (svga.rgb8_en == 1) // guess off <<= 2; + if (svga.rgb16_en == 1) + off <<= 2; + if (svga.rgb24_en == 1) + off <<= 2; + if (svga.rgb32_en == 1) + off <<= 2; // popmessage("Offset: %04x %s %s ** -- actual: %04x",vga.crtc.offset,vga.crtc.dw?"DW":"--",vga.crtc.word_mode?"BYTE":"WORD",off); return off; } @@ -276,22 +281,43 @@ void cirrus_gd5428_device::start_bitblt() { if(m_blt_mode & 0x80) // colour expand { - UINT8 pixel = (vga.memory[m_blt_source_current % vga.svga_intf.vram_size] >> (7-(x % 8)) & 0x01) ? vga.gc.enable_set_reset : vga.gc.set_reset; // use GR0/1/10/11 background/foreground regs + if(m_blt_mode & 0x10) // 16-bit colour expansion / transparency width + { + // use GR0/1/10/11 background/foreground regs + UINT16 pixel = (vga.memory[m_blt_source_current % vga.svga_intf.vram_size] >> (7-((x/2) % 8)) & 0x01) ? ((m_gr11 << 8) | vga.gc.enable_set_reset) : ((m_gr10 << 8) | vga.gc.set_reset); - copy_pixel(pixel, vga.memory[m_blt_dest_current % vga.svga_intf.vram_size]); - if((x % 8) == 7 && !(m_blt_mode & 0x40)) // don't increment if a pattern (it's only 8 bits) - m_blt_source_current++; + if(m_blt_dest_current & 1) + copy_pixel(pixel >> 8, vga.memory[m_blt_dest_current % vga.svga_intf.vram_size]); + else + copy_pixel(pixel & 0xff, vga.memory[m_blt_dest_current % vga.svga_intf.vram_size]); + if((x % 8) == 7 && !(m_blt_mode & 0x40)) // don't increment if a pattern (it's only 8 bits) + m_blt_source_current++; + } + else + { + UINT8 pixel = (vga.memory[m_blt_source_current % vga.svga_intf.vram_size] >> (7-(x % 8)) & 0x01) ? vga.gc.enable_set_reset : vga.gc.set_reset; // use GR0/1/10/11 background/foreground regs + + copy_pixel(pixel, vga.memory[m_blt_dest_current % vga.svga_intf.vram_size]); + if((x % 8) == 7 && !(m_blt_mode & 0x40)) // don't increment if a pattern (it's only 8 bits) + m_blt_source_current++; + } } else { copy_pixel(vga.memory[m_blt_source_current % vga.svga_intf.vram_size], vga.memory[m_blt_dest_current % vga.svga_intf.vram_size]); m_blt_source_current++; } + m_blt_dest_current++; if(m_blt_mode & 0x40 && (x % 8) == 7) // 8x8 pattern - reset pattern source location { if(m_blt_mode & 0x80) // colour expand m_blt_source_current = m_blt_source + (1*(y % 8)); // patterns are linear data + else if(svga.rgb15_en || svga.rgb16_en) + { + if(m_blt_mode & 0x40 && (x % 16) == 15) + m_blt_source_current = m_blt_source + (16*(y % 8)); + } else m_blt_source_current = m_blt_source + (8*(y % 8)); } @@ -300,6 +326,11 @@ void cirrus_gd5428_device::start_bitblt() { if(m_blt_mode & 0x80) // colour expand m_blt_source_current = m_blt_source + (1*(y % 8)); // patterns are linear data + else if(svga.rgb15_en || svga.rgb16_en) + { + if(m_blt_mode & 0x40 && (x % 16) == 15) + m_blt_source_current = m_blt_source + (16*(y % 8)); + } else m_blt_source_current = m_blt_source + (8*(y % 8)); } @@ -326,11 +357,26 @@ void cirrus_gd5428_device::start_reverse_bitblt() { if(m_blt_mode & 0x80) // colour expand { + if(m_blt_mode & 0x10) // 16-bit colour expansion / transparency width + { + // use GR0/1/10/11 background/foreground regs + UINT16 pixel = (vga.memory[m_blt_source_current % vga.svga_intf.vram_size] >> (7-((x/2) % 8)) & 0x01) ? ((m_gr11 << 8) | vga.gc.enable_set_reset) : ((m_gr10 << 8) | vga.gc.set_reset); + + if(m_blt_dest_current & 1) + copy_pixel(pixel >> 8, vga.memory[m_blt_dest_current % vga.svga_intf.vram_size]); + else + copy_pixel(pixel & 0xff, vga.memory[m_blt_dest_current % vga.svga_intf.vram_size]); + if((x % 8) == 7 && !(m_blt_mode & 0x40)) // don't increment if a pattern (it's only 8 bits) + m_blt_source_current--; + } + else + { UINT8 pixel = (vga.memory[m_blt_source_current % vga.svga_intf.vram_size] >> (7-(x % 8)) & 0x01) ? vga.gc.enable_set_reset : vga.gc.set_reset; // use GR0/1/10/11 background/foreground regs copy_pixel(pixel, vga.memory[m_blt_dest_current % vga.svga_intf.vram_size]); if((x % 8) == 7 && !(m_blt_mode & 0x40)) // don't decrement if a pattern (it's only 8 bits) m_blt_source_current--; + } } else { @@ -342,6 +388,11 @@ void cirrus_gd5428_device::start_reverse_bitblt() { if(m_blt_mode & 0x80) // colour expand m_blt_source_current = m_blt_source - (1*(y % 8)); // patterns are linear data + else if(svga.rgb15_en || svga.rgb16_en) + { + if(m_blt_mode & 0x40 && (x % 16) == 15) + m_blt_source_current = m_blt_source - (16*(y % 8)); + } else m_blt_source_current = m_blt_source - (8*(y % 8)); } @@ -350,6 +401,11 @@ void cirrus_gd5428_device::start_reverse_bitblt() { if(m_blt_mode & 0x80) // colour expand m_blt_source_current = m_blt_source - (1*(y % 8)); // patterns are linear data + else if(svga.rgb15_en || svga.rgb16_en) + { + if(m_blt_mode & 0x40 && (x % 16) == 15) + m_blt_source_current = m_blt_source - (16*(y % 8)); + } else m_blt_source_current = m_blt_source - (8*(y % 8)); } @@ -407,7 +463,11 @@ void cirrus_gd5428_device::blit_byte() for(x=0;x<8;x++) { - pixel = ((m_blt_system_buffer & (0x00000001 << (7-x))) >> (7-x)) ? vga.gc.enable_set_reset : vga.gc.set_reset; // use GR0/1/10/11 background/foreground regs + // use GR0/1/10/11 background/foreground regs + if(m_blt_dest_current & 1) + pixel = ((m_blt_system_buffer & (0x00000001 << (7-x))) >> (7-x)) ? m_gr11 : m_gr10; + else + pixel = ((m_blt_system_buffer & (0x00000001 << (7-x))) >> (7-x)) ? vga.gc.enable_set_reset : vga.gc.set_reset; if(m_blt_pixel_count <= m_blt_width - 1) copy_pixel(pixel,vga.memory[m_blt_dest_current % vga.svga_intf.vram_size]); m_blt_dest_current++; @@ -656,9 +716,11 @@ UINT8 cirrus_gd5428_device::cirrus_gc_reg_read(UINT8 index) break; case 0x0e: // Miscellaneous Control break; - case 0x10: // Foreground Colour Byte 1 + case 0x10: // Background Colour Byte 1 + res = m_gr10; break; - case 0x11: // Background Colour Byte 1 + case 0x11: // Foreground Colour Byte 1 + res = m_gr11; break; case 0x20: // BLT Width 0 res = m_blt_width & 0x00ff; @@ -778,9 +840,11 @@ void cirrus_gd5428_device::cirrus_gc_reg_write(UINT8 index, UINT8 data) break; case 0x0e: // Miscellaneous Control break; - case 0x10: // Foreground Colour Byte 1 + case 0x10: // Background Colour Byte 1 + m_gr10 = data; break; - case 0x11: // Background Colour Byte 1 + case 0x11: // Foreground Colour Byte 1 + m_gr11 = data; break; case 0x20: // BLT Width 0 m_blt_width = (m_blt_width & 0xff00) | data; @@ -1328,14 +1392,27 @@ WRITE8_MEMBER(cirrus_gd5428_device::mem_w) else offset &= 0xffff; + // GR0 (and GR10 in 15/16bpp modes) = background colour in write mode 5 + // GR1 (and GR11 in 15/16bpp modes) = foreground colour in write modes 4 or 5 if(vga.gc.write_mode == 4) { int i; for(i=0;i<8;i++) { - if(data & (0x01 << (7-i))) - vga.memory[((addr+offset)*8+i) % vga.svga_intf.vram_size] = vga.gc.enable_set_reset; // GR1 (and GR11 in 16bpp modes) = foreground colour in write modes 4 or 5 + if(svga.rgb8_en) + { + if(data & (0x01 << (7-i))) + vga.memory[((addr+offset)*8+i) % vga.svga_intf.vram_size] = vga.gc.enable_set_reset; + } + else if(svga.rgb15_en || svga.rgb16_en) + { + if(data & (0x01 << (7-i))) + { + vga.memory[((addr+offset)*16+(i*2)) % vga.svga_intf.vram_size] = vga.gc.enable_set_reset; + vga.memory[((addr+offset)*16+(i*2)+1) % vga.svga_intf.vram_size] = m_gr11; + } + } } return; } @@ -1346,10 +1423,26 @@ WRITE8_MEMBER(cirrus_gd5428_device::mem_w) for(i=0;i<8;i++) { - if(data & (0x01 << (7-i))) - vga.memory[((addr+offset)*8+i) % vga.svga_intf.vram_size] = vga.gc.enable_set_reset; // GR1 (and GR11 in 16bpp modes) = foreground colour in write modes 4 or 5 - else - vga.memory[((addr+offset)*8+i) % vga.svga_intf.vram_size] = vga.gc.set_reset; // GR0 (and GR10 in 16bpp modes) = background colour in write mode 5 + if(svga.rgb8_en) + { + if(data & (0x01 << (7-i))) + vga.memory[((addr+offset)*8+i) % vga.svga_intf.vram_size] = vga.gc.enable_set_reset; + else + vga.memory[((addr+offset)*8+i) % vga.svga_intf.vram_size] = vga.gc.set_reset; + } + else if(svga.rgb15_en || svga.rgb16_en) + { + if(data & (0x01 << (7-i))) + { + vga.memory[((addr+offset)*16+(i*2)) % vga.svga_intf.vram_size] = vga.gc.enable_set_reset; + vga.memory[((addr+offset)*16+(i*2)+1) % vga.svga_intf.vram_size] = m_gr11; + } + else + { + vga.memory[((addr+offset)*16+(i*2)) % vga.svga_intf.vram_size] = vga.gc.set_reset; + vga.memory[((addr+offset)*16+(i*2)+1) % vga.svga_intf.vram_size] = m_gr10; + } + } } return; } diff --git a/src/emu/video/clgd542x.h b/src/emu/video/clgd542x.h index 31e1876ef9e..20300d160fd 100644 --- a/src/emu/video/clgd542x.h +++ b/src/emu/video/clgd542x.h @@ -41,6 +41,8 @@ protected: UINT8 gc_bank_1; bool gc_locked; UINT8 m_lock_reg; + UINT8 m_gr10; // high byte of background colour (in 15/16bpp) + UINT8 m_gr11; // high byte of foreground colour (in 15/16bpp) UINT8 m_cr19; UINT8 m_cr1a; diff --git a/src/emu/video/mc6845.c b/src/emu/video/mc6845.c index 2b72a57b47d..7b9f0b1fc1f 100644 --- a/src/emu/video/mc6845.c +++ b/src/emu/video/mc6845.c @@ -453,7 +453,11 @@ READ_LINE_MEMBER( mc6845_device::vsync_r ) void mc6845_device::recompute_parameters(bool postload) { UINT16 hsync_on_pos, hsync_off_pos, vsync_on_pos, vsync_off_pos; - //UINT16 video_char_height = (MODE_INTERLACE_AND_VIDEO ? m_max_ras_addr + 1 : m_max_ras_addr) + 1; + + // needed for the apricot, correct? + if (MODE_INTERLACE_AND_VIDEO) + m_max_ras_addr |= 1; + UINT16 video_char_height = m_max_ras_addr + 1; // fix garbage at the bottom of the screen (eg victor9k) // Would be useful for 'interlace and video' mode support... // UINT16 frame_char_height = (MODE_INTERLACE_AND_VIDEO ? m_max_ras_addr / 2 : m_max_ras_addr) + 1; diff --git a/src/emu/video/mc6847.c b/src/emu/video/mc6847.c index 44ae168b028..76c0dcb4c92 100644 --- a/src/emu/video/mc6847.c +++ b/src/emu/video/mc6847.c @@ -150,7 +150,7 @@ mc6847_friend_device::mc6847_friend_device(const machine_config &mconfig, device // to the clock //------------------------------------------------- -ATTR_FORCE_INLINE emu_timer *mc6847_friend_device::setup_timer(device_timer_id id, double offset, double period) +inline emu_timer *mc6847_friend_device::setup_timer(device_timer_id id, double offset, double period) { emu_timer *timer = timer_alloc(id); timer->adjust( @@ -228,7 +228,7 @@ void mc6847_friend_device::device_post_load(void) // update_field_sync_timer //------------------------------------------------- -ATTR_FORCE_INLINE void mc6847_friend_device::update_field_sync_timer(void) +void mc6847_friend_device::update_field_sync_timer(void) { // are we expecting field sync? bool expected_field_sync = (m_physical_scanline < m_field_sync_falling_edge_scanline) @@ -268,7 +268,7 @@ void mc6847_friend_device::device_timer(emu_timer &timer, device_timer_id id, in // new_frame //------------------------------------------------- -ATTR_FORCE_INLINE void mc6847_friend_device::new_frame(void) +inline void mc6847_friend_device::new_frame(void) { m_physical_scanline = 0; m_logical_scanline = 0; @@ -304,7 +304,7 @@ const char *mc6847_friend_device::scanline_zone_string(scanline_zone zone) // change_horizontal_sync //------------------------------------------------- -ATTR_FORCE_INLINE void mc6847_friend_device::change_horizontal_sync(bool line) +inline void mc6847_friend_device::change_horizontal_sync(bool line) { g_profiler.start(PROFILER_USER1); @@ -372,7 +372,7 @@ ATTR_FORCE_INLINE void mc6847_friend_device::change_horizontal_sync(bool line) // change_field_sync //------------------------------------------------- -ATTR_FORCE_INLINE void mc6847_friend_device::change_field_sync(bool line) +inline void mc6847_friend_device::change_field_sync(bool line) { /* output field sync */ if (line != m_field_sync) @@ -397,7 +397,7 @@ ATTR_FORCE_INLINE void mc6847_friend_device::change_field_sync(bool line) // next_scanline //------------------------------------------------- -ATTR_FORCE_INLINE void mc6847_friend_device::next_scanline(void) +inline void mc6847_friend_device::next_scanline(void) { /* advance to next scanline */ m_physical_scanline++; @@ -678,7 +678,7 @@ void mc6847_base_device::record_scanline_res(int scanline, INT32 start_pos, INT3 // record_body_scanline //------------------------------------------------- -ATTR_FORCE_INLINE void mc6847_base_device::record_body_scanline(UINT16 physical_scanline, UINT16 scanline, INT32 start_pos, INT32 end_pos) +inline void mc6847_base_device::record_body_scanline(UINT16 physical_scanline, UINT16 scanline, INT32 start_pos, INT32 end_pos) { // sanity checks assert(scanline < 192); @@ -780,7 +780,7 @@ void mc6847_base_device::field_sync_changed(bool line) // border_value //------------------------------------------------- -ATTR_FORCE_INLINE mc6847_base_device::pixel_t mc6847_base_device::border_value(UINT8 mode, const pixel_t *palette, bool is_mc6847t1) +inline mc6847_base_device::pixel_t mc6847_base_device::border_value(UINT8 mode, const pixel_t *palette, bool is_mc6847t1) { pixel_t result; switch(mc6847_friend_device::border_value(mode, is_mc6847t1)) diff --git a/src/emu/video/pc_vga.c b/src/emu/video/pc_vga.c index 67a7ea5d0cd..c494e4904ec 100644 --- a/src/emu/video/pc_vga.c +++ b/src/emu/video/pc_vga.c @@ -127,13 +127,15 @@ const device_type MACH8 = &device_creator<mach8_device>; vga_device::vga_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) : device_t(mconfig, type, name, tag, owner, clock, shortname, source), - m_palette(*this, "^palette") + m_palette(*this, "^palette"), + m_screen(*this,"^screen") { } vga_device::vga_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : device_t(mconfig, VGA, "VGA", tag, owner, clock, "vga", __FILE__), - m_palette(*this, "^palette") + m_palette(*this, "^palette"), + m_screen(*this,"^screen") { } @@ -218,7 +220,8 @@ void svga_device::zero() TIMER_CALLBACK_MEMBER(vga_device::vblank_timer_cb) { vga.crtc.start_addr = vga.crtc.start_addr_latch; - m_vblank_timer->adjust( machine().first_screen()->time_until_pos(vga.crtc.vert_blank_start) ); + vga.attribute.pel_shift = vga.attribute.pel_shift_latch; + m_vblank_timer->adjust( machine().first_screen()->time_until_pos(vga.crtc.vert_blank_start + vga.crtc.vert_blank_end) ); } void vga_device::device_start() @@ -468,7 +471,10 @@ void vga_device::vga_vh_vga(bitmap_rgb32 &bitmap, const rectangle &cliprect) if((line + yi) < (vga.crtc.line_compare & mask_comp)) curr_addr = addr; if((line + yi) == (vga.crtc.line_compare & mask_comp)) + { curr_addr = 0; + pel_shift = 0; + } bitmapline = &bitmap.pix32(line + yi); for (pos=curr_addr, c=0, column=0; column<VGA_COLUMNS+1; column++, c+=8, pos++) { @@ -1262,7 +1268,7 @@ void vga_device::recompute_params_clock(int divisor, int xtal) refresh = HZ_TO_ATTOSECONDS(pixel_clock) * (hblank_period) * vblank_period; machine().first_screen()->configure((hblank_period), (vblank_period), visarea, refresh ); //popmessage("%d %d\n",vga.crtc.horz_total * 8,vga.crtc.vert_total); - m_vblank_timer->adjust( machine().first_screen()->time_until_pos(vga.crtc.vert_blank_start) ); + m_vblank_timer->adjust( machine().first_screen()->time_until_pos(vga.crtc.vert_blank_start + vga.crtc.vert_blank_end) ); } void vga_device::recompute_params() @@ -1765,7 +1771,7 @@ void vga_device::attribute_reg_write(UINT8 index, UINT8 data) case 0x10: vga.attribute.data[0x10] = data; break; case 0x11: vga.attribute.data[0x11] = data; break; case 0x12: vga.attribute.data[0x12] = data; break; - case 0x13: vga.attribute.pel_shift = vga.attribute.data[0x13] = data; break; + case 0x13: vga.attribute.pel_shift_latch = vga.attribute.data[0x13] = data; break; case 0x14: vga.attribute.data[0x14] = data; break; } } diff --git a/src/emu/video/pc_vga.h b/src/emu/video/pc_vga.h index 613d38a1616..ee0504a95e1 100644 --- a/src/emu/video/pc_vga.h +++ b/src/emu/video/pc_vga.h @@ -208,6 +208,7 @@ protected: UINT8 index, data[0x15]; int state; UINT8 prot_bit; UINT8 pel_shift; + UINT8 pel_shift_latch; } attribute; @@ -229,6 +230,7 @@ protected: emu_timer *m_vblank_timer; required_device<palette_device> m_palette; + required_device<screen_device> m_screen; }; diff --git a/src/emu/video/rgbgen.h b/src/emu/video/rgbgen.h index 9eda032f361..db88f65b4a0 100644 --- a/src/emu/video/rgbgen.h +++ b/src/emu/video/rgbgen.h @@ -164,6 +164,18 @@ INLINE void rgbaint_add(rgbaint *color1, const rgbaint *color2) color1->b += color2->b; } +/*------------------------------------------------- + rgbaint_add_imm - add immediate INT16 to rgbaint value +-------------------------------------------------*/ + +INLINE void rgbaint_add_imm(rgbaint *color1, const INT16 imm) +{ + color1->a += imm; + color1->r += imm; + color1->g += imm; + color1->b += imm; +} + /*------------------------------------------------- rgbint_sub - subtract two rgbint values @@ -308,7 +320,6 @@ INLINE void rgbaint_blend(rgbaint *color1, const rgbaint *color2, UINT8 color1sc color1->b = (color1->b * scale1 + color2->b * scale2) >> 8; } - /*------------------------------------------------- rgbint_scale_and_clamp - scale the given color by an 8.8 scale factor, immediate or @@ -366,6 +377,50 @@ INLINE void rgbaint_scale_channel_and_clamp(rgbaint *color, const rgbaint *color if ((UINT16)color->b > 255) { color->b = (color->b < 0) ? 0 : 255; } } +INLINE void rgbaint_scale_immediate_add_and_clamp(rgbaint *color1, INT16 colorscale, const rgbaint *color2) +{ + color1->a = (color1->a * colorscale) >> 8; + color1->a += color2->a; + if ((UINT16)color1->a > 255) { color1->a = (color1->a < 0) ? 0 : 255; } + color1->r = (color1->r * colorscale) >> 8; + color1->r += color2->r; + if ((UINT16)color1->r > 255) { color1->r = (color1->r < 0) ? 0 : 255; } + color1->g = (color1->g * colorscale) >> 8; + color1->g += color2->g; + if ((UINT16)color1->g > 255) { color1->g = (color1->g < 0) ? 0 : 255; } + color1->b = (color1->b * colorscale) >> 8; + color1->b += color2->b; + if ((UINT16)color1->b > 255) { color1->b = (color1->b < 0) ? 0 : 255; } +} + +INLINE void rgbaint_scale_channel_add_and_clamp(rgbaint *color1, const rgbaint *colorscale, const rgbaint *color2) +{ + color1->a = (color1->a * colorscale->a) >> 8; + color1->a += color2->a; + if ((UINT16)color1->a > 255) { color1->a = (color1->a < 0) ? 0 : 255; } + color1->r = (color1->r * colorscale->r) >> 8; + color1->r += color2->r; + if ((UINT16)color1->r > 255) { color1->r = (color1->r < 0) ? 0 : 255; } + color1->g = (color1->g * colorscale->g) >> 8; + color1->g += color2->g; + if ((UINT16)color1->g > 255) { color1->g = (color1->g < 0) ? 0 : 255; } + color1->b = (color1->b * colorscale->b) >> 8; + color1->b += color2->b; + if ((UINT16)color1->b > 255) { color1->b = (color1->b < 0) ? 0 : 255; } +} + +INLINE void rgbaint_scale_channel_add_and_clamp(rgbaint *color1, const rgbaint *colorscale1, const rgbaint *color2, const rgbaint *colorscale2) +{ + color1->a = (color1->a * colorscale1->a + color2->a * colorscale2->a) >> 8; + if ((UINT16)color1->a > 255) { color1->a = (color1->a < 0) ? 0 : 255; } + color1->r = (color1->r * colorscale1->r + color2->r * colorscale2->r) >> 8; + if ((UINT16)color1->r > 255) { color1->r = (color1->r < 0) ? 0 : 255; } + color1->g = (color1->g * colorscale1->g + color2->g * colorscale2->g) >> 8; + if ((UINT16)color1->g > 255) { color1->g = (color1->g < 0) ? 0 : 255; } + color1->b = (color1->b * colorscale1->b + color2->b * colorscale2->b) >> 8; + if ((UINT16)color1->b > 255) { color1->b = (color1->b < 0) ? 0 : 255; } +} + /*------------------------------------------------- rgb_bilinear_filter - bilinear filter between diff --git a/src/emu/video/rgbsse.h b/src/emu/video/rgbsse.h index 4822d5519f0..88a345f316c 100644 --- a/src/emu/video/rgbsse.h +++ b/src/emu/video/rgbsse.h @@ -146,6 +146,15 @@ INLINE void rgbaint_add(rgbaint *color1, const rgbaint *color2) *color1 = _mm_add_epi16(*color1, *color2); } +/*------------------------------------------------- + rgbaint_add_imm - add immediate INT16 to rgbaint value +-------------------------------------------------*/ +INLINE void rgbaint_add_imm(rgbaint *color1, const INT16 imm) +{ + __m128i temp = _mm_set_epi16(0, 0, 0, 0, imm, imm, imm, imm); + *color1 = _mm_add_epi16(*color1, temp); +} + /*------------------------------------------------- rgbint_sub - subtract two rgbint values @@ -306,6 +315,38 @@ INLINE void rgbint_scale_channel_and_clamp(rgbint *color, const rgbint *colorsca *color = _mm_min_epi16(*color, *(__m128i *)&rgbsse_statics.maxbyte); } +INLINE void rgbaint_scale_immediate_add_and_clamp(rgbaint *color1, INT16 colorscale, const rgbaint *color2) +{ + // color2 will get mutiplied by 2^8 (256) and then divided by 2^8 by the shift by 8 + __m128i mscale = _mm_unpacklo_epi16(_mm_set1_epi16(colorscale), _mm_set_epi16(0, 0, 0, 0, 256, 256, 256, 256)); + *color1 = _mm_unpacklo_epi16(*color1, *color2); + *color1 = _mm_madd_epi16(*color1, mscale); + *color1 = _mm_srli_epi32(*color1, 8); + *color1 = _mm_packs_epi32(*color1, *color1); + *color1 = _mm_min_epi16(*color1, *(__m128i *)&rgbsse_statics.maxbyte); +} + +INLINE void rgbaint_scale_channel_add_and_clamp(rgbaint *color1, const rgbaint *colorscale, const rgbaint *color2) +{ + // color2 will get mutiplied by 2^8 (256) and then divided by 2^8 by the shift by 8 + __m128i mscale = _mm_unpacklo_epi16(*colorscale, _mm_set_epi16(0, 0, 0, 0, 256, 256, 256, 256)); + *color1 = _mm_unpacklo_epi16(*color1, *color2); + *color1 = _mm_madd_epi16(*color1, mscale); + *color1 = _mm_srli_epi32(*color1, 8); + *color1 = _mm_packs_epi32(*color1, *color1); + *color1 = _mm_min_epi16(*color1, *(__m128i *)&rgbsse_statics.maxbyte); +} + +INLINE void rgbaint_scale_channel_add_and_clamp(rgbaint *color1, const rgbaint *colorscale1, const rgbaint *color2, const rgbaint *colorscale2) + +{ + __m128i mscale = _mm_unpacklo_epi16(*colorscale1, *colorscale2); + *color1 = _mm_unpacklo_epi16(*color1, *color2); + *color1 = _mm_madd_epi16(*color1, mscale); + *color1 = _mm_srli_epi32(*color1, 8); + *color1 = _mm_packs_epi32(*color1, *color1); + *color1 = _mm_min_epi16(*color1, *(__m128i *)&rgbsse_statics.maxbyte); +} /*------------------------------------------------- rgbaint_scale_and_clamp - scale the given diff --git a/src/emu/video/tms3556.c b/src/emu/video/tms3556.c index 819e18840d8..9d073bdbe0d 100644 --- a/src/emu/video/tms3556.c +++ b/src/emu/video/tms3556.c @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Raphael Nabet /* tms3556 emulation diff --git a/src/emu/video/tms3556.h b/src/emu/video/tms3556.h index 8c153ab2d5b..a331b8333e3 100644 --- a/src/emu/video/tms3556.h +++ b/src/emu/video/tms3556.h @@ -1,4 +1,4 @@ -// license:??? +// license:BSD-3-Clause // copyright-holders:Raphael Nabet /*************************************************************************** diff --git a/src/emu/video/vooddefs.h b/src/emu/video/vooddefs.h index a64b0c22f66..437b3c84459 100644 --- a/src/emu/video/vooddefs.h +++ b/src/emu/video/vooddefs.h @@ -23,6 +23,9 @@ enum STALLED_UNTIL_FIFO_EMPTY }; +// Use old macro style or newer SSE2 optimized functions +#define USE_OLD_RASTER 1 + /* maximum number of TMUs */ #define MAX_TMU 2 @@ -2148,10 +2151,10 @@ while (0) #define CLAMPED_ARGB(ITERR, ITERG, ITERB, ITERA, FBZCP, RESULT) \ do \ { \ - INT32 r = (INT32)(ITERR) >> 12; \ - INT32 g = (INT32)(ITERG) >> 12; \ - INT32 b = (INT32)(ITERB) >> 12; \ - INT32 a = (INT32)(ITERA) >> 12; \ + r = (INT32)(ITERR) >> 12; \ + g = (INT32)(ITERG) >> 12; \ + b = (INT32)(ITERB) >> 12; \ + a = (INT32)(ITERA) >> 12; \ \ if (FBZCP_RGBZW_CLAMP(FBZCP) == 0) \ { \ @@ -2193,6 +2196,93 @@ do } \ while (0) +/* use SSE on 64-bit implementations, where it can be assumed */ +#if (!defined(MAME_DEBUG) || defined(__OPTIMIZE__)) && (defined(__SSE2__) || defined(_MSC_VER)) && defined(PTR64) + +ATTR_FORCE_INLINE UINT32 clampARGB(INT32 iterr, INT32 iterg, INT32 iterb, INT32 itera, UINT32 FBZCP) +{ + rgb_t result; + rgbaint colorint; + rgba_comp_to_rgbaint(&colorint, (INT16) (itera>>12), (INT16) (iterr>>12), (INT16) (iterg>>12), (INT16) (iterb>>12)); + + if (FBZCP_RGBZW_CLAMP(FBZCP) == 0) + { + //r &= 0xfff; + __m128i temp = _mm_set1_epi16(0xfff); + colorint = _mm_and_si128(*(__m128i *)&colorint, *(__m128i *)&temp); + //if (r == 0xfff) + temp = _mm_cmpeq_epi16(*(__m128i *)&colorint, *(__m128i *)&temp); + // result.rgb.r = 0; + colorint = _mm_andnot_si128(*(__m128i *)&temp, *(__m128i *)&colorint); + //else if (r == 0x100) + temp = _mm_set1_epi16(0x100); + temp = _mm_cmpeq_epi16(*(__m128i *)&colorint, *(__m128i *)&temp); + // result.rgb.r = 0xff; + colorint = _mm_or_si128(*(__m128i *)&colorint, *(__m128i *)&temp); + + result = rgbaint_to_rgba(&colorint); + } + else + { + result = rgbaint_to_rgba_clamp(&colorint); + } + return result; +} + +#else + +ATTR_FORCE_INLINE UINT32 clampARGB(INT32 iterr, INT32 iterg, INT32 iterb, INT32 itera, UINT32 FBZCP) +{ + rgb_union result; + INT16 r, g, b, a; + r = (INT16)(iterr >> 12); \ + g = (INT16)(iterg >> 12); \ + b = (INT16)(iterb >> 12); \ + a = (INT16)(itera >> 12); \ + + if (FBZCP_RGBZW_CLAMP(FBZCP) == 0) + { + r &= 0xfff; + result.rgb.r = r; + if (r == 0xfff) + result.rgb.r = 0; + else if (r == 0x100) + result.rgb.r = 0xff; + + g &= 0xfff; + result.rgb.g = g; + if (g == 0xfff) + result.rgb.g = 0; + else if (g == 0x100) + result.rgb.g = 0xff; + + b &= 0xfff; + result.rgb.b = b; + if (b == 0xfff) + result.rgb.b = 0; + else if (b == 0x100) + result.rgb.b = 0xff; + + a &= 0xfff; + result.rgb.a = a; + if (a == 0xfff) + result.rgb.a = 0; + else if (a == 0x100) + result.rgb.a = 0xff; + } + else + { + result.rgb.r = (r < 0) ? 0 : (r > 0xff) ? 0xff : r; + result.rgb.g = (g < 0) ? 0 : (g > 0xff) ? 0xff : g; + result.rgb.b = (b < 0) ? 0 : (b > 0xff) ? 0xff : b; + result.rgb.a = (a < 0) ? 0 : (a > 0xff) ? 0xff : a; + } + return result.u; +} + +#endif + + #define CLAMPED_Z(ITERZ, FBZCP, RESULT) \ do \ @@ -2310,6 +2400,71 @@ do } \ while (0) +ATTR_FORCE_INLINE bool chromaKeyTest(voodoo_state *v, stats_block *stats, UINT32 fbzModeReg, rgb_union color) +{ + if (FBZMODE_ENABLE_CHROMAKEY(fbzModeReg)) + { + /* non-range version */ + if (!CHROMARANGE_ENABLE(v->reg[chromaRange].u)) + { + if (((color.u ^ v->reg[chromaKey].u) & 0xffffff) == 0) + { + stats->chroma_fail++; + return false; + } + } + + /* tricky range version */ + else + { + INT32 low, high, test; + int results = 0; + + /* check blue */ + low = v->reg[chromaKey].rgb.b; + high = v->reg[chromaRange].rgb.b; + test = color.rgb.b; + results = (test >= low && test <= high); + results ^= CHROMARANGE_BLUE_EXCLUSIVE(v->reg[chromaRange].u); + results <<= 1; + + /* check green */ + low = v->reg[chromaKey].rgb.g; + high = v->reg[chromaRange].rgb.g; + test = color.rgb.g; + results |= (test >= low && test <= high); + results ^= CHROMARANGE_GREEN_EXCLUSIVE(v->reg[chromaRange].u); + results <<= 1; + + /* check red */ + low = v->reg[chromaKey].rgb.r; + high = v->reg[chromaRange].rgb.r; + test = color.rgb.r; + results |= (test >= low && test <= high); + results ^= CHROMARANGE_RED_EXCLUSIVE(v->reg[chromaRange].u); + + /* final result */ + if (CHROMARANGE_UNION_MODE(v->reg[chromaRange].u)) + { + if (results != 0) + { + stats->chroma_fail++; + return false; + } + } + else + { + if (results == 7) + { + stats->chroma_fail++; + return false; + } + } + } + } + return true; +} + /************************************* @@ -2332,7 +2487,18 @@ do } \ while (0) - +ATTR_FORCE_INLINE bool alphaMaskTest(stats_block *stats, UINT32 fbzModeReg, UINT8 alpha) +{ + if (FBZMODE_ENABLE_ALPHA_MASK(fbzModeReg)) + { + if ((alpha & 1) == 0) + { + stats->afunc_fail++; + return false; + } + } + return true; +} /************************************* * @@ -2407,6 +2573,71 @@ do } \ while (0) +ATTR_FORCE_INLINE bool alphaTest(voodoo_state *v, stats_block *stats, UINT32 alphaModeReg, UINT8 alpha) +{ + if (ALPHAMODE_ALPHATEST(alphaModeReg)) + { + UINT8 alpharef = v->reg[alphaMode].rgb.a; + switch (ALPHAMODE_ALPHAFUNCTION(alphaModeReg)) + { + case 0: /* alphaOP = never */ + stats->afunc_fail++; + return false; + + case 1: /* alphaOP = less than */ + if (alpha >= alpharef) + { + stats->afunc_fail++; + return false; + } + break; + + case 2: /* alphaOP = equal */ + if (alpha != alpharef) + { + stats->afunc_fail++; + return false; + } + break; + + case 3: /* alphaOP = less than or equal */ + if (alpha > alpharef) + { + stats->afunc_fail++; + return false; + } + break; + + case 4: /* alphaOP = greater than */ + if (alpha <= alpharef) + { + stats->afunc_fail++; + return false; + } + break; + + case 5: /* alphaOP = not equal */ + if (alpha == alpharef) + { + stats->afunc_fail++; + return false; + } + break; + + case 6: /* alphaOP = greater than or equal */ + if (alpha < alpharef) + { + stats->afunc_fail++; + return false; + } + break; + + case 7: /* alphaOP = always */ + break; + } + } + return true; +} /************************************* @@ -2571,6 +2802,200 @@ do } \ while (0) +ATTR_FORCE_INLINE void alphaBlend(UINT32 FBZMODE, UINT32 ALPHAMODE, int ditherX, int dpix, int depthX, rgb_union preFog, rgb_union &color) +{ + if (ALPHAMODE_ALPHABLEND(ALPHAMODE)) + { + //int dpix = dest[XX]; + int dr, dg, db; + EXTRACT_565_TO_888(dpix, dr, dg, db); + int da = FBZMODE_ENABLE_ALPHA_PLANES(FBZMODE) ? depthX : 0xff; + //int sr = (RR); + //int sg = (GG); + //int sb = (BB); + //int sa = (AA); + int sa = color.rgb.a; + int ta; + int srcAlphaScale, destAlphaScale; + rgbaint srcScale, destScale; + + /* apply dither subtraction */ + if (FBZMODE_ALPHA_DITHER_SUBTRACT(FBZMODE)) + { + /* look up the dither value from the appropriate matrix */ + //int dith = DITHER[(XX) & 3]; + + /* subtract the dither value */ + dr += (15 - ditherX) >> 1; + dg += (15 - ditherX) >> 2; + db += (15 - ditherX) >> 1; + } + + /* blend the source alpha */ + srcAlphaScale = 0; + if (ALPHAMODE_SRCALPHABLEND(ALPHAMODE) == 4) + srcAlphaScale = 256; + //(AA) = sa; + + /* compute source portion */ + switch (ALPHAMODE_SRCRGBBLEND(ALPHAMODE)) + { + default: /* reserved */ + case 0: /* AZERO */ + rgba_comp_to_rgbaint(&srcScale, srcAlphaScale, 0, 0, 0); + //(RR) = (GG) = (BB) = 0; + break; + + case 1: /* ASRC_ALPHA */ + rgba_comp_to_rgbaint(&srcScale, srcAlphaScale, sa, sa, sa); + //(RR) = (sr * (sa + 1)) >> 8; + //(GG) = (sg * (sa + 1)) >> 8; + //(BB) = (sb * (sa + 1)) >> 8; + break; + + case 2: /* A_COLOR */ + rgba_comp_to_rgbaint(&srcScale, srcAlphaScale-1, dr, dg, db); + rgbaint_add_imm(&srcScale, 1); + //(RR) = (sr * (dr + 1)) >> 8; + //(GG) = (sg * (dg + 1)) >> 8; + //(BB) = (sb * (db + 1)) >> 8; + break; + + case 3: /* ADST_ALPHA */ + ta = da + 1; + rgba_comp_to_rgbaint(&srcScale, srcAlphaScale, ta, ta, ta); + //(RR) = (sr * (da + 1)) >> 8; + //(GG) = (sg * (da + 1)) >> 8; + //(BB) = (sb * (da + 1)) >> 8; + break; + + case 4: /* AONE */ + rgba_comp_to_rgbaint(&srcScale, srcAlphaScale, 256, 256, 256); + break; + + case 5: /* AOMSRC_ALPHA */ + ta = (0x100 - sa); + rgba_comp_to_rgbaint(&srcScale, srcAlphaScale, ta, ta, ta); + //(RR) = (sr * (0x100 - sa)) >> 8; + //(GG) = (sg * (0x100 - sa)) >> 8; + //(BB) = (sb * (0x100 - sa)) >> 8; + break; + + case 6: /* AOM_COLOR */ + rgba_comp_to_rgbaint(&srcScale, srcAlphaScale, (0x100 - dr), (0x100 - dg), (0x100 - db)); + //(RR) = (sr * (0x100 - dr)) >> 8; + //(GG) = (sg * (0x100 - dg)) >> 8; + //(BB) = (sb * (0x100 - db)) >> 8; + break; + + case 7: /* AOMDST_ALPHA */ + ta = (0x100 - da); + rgba_comp_to_rgbaint(&srcScale, srcAlphaScale, ta, ta, ta); + //(RR) = (sr * (0x100 - da)) >> 8; + //(GG) = (sg * (0x100 - da)) >> 8; + //(BB) = (sb * (0x100 - da)) >> 8; + break; + + case 15: /* ASATURATE */ + ta = (sa < (0x100 - da)) ? sa : (0x100 - da); + rgba_comp_to_rgbaint(&srcScale, srcAlphaScale, ta, ta, ta); + //(RR) = (sr * (ta + 1)) >> 8; + //(GG) = (sg * (ta + 1)) >> 8; + //(BB) = (sb * (ta + 1)) >> 8; + break; + } + + /* blend the dest alpha */ + destAlphaScale = 0; + if (ALPHAMODE_DSTALPHABLEND(ALPHAMODE) == 4) + destAlphaScale = 256; + //(AA) += da; + + /* add in dest portion */ + switch (ALPHAMODE_DSTRGBBLEND(ALPHAMODE)) + { + default: /* reserved */ + case 0: /* AZERO */ + rgba_comp_to_rgbaint(&destScale, destAlphaScale, 0, 0, 0); + break; + + case 1: /* ASRC_ALPHA */ + rgba_comp_to_rgbaint(&destScale, destAlphaScale, sa, sa, sa); + rgbaint_add_imm(&destScale, 1); + //(RR) += (dr * (sa + 1)) >> 8; + //(GG) += (dg * (sa + 1)) >> 8; + //(BB) += (db * (sa + 1)) >> 8; + break; + + case 2: /* A_COLOR */ + rgba_to_rgbaint(&destScale, (rgb_t) (((destAlphaScale-1)<<24) | (color.u & 0x00ffffff))); + rgbaint_add_imm(&destScale, 1); + //(RR) += (dr * (sr + 1)) >> 8; + //(GG) += (dg * (sg + 1)) >> 8; + //(BB) += (db * (sb + 1)) >> 8; + break; + + case 3: /* ADST_ALPHA */ + ta = da + 1; + rgba_comp_to_rgbaint(&destScale, destAlphaScale, ta, ta, ta); + //(RR) += (dr * (da + 1)) >> 8; + //(GG) += (dg * (da + 1)) >> 8; + //(BB) += (db * (da + 1)) >> 8; + break; + + case 4: /* AONE */ + rgba_comp_to_rgbaint(&destScale, destAlphaScale, 256, 256, 256); + //(RR) += dr; + //(GG) += dg; + //(BB) += db; + break; + + case 5: /* AOMSRC_ALPHA */ + ta = (0x100 - sa); + rgba_comp_to_rgbaint(&destScale, destAlphaScale, ta, ta, ta); + //(RR) += (dr * (0x100 - sa)) >> 8; + //(GG) += (dg * (0x100 - sa)) >> 8; + //(BB) += (db * (0x100 - sa)) >> 8; + break; + + case 6: /* AOM_COLOR */ + rgba_comp_to_rgbaint(&destScale, destAlphaScale, (0x100 - color.rgb.r), (0x100 - color.rgb.g), (0x100 - color.rgb.b)); + //(RR) += (dr * (0x100 - sr)) >> 8; + //(GG) += (dg * (0x100 - sg)) >> 8; + //(BB) += (db * (0x100 - sb)) >> 8; + break; + + case 7: /* AOMDST_ALPHA */ + ta = (0x100 - da); + rgba_comp_to_rgbaint(&destScale, destAlphaScale, ta, ta, ta); + //(RR) += (dr * (0x100 - da)) >> 8; + //(GG) += (dg * (0x100 - da)) >> 8; + //(BB) += (db * (0x100 - da)) >> 8; + break; + + case 15: /* A_COLORBEFOREFOG */ + rgba_to_rgbaint(&destScale, (rgb_t) (((destAlphaScale-1)<<24) | (preFog.u & 0x00ffffff))); + rgbaint_add_imm(&destScale, 1); + //(RR) += (dr * (prefogr + 1)) >> 8; + //(GG) += (dg * (prefogg + 1)) >> 8; + //(BB) += (db * (prefogb + 1)) >> 8; + break; + } + // Main blend + rgbaint srcColor; + rgbaint destColor; + + rgba_to_rgbaint(&srcColor, (rgb_t) color.u); + rgba_comp_to_rgbaint(&destColor, da, dr, dg, db); + rgbaint_scale_channel_add_and_clamp(&srcColor, &srcScale, &destColor, &destScale); + color.u = rgbaint_to_rgba(&srcColor); + /* clamp */ + //CLAMP((RR), 0x00, 0xff); + //CLAMP((GG), 0x00, 0xff); + //CLAMP((BB), 0x00, 0xff); + //CLAMP((AA), 0x00, 0xff); + } +} /************************************* @@ -2690,6 +3115,134 @@ do } \ while (0) +ATTR_FORCE_INLINE void applyFogging(voodoo_state *v, UINT32 fogModeReg, UINT32 fbzCpReg, const UINT8 ditherX, INT32 fogDepth, rgb_union &color, INT32 iterz, INT64 iterw, rgb_union iterargb) +{ + if (FOGMODE_ENABLE_FOG(fogModeReg)) + { + UINT32 color_alpha = color.u & 0xff000000; + rgbaint tmpA, tmpB; + + //INT32 fr, fg, fb; + + /* constant fog bypasses everything else */ + rgb_union fogColorLocal = v->reg[fogColor]; + rgba_to_rgbaint(&tmpB, (rgb_t) color.u); + if (FOGMODE_FOG_CONSTANT(fogModeReg)) + { + rgba_to_rgbaint(&tmpA, (rgb_t) fogColorLocal.u); + /* if fog_mult is 0, we add this to the original color */ + if (FOGMODE_FOG_MULT(fogModeReg) == 0) + { + rgbaint_add(&tmpA, &tmpB); + //color += fog; + } + + /* otherwise this just becomes the new color */ + //else + //{ + //color = fog; + //} + color.u = rgbaint_to_rgba_clamp(&tmpA); + } + /* non-constant fog comes from several sources */ + else + { + INT32 fogblend = 0; + + /* if fog_add is zero, we start with the fog color */ + if (FOGMODE_FOG_ADD(fogModeReg)) + fogColorLocal.u = 0; + //fr = fg = fb = 0; + + rgba_to_rgbaint(&tmpA, (rgb_t) fogColorLocal.u); + + /* if fog_mult is zero, we subtract the incoming color */ + if (!FOGMODE_FOG_MULT(fogModeReg)) + { + rgbaint_sub(&tmpA, &tmpB); + //fog.rgb -= color.rgb; + //fr -= (RR); + //fg -= (GG); + //fb -= (BB); + } + + /* fog blending mode */ + switch (FOGMODE_FOG_ZALPHA(fogModeReg)) + { + case 0: /* fog table */ + { + INT32 delta = v->fbi.fogdelta[fogDepth >> 10]; + INT32 deltaval; + + /* perform the multiply against lower 8 bits of wfloat */ + deltaval = (delta & v->fbi.fogdelta_mask) * + ((fogDepth >> 2) & 0xff); + + /* fog zones allow for negating this value */ + if (FOGMODE_FOG_ZONES(fogModeReg) && (delta & 2)) + deltaval = -deltaval; + deltaval >>= 6; + + /* apply dither */ + if (FOGMODE_FOG_DITHER(fogModeReg)) + deltaval += ditherX; + deltaval >>= 4; + + /* add to the blending factor */ + fogblend = v->fbi.fogblend[fogDepth >> 10] + deltaval; + break; + } + + case 1: /* iterated A */ + fogblend = iterargb.rgb.a; + break; + + case 2: /* iterated Z */ + CLAMPED_Z(iterz, fbzCpReg, fogblend); + fogblend >>= 8; + break; + + case 3: /* iterated W - Voodoo 2 only */ + CLAMPED_W(iterw, fbzCpReg, fogblend); + break; + } + + /* perform the blend */ + fogblend++; + + //fr = (fr * fogblend) >> 8; + //fg = (fg * fogblend) >> 8; + //fb = (fb * fogblend) >> 8; + /* if fog_mult is 0, we add this to the original color */ + if (FOGMODE_FOG_MULT(fogModeReg) == 0) + { + rgbaint_scale_immediate_add_and_clamp(&tmpA, (INT16) fogblend, &tmpB); + //color += fog; + //(RR) += fr; + //(GG) += fg; + //(BB) += fb; + } + + /* otherwise this just becomes the new color */ + else + { + rgbaint_scale_immediate_and_clamp(&tmpA, fogblend); + //color = fog; + //(RR) = fr; + //(GG) = fg; + //(BB) = fb; + } + color.u = rgbaint_to_rgba(&tmpA); + } + + + /* clamp */ + //CLAMP((RR), 0x00, 0xff); + //CLAMP((GG), 0x00, 0xff); + //CLAMP((BB), 0x00, 0xff); + color.u = (color.u & 0x00ffffff) | color_alpha; + } +} /************************************* @@ -3041,7 +3594,6 @@ while (0) do \ { \ INT32 depthval, wfloat, fogdepth, biasdepth; \ - INT32 prefogr, prefogg, prefogb; \ INT32 r, g, b, a; \ \ (STATS)->pixels_in++; \ @@ -3206,19 +3758,104 @@ do } \ while (0) +ATTR_FORCE_INLINE bool depthTest(UINT16 zaColorReg, stats_block *stats, INT32 destDepth, UINT32 fbzModeReg, INT32 biasdepth) +{ + /* handle depth buffer testing */ + if (FBZMODE_ENABLE_DEPTHBUF(fbzModeReg)) + { + INT32 depthsource; + + /* the source depth is either the iterated W/Z+bias or a */ + /* constant value */ + if (FBZMODE_DEPTH_SOURCE_COMPARE(fbzModeReg) == 0) + depthsource = biasdepth; + else + depthsource = zaColorReg; + + /* test against the depth buffer */ + switch (FBZMODE_DEPTH_FUNCTION(fbzModeReg)) + { + case 0: /* depthOP = never */ + stats->zfunc_fail++; + return false; + + case 1: /* depthOP = less than */ + if (depthsource >= destDepth) + { + stats->zfunc_fail++; + return false; + } + break; + + case 2: /* depthOP = equal */ + if (depthsource != destDepth) + { + stats->zfunc_fail++; + return false; + } + break; + + case 3: /* depthOP = less than or equal */ + if (depthsource > destDepth) + { + stats->zfunc_fail++; + return false; + } + break; + + case 4: /* depthOP = greater than */ + if (depthsource <= destDepth) + { + stats->zfunc_fail++; + return false; + } + break; + + case 5: /* depthOP = not equal */ + if (depthsource == destDepth) + { + stats->zfunc_fail++; + return false; + } + break; + + case 6: /* depthOP = greater than or equal */ + if (depthsource < destDepth) + { + stats->zfunc_fail++; + return false; + } + break; + + case 7: /* depthOP = always */ + break; + } + } + return true; +} #define PIXEL_PIPELINE_END(VV, STATS, DITHER, DITHER4, DITHER_LOOKUP, XX, dest, depth, FBZMODE, FBZCOLORPATH, ALPHAMODE, FOGMODE, ITERZ, ITERW, ITERAXXX) \ \ - /* perform fogging */ \ - prefogr = r; \ - prefogg = g; \ - prefogb = b; \ - APPLY_FOGGING(VV, FOGMODE, FBZCOLORPATH, XX, DITHER4, r, g, b, \ - ITERZ, ITERW, ITERAXXX); \ - \ - /* perform alpha blending */ \ - APPLY_ALPHA_BLEND(FBZMODE, ALPHAMODE, XX, DITHER, r, g, b, a); \ - \ + if (USE_OLD_RASTER) { \ + /* perform fogging */ \ + INT32 prefogr, prefogg, prefogb; \ + prefogr = r; \ + prefogg = g; \ + prefogb = b; \ + APPLY_FOGGING(VV, FOGMODE, FBZCOLORPATH, XX, DITHER4, r, g, b, \ + ITERZ, ITERW, ITERAXXX); \ + \ + /* perform alpha blending */ \ + APPLY_ALPHA_BLEND(FBZMODE, ALPHAMODE, XX, DITHER, r, g, b, a); \ + } else { \ + /* perform fogging */ \ + rgb_union preFog; \ + preFog.u = color.u; \ + applyFogging(VV, FOGMODE, FBZCOLORPATH, DITHER4[XX&3], fogdepth, color, ITERZ, ITERW, ITERAXXX); \ + /* perform alpha blending */ \ + alphaBlend(FBZMODE, ALPHAMODE, DITHER[XX&3], dest[XX], depth[XX], preFog, color); \ + a = color.rgb.a; r = color.rgb.r; g = color.rgb.g; b = color.rgb.b; \ + } \ /* modify the pixel for debugging purposes */ \ MODIFY_PIXEL(VV); \ \ @@ -3391,7 +4028,7 @@ do } \ \ /* select zero or a_other */ \ - if (FBZCP_CCA_ZERO_OTHER(FBZCOLORPATH) == 0) \ + if (!FBZCP_CCA_ZERO_OTHER(FBZCOLORPATH)) \ a = c_other.rgb.a; \ else \ a = 0; \ @@ -3546,6 +4183,254 @@ do } \ while (0) +ATTR_FORCE_INLINE bool combineColor(voodoo_state *VV, stats_block *STATS, UINT32 FBZCOLORPATH, UINT32 FBZMODE, UINT32 ALPHAMODE, + rgb_union TEXELARGB, INT32 ITERZ, INT64 ITERW, rgb_union ITERARGB, rgb_union &color) +{ + rgb_union c_other; + rgb_union c_local; + + /* compute c_other */ + switch (FBZCP_CC_RGBSELECT(FBZCOLORPATH)) + { + case 0: /* iterated RGB */ + c_other.u = ITERARGB.u; + break; + + case 1: /* texture RGB */ + c_other.u = TEXELARGB.u; + break; + + case 2: /* color1 RGB */ + c_other.u = (VV)->reg[color1].u; + break; + + default: /* reserved - voodoo3 framebufferRGB */ + c_other.u = 0; + break; + } + + /* handle chroma key */ + if (!chromaKeyTest(VV, STATS, FBZMODE, c_other)) + return false; + //APPLY_CHROMAKEY(VV, STATS, FBZMODE, c_other); + + /* compute a_other */ + switch (FBZCP_CC_ASELECT(FBZCOLORPATH)) + { + case 0: /* iterated alpha */ + c_other.rgb.a = ITERARGB.rgb.a; + break; + + case 1: /* texture alpha */ + c_other.rgb.a = TEXELARGB.rgb.a; + break; + + case 2: /* color1 alpha */ + c_other.rgb.a = (VV)->reg[color1].rgb.a; + break; + + default: /* reserved */ + c_other.rgb.a = 0; + break; + } + + /* handle alpha mask */ + if (!alphaMaskTest(STATS, FBZMODE, c_other.rgb.a)) + return false; + //APPLY_ALPHAMASK(VV, STATS, FBZMODE, c_other.rgb.a); + + + /* compute c_local */ + if (FBZCP_CC_LOCALSELECT_OVERRIDE(FBZCOLORPATH) == 0) + { + if (FBZCP_CC_LOCALSELECT(FBZCOLORPATH) == 0) /* iterated RGB */ + c_local.u = ITERARGB.u; + else /* color0 RGB */ + c_local.u = (VV)->reg[color0].u; + } + else + { + if (!(TEXELARGB.rgb.a & 0x80)) /* iterated RGB */ + c_local.u = ITERARGB.u; + else /* color0 RGB */ + c_local.u = (VV)->reg[color0].u; + } + + /* compute a_local */ + switch (FBZCP_CCA_LOCALSELECT(FBZCOLORPATH)) + { + default: + case 0: /* iterated alpha */ + c_local.rgb.a = ITERARGB.rgb.a; + break; + + case 1: /* color0 alpha */ + c_local.rgb.a = (VV)->reg[color0].rgb.a; + break; + + case 2: /* clamped iterated Z[27:20] */ + { + int temp; + CLAMPED_Z(ITERZ, FBZCOLORPATH, temp); + c_local.rgb.a = (UINT8)temp; + break; + } + + case 3: /* clamped iterated W[39:32] */ + { + int temp; + CLAMPED_W(ITERW, FBZCOLORPATH, temp); /* Voodoo 2 only */ + c_local.rgb.a = (UINT8)temp; + break; + } + } + + UINT8 a_other = c_other.rgb.a; + UINT8 a_local = c_local.rgb.a; + UINT8 tmp; + rgb_union add_val = c_local; + rgbaint tmpA, tmpB, tmpC; + + + /* select zero or c_other */ + if (FBZCP_CC_ZERO_OTHER(FBZCOLORPATH)) + c_other.u &= 0xff000000; + //r = g = b = 0; + + /* select zero or a_other */ + if (FBZCP_CCA_ZERO_OTHER(FBZCOLORPATH)) + c_other.u &= 0x00ffffff; + + rgba_to_rgbaint(&tmpA, (rgb_t) c_other.u); + + /* subtract a/c_local */ + if (FBZCP_CC_SUB_CLOCAL(FBZCOLORPATH) || (FBZCP_CCA_SUB_CLOCAL(FBZCOLORPATH))) + { + rgb_union sub_val = c_local; + + if (!FBZCP_CC_SUB_CLOCAL(FBZCOLORPATH)) + sub_val.u &= 0xff000000; + + if (!FBZCP_CCA_SUB_CLOCAL(FBZCOLORPATH)) + sub_val.u &= 0x00ffffff; + + rgba_to_rgbaint(&tmpB, (rgb_t) sub_val.u); + rgbaint_sub(&tmpA, &tmpB); + } + + /* blend RGB */ + switch (FBZCP_CC_MSELECT(FBZCOLORPATH)) + { + default: /* reserved */ + case 0: /* 0 */ + c_local.u &= 0xff000000; + break; + + case 1: /* c_local */ + break; + + case 2: /* a_other */ + c_local.u = (c_local.u & 0xff000000) | (a_other<<16) | (a_other<<8) | (a_other); + break; + + case 3: /* a_local */ + c_local.u = (c_local.u & 0xff000000) | (a_local<<16) | (a_local<<8) | (a_local); + break; + + case 4: /* texture alpha */ + tmp = TEXELARGB.rgb.a; + c_local.u = (c_local.u & 0xff000000) | (tmp<<16) | (tmp<<8) | (tmp); + break; + + case 5: /* texture RGB (Voodoo 2 only) */ + c_local.u = (c_local.u & 0xff000000) | (TEXELARGB.u & 0x00ffffff); + break; + } + + /* blend alpha */ + switch (FBZCP_CCA_MSELECT(FBZCOLORPATH)) + { + default: /* reserved */ + case 0: /* 0 */ + c_local.u &= 0x00ffffff; + break; + + case 1: /* a_local */ + case 3: /* a_local */ + c_local.rgb.a = a_local; + break; + + case 2: /* a_other */ + c_local.rgb.a = a_other; + break; + + case 4: /* texture alpha */ + c_local.rgb.a = TEXELARGB.rgb.a; + break; + } + + /* reverse the RGB blend */ + if (!FBZCP_CC_REVERSE_BLEND(FBZCOLORPATH)) + c_local.u ^= 0x00ffffff; + + /* reverse the alpha blend */ + if (!FBZCP_CCA_REVERSE_BLEND(FBZCOLORPATH)) + c_local.u ^= 0xff000000; + + /* do the blend */ + //color.rgb.a = (color.rgb.a * (blenda + 1)) >> 8; + //color.rgb.r = (color.rgb.r * (blendr + 1)) >> 8; + //color.rgb.g = (color.rgb.g * (blendg + 1)) >> 8; + //color.rgb.b = (color.rgb.b * (blendb + 1)) >> 8; + + /* add clocal or alocal to alpha */ + if (!FBZCP_CCA_ADD_ACLOCAL(FBZCOLORPATH)) + add_val.u &= 0x00ffffff; + //color.rgb.a += c_local.rgb.a; + + /* add clocal or alocal to RGB */ + switch (FBZCP_CC_ADD_ACLOCAL(FBZCOLORPATH)) + { + case 3: /* reserved */ + case 0: /* nothing */ + add_val.u &= 0xff000000; + break; + + case 1: /* add c_local */ + break; + + case 2: /* add_alocal */ + add_val.u = (add_val.u & 0xff000000) | (a_local<<16) | (a_local<<8) | (a_local); + break; + } + + /* clamp */ + //CLAMP(color.rgb.a, 0x00, 0xff); + //CLAMP(color.rgb.r, 0x00, 0xff); + //CLAMP(color.rgb.g, 0x00, 0xff); + //CLAMP(color.rgb.b, 0x00, 0xff); + rgba_to_rgbaint(&tmpB, (rgb_t) c_local.u); + rgbaint_add_imm(&tmpB, 1); + rgba_to_rgbaint(&tmpC, (rgb_t) add_val.u); + rgbaint_scale_channel_add_and_clamp(&tmpA, &tmpB, &tmpC); + color.u = rgbaint_to_rgba(&tmpA); + + /* invert */ + if (FBZCP_CCA_INVERT_OUTPUT(FBZCOLORPATH)) + color.u ^= 0xff000000; + /* invert */ + if (FBZCP_CC_INVERT_OUTPUT(FBZCOLORPATH)) + color.u ^= 0x00ffffff; + + + /* handle alpha test */ + if (!alphaTest(VV, STATS, ALPHAMODE, color.rgb.a)) + return false; + //APPLY_ALPHATEST(VV, STATS, ALPHAMODE, color.rgb.a); + + return true; +} + /************************************* @@ -3639,47 +4524,80 @@ static void raster_##name(void *destbase, INT32 y, const poly_extent *extent, co iters1 = extra->starts1 + dy * extra->ds1dy + dx * extra->ds1dx; \ itert1 = extra->startt1 + dy * extra->dt1dy + dx * extra->dt1dx; \ } \ - \ + extra->info->hits++; \ /* loop in X */ \ for (x = startx; x < stopx; x++) \ { \ - rgb_union iterargb = { 0 }; \ + rgb_union iterargb; \ rgb_union texel = { 0 }; \ + rgb_union color; \ \ /* pixel pipeline part 1 handles depth setup and stippling */ \ - PIXEL_PIPELINE_BEGIN(v, stats, x, y, FBZCOLORPATH, FBZMODE, \ - iterz, iterw); \ - /* depth testing */ \ - DEPTH_TEST(v, stats, x, FBZMODE); \ - \ - /* run the texture pipeline on TMU1 to produce a value in texel */ \ - /* note that they set LOD min to 8 to "disable" a TMU */ \ - if (TMUS >= 2 && v->tmu[1].lodmin < (8 << 8)) \ - TEXTURE_PIPELINE(&v->tmu[1], x, dither4, TEXMODE1, texel, \ - v->tmu[1].lookup, extra->lodbase1, \ - iters1, itert1, iterw1, texel); \ - \ - /* run the texture pipeline on TMU0 to produce a final */ \ - /* result in texel */ \ - /* note that they set LOD min to 8 to "disable" a TMU */ \ - if (TMUS >= 1 && v->tmu[0].lodmin < (8 << 8)) \ + PIXEL_PIPELINE_BEGIN(v, stats, x, y, FBZCOLORPATH, FBZMODE, iterz, iterw); \ + if (USE_OLD_RASTER) { \ + DEPTH_TEST(v, stats, x, FBZMODE); \ + \ + /* run the texture pipeline on TMU1 to produce a value in texel */ \ + /* note that they set LOD min to 8 to "disable" a TMU */ \ + if (TMUS >= 2 && v->tmu[1].lodmin < (8 << 8)) \ + TEXTURE_PIPELINE(&v->tmu[1], x, dither4, TEXMODE1, texel, \ + v->tmu[1].lookup, extra->lodbase1, \ + iters1, itert1, iterw1, texel); \ + \ + /* run the texture pipeline on TMU0 to produce a final */ \ + /* result in texel */ \ + /* note that they set LOD min to 8 to "disable" a TMU */ \ + if (TMUS >= 1 && v->tmu[0].lodmin < (8 << 8)) \ + { \ + if (!v->send_config) \ + TEXTURE_PIPELINE(&v->tmu[0], x, dither4, TEXMODE0, texel, \ + v->tmu[0].lookup, extra->lodbase0, \ + iters0, itert0, iterw0, texel); \ + else \ + texel.u = v->tmu_config; \ + } \ + /* colorpath pipeline selects source colors and does blending */ \ + CLAMPED_ARGB(iterr, iterg, iterb, itera, FBZCOLORPATH, iterargb); \ + COLORPATH_PIPELINE(v, stats, FBZCOLORPATH, FBZMODE, ALPHAMODE, texel, \ + iterz, iterw, iterargb); \ + } else { \ + /* depth testing */ \ + if (!depthTest((UINT16) v->reg[zaColor].u, stats, depth[x], FBZMODE, biasdepth)) \ + goto skipdrawdepth; \ + \ + /* run the texture pipeline on TMU1 to produce a value in texel */ \ + /* note that they set LOD min to 8 to "disable" a TMU */ \ + if (TMUS >= 2 && v->tmu[1].lodmin < (8 << 8)) { \ + INT32 tmp; \ + const rgb_union texelZero = {0}; \ + texel.u = genTexture(&v->tmu[1], dither4[x&3], TEXMODE1, v->tmu[1].lookup, extra->lodbase1, \ + iters1, itert1, iterw1, tmp); \ + texel.u = combineTexture(&v->tmu[1], TEXMODE1, texel, texelZero, tmp); \ + } \ + /* run the texture pipeline on TMU0 to produce a final */ \ + /* result in texel */ \ + /* note that they set LOD min to 8 to "disable" a TMU */ \ + if (TMUS >= 1 && v->tmu[0].lodmin < (8 << 8)) \ + { \ + rgb_union texelT0; \ + if (!v->send_config) \ { \ - if (!v->send_config) \ - { \ - TEXTURE_PIPELINE(&v->tmu[0], x, dither4, TEXMODE0, texel, \ - v->tmu[0].lookup, extra->lodbase0, \ - iters0, itert0, iterw0, texel); \ - } \ - else \ - { \ - texel.u=v->tmu_config; \ - } \ + INT32 lod0; \ + texelT0.u = genTexture(&v->tmu[0], dither4[x&3], TEXMODE0, v->tmu[0].lookup, extra->lodbase0, \ + iters0, itert0, iterw0, lod0); \ + texel.u = combineTexture(&v->tmu[0], TEXMODE0, texelT0, texel, lod0); \ } \ - \ - /* colorpath pipeline selects source colors and does blending */ \ - CLAMPED_ARGB(iterr, iterg, iterb, itera, FBZCOLORPATH, iterargb); \ - COLORPATH_PIPELINE(v, stats, FBZCOLORPATH, FBZMODE, ALPHAMODE, texel, \ - iterz, iterw, iterargb); \ + else \ + { \ + texel.u=v->tmu_config; \ + } \ + } \ + \ + /* colorpath pipeline selects source colors and does blending */ \ + iterargb.u = clampARGB(iterr, iterg, iterb, itera, FBZCOLORPATH); \ + if (!combineColor(v, stats, FBZCOLORPATH, FBZMODE, ALPHAMODE, texel, iterz, iterw, iterargb, color)) \ + goto skipdrawdepth; \ + } \ \ /* pixel pipeline part 2 handles fog, alpha, and final output */ \ PIXEL_PIPELINE_END(v, stats, dither, dither4, dither_lookup, x, dest, depth, \ @@ -3707,3 +4625,358 @@ static void raster_##name(void *destbase, INT32 y, const poly_extent *extent, co } \ } \ } + +ATTR_FORCE_INLINE UINT32 genTexture(tmu_state *TT, const UINT8 ditherX, const UINT32 TEXMODE, rgb_t *LOOKUP, INT32 LODBASE, INT64 ITERS, INT64 ITERT, INT64 ITERW, INT32 &lod) +{ + UINT32 result; + INT32 oow, s, t, ilod; + INT32 smax, tmax; + UINT32 texbase; + + /* determine the S/T/LOD values for this texture */ + lod = (LODBASE); + /* clamp W */ + if (TEXMODE_CLAMP_NEG_W(TEXMODE) && (ITERW) < 0) + { + s = t = 0; + } + else if (TEXMODE_ENABLE_PERSPECTIVE(TEXMODE)) + { + INT32 wLog; + oow = fast_reciplog((ITERW), &wLog); + lod += wLog; + s = ((INT64)oow * (ITERS)) >> 29; + t = ((INT64)oow * (ITERT)) >> 29; + } + else + { + s = (ITERS) >> 14; + t = (ITERT) >> 14; + } + + + /* clamp the LOD */ + lod += (TT)->lodbias; + if (TEXMODE_ENABLE_LOD_DITHER(TEXMODE)) + lod += ditherX << 4; + if (lod < (TT)->lodmin) + lod = (TT)->lodmin; + else if (lod > (TT)->lodmax) + lod = (TT)->lodmax; + + /* now the LOD is in range; if we don't own this LOD, take the next one */ + ilod = lod >> 8; + if (!(((TT)->lodmask >> ilod) & 1)) + ilod++; + + /* fetch the texture base */ + texbase = (TT)->lodoffset[ilod]; + + /* compute the maximum s and t values at this LOD */ + smax = (TT)->wmask >> ilod; + tmax = (TT)->hmask >> ilod; + + /* determine whether we are point-sampled or bilinear */ + if ((lod == (TT)->lodmin && !TEXMODE_MAGNIFICATION_FILTER(TEXMODE)) || + (lod != (TT)->lodmin && !TEXMODE_MINIFICATION_FILTER(TEXMODE))) + { + /* point sampled */ + + UINT32 texel0; + + /* adjust S/T for the LOD and strip off the fractions */ + s >>= ilod + 18; + t >>= ilod + 18; + + /* clamp/wrap S/T if necessary */ + if (TEXMODE_CLAMP_S(TEXMODE)) + CLAMP(s, 0, smax); + if (TEXMODE_CLAMP_T(TEXMODE)) + CLAMP(t, 0, tmax); + s &= smax; + t &= tmax; + t *= smax + 1; + + /* fetch texel data */ + if (TEXMODE_FORMAT(TEXMODE) < 8) + { + texel0 = *(UINT8 *)&(TT)->ram[(texbase + t + s) & (TT)->mask]; + result = (LOOKUP)[texel0]; + } + else + { + texel0 = *(UINT16 *)&(TT)->ram[(texbase + 2*(t + s)) & (TT)->mask]; + if (TEXMODE_FORMAT(TEXMODE) >= 10 && TEXMODE_FORMAT(TEXMODE) <= 12) + result = (LOOKUP)[texel0]; + else + result = ((LOOKUP)[texel0 & 0xff] & 0xffffff) | ((texel0 & 0xff00) << 16); + } + } + else + { + /* bilinear filtered */ + + UINT32 texel0, texel1, texel2, texel3; + UINT32 sfrac, tfrac; + INT32 s1, t1; + + /* adjust S/T for the LOD and strip off all but the low 8 bits of */ + /* the fraction */ + s >>= ilod + 10; + t >>= ilod + 10; + + /* also subtract 1/2 texel so that (0.5,0.5) = a full (0,0) texel */ + s -= 0x80; + t -= 0x80; + + /* extract the fractions */ + sfrac = s & (TT)->bilinear_mask; + tfrac = t & (TT)->bilinear_mask; + + /* now toss the rest */ + s >>= 8; + t >>= 8; + s1 = s + 1; + t1 = t + 1; + + /* clamp/wrap S/T if necessary */ + if (TEXMODE_CLAMP_S(TEXMODE)) + { + if (s < 0) { + s = 0; + s1 = 0; + } else if (s >= smax) { + s = smax; + s1 = smax; + } + //CLAMP(s, 0, smax); + //CLAMP(s1, 0, smax); + } else { + s &= smax; + s1 &= smax; + } + + if (TEXMODE_CLAMP_T(TEXMODE)) + { + if (t < 0) { + t = 0; + t1 = 0; + } else if (t >= tmax) { + t = tmax; + t1 = tmax; + } + //CLAMP(t, 0, tmax); + //CLAMP(t1, 0, tmax); + } else { + t &= tmax; + t1 &= tmax; + } + t *= smax + 1; + t1 *= smax + 1; + + /* fetch texel data */ + if (TEXMODE_FORMAT(TEXMODE) < 8) + { + texel0 = *(UINT8 *)&(TT)->ram[(texbase + t + s)]; + texel1 = *(UINT8 *)&(TT)->ram[(texbase + t + s1)]; + texel2 = *(UINT8 *)&(TT)->ram[(texbase + t1 + s)]; + texel3 = *(UINT8 *)&(TT)->ram[(texbase + t1 + s1)]; + texel0 = (LOOKUP)[texel0]; + texel1 = (LOOKUP)[texel1]; + texel2 = (LOOKUP)[texel2]; + texel3 = (LOOKUP)[texel3]; + } + else + { + texel0 = *(UINT16 *)&(TT)->ram[(texbase + 2*(t + s))]; + texel1 = *(UINT16 *)&(TT)->ram[(texbase + 2*(t + s1))]; + texel2 = *(UINT16 *)&(TT)->ram[(texbase + 2*(t1 + s))]; + texel3 = *(UINT16 *)&(TT)->ram[(texbase + 2*(t1 + s1))]; + if (TEXMODE_FORMAT(TEXMODE) >= 10 && TEXMODE_FORMAT(TEXMODE) <= 12) + { + texel0 = (LOOKUP)[texel0]; + texel1 = (LOOKUP)[texel1]; + texel2 = (LOOKUP)[texel2]; + texel3 = (LOOKUP)[texel3]; + } + else + { + texel0 = ((LOOKUP)[texel0 & 0xff] & 0xffffff) | ((texel0 & 0xff00) << 16); + texel1 = ((LOOKUP)[texel1 & 0xff] & 0xffffff) | ((texel1 & 0xff00) << 16); + texel2 = ((LOOKUP)[texel2 & 0xff] & 0xffffff) | ((texel2 & 0xff00) << 16); + texel3 = ((LOOKUP)[texel3 & 0xff] & 0xffffff) | ((texel3 & 0xff00) << 16); + } + } + + /* weigh in each texel */ + result = rgba_bilinear_filter(texel0, texel1, texel2, texel3, sfrac, tfrac); + } + return result; +} + +ATTR_FORCE_INLINE UINT32 combineTexture(tmu_state *TT, const UINT32 TEXMODE, rgb_union c_local, rgb_union c_other, INT32 lod) +{ + UINT32 result; + //INT32 blendr, blendg, blendb, blenda; + //INT32 tr, tg, tb, ta; + UINT8 a_other = c_other.rgb.a; + UINT8 a_local = c_local.rgb.a; + rgb_union add_val = c_local; + UINT8 tmp; + rgbaint tmpA, tmpB, tmpC; + + /* select zero/other for RGB */ + if (TEXMODE_TC_ZERO_OTHER(TEXMODE)) + c_other.u &= 0xff000000; + + /* select zero/other for alpha */ + if (TEXMODE_TCA_ZERO_OTHER(TEXMODE)) + c_other.u &= 0x00ffffff; + + rgba_to_rgbaint(&tmpA, (rgb_t) c_other.u); + + if (TEXMODE_TC_SUB_CLOCAL(TEXMODE) || TEXMODE_TCA_SUB_CLOCAL(TEXMODE)) + { + rgb_union sub_val = c_local; + + /* potentially subtract c_local */ + if (!TEXMODE_TC_SUB_CLOCAL(TEXMODE)) + sub_val.u &= 0xff000000; + + if (!TEXMODE_TCA_SUB_CLOCAL(TEXMODE)) + sub_val.u &= 0x00ffffff; + + rgba_to_rgbaint(&tmpB, (rgb_t) sub_val.u); + rgbaint_sub(&tmpA, &tmpB); + } + + /* blend RGB */ + switch (TEXMODE_TC_MSELECT(TEXMODE)) + { + default: /* reserved */ + case 0: /* zero */ + c_local.u &= 0xff000000; + break; + + case 1: /* c_local */ + break; + + case 2: /* a_other */ + c_local.u = (c_local.u & 0xff000000) | (a_other<<16) | (a_other<<8) | (a_other); + break; + + case 3: /* a_local */ + c_local.u = (c_local.u & 0xff000000) | (a_local<<16) | (a_local<<8) | (a_local); + break; + + case 4: /* LOD (detail factor) */ + if ((TT)->detailbias <= lod) + c_local.u &= 0xff000000; + else + { + tmp = ((((TT)->detailbias - lod) << (TT)->detailscale) >> 8); + if (tmp > (TT)->detailmax) + tmp = (TT)->detailmax; + c_local.u = (c_local.u & 0xff000000) | (tmp<<16) | (tmp<<8) | (tmp); + } + break; + + case 5: /* LOD fraction */ + tmp = lod & 0xff; + c_local.u = (c_local.u & 0xff000000) | (tmp<<16) | (tmp<<8) | (tmp); + break; + } + + /* blend alpha */ + switch (TEXMODE_TCA_MSELECT(TEXMODE)) + { + default: /* reserved */ + case 0: /* zero */ + c_local.u &= 0x00ffffff; + break; + + case 1: /* c_local */ + break; + + case 2: /* a_other */ + c_local.rgb.a = a_other; + break; + + case 3: /* a_local */ + break; + + case 4: /* LOD (detail factor) */ + if ((TT)->detailbias <= lod) + c_local.u &= 0x00ffffff; + else + { + tmp = ((((TT)->detailbias - lod) << (TT)->detailscale) >> 8); + if (tmp > (TT)->detailmax) + tmp = (TT)->detailmax; + c_local.rgb.a = tmp; + } + break; + + case 5: /* LOD fraction */ + c_local.rgb.a = lod & 0xff; + break; + } + + /* reverse the RGB blend */ + if (!TEXMODE_TC_REVERSE_BLEND(TEXMODE)) + { + c_local.u ^= 0x00ffffff; + } + + /* reverse the alpha blend */ + if (!TEXMODE_TCA_REVERSE_BLEND(TEXMODE)) + c_local.u ^= 0xff000000; + + /* do the blend */ + //tr = (tr * (blendr + 1)) >> 8; + //tg = (tg * (blendg + 1)) >> 8; + //tb = (tb * (blendb + 1)) >> 8; + //ta = (ta * (blenda + 1)) >> 8; + + /* add clocal or alocal to RGB */ + switch (TEXMODE_TC_ADD_ACLOCAL(TEXMODE)) + { + case 3: /* reserved */ + case 0: /* nothing */ + add_val.u &= 0xff000000; + break; + + case 1: /* add c_local */ + break; + + case 2: /* add_alocal */ + add_val.u = (add_val.u & 0xff000000) | (a_local << 16) | (a_local << 8) | (a_local << 0); + //tr += c_local.rgb.a; + //tg += c_local.rgb.a; + //tb += c_local.rgb.a; + break; + } + + /* add clocal or alocal to alpha */ + if (!TEXMODE_TCA_ADD_ACLOCAL(TEXMODE)) + add_val.u &= 0x00ffffff; + //ta += c_local.rgb.a; + + /* clamp */ + //result.rgb.r = (tr < 0) ? 0 : (tr > 0xff) ? 0xff : tr; + //result.rgb.g = (tg < 0) ? 0 : (tg > 0xff) ? 0xff : tg; + //result.rgb.b = (tb < 0) ? 0 : (tb > 0xff) ? 0xff : tb; + //result.rgb.a = (ta < 0) ? 0 : (ta > 0xff) ? 0xff : ta; + rgba_to_rgbaint(&tmpB, (rgb_t) c_local.u); + rgbaint_add_imm(&tmpB, 1); + rgba_to_rgbaint(&tmpC, (rgb_t) add_val.u); + rgbaint_scale_channel_add_and_clamp(&tmpA, &tmpB, &tmpC); + result = rgbaint_to_rgba(&tmpA); + + /* invert */ + if (TEXMODE_TC_INVERT_OUTPUT(TEXMODE)) + result ^= 0x00ffffff; + if (TEXMODE_TCA_INVERT_OUTPUT(TEXMODE)) + result ^= 0xff000000; + return result; +} diff --git a/src/emu/video/voodoo.c b/src/emu/video/voodoo.c index 1942aaa392f..73c421b90d0 100644 --- a/src/emu/video/voodoo.c +++ b/src/emu/video/voodoo.c @@ -892,7 +892,7 @@ static void swap_buffers(voodoo_state *v) /* periodically log rasterizer info */ v->stats.swaps++; - if (LOG_RASTERIZERS && v->stats.swaps % 100 == 0) + if (LOG_RASTERIZERS && v->stats.swaps % 1000 == 0) dump_rasterizer_stats(v); /* update the statistics (debug) */ @@ -3302,10 +3302,7 @@ static INT32 lfb_w(voodoo_state *v, offs_t offset, UINT32 data, UINT32 mem_mask, //PIXEL_PIPELINE_BEGIN(v, stats, x, y, v->reg[fbzColorPath].u, v->reg[fbzMode].u, iterz, iterw); // Start PIXEL_PIPE_BEGIN copy //#define PIXEL_PIPELINE_BEGIN(VV, STATS, XX, YY, FBZCOLORPATH, FBZMODE, ITERZ, ITERW) - do - { INT32 fogdepth, biasdepth; - INT32 prefogr, prefogg, prefogb; INT32 r, g, b, a; (stats)->pixels_in++; @@ -3334,7 +3331,7 @@ static INT32 lfb_w(voodoo_state *v, offs_t offset, UINT32 data, UINT32 mem_mask, if (((v->reg[stipple].u >> stipple_index) & 1) == 0) { v->stats.total_stippled++; - goto skipdrawdepth; + goto nextpixel; } } } @@ -3343,25 +3340,40 @@ static INT32 lfb_w(voodoo_state *v, offs_t offset, UINT32 data, UINT32 mem_mask, // Depth testing value for lfb pipeline writes is directly from write data, no biasing is used fogdepth = biasdepth = (UINT32) sw[pix]; - /* Perform depth testing */ - DEPTH_TEST(v, stats, x, v->reg[fbzMode].u); - /* use the RGBA we stashed above */ color.rgb.r = r = sr[pix]; color.rgb.g = g = sg[pix]; color.rgb.b = b = sb[pix]; color.rgb.a = a = sa[pix]; - /* apply chroma key, alpha mask, and alpha testing */ - APPLY_CHROMAKEY(v, stats, v->reg[fbzMode].u, color); - APPLY_ALPHAMASK(v, stats, v->reg[fbzMode].u, color.rgb.a); - APPLY_ALPHATEST(v, stats, v->reg[alphaMode].u, color.rgb.a); + if (USE_OLD_RASTER) { + /* Perform depth testing */ + DEPTH_TEST(v, stats, x, v->reg[fbzMode].u); + + /* apply chroma key, alpha mask, and alpha testing */ + APPLY_CHROMAKEY(v, stats, v->reg[fbzMode].u, color); + APPLY_ALPHAMASK(v, stats, v->reg[fbzMode].u, color.rgb.a); + APPLY_ALPHATEST(v, stats, v->reg[alphaMode].u, color.rgb.a); + } else { + /* Perform depth testing */ + if (!depthTest((UINT16) v->reg[zaColor].u, stats, depth[x], v->reg[fbzMode].u, biasdepth)) + goto nextpixel; + + /* handle chroma key */ + if (!chromaKeyTest(v, stats, v->reg[fbzMode].u, color)) + goto nextpixel; + /* handle alpha mask */ + if (!alphaMaskTest(stats, v->reg[fbzMode].u, color.rgb.a)) + goto nextpixel; + /* handle alpha test */ + if (!alphaTest(v, stats, v->reg[alphaMode].u, color.rgb.a)) + goto nextpixel; + } /* pixel pipeline part 2 handles color combine, fog, alpha, and final output */ PIXEL_PIPELINE_END(v, stats, dither, dither4, dither_lookup, x, dest, depth, v->reg[fbzMode].u, v->reg[fbzColorPath].u, v->reg[alphaMode].u, v->reg[fogMode].u, iterz, iterw, iterargb); - } nextpixel: /* advance our pointers */ x++; @@ -5658,6 +5670,7 @@ static raster_info *add_rasterizer(voodoo_state *v, const raster_info *cinfo) /* fill in the data */ info->hits = 0; info->polys = 0; + info->hash = hash; /* hook us into the hash table */ info->next = v->raster_hash[hash]; @@ -5760,7 +5773,7 @@ static void dump_rasterizer_stats(voodoo_state *v) break; /* print it */ - printf("RASTERIZER_ENTRY( 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X ) /* %c %8d %10d */\n", + printf("RASTERIZER_ENTRY( 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X ) /* %c %2d %8d %10d */\n", best->eff_color_path, best->eff_alpha_mode, best->eff_fog_mode, @@ -5768,6 +5781,7 @@ static void dump_rasterizer_stats(voodoo_state *v) best->eff_tex_mode_0, best->eff_tex_mode_1, best->is_generic ? '*' : ' ', + best->hash, best->polys, best->hits); @@ -6436,5 +6450,26 @@ RASTERIZER_ENTRY( 0x00602439, 0x00044119, 0x00000000, 0x000B0379, 0x00000009, 0x //RASTERIZER_ENTRY( 0x00002809, 0x00004110, 0x00000001, 0x00030FFB, 0x08241AC7, 0xFFFFFFFF ) /* in-game */ //RASTERIZER_ENTRY( 0x00424219, 0x00000000, 0x00000001, 0x00030F7B, 0x08241AC7, 0xFFFFFFFF ) /* in-game */ //RASTERIZER_ENTRY( 0x0200421A, 0x00001510, 0x00000001, 0x00030F7B, 0x08241AC7, 0xFFFFFFFF ) /* in-game */ +/* gtfore06 ----> fbzColorPath alphaMode fogMode, fbzMode, texMode0, texMode1 hash */ +RASTERIZER_ENTRY( 0x00482405, 0x00045119, 0x000000C1, 0x00010F79, 0x0C261ACD, 0x0C261ACD ) /* 18 1064626 69362127 */ +RASTERIZER_ENTRY( 0x00002425, 0x00045119, 0x000000C1, 0x00010F79, 0x0C224A0D, 0x0C261ACD ) /* 47 3272483 31242799 */ +RASTERIZER_ENTRY( 0x00482405, 0x00045119, 0x000000C1, 0x00010F79, 0x00000ACD, 0x0C261ACD ) /* 9 221917 12348555 */ +RASTERIZER_ENTRY( 0x00002425, 0x00045110, 0x000000C1, 0x00010FF9, 0x00000ACD, 0x0C261ACD ) /* 26 57291 9357989 */ +RASTERIZER_ENTRY( 0x00002429, 0x00000000, 0x000000C1, 0x00010FF9, 0x00000A09, 0x0C261A0F ) /* 12 97156 8530607 */ +RASTERIZER_ENTRY( 0x00482405, 0x00045119, 0x000000C1, 0x00010F79, 0x000000C4, 0x0C261ACD ) /* 55 110144 5265532 */ +RASTERIZER_ENTRY( 0x00002425, 0x00045110, 0x000000C1, 0x00010FF9, 0x000000C4, 0x0C261ACD ) /* 61 16644 1079382 */ +RASTERIZER_ENTRY( 0x00002425, 0x00045119, 0x000000C1, 0x00010FF9, 0x000000C4, 0x0C261ACD ) /* 5 8332 1065229 */ +RASTERIZER_ENTRY( 0x00002425, 0x00045119, 0x000000C1, 0x00010F79, 0x0C224A0D, 0x0C261A0D ) /* 45 8148 505013 */ +RASTERIZER_ENTRY( 0x00002425, 0x00045119, 0x00000000, 0x00010F79, 0x0C224A0D, 0x0C261A0D ) /* 84 45233 248267 */ +RASTERIZER_ENTRY( 0x00482405, 0x00045119, 0x000000C1, 0x00010F79, 0x0C261ACD, 0x0C2610C4 ) /* 90 10235 193036 */ +RASTERIZER_ENTRY( 0x00482405, 0x00045119, 0x000000C1, 0x00010FF9, 0x0C261ACD, 0x0C261ACD ) /* * 29 3777 83777 */ +RASTERIZER_ENTRY( 0x00482405, 0x00045119, 0x00000000, 0x00010FF9, 0x0C261ACD, 0x042210C0 ) /* 2 24952 66761 */ +RASTERIZER_ENTRY( 0x00002429, 0x00000000, 0x00000000, 0x00010FF9, 0x00000A09, 0x0C261A0F ) /* 24 661 50222 */ +RASTERIZER_ENTRY( 0x00482405, 0x00045119, 0x00000000, 0x00010FF9, 0x0C261ACD, 0x04221AC9 ) /* 92 12504 43720 */ +RASTERIZER_ENTRY( 0x00482405, 0x00045119, 0x000000C1, 0x00010FF9, 0x0C261ACD, 0x0C2610C4 ) /* 79 2160 43650 */ +RASTERIZER_ENTRY( 0x00482405, 0x00045119, 0x00000000, 0x00010FF9, 0x000000C4, 0x04221AC9 ) /* 19 2796 30377 */ +RASTERIZER_ENTRY( 0x00002425, 0x00045119, 0x000000C1, 0x00010FF9, 0x00000ACD, 0x0C261ACD ) /* 67 1962 14755 */ +RASTERIZER_ENTRY( 0x00482405, 0x00045119, 0x000000C1, 0x00010FF9, 0x000000C4, 0x0C261ACD ) /* * 66 74 3951 */ +RASTERIZER_ENTRY( 0x00482405, 0x00045119, 0x00000000, 0x00010FF9, 0x00000ACD, 0x04221AC9 ) /* 70 374 3691 */ #endif |