summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu')
-rw-r--r--src/emu/bus/a7800/a78_slot.c2
-rw-r--r--src/emu/bus/apricot/cards.c15
-rw-r--r--src/emu/bus/apricot/cards.h19
-rw-r--r--src/emu/bus/apricot/expansion.c192
-rw-r--r--src/emu/bus/apricot/expansion.h208
-rw-r--r--src/emu/bus/apricot/ram.c177
-rw-r--r--src/emu/bus/apricot/ram.h89
-rw-r--r--src/emu/bus/bml3/bml3mp1802.c69
-rw-r--r--src/emu/bus/bml3/bml3mp1802.h12
-rw-r--r--src/emu/bus/cgenie/expansion/floppy.c11
-rw-r--r--src/emu/bus/coco/coco_fdc.c85
-rw-r--r--src/emu/bus/coco/coco_fdc.h8
-rw-r--r--src/emu/bus/gameboy/gb_slot.c2
-rw-r--r--src/emu/bus/gameboy/mbc.c33
-rw-r--r--src/emu/bus/gameboy/mbc.h4
-rw-r--r--src/emu/bus/isa/gblaster.c33
-rw-r--r--src/emu/bus/isa/gblaster.h3
-rw-r--r--src/emu/bus/isa/hdc.c2
-rw-r--r--src/emu/bus/isa/hdc.h2
-rw-r--r--src/emu/bus/isa/sblaster.c9
-rw-r--r--src/emu/bus/kc/d004.h1
-rw-r--r--src/emu/bus/megadrive/md_slot.c2
-rw-r--r--src/emu/bus/megadrive/svp.c2
-rw-r--r--src/emu/bus/megadrive/svp.h2
-rw-r--r--src/emu/bus/nubus/nubus_image.c17
-rw-r--r--src/emu/bus/sega8/sega8_slot.c2
-rw-r--r--src/emu/bus/ti99_peb/bwg.c503
-rw-r--r--src/emu/bus/ti99_peb/bwg.h108
-rw-r--r--src/emu/bus/ti99_peb/hfdc.c51
-rw-r--r--src/emu/bus/ti99_peb/hfdc.h21
-rw-r--r--src/emu/bus/ti99_peb/peribox.c4
-rw-r--r--src/emu/bus/ti99_peb/ti_fdc.c310
-rw-r--r--src/emu/bus/ti99_peb/ti_fdc.h81
-rw-r--r--src/emu/bus/vboy/slot.c2
-rw-r--r--src/emu/bus/vtech/memexp/floppy.c14
-rw-r--r--src/emu/bus/vtech/memexp/floppy.h4
-rw-r--r--src/emu/bus/wswan/slot.c2
-rw-r--r--src/emu/cheat.c15
-rw-r--r--src/emu/clifront.c3
-rw-r--r--src/emu/cpu/alto2/a2roms.h2
-rw-r--r--src/emu/cpu/apexc/apexc.c2
-rw-r--r--src/emu/cpu/apexc/apexc.h2
-rw-r--r--src/emu/cpu/apexc/apexcdsm.c2
-rw-r--r--src/emu/cpu/arm7/arm7.c14
-rw-r--r--src/emu/cpu/arm7/arm7.h14
-rw-r--r--src/emu/cpu/arm7/arm7core.h14
-rw-r--r--src/emu/cpu/arm7/arm7core.inc14
-rw-r--r--src/emu/cpu/arm7/arm7dasm.c14
-rw-r--r--src/emu/cpu/arm7/arm7drc.inc14
-rw-r--r--src/emu/cpu/arm7/arm7help.h2
-rw-r--r--src/emu/cpu/arm7/arm7ops.c2
-rw-r--r--src/emu/cpu/arm7/arm7tdrc.inc2
-rw-r--r--src/emu/cpu/arm7/arm7thmb.c2
-rw-r--r--src/emu/cpu/cp1610/cp1610.c10
-rw-r--r--src/emu/cpu/cp1610/cp1610.h10
-rw-r--r--src/emu/cpu/hmcs40/hmcs40.c31
-rw-r--r--src/emu/cpu/hmcs40/hmcs40.h10
-rw-r--r--src/emu/cpu/i8089/i8089.c2
-rw-r--r--src/emu/cpu/i8089/i8089_channel.c20
-rw-r--r--src/emu/cpu/i8089/i8089_channel.h1
-rw-r--r--src/emu/cpu/i86/i86.c8
-rw-r--r--src/emu/cpu/i86/i86.h10
-rw-r--r--src/emu/cpu/lr35902/lr35902d.c14
-rw-r--r--src/emu/cpu/m6809/hd6309.c26
-rw-r--r--src/emu/cpu/m6809/konami.c20
-rw-r--r--src/emu/cpu/m6809/m6809.c6
-rw-r--r--src/emu/cpu/m6809/m6809.h38
-rw-r--r--src/emu/cpu/mcs51/mcs51.c14
-rw-r--r--src/emu/cpu/mcs51/mcs51.h14
-rw-r--r--src/emu/cpu/mcs51/mcs51dasm.c14
-rw-r--r--src/emu/cpu/mcs96/i8xc196.c4
-rw-r--r--src/emu/cpu/mcs96/i8xc196.h1
-rw-r--r--src/emu/cpu/melps4/m58846.c7
-rw-r--r--src/emu/cpu/melps4/melps4.c144
-rw-r--r--src/emu/cpu/melps4/melps4.h126
-rw-r--r--src/emu/cpu/melps4/melps4op.inc106
-rw-r--r--src/emu/cpu/mips/mips3.c18
-rw-r--r--src/emu/cpu/mips/mips3.h3
-rw-r--r--src/emu/cpu/mips/mips3drc.c3
-rw-r--r--src/emu/cpu/mn10200/mn10200.c204
-rw-r--r--src/emu/cpu/mn10200/mn10200.h96
-rw-r--r--src/emu/cpu/pdp1/pdp1.c2
-rw-r--r--src/emu/cpu/pdp1/pdp1.h2
-rw-r--r--src/emu/cpu/pdp1/pdp1dasm.c2
-rw-r--r--src/emu/cpu/pdp1/tx0.c2
-rw-r--r--src/emu/cpu/pdp1/tx0.h2
-rw-r--r--src/emu/cpu/pdp1/tx0dasm.c2
-rw-r--r--src/emu/cpu/pic16c62x/pic16c62x.c9
-rw-r--r--src/emu/cpu/rsp/rspcp2.c9
-rw-r--r--src/emu/cpu/rsp/rspcp2.h7
-rw-r--r--src/emu/cpu/rsp/rspcp2d.c208
-rw-r--r--src/emu/cpu/sc61860/sc61860.c12
-rw-r--r--src/emu/cpu/sc61860/sc61860.h12
-rw-r--r--src/emu/cpu/sc61860/scdasm.c12
-rw-r--r--src/emu/cpu/sc61860/scops.inc12
-rw-r--r--src/emu/cpu/scudsp/scudsp.c11
-rw-r--r--src/emu/cpu/ssp1601/ssp1601.c2
-rw-r--r--src/emu/cpu/tms0980/tms0980.c19
-rw-r--r--src/emu/cpu/tms9900/9900dasm.c2
-rw-r--r--src/emu/cpu/tms9900/99xxcore.h2
-rw-r--r--src/emu/cpu/ucom4/ucom4.c3
-rw-r--r--src/emu/devdelegate.h4
-rw-r--r--src/emu/emuopts.c7
-rw-r--r--src/emu/emuopts.h12
-rw-r--r--src/emu/imagedev/floppy.c29
-rw-r--r--src/emu/imagedev/floppy.h1
-rw-r--r--src/emu/input.c12
-rw-r--r--src/emu/machine/68561mpcc.c6
-rw-r--r--src/emu/machine/corvushd.c2
-rw-r--r--src/emu/machine/corvushd.h2
-rw-r--r--src/emu/machine/hdc9234.c682
-rw-r--r--src/emu/machine/hdc9234.h44
-rw-r--r--src/emu/machine/idehd.c2
-rw-r--r--src/emu/machine/mm58274c.c2
-rw-r--r--src/emu/machine/mm58274c.h2
-rw-r--r--src/emu/machine/mos6526.c10
-rw-r--r--src/emu/machine/netlist.c14
-rw-r--r--src/emu/machine/netlist.h17
-rw-r--r--src/emu/machine/ti99_hd.c653
-rw-r--r--src/emu/machine/ti99_hd.h154
-rw-r--r--src/emu/machine/tms1024.c82
-rw-r--r--src/emu/machine/tms1024.h96
-rw-r--r--src/emu/machine/wd17xx.c2107
-rw-r--r--src/emu/machine/wd17xx.h401
-rw-r--r--src/emu/machine/wd_fdc.c171
-rw-r--r--src/emu/machine/wd_fdc.h25
-rw-r--r--src/emu/machine/z80dart.h10
-rw-r--r--src/emu/netlist/analog/nld_bjt.c9
-rw-r--r--src/emu/netlist/analog/nld_bjt.h21
-rw-r--r--src/emu/netlist/analog/nld_fourterm.c1
-rw-r--r--src/emu/netlist/analog/nld_fourterm.h18
-rw-r--r--src/emu/netlist/analog/nld_ms_direct.h127
-rw-r--r--src/emu/netlist/analog/nld_ms_direct1.h2
-rw-r--r--src/emu/netlist/analog/nld_ms_direct2.h2
-rw-r--r--src/emu/netlist/analog/nld_ms_jakobi.h362
-rw-r--r--src/emu/netlist/analog/nld_ms_sor.h24
-rw-r--r--src/emu/netlist/analog/nld_ms_sor_mat.h36
-rw-r--r--src/emu/netlist/analog/nld_opamps.h2
-rw-r--r--src/emu/netlist/analog/nld_solver.c41
-rw-r--r--src/emu/netlist/analog/nld_solver.h23
-rw-r--r--src/emu/netlist/analog/nld_twoterm.c4
-rw-r--r--src/emu/netlist/analog/nld_twoterm.h22
-rw-r--r--src/emu/netlist/devices/net_lib.c4
-rw-r--r--src/emu/netlist/devices/net_lib.h2
-rw-r--r--src/emu/netlist/devices/nld_4020.c4
-rw-r--r--src/emu/netlist/devices/nld_7400.c16
-rw-r--r--src/emu/netlist/devices/nld_7402.c16
-rw-r--r--src/emu/netlist/devices/nld_7404.c45
-rw-r--r--src/emu/netlist/devices/nld_7404.h9
-rw-r--r--src/emu/netlist/devices/nld_7408.c16
-rw-r--r--src/emu/netlist/devices/nld_7410.c18
-rw-r--r--src/emu/netlist/devices/nld_7411.c18
-rw-r--r--src/emu/netlist/devices/nld_74123.c3
-rw-r--r--src/emu/netlist/devices/nld_74192.c2
-rw-r--r--src/emu/netlist/devices/nld_7420.c16
-rw-r--r--src/emu/netlist/devices/nld_7425.c16
-rw-r--r--src/emu/netlist/devices/nld_7427.c18
-rw-r--r--src/emu/netlist/devices/nld_74279.c20
-rw-r--r--src/emu/netlist/devices/nld_7430.c16
-rw-r--r--src/emu/netlist/devices/nld_7432.c16
-rw-r--r--src/emu/netlist/devices/nld_7437.c16
-rw-r--r--src/emu/netlist/devices/nld_7448.c2
-rw-r--r--src/emu/netlist/devices/nld_7448.h1
-rw-r--r--src/emu/netlist/devices/nld_7486.c105
-rw-r--r--src/emu/netlist/devices/nld_7486.h10
-rw-r--r--src/emu/netlist/devices/nld_7490.c32
-rw-r--r--src/emu/netlist/devices/nld_7493.c10
-rw-r--r--src/emu/netlist/devices/nld_7493.h1
-rw-r--r--src/emu/netlist/devices/nld_82S16.c2
-rw-r--r--src/emu/netlist/devices/nld_9310.c2
-rw-r--r--src/emu/netlist/devices/nld_9312.c30
-rw-r--r--src/emu/netlist/devices/nld_9316.c2
-rw-r--r--src/emu/netlist/devices/nld_legacy.c7
-rw-r--r--src/emu/netlist/devices/nld_signal.h24
-rw-r--r--src/emu/netlist/devices/nld_system.c8
-rw-r--r--src/emu/netlist/devices/nld_system.h117
-rw-r--r--src/emu/netlist/devices/nld_truthtable.c60
-rw-r--r--src/emu/netlist/devices/nld_truthtable.h148
-rw-r--r--src/emu/netlist/nl_base.c91
-rw-r--r--src/emu/netlist/nl_base.h293
-rw-r--r--src/emu/netlist/nl_config.h67
-rw-r--r--src/emu/netlist/nl_factory.c30
-rw-r--r--src/emu/netlist/nl_factory.h46
-rw-r--r--src/emu/netlist/nl_lists.h82
-rw-r--r--src/emu/netlist/nl_parser.c117
-rw-r--r--src/emu/netlist/nl_parser.h114
-rw-r--r--src/emu/netlist/nl_setup.c136
-rw-r--r--src/emu/netlist/nl_setup.h133
-rw-r--r--src/emu/netlist/nl_time.h57
-rw-r--r--src/emu/netlist/nl_util.h86
-rw-r--r--src/emu/netlist/pconfig.h82
-rw-r--r--src/emu/netlist/plib/palloc.c (renamed from src/emu/netlist/palloc.c)0
-rw-r--r--src/emu/netlist/plib/palloc.h (renamed from src/emu/netlist/palloc.h)14
-rw-r--r--src/emu/netlist/plib/pconfig.h198
-rw-r--r--src/emu/netlist/plib/plists.h (renamed from src/emu/netlist/plists.h)166
-rw-r--r--src/emu/netlist/plib/poptions.h (renamed from src/emu/netlist/poptions.h)24
-rw-r--r--src/emu/netlist/plib/pparser.c (renamed from src/emu/netlist/pparser.c)103
-rw-r--r--src/emu/netlist/plib/pparser.h (renamed from src/emu/netlist/pparser.h)23
-rw-r--r--src/emu/netlist/plib/pstate.c (renamed from src/emu/netlist/pstate.c)0
-rw-r--r--src/emu/netlist/plib/pstate.h (renamed from src/emu/netlist/pstate.h)1
-rw-r--r--src/emu/netlist/plib/pstring.c (renamed from src/emu/netlist/pstring.c)18
-rw-r--r--src/emu/netlist/plib/pstring.h (renamed from src/emu/netlist/pstring.h)61
-rw-r--r--src/emu/netlist/tools/nl_convert.c458
-rw-r--r--src/emu/netlist/tools/nl_convert.h219
-rw-r--r--src/emu/schedule.h2
-rw-r--r--src/emu/softlist.c7
-rw-r--r--src/emu/sound/aica.c2
-rw-r--r--src/emu/sound/aica.h2
-rw-r--r--src/emu/sound/aicadsp.c2
-rw-r--r--src/emu/sound/aicadsp.h2
-rw-r--r--src/emu/sound/c352.c29
-rw-r--r--src/emu/sound/c352.h25
-rw-r--r--src/emu/sound/disc_cls.h2
-rw-r--r--src/emu/sound/discrete.c2
-rw-r--r--src/emu/sound/discrete.h2
-rw-r--r--src/emu/sound/es5503.c3
-rw-r--r--src/emu/sound/fmopl.c4
-rw-r--r--src/emu/sound/ics2115.c4
-rw-r--r--src/emu/sound/ics2115.h4
-rw-r--r--src/emu/sound/n63701x.c10
-rw-r--r--src/emu/sound/okim9810.c2
-rw-r--r--src/emu/sound/okim9810.h2
-rw-r--r--src/emu/sound/qsound.c2
-rw-r--r--src/emu/sound/qsound.h2
-rw-r--r--src/emu/sound/st0016.c5
-rw-r--r--src/emu/sound/tms5110.c2
-rw-r--r--src/emu/sound/tms5110.h2
-rw-r--r--src/emu/sound/ym2413.c4
-rw-r--r--src/emu/sound/ymf262.c4
-rw-r--r--src/emu/sound/zsg2.c8
-rw-r--r--src/emu/ui/filesel.c3
-rw-r--r--src/emu/ui/imgcntrl.c1
-rw-r--r--src/emu/ui/ui.c5
-rw-r--r--src/emu/video/clgd542x.c133
-rw-r--r--src/emu/video/clgd542x.h2
-rw-r--r--src/emu/video/mc6845.c6
-rw-r--r--src/emu/video/mc6847.c16
-rw-r--r--src/emu/video/pc_vga.c16
-rw-r--r--src/emu/video/pc_vga.h2
-rw-r--r--src/emu/video/rgbgen.h57
-rw-r--r--src/emu/video/rgbsse.h41
-rw-r--r--src/emu/video/tms3556.c2
-rw-r--r--src/emu/video/tms3556.h2
-rw-r--r--src/emu/video/vooddefs.h1373
-rw-r--r--src/emu/video/voodoo.c63
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 &params, const int size);
- netlist_matrix_solver_direct_t(const eSolverType type, const netlist_solver_parameters_t &params, 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 &params, 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 &params, 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 &params)
+ 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 &params)
+ 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 &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)
- , 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 &params, 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 &params, 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 &params)
+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 &params);
- /* 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 &param);
- ATTR_COLD /* inline */ void initial(const pstring &val) { m_param = val; }
+ ATTR_HOT void setTo(const pstring &param);
+ 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 &param_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 &param = 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 &param, 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 &param_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 &param, const pstring &value);
void register_param(const pstring &param, 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 &param_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