summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/bus/econet/e01.cpp11
-rw-r--r--src/devices/bus/econet/e01.h3
-rw-r--r--src/devices/bus/electron/exp.cpp104
-rw-r--r--src/devices/bus/electron/exp.h158
-rw-r--r--src/devices/machine/terminal.cpp2
-rw-r--r--src/devices/video/vector.cpp2
-rw-r--r--src/emu/emuopts.cpp1
-rw-r--r--src/emu/emuopts.h2
-rw-r--r--src/emu/output.cpp5
-rw-r--r--src/emu/output.h3
-rw-r--r--src/emu/rendutil.cpp2
-rw-r--r--src/frontend/mame/ui/ui.cpp4
-rw-r--r--src/lib/formats/afs_dsk.cpp60
-rw-r--r--src/lib/formats/afs_dsk.h37
-rw-r--r--src/lib/formats/fsd_dsk.cpp31
-rw-r--r--src/mame/drivers/electron.cpp3
-rw-r--r--src/mame/drivers/imds2.cpp17
-rw-r--r--src/mame/drivers/naomi.cpp47
-rw-r--r--src/mame/drivers/sorcerer.cpp18
-rw-r--r--src/mame/drivers/sun3.cpp981
-rw-r--r--src/mame/drivers/sun3x.cpp684
-rw-r--r--src/mame/includes/electron.h1
-rw-r--r--src/mame/includes/sorcerer.h6
-rw-r--r--src/mame/machine/dec_lk201.cpp2
-rw-r--r--src/mame/machine/sorcerer.cpp20
-rw-r--r--src/mame/mame.lst9
-rw-r--r--src/mame/mess.flt1
-rw-r--r--src/mame/video/powervr2.cpp2
-rw-r--r--src/osd/modules/debugger/debugimgui.cpp100
-rw-r--r--src/osd/modules/lib/osdobj_common.cpp2
-rw-r--r--src/osd/modules/output/output_module.h7
-rw-r--r--src/osd/modules/output/win32_output.cpp340
-rw-r--r--src/osd/modules/output/win32_output.h86
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_distortion.sc18
-rw-r--r--src/osd/modules/render/d3d/d3dhlsl.cpp7
-rw-r--r--src/osd/modules/render/d3d/d3dhlsl.h1
-rw-r--r--src/osd/modules/render/drawbgfx.cpp7
-rw-r--r--src/osd/modules/render/drawd3d.cpp200
-rw-r--r--src/osd/modules/render/drawogl.cpp24
-rw-r--r--src/osd/windows/ledutil.cpp709
-rw-r--r--src/osd/windows/winmain.cpp1
-rw-r--r--src/osd/windows/winmain.h2
42 files changed, 2994 insertions, 726 deletions
diff --git a/src/devices/bus/econet/e01.cpp b/src/devices/bus/econet/e01.cpp
index ed60ccc2d28..6176268d6d7 100644
--- a/src/devices/bus/econet/e01.cpp
+++ b/src/devices/bus/econet/e01.cpp
@@ -53,7 +53,7 @@
#include "e01.h"
#include "bus/scsi/scsihd.h"
-
+#include "softlist.h"
//**************************************************************************
@@ -166,6 +166,10 @@ WRITE_LINE_MEMBER( e01_device::clk_en_w )
m_clk_en = state;
}
+FLOPPY_FORMATS_MEMBER( floppy_formats_afs )
+ FLOPPY_AFS_FORMAT
+FLOPPY_FORMATS_END0
+
static SLOT_INTERFACE_START( e01_floppies )
SLOT_INTERFACE( "35dd", FLOPPY_35_DD ) // NEC FD1036 A
SLOT_INTERFACE_END
@@ -253,8 +257,9 @@ static MACHINE_CONFIG_FRAGMENT( e01 )
MCFG_WD2793_ADD(WD2793_TAG, XTAL_8MHz/4)
MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(e01_device, fdc_irq_w))
MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(e01_device, fdc_drq_w))
- MCFG_FLOPPY_DRIVE_ADD(WD2793_TAG":0", e01_floppies, "35dd", floppy_image_device::default_floppy_formats)
- MCFG_FLOPPY_DRIVE_ADD(WD2793_TAG":1", e01_floppies, "35dd", floppy_image_device::default_floppy_formats)
+ MCFG_FLOPPY_DRIVE_ADD(WD2793_TAG":0", e01_floppies, "35dd", floppy_formats_afs)
+ MCFG_FLOPPY_DRIVE_ADD(WD2793_TAG":1", e01_floppies, "35dd", floppy_formats_afs)
+ MCFG_SOFTWARE_LIST_ADD("flop_ls_e01", "e01_flop")
MCFG_CENTRONICS_ADD(CENTRONICS_TAG, centronics_devices, "printer")
MCFG_CENTRONICS_ACK_HANDLER(DEVWRITELINE(R6522_TAG, via6522_device, write_ca1))
diff --git a/src/devices/bus/econet/e01.h b/src/devices/bus/econet/e01.h
index e83b9a0b6bd..02a432c936d 100644
--- a/src/devices/bus/econet/e01.h
+++ b/src/devices/bus/econet/e01.h
@@ -22,6 +22,7 @@
#include "machine/mc6854.h"
#include "machine/ram.h"
#include "machine/wd_fdc.h"
+#include "formats/afs_dsk.h"
class e01_device : public device_t,
public device_econet_interface
@@ -37,6 +38,8 @@ public:
TYPE_E01S
};
+ DECLARE_FLOPPY_FORMATS(floppy_formats_afs);
+
DECLARE_READ8_MEMBER( read );
DECLARE_WRITE8_MEMBER( write );
DECLARE_READ8_MEMBER( ram_select_r );
diff --git a/src/devices/bus/electron/exp.cpp b/src/devices/bus/electron/exp.cpp
new file mode 100644
index 00000000000..b13f6534002
--- /dev/null
+++ b/src/devices/bus/electron/exp.cpp
@@ -0,0 +1,104 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Electron Expansion Port emulation
+
+**********************************************************************/
+
+#include "exp.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+const device_type ELECTRON_EXPANSION_SLOT = &device_creator<electron_expansion_slot_device>;
+
+
+//**************************************************************************
+// DEVICE ELECTRON_EXPANSION CARD INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_electron_expansion_interface - constructor
+//-------------------------------------------------
+
+device_electron_expansion_interface::device_electron_expansion_interface(const machine_config &mconfig, device_t &device)
+ : device_slot_card_interface(mconfig, device)
+{
+ m_slot = dynamic_cast<electron_expansion_slot_device *>(device.owner());
+}
+
+
+//-------------------------------------------------
+// ~device_electron_expansion_card_interface - destructor
+//-------------------------------------------------
+
+device_electron_expansion_interface::~device_electron_expansion_interface()
+{
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// electron_expansion_slot_device - constructor
+//-------------------------------------------------
+
+electron_expansion_slot_device::electron_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, ELECTRON_EXPANSION_SLOT, "Expansion port", tag, owner, clock, "electron_expansion_slot", __FILE__),
+ device_slot_interface(mconfig, *this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void electron_expansion_slot_device::device_start()
+{
+ m_card = dynamic_cast<device_electron_expansion_interface *>(get_card_device());
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void electron_expansion_slot_device::device_reset()
+{
+ if (get_card_device())
+ {
+ get_card_device()->reset();
+ }
+}
+
+
+//-------------------------------------------------
+// SLOT_INTERFACE( electron_expansion_devices )
+//-------------------------------------------------
+
+
+// slot devices
+//#include "plus1.h"
+//#include "plus3.h"
+//#include "aplus3.h"
+//#include "aplus5.h"
+//#include "slogger.h"
+//#include "fbjoy.h"
+//#include "m2105.h"
+
+
+SLOT_INTERFACE_START( electron_expansion_devices )
+ //SLOT_INTERFACE("plus1", ELECTRON_PLUS1)
+ //SLOT_INTERFACE("plus3", ELECTRON_PLUS3)
+ //SLOT_INTERFACE("aplus3", ELECTRON_APLUS3)
+ //SLOT_INTERFACE("aplus5", ELECTRON_APLUS5)
+ //SLOT_INTERFACE("slogger", ELECTRON_SLOGGER)
+ //SLOT_INTERFACE("fbjoy", ELECTRON_FBJOY)
+ //SLOT_INTERFACE("m2105", ELECTRON_M2105)
+SLOT_INTERFACE_END
diff --git a/src/devices/bus/electron/exp.h b/src/devices/bus/electron/exp.h
new file mode 100644
index 00000000000..cfcb7478a10
--- /dev/null
+++ b/src/devices/bus/electron/exp.h
@@ -0,0 +1,158 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Electron Expansion Port emulation
+
+**********************************************************************
+
+ Pinout:
+
+ 18V AC 2 1 18V AC
+ AC RETURN 4 3 AC RETURN
+ -5V 6 5 -5V
+ 0V 8 7 0V
+ +5V 10 9 +5V
+ 16MHz 12 11 SOUND O/P
+ PHI OUT 14 13 ÷13 IN
+ NMI 16 15 RST
+ R/W 18 17 IRQ
+ D6 20 19 D7
+ D4 22 21 D5
+ D2 24 23 D3
+ D0 26 25 D1
+ NC 28 27 RDY
+ SLOT 30 29 SLOT
+ A14 32 31 A15
+ A12 34 33 A13
+ A10 36 35 A11
+ A0 38 37 A9
+ A2 40 39 A1
+ A4 42 41 A3
+ A6 44 43 A5
+ A8 46 45 A7
+ 0V 48 47 0V
+ +5V 50 49 +5V
+
+ Signal Definitions:
+
+ 18V AC (pins 1,2) - These lines are connected directly to the output from the Electron mains power
+AC RETURNS (pins 3,4) - adaptor. A total of 6W may be drawn from these lines as long as no power is
+ taken from +5V (pins 9,10,49,50). For safety reasons these lines must never
+ be used as an AC input to the Electron.
+ -5V (pins 5,6) - A -5V supply from the Electron. Up to 20mA (total) may safely be drawn
+ from this line by expansion modules.
+ 0V (pins 7,8,47,48) - Ground. Expansion modules with their own power supply must have the 0V
+ lines commoned with the Electron.
++5V (pins 9,10,49,50) - A +5V supply from the Electron. Up to 500mA (total) may safely be drawn
+ from this line by expansion modules as long as no power is taken from 18V
+ AC (pins 1,2,3,4).
+ SOUND O/P (pin 11) - Sound output. A 3V peak to peak source via a 1K series resistor from the
+ Electron ULA.
+ 16 MHz (pin 12) - 16 Megahertz from the Electron main oscillator. This output may be used
+ for clock generation within an expansion module.
+ /13 IN (pin 13) - 16 Megahertz divided by 13. This output may be used for baud rate
+ generation. If divided by 1024 it will give approximately 1200Hz.
+ PHI OUT (pin 14) - The 6502 input clock. The low time is nominally 250ns. The high time may
+ be 250ns (2MHz operation when reading ROMs) or 750ns or 1250ns
+ (stretched clock for a 1MHz access, the length depending on the phase of the
+ 2MHz clock) or up to 40us (if in modes 0-3)
+ RST (pin 15) - Reset (active low). This is an OUTPUT ONLY for the system reset line. It
+ may be used to initialise expansion modules on power up and when the
+ BREAK key is pressed.
+ NMI (pin 16) - Non-Maskable Interrupt (negative edge triggered). This is the system NMI
+ line which is open collector (wire-OR) and may be asserted by an expansion
+ module. The pull-up resistor on this line inside the ULA is 3k3. Care must
+ be taken to avoid masking other interrupts by holding the line low. Using
+ NMI on the Electron requires knowledge of operating system protocols.
+ IRQ (pin 17) - Interrupt Request (active low). This is the system IRQ line which is open
+ collector (wire-OR) and may be asserted by an expansion module. The pull-
+ up resistor on this line inside the ULA is 3k3. It is essential for the correct
+ operation of the machine that interrupts to not occur until the software is
+ capable of dealing with them. Interrupts on the Electron expansion bus should
+ therefore be disabled on power-up and reset. Significant use of interrupt
+ service time may affect other machine functions, eg the real time clock.
+ R/W (pin 18) - The system read/write line from the 6502.
+ D7-D0 (pins 19-26) - Bi-directional data bus. The direction of data is determined by R/W.
+ RDY (pin 27) - 6502 ready line (active low). May be asserted by an expansion module to
+ stop the processor when reading slow memory. This line works on read only
+ (R/W=1).
+ (pin 28) - No connection
+ (pins 29,30) - Polarising key connector.
+ A0-A15 (pins 31-46) - 6502 address bus.
+
+**********************************************************************/
+
+#pragma once
+
+#ifndef __ELECTRON_EXPANSION_SLOT__
+#define __ELECTRON_EXPANSION_SLOT__
+
+#include "emu.h"
+
+
+//**************************************************************************
+// CONSTANTS
+//**************************************************************************
+
+#define ELECTRON_EXPANSION_SLOT_TAG "exp"
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_ELECTRON_EXPANSION_SLOT_ADD(_tag, _slot_intf, _def_slot) \
+ MCFG_DEVICE_ADD(_tag, ELECTRON_EXPANSION_SLOT, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false)
+
+#define MCFG_ELECTRON_PASSTHRU_EXPANSION_SLOT_ADD() \
+ MCFG_ELECTRON_EXPANSION_SLOT_ADD(ELECTRON_EXPANSION_SLOT_TAG, 0, electron_expansion_devices, nullptr)
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> electron_expansion_slot_device
+
+class device_electron_expansion_interface;
+
+class electron_expansion_slot_device : public device_t,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ electron_expansion_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~electron_expansion_slot_device() {}
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ device_electron_expansion_interface *m_card;
+};
+
+
+// ======================> device_electron_expansion_card_interface
+
+class device_electron_expansion_interface : public device_slot_card_interface
+{
+public:
+ // construction/destruction
+ device_electron_expansion_interface(const machine_config &mconfig, device_t &device);
+ virtual ~device_electron_expansion_interface();
+
+protected:
+ electron_expansion_slot_device *m_slot;
+};
+
+
+// device type definition
+extern const device_type ELECTRON_EXPANSION_SLOT;
+
+SLOT_INTERFACE_EXTERN( electron_expansion_devices );
+
+
+#endif
diff --git a/src/devices/machine/terminal.cpp b/src/devices/machine/terminal.cpp
index 86388182f15..a2be090b261 100644
--- a/src/devices/machine/terminal.cpp
+++ b/src/devices/machine/terminal.cpp
@@ -319,7 +319,7 @@ WRITE8_MEMBER( generic_terminal_device::kbd_put )
***************************************************************************/
static MACHINE_CONFIG_FRAGMENT( generic_terminal )
- MCFG_SCREEN_ADD_MONOCHROME(TERMINAL_SCREEN_TAG, RASTER, rgb_t::green)
+ MCFG_SCREEN_ADD_MONOCHROME(TERMINAL_SCREEN_TAG, RASTER, rgb_t::white)
MCFG_SCREEN_REFRESH_RATE(50)
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
MCFG_SCREEN_SIZE(TERMINAL_WIDTH*8, TERMINAL_HEIGHT*10)
diff --git a/src/devices/video/vector.cpp b/src/devices/video/vector.cpp
index 8606fe666aa..53286f3c623 100644
--- a/src/devices/video/vector.cpp
+++ b/src/devices/video/vector.cpp
@@ -145,7 +145,7 @@ void vector_device::clear_list(void)
UINT32 vector_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- UINT32 flags = PRIMFLAG_ANTIALIAS(machine().options().antialias() ? 1 : 0) | PRIMFLAG_BLENDMODE(BLENDMODE_ADD) | PRIMFLAG_VECTOR(1);
+ UINT32 flags = PRIMFLAG_ANTIALIAS(1) | PRIMFLAG_BLENDMODE(BLENDMODE_ADD) | PRIMFLAG_VECTOR(1);
const rectangle &visarea = screen.visible_area();
float xscale = 1.0f / (65536 * visarea.width());
float yscale = 1.0f / (65536 * visarea.height());
diff --git a/src/emu/emuopts.cpp b/src/emu/emuopts.cpp
index 1b99a55e1ba..dc799ca235b 100644
--- a/src/emu/emuopts.cpp
+++ b/src/emu/emuopts.cpp
@@ -120,7 +120,6 @@ const options_entry emu_options::s_option_entries[] =
// vector options
{ nullptr, nullptr, OPTION_HEADER, "CORE VECTOR OPTIONS" },
- { OPTION_ANTIALIAS ";aa", "1", OPTION_BOOLEAN, "use antialiasing when drawing vectors" },
{ OPTION_BEAM_WIDTH_MIN, "1.0", OPTION_FLOAT, "set vector beam width minimum" },
{ OPTION_BEAM_WIDTH_MAX, "1.0", OPTION_FLOAT, "set vector beam width maximum" },
{ OPTION_BEAM_INTENSITY_WEIGHT, "0", OPTION_FLOAT, "set vector beam intensity weight " },
diff --git a/src/emu/emuopts.h b/src/emu/emuopts.h
index 2b6630d38dd..e3ae4bda6d8 100644
--- a/src/emu/emuopts.h
+++ b/src/emu/emuopts.h
@@ -108,7 +108,6 @@
#define OPTION_EFFECT "effect"
// core vector options
-#define OPTION_ANTIALIAS "antialias"
#define OPTION_BEAM_WIDTH_MIN "beam_width_min"
#define OPTION_BEAM_WIDTH_MAX "beam_width_max"
#define OPTION_BEAM_INTENSITY_WEIGHT "beam_intensity_weight"
@@ -295,7 +294,6 @@ public:
const char *effect() const { return value(OPTION_EFFECT); }
// core vector options
- bool antialias() const { return bool_value(OPTION_ANTIALIAS); }
float beam_width_min() const { return float_value(OPTION_BEAM_WIDTH_MIN); }
float beam_width_max() const { return float_value(OPTION_BEAM_WIDTH_MAX); }
float beam_intensity_weight() const { return float_value(OPTION_BEAM_INTENSITY_WEIGHT); }
diff --git a/src/emu/output.cpp b/src/emu/output.cpp
index b905c45d70b..026e5f84ad0 100644
--- a/src/emu/output.cpp
+++ b/src/emu/output.cpp
@@ -9,6 +9,7 @@
#include "emu.h"
#include "coreutil.h"
+#include "modules/output/output_module.h"
//**************************************************************************
// OUTPUT MANAGER
@@ -210,10 +211,10 @@ void output_manager::set_notifier(const char *outname, output_notifier_func call
notifier for all outputs
-------------------------------------------------*/
-void output_manager::notify_all(output_notifier_func callback, void *param)
+void output_manager::notify_all(output_module *module)
{
for (auto &item : m_itemtable)
- (*callback)(item.second.name.c_str(), item.second.value, param);
+ module->notify(item.second.name.c_str(), item.second.value);
}
diff --git a/src/emu/output.h b/src/emu/output.h
index e83399aa4b1..69c5bc5b402 100644
--- a/src/emu/output.h
+++ b/src/emu/output.h
@@ -21,6 +21,7 @@
TYPE DEFINITIONS
***************************************************************************/
+class output_module;
typedef void (*output_notifier_func)(const char *outname, INT32 value, void *param);
// ======================> output_manager
@@ -72,7 +73,7 @@ public:
void set_notifier(const char *outname, output_notifier_func callback, void *param);
// set a notifier on a particular output, or globally if nullptr
- void notify_all(output_notifier_func callback, void *param);
+ void notify_all(output_module *module);
// map a name to a unique ID
UINT32 name_to_id(const char *outname);
diff --git a/src/emu/rendutil.cpp b/src/emu/rendutil.cpp
index ee78ad5125d..8fa5b1b7046 100644
--- a/src/emu/rendutil.cpp
+++ b/src/emu/rendutil.cpp
@@ -535,7 +535,7 @@ void render_line_to_quad(const render_bounds *bounds, float width, float length_
bounds1->x0 = modbounds.x1 - unity;
bounds1->y0 = modbounds.y1 + unitx;
- /* rotate the unit vector by -09 degrees and add to point 1 */
+ /* rotate the unit vector by -90 degrees and add to point 1 */
bounds1->x1 = modbounds.x1 + unity;
bounds1->y1 = modbounds.y1 - unitx;
}
diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp
index 4f0f6be9a83..d1999a1ce16 100644
--- a/src/frontend/mame/ui/ui.cpp
+++ b/src/frontend/mame/ui/ui.cpp
@@ -2015,8 +2015,8 @@ std::vector<ui::menu_item> mame_ui_manager::slider_init(running_machine &machine
{
// add vector control
sliders.push_back(slider_alloc(machine, SLIDER_ID_FLICKER + slider_index, _("Vector Flicker"), 0, 0, 1000, 10, nullptr));
- sliders.push_back(slider_alloc(machine, SLIDER_ID_BEAM_WIDTH_MIN + slider_index, _("Beam Width Minimum"), 1, 100, 1000, 1, nullptr));
- sliders.push_back(slider_alloc(machine, SLIDER_ID_BEAM_WIDTH_MAX + slider_index, _("Beam Width Maximum"), 1, 100, 1000, 1, nullptr));
+ sliders.push_back(slider_alloc(machine, SLIDER_ID_BEAM_WIDTH_MIN + slider_index, _("Beam Width Minimum"), 100, 100, 1000, 1, nullptr));
+ sliders.push_back(slider_alloc(machine, SLIDER_ID_BEAM_WIDTH_MAX + slider_index, _("Beam Width Maximum"), 100, 100, 1000, 1, nullptr));
sliders.push_back(slider_alloc(machine, SLIDER_ID_BEAM_INTENSITY + slider_index, _("Beam Intensity Weight"), -1000, 0, 1000, 10, nullptr));
slider_index++;
break;
diff --git a/src/lib/formats/afs_dsk.cpp b/src/lib/formats/afs_dsk.cpp
new file mode 100644
index 00000000000..5e1ff5aa66c
--- /dev/null
+++ b/src/lib/formats/afs_dsk.cpp
@@ -0,0 +1,60 @@
+// license:GPL-2.0+
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Acorn FileStore
+
+ Disk image formats
+
+***************************************************************************/
+
+#include "afs_dsk.h"
+
+
+afs_format::afs_format() : wd177x_format(formats)
+{
+}
+
+const char *afs_format::name() const
+{
+ return "afs";
+}
+
+const char *afs_format::description() const
+{
+ return "Acorn FileStore disk image";
+}
+
+const char *afs_format::extensions() const
+{
+ return "adl,img";
+}
+
+int afs_format::identify(io_generic *io, UINT32 form_factor)
+{
+ int type = find_size(io, form_factor);
+
+ if (type != -1)
+ return 50;
+ return 0;
+}
+
+int afs_format::get_image_offset(const format &f, int head, int track)
+{
+ if (f.sector_base_id == -1)
+ return (track * f.head_count + head) * compute_track_size(f);
+ else
+ return (f.track_count * head + track) * compute_track_size(f);
+}
+
+const afs_format::format afs_format::formats[] =
+{
+ { // 640K 3 1/2 inch 80 track double sided double density (interleaved) - gaps unverified
+ floppy_image::FF_35, floppy_image::DSQD, floppy_image::MFM,
+ 2000, 16, 80, 2, 256, {}, -1, { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }, 60, 22, 43
+ },
+ {}
+};
+
+
+const floppy_format_type FLOPPY_AFS_FORMAT = &floppy_image_format_creator<afs_format>;
diff --git a/src/lib/formats/afs_dsk.h b/src/lib/formats/afs_dsk.h
new file mode 100644
index 00000000000..e8e7190f7cd
--- /dev/null
+++ b/src/lib/formats/afs_dsk.h
@@ -0,0 +1,37 @@
+// license:GPL-2.0+
+// copyright-holders:Nigel Barnes
+/***************************************************************************
+
+ Acorn FileStore
+
+ Disk image formats
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __AFS_DSK_H__
+#define __AFS_DSK_H__
+
+#include "wd177x_dsk.h"
+
+
+class afs_format : public wd177x_format
+{
+public:
+ afs_format();
+
+ virtual int identify(io_generic *io, UINT32 form_factor) override;
+ virtual int get_image_offset(const format &f, int head, int track) override;
+ virtual const char *name() const override;
+ virtual const char *description() const override;
+ virtual const char *extensions() const override;
+
+private:
+ static const format formats[];
+};
+
+
+extern const floppy_format_type FLOPPY_AFS_FORMAT;
+
+#endif // __AFS_DSK_H__
diff --git a/src/lib/formats/fsd_dsk.cpp b/src/lib/formats/fsd_dsk.cpp
index 6fec1c9754e..0896c47d8ac 100644
--- a/src/lib/formats/fsd_dsk.cpp
+++ b/src/lib/formats/fsd_dsk.cpp
@@ -92,6 +92,7 @@ int fsd_format::identify(io_generic *io, UINT32 form_factor)
if (memcmp(h, "FSD", 3) == 0) {
return 100;
}
+ LOG_FORMATS("fsd: no match\n");
return 0;
}
@@ -112,18 +113,18 @@ bool fsd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
//popmessage("Loading image of '%s'\n", title);
- desc_pc_sector sects[10];
+ desc_pc_sector sects[256];
UINT8 total_tracks = img[pos++];
UINT8 tnum, hnum, snum, ssize, error;
hnum = 0;
- //osd_printf_verbose("%d Tracks\n", total_tracks+1);
- //osd_printf_verbose("Tr.# No.S Sec.# Tr.ID Head# SecID IDsiz REsiz Error\n");
+ LOG_FORMATS("%02d Tracks\n", total_tracks+1);
+ LOG_FORMATS("Tr.# No.S Sec.# Tr.ID Head# SecID IDsiz REsiz Error\n");
for(int curr_track=0; curr_track <= total_tracks; curr_track++)
{
UINT8 track = img[pos++];
UINT8 spt = img[pos++];
- //osd_printf_verbose("%x %x\n", track, spt);
+ LOG_FORMATS("%02X %02X\n", track, spt);
if (spt > 0) // formatted
{
UINT8 readable = img[pos++];
@@ -145,22 +146,16 @@ bool fsd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
sects[i].bad_crc = (error & 0x0e) == 0x0e;
sects[i].data = &img[pos];
pos += sects[i].actual_size;
- //osd_printf_verbose("Read %x %x %x %x %x %x %x\n", i, sects[i].track, sects[i].head, sects[i].sector, sects[i].size, sects[i].actual_size, error);
+ LOG_FORMATS("Read %02X %02X %02X %02X %02X %02X %02X\n", i, sects[i].track, sects[i].head, sects[i].sector, sects[i].size, sects[i].actual_size, error);
}
else
{
- throw emu_fatalerror("fsd_format: Unsupported unreadable sector on track %d sector %d head %d", track, i, hnum);
-
- // Unreadable sectors not supported!!
- //sects[i].track = track;
- //sects[i].head = 0;
- //sects[i].sector = i;
- //sects[i].size = 0;
- //sects[i].actual_size = 0;
- //sects[i].deleted = false;
- //sects[i].bad_crc = false;
- //sects[i].data = nullptr;
- //osd_printf_verbose("Unread %x %x %x %x %x %x %x\n", i, sects[i].track, sects[i].head, sects[i].sector, sects[i].size, sects[i].actual_size, 0);
+ LOG_FORMATS("Unreadable sector on track %02d sector %02X head %02d", track, i, hnum);
+ sects[i].actual_size = 0;
+ sects[i].deleted = false;
+ sects[i].bad_crc = false;
+ sects[i].data = nullptr;
+ LOG_FORMATS("Unread %02X %02X %02X %02X %02X %02X %02X\n", i, sects[i].track, sects[i].head, sects[i].sector, sects[i].size, sects[i].actual_size, 0);
}
}
}
@@ -170,7 +165,7 @@ bool fsd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
sects[0].head = hnum;
sects[0].sector = 0;
sects[0].size = 0;
- //osd_printf_verbose("Unform %x %x %x %x %x %x %x\n", 0, sects[0].track, sects[0].head, sects[0].sector, sects[0].size, sects[0].actual_size, 0);
+ LOG_FORMATS("Unform %02X %02X %02X %02X %02X %02X %02X\n", 0, sects[0].track, sects[0].head, sects[0].sector, sects[0].size, sects[0].actual_size, 0);
}
build_wd_track_fm(curr_track, hnum, image, 50000, spt, sects, 10, 40, 10);
}
diff --git a/src/mame/drivers/electron.cpp b/src/mame/drivers/electron.cpp
index 106fc034a03..ac902576be6 100644
--- a/src/mame/drivers/electron.cpp
+++ b/src/mame/drivers/electron.cpp
@@ -223,6 +223,9 @@ static MACHINE_CONFIG_START( electron, electron_state )
MCFG_GENERIC_CARTSLOT_ADD("cartslot", generic_plain_slot, "electron_cart")
MCFG_GENERIC_LOAD(electron_state, electron_cart)
+ /* expansion ports */
+ MCFG_ELECTRON_EXPANSION_SLOT_ADD("exp", electron_expansion_devices, nullptr)
+
/* software lists */
MCFG_SOFTWARE_LIST_ADD("cass_list","electron_cass")
MCFG_SOFTWARE_LIST_ADD("cart_list","electron_cart")
diff --git a/src/mame/drivers/imds2.cpp b/src/mame/drivers/imds2.cpp
index 65e32e3009f..bcc2358c81c 100644
--- a/src/mame/drivers/imds2.cpp
+++ b/src/mame/drivers/imds2.cpp
@@ -62,7 +62,7 @@
//
// NOTE:
// Firmware running on PIO is NOT original because a dump is not available at the moment.
-// Emulator runs a version of PIO firmware that was specifically developped by me to implement
+// Emulator runs a version of PIO firmware that was specifically developed by me to implement
// line printer output.
//
// TODO:
@@ -881,7 +881,18 @@ MACHINE_CONFIG_END
ROM_START(imds2)
// ROM definition of IPC cpu (8085A)
ROM_REGION(0x1000 , "ipcrom" , 0)
- ROM_LOAD("ipc_a82.bin" , 0x0000 , 0x1000 , CRC(0889394f) SHA1(b7525baf1884a7d67402dea4b5566016a9861ef2))
+ ROM_DEFAULT_BIOS("mon13")
+ // 1x2732 Copyright 1979
+ ROM_SYSTEM_BIOS(0, "mon13", "Series II Monitor v1.3")
+ ROMX_LOAD("ipc13_a82.bin" , 0x0000 , 0x1000 , CRC(0889394f) SHA1(b7525baf1884a7d67402dea4b5566016a9861ef2), ROM_BIOS(1))
+ // 2x2716 Copyright 1978
+ ROM_SYSTEM_BIOS(1, "mon12", "Series II Monitor v1.2")
+ ROMX_LOAD("ipc12_a57.bin" , 0x0000 , 0x0800 , CRC(6496efaf) SHA1(1a9c0f1b19c1807803db3f1543f51349d7fd693a), ROM_BIOS(2))
+ ROMX_LOAD("ipc12_a48.bin" , 0x0800 , 0x0800 , CRC(258dc9a6) SHA1(3fde993aee06d9af5093d7a2d9a8cbd71fed0951), ROM_BIOS(2))
+ // 2x2716 Copyright 1977
+ ROM_SYSTEM_BIOS(2, "mon11", "Series II Monitor v1.1")
+ ROMX_LOAD("ipc11_a57.bin" , 0x0000 , 0x0800 , CRC(ffb7c036) SHA1(6f60cdfe20621c4b633c972adcb644a1c02eaa39), ROM_BIOS(3))
+ ROMX_LOAD("ipc11_a48.bin" , 0x0800 , 0x0800 , CRC(3696ff28) SHA1(38b435e10a81629430275aec051fb0a55ec1f6fd), ROM_BIOS(3))
// ROM definition of IOC cpu (8080A)
ROM_REGION(0x2000 , "ioccpu" , 0)
@@ -891,7 +902,7 @@ ROM_START(imds2)
ROM_LOAD("ioc_a53.bin" , 0x1800 , 0x0800 , CRC(c8df4bb9) SHA1(2dfb921e94ae7033a7182457b2f00657674d1b77))
// ROM definition of PIO controller (8041A)
- // For the time being a specially developped PIO firmware is used until a dump of the original PIO is
+ // For the time being a specially developed PIO firmware is used until a dump of the original PIO is
// available.
ROM_REGION(0x400 , "iocpio" , 0)
ROM_LOAD("pio_a72.bin" , 0 , 0x400 , BAD_DUMP CRC(8c8e740b))
diff --git a/src/mame/drivers/naomi.cpp b/src/mame/drivers/naomi.cpp
index a6fd8205c72..e3fcb568072 100644
--- a/src/mame/drivers/naomi.cpp
+++ b/src/mame/drivers/naomi.cpp
@@ -411,7 +411,7 @@ Power Stone 841-0001C 21597 8 (64Mb)
Power Stone 2 841-0008C 23127 9 (64Mb) present 315-6213 317-5054-COM joystick + 3 buttons
Puyo Puyo Da! 841-0006C 22206 20 (64Mb) ? 315-6213 317-5052-COM
Ring Out 4x4 840-0004C 21779 10 (64Mb) present 315-6213 317-0250-COM requires 2 JVS boards
-Samba de Amigo (Rev B) 840-0020C 22966B 16 (64Mb) present 315-6213 317-0270-COM will boot but requires special controller to play it
+Samba de Amigo (Rev B) (Rev A) 840-0020C 22966B 16 (64Mb) present 315-6213 317-0270-COM will boot but requires special controller to play it
Sega Marine Fishing 840-0027C 22221 10 (64Mb) ? 315-6213 not present ROM 3&4 not present. Requires 837-13844 JVS IO with all DIPSW Off and fishing controller
Sega Strike Fighter (Rev A, set 1) 840-0035C 23323A 20 (64Mb) present 315-6213 317-0281-COM have "Rev. A" label on case
Sega Strike Fighter (Rev A, set 2) 840-0035C 23786A 20 (64Mb) present 315-6213 317-0281-COM have "Rev. A" label on PCB
@@ -5295,7 +5295,7 @@ ROM_START( samba )
NAOMI_DEFAULT_EEPROM
ROM_REGION( 0x8800000, "rom_board", ROMREGION_ERASEFF)
- ROM_LOAD("epr-22966b.ic22",0x0000000, 0x0400000, CRC(893116b8) SHA1(35cb4f40690ff21af5ab7cc5adbc53228d6fb0b3) )
+ ROM_LOAD("epr-22966b.ic22",0x0000000, 0x0400000, CRC(893116b8) SHA1(35cb4f40690ff21af5ab7cc5adbc53228d6fb0b3) ) // was also found in cartridge with Rev.A case label
ROM_LOAD("mpr-22950.ic1", 0x0800000, 0x0800000, CRC(16dee15c) SHA1(b46849e492756ff406bf8956303472255fcf55a5) )
ROM_LOAD("mpr-22951.ic2", 0x1000000, 0x0800000, CRC(f509496f) SHA1(41281576f7d58c8ede9c0a89bfd46a98d5b97033) )
ROM_LOAD("mpr-22952.ic3", 0x1800000, 0x0800000, CRC(fb9b3ef0) SHA1(e9d44b673c273e97445a12186496a0594e291542) )
@@ -8761,10 +8761,34 @@ ROM_END
/**********************************************
*
-* Naomi 2 network DVD-ROM defines
+* Naomi 2 network CD and DVD-ROM defines
*
*********************************************/
+ROM_START( wccf116 )
+ NAOMIGD_BIOS
+ NAOMI_DEFAULT_EEPROM
+
+ DISK_REGION( "gdrom" )
+ DISK_IMAGE_READONLY( "cdp-10001c", 0, SHA1(efa6ef20f278c99efbf7c3630b1c8e2cad0a05c0) ) // CD-R
+
+ ROM_REGION( 0x4000, "pic", ROMREGION_ERASEFF)
+ //PIC is missing
+ ROM_LOAD("wccf1.pic", 0x00, 0x4000, NO_DUMP )
+ROM_END
+
+ROM_START( wccf1dup )
+ NAOMIGD_BIOS
+ NAOMI_DEFAULT_EEPROM
+
+ DISK_REGION( "gdrom" )
+ DISK_IMAGE_READONLY( "cdp-10003", 0, SHA1(13064b6e03527f1222b6bd01c0ba9a063d7be949) )
+
+ ROM_REGION( 0x4000, "pic", ROMREGION_ERASEFF)
+ //PIC is missing, same as CDP-10001C
+ ROM_LOAD("wccf1.pic", 0x00, 0x4000, NO_DUMP )
+ROM_END
+
ROM_START( wccf212e )
NAOMIGD_BIOS
NAOMI_DEFAULT_EEPROM
@@ -8783,6 +8807,18 @@ ROM_START( wccf212e )
ROM_LOAD("fpr23911.ic18", 0x000000, 0x200000, CRC(1a1da741) SHA1(532ea7fc4dab11e012a521abcf5fdadd9b40d631) )
ROM_END
+// "Drive Checker", contain only optical media ejector win32 program
+ROM_START( wccf2chk )
+ NAOMIGD_BIOS
+ NAOMI_DEFAULT_EEPROM
+
+ DISK_REGION( "gdrom" )
+ DISK_IMAGE_READONLY( "cdv-10007", 0, SHA1(6c5994c9b5ba5719569c541fabdd71a7ff1275aa) )
+
+ ROM_REGION( 0x4000, "pic", ROMREGION_ERASEFF)
+ // not used
+ROM_END
+
ROM_START( wccf234j )
NAOMIGD_BIOS
NAOMI_DEFAULT_EEPROM
@@ -9763,9 +9799,10 @@ GAME( 2003, puyofevp, naomi, naomim1, naomi, naomi_state, naomi, ROT0, "Sega", "
// 00?? ExZeus (GDL-00xx)
/* CDP-xxxxx and CDV-xxxxx (CD-ROM and DVD-ROM for Naomi 2 Satellite Terminal) */
-// CDP-10001 - World Club Champion Football Serie A 2001-2002 Ver.2 (Hitmaker / Sega, 2003)
+/* CDP-10001C*/ GAME( 2003, wccf116, naomigd, naomigd, naomi, naomi_state, naomigd, ROT0, "Hitmaker / Sega", "World Club Champion Football Serie A 2001-2002 Ver. 2 (CDP-10001C)", GAME_FLAGS )
+/* CDP-10003 */ GAME( 2002, wccf1dup, naomigd, naomigd, naomi, naomi_state, naomigd, ROT0, "Hitmaker / Sega", "World Club Champion Football Serie A 2001-2002 DIMM FIRM Ver.3.03 (CDP-10003)", GAME_FLAGS )
/* CDV-10002 */ GAME( 2004, wccf212e, naomigd, naomigd, naomi, naomi_state, naomigd, ROT0, "Hitmaker / Sega", "World Club Champion Football Serie A 2002-2003 Ver.2.12 (CDV-10002)", GAME_FLAGS )
-// CDV-10007 - World Club Champion Football Serie A 2002-2003 (Hitmaker / Sega, 2003)
+/* CDV-10007 */ GAME( 2004, wccf2chk, naomigd, naomigd, naomi, naomi_state, naomigd, ROT0, "Hitmaker / Sega", "World Club Champion Football Serie A 2002-2003 Drive Checker (CDV-10007)", GAME_FLAGS ) // actually just disc ejector
/* CDV-10008 */ GAME( 2004, wccf234j, naomigd, naomigd, naomi, naomi_state, naomigd, ROT0, "Hitmaker / Sega", "World Club Champion Football Serie A 2002-2003 Ver.2.34 (CDV-10008)", GAME_FLAGS )
/* CDV-10013 */ GAME( 2005, wccf310j, naomigd, naomigd, naomi, naomi_state, naomigd, ROT0, "Sega", "World Club Champion Football European Clubs 2004-2005 (CDV-10013)", GAME_FLAGS )
/* CDV-10015 */ GAME( 2005, wccf331e, wccf322e,naomigd, naomi, naomi_state, naomigd, ROT0, "Sega", "World Club Champion Football European Clubs 2004-2005 Ver.1.1 (CDV-10015)", GAME_FLAGS )
diff --git a/src/mame/drivers/sorcerer.cpp b/src/mame/drivers/sorcerer.cpp
index d596e241355..8b090c49a43 100644
--- a/src/mame/drivers/sorcerer.cpp
+++ b/src/mame/drivers/sorcerer.cpp
@@ -115,8 +115,7 @@ It was often hooked to a printer, a joystick, a music card, or a speaker.
We emulate the printer and the speaker.
Another 25-pin port provided two-way serial communications. Only two speeds are
-available - 300 baud and 1200 baud. There is no handshaking. This protocol is
-currently not emulated.
+available - 300 baud and 1200 baud. There is no handshaking.
Other pins on this connector provided for two cassette players. The connections
for cassette unit 1 are duplicated on a set of phono plugs.
@@ -155,6 +154,11 @@ NOTES (2011-08-08)
stable, so be prepared to cold boot whenever something
goes wrong.
+NOTES (2016-06-06)
+1. SORCERER_USING_RS232 removed, since the core now supports RS-232 as a device.
+ Not actually tested due to the bios bugs making it
+ pretty much impossible to use.
+
********************************************************************************/
#include "includes/sorcerer.h"
@@ -396,6 +400,14 @@ static const floppy_interface sorcerer_floppy_interface =
"floppy_8"
};
+static DEVICE_INPUT_DEFAULTS_START( terminal )
+ DEVICE_INPUT_DEFAULTS( "RS232_TXBAUD", 0xff, RS232_BAUD_1200 )
+ DEVICE_INPUT_DEFAULTS( "RS232_RXBAUD", 0xff, RS232_BAUD_1200 )
+ DEVICE_INPUT_DEFAULTS( "RS232_STARTBITS", 0xff, RS232_STARTBITS_1 )
+ DEVICE_INPUT_DEFAULTS( "RS232_DATABITS", 0xff, RS232_DATABITS_8 )
+ DEVICE_INPUT_DEFAULTS( "RS232_PARITY", 0xff, RS232_PARITY_NONE )
+ DEVICE_INPUT_DEFAULTS( "RS232_STOPBITS", 0xff, RS232_STOPBITS_2 )
+DEVICE_INPUT_DEFAULTS_END
static MACHINE_CONFIG_START( sorcerer, sorcerer_state )
/* basic machine hardware */
@@ -425,6 +437,8 @@ static MACHINE_CONFIG_START( sorcerer, sorcerer_state )
MCFG_DEVICE_ADD( "uart", AY31015, 0 )
MCFG_AY31015_TX_CLOCK(ES_UART_CLOCK)
MCFG_AY31015_RX_CLOCK(ES_UART_CLOCK)
+ MCFG_RS232_PORT_ADD("rs232", default_rs232_devices, "null_modem")
+ MCFG_DEVICE_CARD_DEVICE_INPUT_DEFAULTS("terminal", terminal)
/* printer */
MCFG_CENTRONICS_ADD("centronics", centronics_devices, "covox")
diff --git a/src/mame/drivers/sun3.cpp b/src/mame/drivers/sun3.cpp
index 00126ba93a9..acd477636fa 100644
--- a/src/mame/drivers/sun3.cpp
+++ b/src/mame/drivers/sun3.cpp
@@ -2,20 +2,7 @@
// copyright-holders:Miodrag Milanovic, R. Belmont
/***************************************************************************
- sun3.c: preliminary driver for Sun 3 and Sun 3x models.
-
- status: 3/80 POSTs, 3/460 needs its unique RTC chip (also used by non-3x Sun 3s).
-
- TODO:
- - Z8530 SCC needs to actually speak serial so we can hook up the mouse and keyboard.
- - Improve interrupt controller emulation.
- - Figure out how the IOMMU works.
- - Intersil 7170 device for 3/460 and 3/480 (they use the same PROMs).
- - Sun custom MMU for original Sun 3 models.
- - AM7990 LANCE chip support for everyone.
- - Figure out how the parallel printer port maps to Centronics and make it so.
- - Much more...
-
+ sun3.c: preliminary driver for Sun 3 models
Sun-3 Models
------------
@@ -162,55 +149,6 @@
4/280 by replacing the CPU board. Code-named
"Sirius".
- 3/80
- Processor(s): 68030 @ 20MHz, 68882 @ 20MHz, 68030 on-chip
- MMU, 3 MIPS, 0.16 MFLOPS
- CPU: 501-1401/1650
- Chassis type: square pizza box
- Bus: P4 connector (not same as P4 on 3/60)
- Memory: 16M or 40M physical, 4G virtual, 100ns cycle
- Notes: Similar packaging to SparcStation 1. Parallel
- port, SCSI port, AUI Ethernet, 1.44M 3.5" floppy
- (720K on early units?). No onboard framebuffer.
- Code-named "Hydra". Type-4 keyboard and Sun-4
- mouse, plugged together and into the machine
- with a small DIN plug. 1M x 9 30-pin 100ns
- SIMMs. Boot ROM versions 3.0.2 and later allow
- using 4M SIMMs in some slots for up to 40M (see
- Misc Q&A #15).
-
- 3/460
- Processor(s): 68030 @ 33 MHz, 68882, 68030 on-chip MMU,
- 7 MIPS, 0.6 MFLOPS
- CPU: 501-1299/1550
- Bus: VME
- Memory: 128M physical with ECC, 4G/process virtual,
- 64K cache, 80ns cycle
- Notes: A 3/260 upgraded with a 3/4xx CPU board. Uses
- original 3/2xx memory boards.
-
- 3/470
- Processor(s): 68030 @ 33 MHz, 68882, 68030 on-chip MMU,
- 7 MIPS, 0.6 MFLOPS
- CPU: 501-1299/1550
- Chassis type: deskside
- Bus: VME
- Memory: 128M physical with ECC, 4G/process virtual,
- 64K cache, 80ns cycle
- Notes: Rare. Code-named "Pegasus". 8M standard, uses
- same memory boards as 3/2xx.
-
- 3/480
- Processor(s): 68030 @ 33 MHz, 68882, 68030 on-chip MMU,
- 7 MIPS, 0.6 MFLOPS
- CPU: 501-1299/1550
- Chassis type: rackmount
- Bus: VME
- Memory: 128M physical with ECC, 4G/process virtual,
- 64K cache, 80ns cycle
- Notes: Rare. Code-named "Pegasus". 8M standard, uses
- same memory boards as 3/2xx.
-
3/E
Processor(s): 68020
CPU: 501-8028
@@ -220,87 +158,51 @@
factor. Serial and keyboard ports. External RAM,
framebuffer, and SCSI/ethernet boards
available.
-
- Sun3X notes from NetBSD and Linux:
-
- RAM_END 0x40000000
- P4DAC 0x50200000
- VIDEO_P4ID 0x50300000
- BW2_ADDR 0x50400000
- ENA_PLANE 0x50600000
- FPA_ADDR 0x5c000000
- IOMMU 0x60000000
- ENABLEREG 0x61000000
- BUSERRREG 0x61000400
- DIAGREG 0x61000800
- IDPROM1 0x61000c00 (3/470)
- MEMREG 0x61001000
- INTERREG 0x61001400
- SCC1 0x62000000 (keyboard/mouse)
- SCC2 0x62002000 (serial console)
- EEPROM 0x64000000
- IDPROM2 0x640007d8 (3/80)
- CLOCK2 0x640007f8 (3/80 Mostek 48T02)
- CLOCK1 0x64002000 (3/470 Intersil 7170)
- INTELETH 0x65000000
- LANCEETH 0x65002000
- EMULEXSCSI 0x66000000 (3/80 5394)
- EMULLEXDMA 0x66001000 (3/80)
- PCACHETAG 0x68000000
- ECCPARREG 0x6a1e0000
- IOCTAGS 0x6c000000
- IOCFLUSH 0x6d000000
- FDC 0x6e000000 (3/80 Intel 82077)
- FDC_CNTRL 0x6e000400
- FDC_VEC 0x6e000800
- PRINTER 0x6f00003c (3/80)
-
- The Sun3x System Enable Register controls the function of a few
- on-board devices and general system operation. It is cleared when
- the system is reset.
-
- 15 0
- +---+---+---+---+---+---+---+---+---+---+---+---+---+---.---.---+
- |BT |FPP|DMA| 0 |VID|RES|FPA|DIA| 0 |CCH|IOC|LBK|DCH| UNUSED |
- +---+---+---+---+---+---+---+---+---+---+---+---+---+---.---.---+
-
- Where: DCH = debug mode for system cache
- LBK = VME loopback
- IOC = I/O cache enable
- CCH = system cache enable
- DIA = diagnostic switch
- FPA = enable floating-point accelerator
- RES = 0 for hi-res, 1 for low res
- VID = enable video display
- DMA = enable system DVMA
- FPP = enable 68881/2 FPU
- BT = 0 for boot state, 1 for normal state
-
- bad '030 MMU mapping: L fef82000 -> P 00000000
-
+
+3/60 ROM breakpoints for start-of-tests
+fefb104 - bus error test
+fefb18e - interrupt test
+fefb1da - clock IRQ test
+fefb344 - MMU page valid test
+fefb3c4 - MMU read-only permissions test
+fefb45e - parity test: no spurious NMI generated from normal parity operation
+fefb50c - parity test: NMI is generated when we write with inverted parity and enable parity NMIs
+fefb5c8 - size memory by bus error
+fef58c0 - EPROM checksum read?
+
+fefcb34 - bpset for each test on 3/260 ROM
****************************************************************************/
#include "emu.h"
#include "cpu/m68000/m68000.h"
#include "machine/timekpr.h"
+#include "machine/ram.h"
#include "machine/z80scc.h"
-#include "bus/scsi/scsi.h"
-#include "bus/scsi/scsihd.h"
-#include "bus/scsi/scsicd.h"
-#include "machine/ncr539x.h"
-#include "machine/upd765.h"
-#include "formats/pc_dsk.h"
-#include "formats/mfi_dsk.h"
+#include "machine/bankdev.h"
#include "bus/rs232/rs232.h"
#define TIMEKEEPER_TAG "timekpr"
#define SCC1_TAG "scc1"
#define SCC2_TAG "scc2"
-#define ESP_TAG "esp"
-#define FDC_TAG "fdc"
#define RS232A_TAG "rs232a"
#define RS232B_TAG "rs232b"
+// page table entry constants
+#define PM_VALID (0x80000000) // page is valid
+#define PM_WRITEMASK (0x40000000) // writable?
+#define PM_SYSMASK (0x20000000) // system use only?
+#define PM_CACHE (0x10000000) // cachable?
+#define PM_TYPEMASK (0x0c000000) // type mask
+#define PM_ACCESSED (0x02000000) // accessed flag
+#define PM_MODIFIED (0x01000000) // modified flag
+
+#define BE_FPENABLE (0x04) // FPU not enabled
+#define BE_FPBERR (0x08) // FPU encountered a bus error
+#define BE_VMEBERR (0x10) // VME encountered a bus error
+#define BE_TIMEOUT (0x20) // timeout - memory doesn't exist
+#define BE_PROTERR (0x40) // protection failed on MMU page lookup
+#define BE_INVALID (0x80) // invalid entry on MMU page lookup
+
class sun3_state : public driver_device
{
public:
@@ -309,244 +211,473 @@ public:
m_maincpu(*this, "maincpu"),
m_scc1(*this, SCC1_TAG),
m_scc2(*this, SCC2_TAG),
- m_fdc(*this, FDC_TAG),
m_p_ram(*this, "p_ram"),
- m_bw2_vram(*this, "bw2_vram")
+ m_bw2_vram(*this, "bw2_vram"),
+ m_type0space(*this, "type0"),
+ m_type1space(*this, "type1"),
+ m_type2space(*this, "type2"),
+ m_type3space(*this, "type3"),
+ m_rom(*this, "user1"),
+ m_ram(*this, RAM_TAG)
{ }
- required_device<cpu_device> m_maincpu;
+ required_device<m68020_device> m_maincpu;
required_device<z80scc_device> m_scc1;
required_device<z80scc_device> m_scc2;
- optional_device<n82077aa_device> m_fdc;
+ virtual void machine_start() override;
virtual void machine_reset() override;
- required_shared_ptr<UINT32> m_p_ram;
+ optional_shared_ptr<UINT32> m_p_ram;
optional_shared_ptr<UINT32> m_bw2_vram;
-
- DECLARE_READ32_MEMBER(enable_r);
- DECLARE_WRITE32_MEMBER(enable_w);
- DECLARE_READ32_MEMBER(buserr_r);
- DECLARE_WRITE32_MEMBER(buserr_w);
- DECLARE_READ32_MEMBER(diag_r);
- DECLARE_WRITE32_MEMBER(diag_w);
- DECLARE_READ32_MEMBER(printer_r);
- DECLARE_WRITE32_MEMBER(printer_w);
- DECLARE_READ32_MEMBER(iommu_r);
- DECLARE_WRITE32_MEMBER(iommu_w);
- DECLARE_READ32_MEMBER(irqctrl_r);
- DECLARE_WRITE32_MEMBER(irqctrl_w);
- DECLARE_READ32_MEMBER(memreg_r);
- DECLARE_WRITE32_MEMBER(memreg_w);
- DECLARE_READ32_MEMBER(memrerraddr_r);
- DECLARE_WRITE32_MEMBER(memrerraddr_w);
- DECLARE_READ32_MEMBER(fdc_control_r);
- DECLARE_WRITE32_MEMBER(fdc_control_w);
- DECLARE_READ32_MEMBER(cause_buserr_r);
- DECLARE_WRITE32_MEMBER(cause_buserr_w);
- DECLARE_WRITE32_MEMBER(ramwrite_w);
- DECLARE_READ32_MEMBER(fpa_r);
- DECLARE_READ32_MEMBER(p4id_r);
-
- DECLARE_FLOPPY_FORMATS( floppy_formats );
-
- TIMER_DEVICE_CALLBACK_MEMBER(sun380_timer);
+ optional_device<address_map_bank_device> m_type0space, m_type1space, m_type2space, m_type3space;
+ required_memory_region m_rom;
+ required_device<ram_device> m_ram;
+
+ DECLARE_READ32_MEMBER( tl_mmu_r );
+ DECLARE_WRITE32_MEMBER( tl_mmu_w );
+ DECLARE_READ32_MEMBER( ram_r );
+ DECLARE_WRITE32_MEMBER( ram_w );
+ DECLARE_READ32_MEMBER( parity_r );
+ DECLARE_WRITE32_MEMBER( parity_w );
+ DECLARE_READ32_MEMBER( irqctrl_r );
+ DECLARE_WRITE32_MEMBER( irqctrl_w );
+ DECLARE_WRITE8_MEMBER( rtc7170_w );
UINT32 bw2_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
private:
- UINT32 m_enable, m_buserr, m_diag, m_printer, m_irqctrl, m_memreg, m_memerraddr;
- UINT32 m_iommu[0x800];
+ UINT32 *m_rom_ptr, *m_ram_ptr;
+ UINT32 m_enable, m_buserr, m_diag, m_dvma_enable, m_parregs[8], m_irqctrl;
+
+ UINT32 m_context;
+ UINT8 m_segmap[8][2048];
+ UINT32 m_pagemap[4096];
+ UINT32 m_ram_size, m_ram_size_words;
bool m_bInBusErr;
};
-static ADDRESS_MAP_START(sun3_mem, AS_PROGRAM, 32, sun3_state)
- ADDRESS_MAP_UNMAP_HIGH
- AM_RANGE(0x00000000, 0x00ffffff) AM_RAM AM_SHARE("p_ram") // 16MB
- AM_RANGE(0x0fef0000, 0x0fefffff) AM_ROM AM_REGION("user1",0)
-ADDRESS_MAP_END
-
-static ADDRESS_MAP_START(sun3_80_mem, AS_PROGRAM, 32, sun3_state)
- AM_RANGE(0x00000000, 0x03ffffff) AM_RAM AM_SHARE("p_ram") AM_WRITE(ramwrite_w)
- AM_RANGE(0x40000000, 0x40000003) AM_READWRITE(cause_buserr_r, cause_buserr_w)
- AM_RANGE(0x50300000, 0x50300003) AM_READ(p4id_r)
- AM_RANGE(0x50400000, 0x504fffff) AM_RAM AM_SHARE("bw2_vram")
- AM_RANGE(0x60000000, 0x60001fff) AM_READWRITE(iommu_r, iommu_w)
- AM_RANGE(0x61000000, 0x61000003) AM_READWRITE(enable_r, enable_w)
- AM_RANGE(0x61000400, 0x61000403) AM_READWRITE(buserr_r, buserr_w)
- AM_RANGE(0x61000800, 0x61000803) AM_READWRITE(diag_r, diag_w)
- AM_RANGE(0x61001000, 0x61001003) AM_READWRITE(memreg_r, memreg_w)
- AM_RANGE(0x61001004, 0x61001007) AM_READWRITE(memrerraddr_r, memrerraddr_w)
- AM_RANGE(0x61001400, 0x61001403) AM_READWRITE(irqctrl_r, irqctrl_w)
- AM_RANGE(0x62000000, 0x6200000f) AM_DEVREADWRITE8(SCC1_TAG, z80scc_device, ba_cd_inv_r, ba_cd_inv_w, 0xff00ff00)
- AM_RANGE(0x62002000, 0x6200200f) AM_DEVREADWRITE8(SCC2_TAG, z80scc_device, ba_cd_inv_r, ba_cd_inv_w, 0xff00ff00)
- AM_RANGE(0x63000000, 0x6301ffff) AM_ROM AM_REGION("user1",0)
- AM_RANGE(0x64000000, 0x640007ff) AM_DEVREADWRITE8(TIMEKEEPER_TAG, timekeeper_device, read, write, 0xffffffff)
- AM_RANGE(0x66000000, 0x6600003f) AM_DEVREADWRITE8(ESP_TAG, ncr539x_device, read, write, 0xff000000)
- AM_RANGE(0x6e000000, 0x6e000007) AM_DEVICE8(FDC_TAG, n82077aa_device, map, 0xffffffff)
- AM_RANGE(0x6e000400, 0x6e000403) AM_READWRITE(fdc_control_r, fdc_control_w)
- AM_RANGE(0x6f00003c, 0x6f00003f) AM_READWRITE(printer_r, printer_w)
- AM_RANGE(0xfefe0000, 0xfefeffff) AM_ROM AM_REGION("user1",0)
-ADDRESS_MAP_END
-
-static ADDRESS_MAP_START(sun3_460_mem, AS_PROGRAM, 32, sun3_state)
- AM_RANGE(0x00000000, 0x03ffffff) AM_RAM AM_SHARE("p_ram") AM_WRITE(ramwrite_w)
- AM_RANGE(0x09000000, 0x09000003) AM_READWRITE(cause_buserr_r, cause_buserr_w)
- AM_RANGE(0x50300000, 0x50300003) AM_READ(p4id_r)
- AM_RANGE(0x50400000, 0x504fffff) AM_RAM AM_SHARE("bw2_vram")
- AM_RANGE(0x5c000f14, 0x5c000f17) AM_READ(fpa_r)
- AM_RANGE(0x60000000, 0x60001fff) AM_READWRITE(iommu_r, iommu_w)
- AM_RANGE(0x61000000, 0x61000003) AM_READWRITE(enable_r, enable_w)
- AM_RANGE(0x61000400, 0x61000403) AM_READWRITE(buserr_r, buserr_w)
- AM_RANGE(0x61000800, 0x61000803) AM_READWRITE(diag_r, diag_w)
- AM_RANGE(0x61001000, 0x61001003) AM_READWRITE(memreg_r, memreg_w)
- AM_RANGE(0x61001004, 0x61001007) AM_READWRITE(memrerraddr_r, memrerraddr_w)
- AM_RANGE(0x61001400, 0x61001403) AM_READWRITE(irqctrl_r, irqctrl_w)
- AM_RANGE(0x62000000, 0x6200000f) AM_DEVREADWRITE8(SCC1_TAG, z80scc_device, ba_cd_inv_r, ba_cd_inv_w, 0xff00ff00)
- AM_RANGE(0x62002000, 0x6200200f) AM_DEVREADWRITE8(SCC2_TAG, z80scc_device, ba_cd_inv_r, ba_cd_inv_w, 0xff00ff00)
- AM_RANGE(0x63000000, 0x6301ffff) AM_ROM AM_REGION("user1",0)
-
- AM_RANGE(0x6f00003c, 0x6f00003f) AM_READWRITE(printer_r, printer_w)
- AM_RANGE(0xfefe0000, 0xfefeffff) AM_ROM AM_REGION("user1",0)
-ADDRESS_MAP_END
-
-READ32_MEMBER( sun3_state::p4id_r )
-{
- return (1<<24); // 0 = hires bw2 1600x1280, 1 = bw2 1152x900, 0x45 is "Ibis" color, blt 0x68 is "Lego" color
-}
-
-WRITE32_MEMBER( sun3_state::fdc_control_w )
+READ32_MEMBER( sun3_state::ram_r )
{
- logerror("FDC write %02x (%08x)\n", data >> 24, space.device().safe_pc());
-}
-
-READ32_MEMBER( sun3_state::fdc_control_r )
-{
- // Type of floppy present
- // 0 = no floppy in drive
- // 1 = ed
- // 2 = hd
- // 3 = dd
-
- if(m_fdc) {
- floppy_image_device *fdev = machine().device<floppy_connector>(":fdc:0")->get_device();
- if(fdev->exists()) {
- UINT32 variant = fdev->get_variant();
- switch(variant) {
- case floppy_image::SSSD:
- case floppy_image::SSDD:
- case floppy_image::DSDD:
- return 3 << 24;
-
- case floppy_image::DSHD:
- return 2 << 24;
-
- case floppy_image::DSED:
- return 1 << 24;
- }
- }
- }
+ if (offset < m_ram_size_words) return m_ram_ptr[offset];
- return 0 << 24;
+ if (!m_bInBusErr)
+ {
+ //printf("ram_r: bus error on timeout, access to invalid addr %08x, PC=%x\n", offset<<2, m_maincpu->pc);
+ m_buserr = BE_TIMEOUT;
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
+ }
+
+ return 0xffffffff;
}
-WRITE32_MEMBER(sun3_state::ramwrite_w)
+WRITE32_MEMBER( sun3_state::ram_w )
{
- UINT32 *pRAM = (UINT32 *)m_p_ram.target();
-
- if (((m_memreg & 0xf0000000) == 0x70000000) &&
+ // if writing bad parity is enabled
+ if (((m_parregs[0] & 0x20000000) == 0x20000000) &&
(m_irqctrl & 0x01000000) &&
!(m_bInBusErr))
{
- m_memerraddr = offset<<2;
-
- // low 4 bits of memreg are the byte lane(s) involved, negative logic
- m_memreg |= 0x0f;
+ m_parregs[1] = offset<<2;
+ //printf("Generating parity error, mem_mask %08x\n", mem_mask);
switch (mem_mask)
{
case 0xff000000:
- m_memreg &= ~0x08;
+ m_parregs[0] |= 0x08<<24;
break;
case 0x00ff0000:
- m_memerraddr += 1;
- m_memreg &= ~0x04;
+ m_parregs[1] += 1;
+ m_parregs[0] |= 0x04<<24;
break;
case 0x0000ff00:
- m_memerraddr += 2;
- m_memreg &= ~0x02;
+ m_parregs[1] += 2;
+ m_parregs[0] |= 0x02<<24;
break;
case 0x000000ff:
- m_memerraddr += 3;
- m_memreg &= ~0x01;
+ m_parregs[1] += 3;
+ m_parregs[0] |= 0x01<<24;
break;
case 0x0000ffff:
- m_memerraddr += 2;
- m_memreg &= ~0x03;
+ m_parregs[1] += 2;
+ m_parregs[0] |= 0x03<<24;
break;
case 0xffff0000:
- m_memreg &= ~0x0c;
+ m_parregs[0] |= 0x0c<<24;
break;
case 0xffffffff: // no address adjust, show all 4 lanes as problematic
+ m_parregs[0] |= 0x0f<<24;
break;
}
-
- m_bInBusErr = true; // prevent recursion
- m_maincpu->set_input_line_and_vector(M68K_IRQ_7, ASSERT_LINE, 2);
+
+ // indicate parity interrupt
+ m_parregs[0] |= 0x80000000;
+
+ // and can we take that now?
+ if (m_parregs[0] & 0x40000000)
+ {
+ m_bInBusErr = true; // prevent recursion
+ m_maincpu->set_input_line(M68K_IRQ_7, ASSERT_LINE);
+ }
}
- COMBINE_DATA(&pRAM[offset]);
+ if (offset < m_ram_size_words)
+ {
+ COMBINE_DATA(&m_ram_ptr[offset]);
+ return;
+ }
+
+ if (!m_bInBusErr)
+ {
+ //printf("ram_w: bus error on timeout, access to invalid addr %08x, PC=%x\n", offset<<2, m_maincpu->pc);
+ m_buserr = BE_TIMEOUT;
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
+ }
}
-READ32_MEMBER(sun3_state::enable_r)
+READ32_MEMBER( sun3_state::tl_mmu_r )
{
- return m_enable;
+ UINT8 fc = m_maincpu->get_fc();
+
+ if ((fc == 3) && !space.debugger_access())
+ {
+ int page;
+
+ switch (offset >> 26)
+ {
+ case 0: // IDPROM
+ printf("sun3: Read IDPROM at %x\n", offset);
+ return 0xffffffff;
+
+ case 1: // page map
+ page = m_segmap[m_context & 7][(offset >> 15) & 0x7ff] << 4;
+ page += (offset >> 11) & 0xf;
+
+ //printf("sun3: Read page map at %x (entry %d)\n", offset<<1, page);
+ return m_pagemap[page];
+
+ case 2: // segment map
+ //printf("sun3: Read segment map at %x (entry %d, user ctx %d mask %x)\n", offset<<2, (offset & ~0x3c000000) >> 15, m_context & 7, mem_mask);
+ return m_segmap[m_context & 7][(offset & ~0x3c000000) >> 15]<<24;
+
+ case 3: // context reg
+ //printf("sun3: Read context reg\n");
+ return m_context<<24;
+
+ case 4: // enable reg
+ return m_enable;
+
+ case 5: // DVMA enable
+ return m_dvma_enable<<24;
+
+ case 6: // bus error
+ m_bInBusErr = false;
+ return m_buserr<<24;
+
+ case 7: // diagnostic reg
+ return m_diag<<24;
+
+ case 8: // cache tags
+ printf("sun3: read cache tags @ %x, PC = %x\n", offset, m_maincpu->pc);
+ return 0xffffffff;
+
+ case 9: // cache data
+ printf("sun3: read cache data @ %x, PC = %x\n", offset, m_maincpu->pc);
+ return 0xffffffff;
+
+ case 10: // flush cache
+ return 0xffffffff;
+
+ case 11: // block copy
+ printf("sun3: read block copy @ %x, PC = %x\n", offset, m_maincpu->pc);
+ return 0xffffffff;
+
+ case 15: // UART bypass
+ printf("sun3: read UART bypass @ %x, PC = %x\n", offset, m_maincpu->pc);
+ return 0xffffffff;
+ }
+ }
+
+ // boot mode?
+ if ((fc == M68K_FC_SUPERVISOR_PROGRAM) && !(m_enable & 0x80))
+ {
+ return m_rom_ptr[offset & 0x3fff];
+ }
+
+ // debugger hack
+ if ((space.debugger_access()) && (offset >= (0xfef0000>>2)) && (offset <= (0xfefffff>>2)))
+ {
+ return m_rom_ptr[offset & 0x3fff];
+ }
+
+ // it's translation time
+ UINT8 pmeg = m_segmap[m_context & 7][(offset >> 15) & 0x7ff];
+ UINT32 entry = (pmeg << 4) + ((offset >> 11) & 0xf);
+
+ // printf("sun3: Context = %d, pmeg = %d, offset >> 14 = %x, entry = %d, page = %d\n", m_context&7, pmeg, offset >> 14, entry, (offset >> 10) & 0xf);
+
+ if (m_pagemap[entry] & PM_VALID)
+ {
+ if ((m_pagemap[entry] & PM_SYSMASK) && (fc < M68K_FC_SUPERVISOR_DATA))
+ {
+ m_buserr = BE_PROTERR;
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
+ return 0xffffffff;
+ }
+
+ m_pagemap[entry] |= PM_ACCESSED;
+
+ UINT32 tmp = (m_pagemap[entry] & 0x7ffff) << 11;
+ tmp |= (offset & 0x7ff);
+
+ //printf("pmeg %d, entry %d = %08x, virt %08x => tmp %08x\n", pmeg, entry, m_pagemap[entry], offset << 2, tmp);
+
+ // if (!space.debugger_access())
+ // printf("sun2: Translated addr: %08x, type %d (page %d page entry %08x, orig virt %08x, FC %d)\n", tmp << 1, (m_pagemap[entry] >> 22) & 7, entry, m_pagemap[entry], offset<<1, fc);
+
+ switch ((m_pagemap[entry] >> 26) & 3)
+ {
+ case 0: // type 0 space
+ return m_type0space->read32(space, tmp, mem_mask);
+
+ case 1: // type 1 space
+ //printf("read device space @ %x\n", tmp<<1);
+ return m_type1space->read32(space, tmp, mem_mask);
+
+ case 2: // type 2 space
+ return m_type2space->read32(space, tmp, mem_mask);
+
+ case 3: // type 3 space
+ return m_type3space->read32(space, tmp, mem_mask);
+ }
+ }
+ else
+ {
+ // uncomment to see real state of driver
+/* if (!space.debugger_access()) printf("sun3: pagemap entry not valid! (PC=%x)\n", m_maincpu->pc);
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);*/
+ return 0xffffffff;
+ }
+
+ if (!space.debugger_access()) printf("sun3: Unmapped read @ %08x (FC %d, mask %08x, PC=%x, seg %x)\n", offset<<2, fc, mem_mask, m_maincpu->pc, offset>>15);
+
+ return 0xffffffff;
}
-WRITE32_MEMBER(sun3_state::enable_w)
+WRITE32_MEMBER( sun3_state::tl_mmu_w )
{
-// printf("sun3x: %08x to enable (mask %08x)\n", data, mem_mask);
- COMBINE_DATA(&m_enable);
+ UINT8 fc = m_maincpu->get_fc();
+
+ //printf("sun3: Write %08x (FC %d, mask %08x, PC=%x) to %08x\n", data, fc, mem_mask, m_maincpu->pc, offset<<1);
+
+ if (fc == 3) // control space
+ {
+ int page;
+
+ switch (offset >> 26)
+ {
+ case 0: // IDPROM
+ return;
+
+ case 1: // page map fefaf32
+ page = m_segmap[m_context & 7][(offset >> 15) & 0x7ff] << 4;
+ //printf("context = %d, segment = %d, PMEG = %d\n", m_context & 7, (offset >> 15) & 0x7ff, page);
+ page += (offset >> 11) & 0xf;
+ //printf("add = %d\n", (offset >> 11) & 0xf);
+
+ //printf("sun3: Write %04x to page map at %x (entry %d), ", data, offset<<2, page);
+ COMBINE_DATA(&m_pagemap[page]);
+
+ //printf("entry now %08x (adr %08x PC=%x mask %x)\n", m_pagemap[page], (m_pagemap[page] & 0xfffff) << 13, m_maincpu->pc, mem_mask);
+ return;
+
+ case 2: // segment map
+ //printf("sun3: Write %02x to segment map at %x (entry %d, user ctx %d PC=%x mask %x)\n", (data>>24) & 0xff, offset<<2, (offset & ~0x3c000000)>>15, m_context & 7, m_maincpu->pc, mem_mask);
+ m_segmap[m_context & 7][(offset & ~0x3c000000) >> 15] = (data>>24) & 0xff;
+ //printf("segment map[%d][%d] now %x\n", m_context & 7, (offset & ~0x3c000000) >> 15, m_segmap[m_context & 7][(offset & ~0x3c000000) >> 15] = (data>>24) & 0xff);
+ return;
+
+ case 3: // context reg
+ //printf("sun3: Write (%x) %x to context\n", data, data>>24);
+ m_context = data >> 24;
+ return;
+
+ case 4: // enable reg
+ //printf("sun3: Write %x to enable, PC=%x\n", data, m_maincpu->pc);
+ COMBINE_DATA(&m_enable);
+ return;
+
+ case 5: // DVMA enable
+ m_dvma_enable = data>>24;
+ return;
+
+ case 6: // bus error
+ m_buserr = data >> 24;
+ return;
+
+ case 7: // diagnostic reg
+ m_diag = data >> 24;
+ printf("sun3: CPU LEDs to %02x (PC=%x) => ", ((data>>24) & 0xff) ^ 0xff, m_maincpu->pc);
+ for (int i = 0; i < 8; i++)
+ {
+ if (m_diag & (1<<i))
+ {
+ printf(".");
+ }
+ else
+ {
+ printf("*");
+ }
+ }
+ printf("\n");
+ return;
+
+ case 8: // cache tags
+ printf("sun3: %08x to cache tags @ %x, PC = %x\n", data, offset, m_maincpu->pc);
+ return;
+
+ case 9: // cache data
+ printf("sun3: %08x to cache data @ %x, PC = %x\n", data, offset, m_maincpu->pc);
+ return;
+
+ case 10: // flush cache
+ return;
+
+ case 11: // block copy
+ printf("sun3: %08x to block copy @ %x, PC = %x\n", data, offset, m_maincpu->pc);
+ return;
+
+ case 15: // UART bypass
+ printf("sun3: %08x to UART bypass @ %x, PC = %x\n", data, offset, m_maincpu->pc);
+ return;
+ }
+ }
+
+ // it's translation time
+ UINT8 pmeg = m_segmap[m_context & 7][(offset >> 15) & 0x7ff];
+ UINT32 entry = (pmeg << 4) + ((offset >> 11) & 0xf);
+
+ if (m_pagemap[entry] & PM_VALID)
+ {
+ if ((!(m_pagemap[entry] & PM_WRITEMASK)) ||
+ ((m_pagemap[entry] & PM_SYSMASK) && (fc < M68K_FC_SUPERVISOR_DATA)))
+ {
+ m_buserr = BE_PROTERR;
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
+ return;
+ }
+
+ m_pagemap[entry] |= (PM_ACCESSED | PM_MODIFIED);
+
+ UINT32 tmp = (m_pagemap[entry] & 0x7ffff) << 11;
+ tmp |= (offset & 0x7ff);
+
+ //if (!space.debugger_access()) printf("sun2: Translated addr: %08x, type %d (page entry %08x, orig virt %08x)\n", tmp << 1, (m_pagemap[entry] >> 22) & 7, m_pagemap[entry], offset<<1);
+
+ //if (((m_pagemap[entry] >> 26) & 3) == 1)
+ {
+ //printf("pmeg %d, entry %d = %08x, virt %08x => tmp %08x\n", pmeg, entry, m_pagemap[entry], offset << 2, tmp);
+ }
+
+ switch ((m_pagemap[entry] >> 26) & 3)
+ {
+ case 0: // type 0
+ m_type0space->write32(space, tmp, data, mem_mask);
+ return;
+
+ case 1: // type 1
+ //printf("write device space @ %x\n", tmp<<1);
+ m_type1space->write32(space, tmp, data, mem_mask);
+ return;
+
+ case 2: // type 2
+ m_type2space->write32(space, tmp, data, mem_mask);
+ return;
+
+ case 3: // type 3
+ m_type3space->write32(space, tmp, data, mem_mask);
+ return;
+ }
+ }
+ else
+ {
+ if (!space.debugger_access()) printf("sun3: pagemap entry not valid!\n");
+ m_buserr = BE_INVALID;
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
+ }
+
+ printf("sun3: Unmapped write %04x (FC %d, mask %04x, PC=%x) to %08x\n", data, fc, mem_mask, m_maincpu->pc, offset<<2);
}
-READ32_MEMBER(sun3_state::buserr_r)
+READ32_MEMBER(sun3_state::parity_r)
{
- UINT32 rv = m_buserr;
- m_buserr = 0;
+ UINT32 rv = m_parregs[offset];
+
+ if (offset == 0) // clear interrupt if any
+ {
+ m_maincpu->set_input_line(M68K_IRQ_7, CLEAR_LINE);
+ m_parregs[offset] &= ~0x8f000000;
+ }
+
return rv;
}
-WRITE32_MEMBER(sun3_state::buserr_w)
+WRITE32_MEMBER(sun3_state::parity_w)
{
-// printf("sun3x: %08x to buserr (mask %08x)\n", data, mem_mask);
- COMBINE_DATA(&m_buserr);
+ //printf("sun3: %08x to parity registers @ %x (mask %08x)\n", data, offset, mem_mask);
+
+ if (offset == 0)
+ {
+ m_parregs[0] &= 0x8f000000;
+
+ if ((m_parregs[0] & 0x80000000) && (data & 0x40000000))
+ {
+ m_maincpu->set_input_line(M68K_IRQ_7, ASSERT_LINE);
+ }
+
+ m_parregs[0] |= (data & 0x70000000);
+ }
+ else
+ {
+ COMBINE_DATA(&m_parregs[offset]);
+ }
}
-READ32_MEMBER(sun3_state::diag_r)
-{
- return m_diag;
-}
+static ADDRESS_MAP_START(sun3_mem, AS_PROGRAM, 32, sun3_state)
+ AM_RANGE(0x00000000, 0xffffffff) AM_READWRITE( tl_mmu_r, tl_mmu_w )
+ADDRESS_MAP_END
-WRITE32_MEMBER(sun3_state::diag_w)
-{
-// printf("sun3x: %08x to diag (mask %08x)\n", data, mem_mask);
- COMBINE_DATA(&m_diag);
-}
+// type 0 device space
+static ADDRESS_MAP_START(vmetype0space_map, AS_PROGRAM, 32, sun3_state)
+ AM_RANGE(0x00000000, 0x01ffffff) AM_READWRITE(ram_r, ram_w)
+ADDRESS_MAP_END
-READ32_MEMBER(sun3_state::printer_r)
-{
- return m_printer;
-}
+// type 1 device space
+static ADDRESS_MAP_START(vmetype1space_map, AS_PROGRAM, 32, sun3_state)
+ AM_RANGE(0x00020000, 0x0002000f) AM_DEVREADWRITE8(SCC2_TAG, z80scc_device, ba_cd_inv_r, ba_cd_inv_w, 0xff00ff00)
+ AM_RANGE(0x00060000, 0x0006ffff) AM_WRITE8(rtc7170_w, 0xffffffff)
+ AM_RANGE(0x00080000, 0x0008000f) AM_READWRITE(parity_r, parity_w)
+ AM_RANGE(0x000a0000, 0x000a0003) AM_READWRITE(irqctrl_r, irqctrl_w)
+ AM_RANGE(0x00100000, 0x0010ffff) AM_ROM AM_REGION("user1", 0)
+ADDRESS_MAP_END
-WRITE32_MEMBER(sun3_state::printer_w)
-{
-// printf("sun3x: %08x to printer (mask %08x)\n", data, mem_mask);
- COMBINE_DATA(&m_printer);
-}
+// type 2 device space
+static ADDRESS_MAP_START(vmetype2space_map, AS_PROGRAM, 32, sun3_state)
+ADDRESS_MAP_END
+
+// type 3 device space
+static ADDRESS_MAP_START(vmetype3space_map, AS_PROGRAM, 32, sun3_state)
+ADDRESS_MAP_END
READ32_MEMBER(sun3_state::irqctrl_r)
{
@@ -555,7 +686,7 @@ READ32_MEMBER(sun3_state::irqctrl_r)
WRITE32_MEMBER(sun3_state::irqctrl_w)
{
-// printf("sun3x: %08x to interrupt control (mask %08x)\n", data, mem_mask);
+ //printf("sun3: %08x to interrupt control (mask %08x)\n", data, mem_mask);
COMBINE_DATA(&m_irqctrl);
if (data & 0x01000000)
@@ -572,10 +703,6 @@ WRITE32_MEMBER(sun3_state::irqctrl_w)
{
m_maincpu->set_input_line(M68K_IRQ_3, ASSERT_LINE);
}
- if (!(data & 0x80000000))
- {
- m_maincpu->set_input_line(M68K_IRQ_7, CLEAR_LINE);
- }
}
else // master enable clear, clear all interrupts
{
@@ -589,83 +716,22 @@ WRITE32_MEMBER(sun3_state::irqctrl_w)
}
}
-READ32_MEMBER(sun3_state::memreg_r)
-{
- return m_memreg;
-}
-
-WRITE32_MEMBER(sun3_state::memreg_w)
-{
-// printf("sun3x: %08x to memory control (mask %08x)\n", data, mem_mask);
- COMBINE_DATA(&m_memreg);
-}
-
-READ32_MEMBER(sun3_state::memrerraddr_r)
-{
- m_bInBusErr = false;
- m_maincpu->set_input_line(M68K_IRQ_7, CLEAR_LINE);
- return m_memerraddr;
-}
-
-WRITE32_MEMBER(sun3_state::memrerraddr_w)
-{
-// printf("sun3x: %08x to memory error address (mask %08x)\n", data, mem_mask);
- COMBINE_DATA(&m_memerraddr);
-}
-
-READ32_MEMBER(sun3_state::iommu_r)
+WRITE8_MEMBER(sun3_state::rtc7170_w)
{
- return m_iommu[offset];
-}
-
-// IOMMU entry defs:
-// address mask: 0x03ffe000
-// cache inhibit: 0x00000040
-// full block: 0x00000020
-// modified: 0x00000010
-// used: 0x00000008
-// write prot: 0x00000004
-// bad: 0x00000002
-// valid: 0x00000001
-WRITE32_MEMBER(sun3_state::iommu_w)
-{
- COMBINE_DATA(&m_iommu[offset]);
-}
-
-READ32_MEMBER(sun3_state::fpa_r)
-{
- m_buserr |= 0x04000000;
- m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
- m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
- return 0xffffffff;
-}
-
-READ32_MEMBER(sun3_state::cause_buserr_r)
-{
- m_buserr |= 0x20000000;
- m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
- m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
- return 0xffffffff;
-}
-
-WRITE32_MEMBER(sun3_state::cause_buserr_w)
-{
- m_buserr |= 0x20000000;
- m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
- m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
-}
-
-TIMER_DEVICE_CALLBACK_MEMBER(sun3_state::sun380_timer)
-{
- if ((m_irqctrl & 0x81000000) == 0x81000000)
+ //printf("%02x to 7170 @ %x\n", data, offset);
+
+ if ((offset == 0x11) && (data == 0x1c))
{
- m_maincpu->set_input_line(M68K_IRQ_7, CLEAR_LINE);
- m_maincpu->set_input_line(M68K_IRQ_7, ASSERT_LINE);
+ if ((m_irqctrl & 0x21000000) == 0x21000000)
+ {
+ m_maincpu->set_input_line(M68K_IRQ_5, ASSERT_LINE);
+ }
}
}
UINT32 sun3_state::bw2_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
+#if 0
UINT32 *scanline;
int x, y;
UINT8 pixels;
@@ -689,7 +755,7 @@ UINT32 sun3_state::bw2_update(screen_device &screen, bitmap_rgb32 &bitmap, const
*scanline++ = palette[(pixels&1)];
}
}
-
+#endif
return 0;
}
@@ -697,93 +763,63 @@ UINT32 sun3_state::bw2_update(screen_device &screen, bitmap_rgb32 &bitmap, const
static INPUT_PORTS_START( sun3 )
INPUT_PORTS_END
-
-void sun3_state::machine_reset()
+void sun3_state::machine_start()
{
- UINT8* user1 = memregion("user1")->base();
-
- memcpy((UINT8*)m_p_ram.target(),user1,0x10000);
+ m_rom_ptr = (UINT32 *)m_rom->base();
+ m_ram_ptr = (UINT32 *)m_ram->pointer();
+ m_ram_size = m_ram->size();
+ m_ram_size_words = m_ram_size >> 2;
+}
+void sun3_state::machine_reset()
+{
m_maincpu->reset();
-
- memset(m_iommu, 0, sizeof(m_iommu));
-
m_enable = 0;
m_buserr = 0;
m_diag = 0;
- m_printer = 0;
+ m_dvma_enable = 0;
m_irqctrl = 0;
- m_memreg = 0;
- m_memerraddr = 0;
m_bInBusErr = false;
}
-FLOPPY_FORMATS_MEMBER( sun3_state::floppy_formats )
- FLOPPY_PC_FORMAT
-FLOPPY_FORMATS_END
-
-static SLOT_INTERFACE_START( sun_floppies )
- SLOT_INTERFACE( "35hd", FLOPPY_35_HD )
-SLOT_INTERFACE_END
-
static MACHINE_CONFIG_START( sun3, sun3_state )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", M68020, 16670000)
MCFG_CPU_PROGRAM_MAP(sun3_mem)
- MCFG_SCC8530_ADD(SCC1_TAG, XTAL_4_9152MHz, 0, 0, 0, 0)
- MCFG_SCC8530_ADD(SCC2_TAG, XTAL_4_9152MHz, 0, 0, 0, 0)
-MACHINE_CONFIG_END
-
-static MACHINE_CONFIG_START( sun3_80, sun3_state )
- /* basic machine hardware */
- MCFG_CPU_ADD("maincpu", M68030, 20000000)
- MCFG_CPU_PROGRAM_MAP(sun3_80_mem)
-
- MCFG_M48T02_ADD(TIMEKEEPER_TAG)
-
- MCFG_SCC8530_ADD(SCC1_TAG, XTAL_4_9152MHz, 0, 0, 0, 0)
- MCFG_SCC8530_ADD(SCC2_TAG, XTAL_4_9152MHz, 0, 0, 0, 0)
- MCFG_Z80SCC_OUT_TXDA_CB(DEVWRITELINE(RS232A_TAG, rs232_port_device, write_txd))
- MCFG_Z80SCC_OUT_TXDB_CB(DEVWRITELINE(RS232B_TAG, rs232_port_device, write_txd))
-
- MCFG_RS232_PORT_ADD(RS232A_TAG, default_rs232_devices, nullptr)
- MCFG_RS232_RXD_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, rxa_w))
- MCFG_RS232_DCD_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, dcda_w))
- MCFG_RS232_CTS_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, ctsa_w))
-
- MCFG_RS232_PORT_ADD(RS232B_TAG, default_rs232_devices, nullptr)
- MCFG_RS232_RXD_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, rxb_w))
- MCFG_RS232_DCD_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, dcdb_w))
- MCFG_RS232_CTS_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, ctsb_w))
-
- MCFG_DEVICE_ADD("scsi", SCSI_PORT, 0)
- MCFG_SCSIDEV_ADD("scsi:" SCSI_PORT_DEVICE1, "harddisk", SCSIHD, SCSI_ID_6)
- MCFG_SCSIDEV_ADD("scsi:" SCSI_PORT_DEVICE2, "harddisk", SCSIHD, SCSI_ID_5)
-
- MCFG_DEVICE_ADD(ESP_TAG, NCR539X, 20000000/2)
- MCFG_LEGACY_SCSI_PORT("scsi")
-
- MCFG_N82077AA_ADD("fdc", n82077aa_device::MODE_PS2)
- MCFG_FLOPPY_DRIVE_ADD("fdc:0", sun_floppies, "35hd", sun3_state::floppy_formats)
-
- // the timekeeper has no interrupt output, so 3/80 includes a dedicated timer circuit
- MCFG_TIMER_DRIVER_ADD_PERIODIC("timer", sun3_state, sun380_timer, attotime::from_hz(100))
-
- MCFG_SCREEN_ADD("bwtwo", RASTER)
- MCFG_SCREEN_UPDATE_DRIVER(sun3_state, bw2_update)
- MCFG_SCREEN_SIZE(1152,900)
- MCFG_SCREEN_VISIBLE_AREA(0, 1152-1, 0, 900-1)
- MCFG_SCREEN_REFRESH_RATE(72)
-MACHINE_CONFIG_END
-
-static MACHINE_CONFIG_START( sun3_460, sun3_state )
- /* basic machine hardware */
- MCFG_CPU_ADD("maincpu", M68030, 33000000)
- MCFG_CPU_PROGRAM_MAP(sun3_460_mem)
-
- MCFG_M48T02_ADD(TIMEKEEPER_TAG)
-
+ MCFG_RAM_ADD(RAM_TAG)
+ MCFG_RAM_DEFAULT_SIZE("2M")
+ MCFG_RAM_EXTRA_OPTIONS("4M,6M,8M,12M,16M,20M,24M,28M,32M")
+ MCFG_RAM_DEFAULT_VALUE(0x00)
+
+ // MMU Type 0 device space
+ MCFG_DEVICE_ADD("type0", ADDRESS_MAP_BANK, 0)
+ MCFG_DEVICE_PROGRAM_MAP(vmetype0space_map)
+ MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_BIG)
+ MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(32)
+ MCFG_ADDRESS_MAP_BANK_STRIDE(0x80000000)
+
+ // MMU Type 1 device space
+ MCFG_DEVICE_ADD("type1", ADDRESS_MAP_BANK, 0)
+ MCFG_DEVICE_PROGRAM_MAP(vmetype1space_map)
+ MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_BIG)
+ MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(32)
+ MCFG_ADDRESS_MAP_BANK_STRIDE(0x80000000)
+
+ // MMU Type 2 device space
+ MCFG_DEVICE_ADD("type2", ADDRESS_MAP_BANK, 0)
+ MCFG_DEVICE_PROGRAM_MAP(vmetype2space_map)
+ MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_BIG)
+ MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(32)
+ MCFG_ADDRESS_MAP_BANK_STRIDE(0x80000000)
+
+ // MMU Type 3 device space
+ MCFG_DEVICE_ADD("type3", ADDRESS_MAP_BANK, 0)
+ MCFG_DEVICE_PROGRAM_MAP(vmetype3space_map)
+ MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_BIG)
+ MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(32)
+ MCFG_ADDRESS_MAP_BANK_STRIDE(0x80000000)
+
MCFG_SCC8530_ADD(SCC1_TAG, XTAL_4_9152MHz, 0, 0, 0, 0)
MCFG_SCC8530_ADD(SCC2_TAG, XTAL_4_9152MHz, 0, 0, 0, 0)
MCFG_Z80SCC_OUT_TXDA_CB(DEVWRITELINE(RS232A_TAG, rs232_port_device, write_txd))
@@ -917,48 +953,6 @@ ROM_START( sun3_e )
ROMX_LOAD( "sun3_e.32", 0x0000, 0x10000, CRC(acedde7e) SHA1(1ab6ec28f4365a613a5e326c34cb37585c3f0ecc), ROM_BIOS(1))
ROM_END
-ROM_START( sun3_80 )
- ROM_REGION32_BE( 0x20000, "user1", ROMREGION_ERASEFF )
-/*
-Sun 3/80 V1.0 Bootprom
-Sun 3/80 V2.2 Bootprom
-Sun 3/80 V2.3 Bootprom
-Sun 3/80 V2.9.2 Bootprom
-Sun 3/80 V3.0 Bootprom
-Sun 3/80 V3.0.2 Bootprom
-Sun 3/80 V3.0.3 Bootprom
-*/
- ROM_SYSTEM_BIOS(0, "rev303", "Rev 3.0.3")
- ROMX_LOAD( "sun3_80_v3.0.3", 0x0000, 0x20000, CRC(8f983115) SHA1(e4be2dcbb29fc5c60ed9d838ab241c634fdd24e5), ROM_BIOS(1))
- ROM_SYSTEM_BIOS(1, "rev302", "Rev 3.0.2")
- ROMX_LOAD( "sun3_80_v3.0.2", 0x0000, 0x20000, CRC(c09a3592) SHA1(830187dfe58e65289533717a797d2c42da86ac4e), ROM_BIOS(2))
- ROM_SYSTEM_BIOS(2, "rev30", "Rev 3.0")
- ROMX_LOAD( "sun3_80_v3.0", 0x0000, 0x20000, CRC(47e3b012) SHA1(1e045b6f542aaf7808d6567c28a9e734a8c5d815), ROM_BIOS(3))
- ROM_SYSTEM_BIOS(3, "rev292", "Rev 2.9.2")
- ROMX_LOAD( "sun3_80_v2.9.2", 0x0000, 0x20000, CRC(32bcf711) SHA1(7ecd4a0d0988c1d1d53fd79ac16c8456ed73ace1), ROM_BIOS(4))
-
- // default NVRAM: includes valid settings for console on framebuffer, boot from SCSI disk, Ethernet ID, more
- ROM_REGION( 0x800, TIMEKEEPER_TAG, 0 )
- ROM_LOAD( "timekpr_380.bin", 0x000000, 0x000800, CRC(e76f1aae) SHA1(8e7c36e3928887a94a8133e8416ee4126c31edd7) )
-ROM_END
-
-ROM_START( sun3_460 )
- ROM_REGION32_BE( 0x20000, "user1", ROMREGION_ERASEFF )
-/*
-Sun 3/460/480 V1.2.3 Bootprom
-Sun 3/460/480 V2.9.1 Bootprom (2 Files, one for odd and one for even addresses)
-Sun 3/460/480 V2.9.2 Bootprom
-Sun 3/460/480 V2.9.3 Bootprom
-Sun 3/460/480 V3.0 Bootprom (2 Files, one for odd and one for even addresses)
-*/
- ROM_SYSTEM_BIOS(0, "rev30", "Rev 3.0")
- ROMX_LOAD( "3_400_l.300", 0x00000, 0x10000, CRC(1312a04b) SHA1(6c3b67ba3567991897a48fe20f589ebbfcf0a35d), ROM_BIOS(1))
- ROMX_LOAD( "3_400_h.300", 0x10000, 0x10000, CRC(8d688672) SHA1(a5593844ce6af6c4f7f39bb653dc8f964b73b095), ROM_BIOS(1))
- ROM_SYSTEM_BIOS(1, "rev291", "Rev 2.9.1")
- ROMX_LOAD( "sun3_460_v2.9.1_0", 0x00000, 0x10000, CRC(d62dbf09) SHA1(4a6b5fd7840b44fe93c9058a8973d8dd3c9f7d24), ROM_BIOS(2))
- ROMX_LOAD( "sun3_460_v2.9.1_1", 0x10000, 0x10000, CRC(3b5a5942) SHA1(ed6250e3c07d7cb62d4dd517a8637c8d37e16dc5), ROM_BIOS(2))
-ROM_END
-
/* Driver */
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */
@@ -968,6 +962,3 @@ COMP( 198?, sun3_110, 0, 0, sun3, sun3, driver_device, 0,
COMP( 198?, sun3_150, 0, 0, sun3, sun3, driver_device, 0, "Sun Microsystems", "Sun 3/75/140/150/160/180", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) // AKA Carrera
COMP( 198?, sun3_260, 0, 0, sun3, sun3, driver_device, 0, "Sun Microsystems", "Sun 3/260/280", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) // Prism
COMP( 198?, sun3_e, 0, 0, sun3, sun3, driver_device, 0, "Sun Microsystems", "Sun 3/E", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) // Polaris
-
-COMP( 198?, sun3_80, 0, 0, sun3_80, sun3, driver_device, 0, "Sun Microsystems", "Sun 3x/80", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) // Hydra
-COMP( 198?, sun3_460, 0, 0, sun3_460, sun3, driver_device, 0, "Sun Microsystems", "Sun 3x/460/470/480", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) // Pegasus
diff --git a/src/mame/drivers/sun3x.cpp b/src/mame/drivers/sun3x.cpp
new file mode 100644
index 00000000000..d81688727d2
--- /dev/null
+++ b/src/mame/drivers/sun3x.cpp
@@ -0,0 +1,684 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic, R. Belmont
+/***************************************************************************
+
+ sun3.c: preliminary driver for Sun 3x models.
+
+ status: 3/80 POSTs, 3/460 needs its unique RTC chip (also used by non-3x Sun 3s).
+
+ TODO:
+ - Z8530 SCC needs to actually speak serial so we can hook up the mouse and keyboard.
+ - Improve interrupt controller emulation.
+ - Figure out how the IOMMU works.
+ - Intersil 7170 device for 3/460 and 3/480 (they use the same PROMs).
+ - Sun custom MMU for original Sun 3 models.
+ - AM7990 LANCE chip support for everyone.
+ - Figure out how the parallel printer port maps to Centronics and make it so.
+ - Much more...
+
+
+ Sun-3x Models
+ ------------
+
+ 3/80
+ Processor(s): 68030 @ 20MHz, 68882 @ 20MHz, 68030 on-chip
+ MMU, 3 MIPS, 0.16 MFLOPS
+ CPU: 501-1401/1650
+ Chassis type: square pizza box
+ Bus: P4 connector (not same as P4 on 3/60)
+ Memory: 16M or 40M physical, 4G virtual, 100ns cycle
+ Notes: Similar packaging to SparcStation 1. Parallel
+ port, SCSI port, AUI Ethernet, 1.44M 3.5" floppy
+ (720K on early units?). No onboard framebuffer.
+ Code-named "Hydra". Type-4 keyboard and Sun-4
+ mouse, plugged together and into the machine
+ with a small DIN plug. 1M x 9 30-pin 100ns
+ SIMMs. Boot ROM versions 3.0.2 and later allow
+ using 4M SIMMs in some slots for up to 40M (see
+ Misc Q&A #15).
+
+ 3/460
+ Processor(s): 68030 @ 33 MHz, 68882, 68030 on-chip MMU,
+ 7 MIPS, 0.6 MFLOPS
+ CPU: 501-1299/1550
+ Bus: VME
+ Memory: 128M physical with ECC, 4G/process virtual,
+ 64K cache, 80ns cycle
+ Notes: A 3/260 upgraded with a 3/4xx CPU board. Uses
+ original 3/2xx memory boards.
+
+ 3/470
+ Processor(s): 68030 @ 33 MHz, 68882, 68030 on-chip MMU,
+ 7 MIPS, 0.6 MFLOPS
+ CPU: 501-1299/1550
+ Chassis type: deskside
+ Bus: VME
+ Memory: 128M physical with ECC, 4G/process virtual,
+ 64K cache, 80ns cycle
+ Notes: Rare. Code-named "Pegasus". 8M standard, uses
+ same memory boards as 3/2xx.
+
+ 3/480
+ Processor(s): 68030 @ 33 MHz, 68882, 68030 on-chip MMU,
+ 7 MIPS, 0.6 MFLOPS
+ CPU: 501-1299/1550
+ Chassis type: rackmount
+ Bus: VME
+ Memory: 128M physical with ECC, 4G/process virtual,
+ 64K cache, 80ns cycle
+ Notes: Rare. Code-named "Pegasus". 8M standard, uses
+ same memory boards as 3/2xx.
+
+ Sun3X notes from NetBSD and Linux:
+
+ RAM_END 0x40000000
+ P4DAC 0x50200000
+ VIDEO_P4ID 0x50300000
+ BW2_ADDR 0x50400000
+ ENA_PLANE 0x50600000
+ FPA_ADDR 0x5c000000
+ IOMMU 0x60000000
+ ENABLEREG 0x61000000
+ BUSERRREG 0x61000400
+ DIAGREG 0x61000800
+ IDPROM1 0x61000c00 (3/470)
+ MEMREG 0x61001000
+ INTERREG 0x61001400
+ SCC1 0x62000000 (keyboard/mouse)
+ SCC2 0x62002000 (serial console)
+ EEPROM 0x64000000
+ IDPROM2 0x640007d8 (3/80)
+ CLOCK2 0x640007f8 (3/80 Mostek 48T02)
+ CLOCK1 0x64002000 (3/470 Intersil 7170)
+ INTELETH 0x65000000
+ LANCEETH 0x65002000
+ EMULEXSCSI 0x66000000 (3/80 5394)
+ EMULLEXDMA 0x66001000 (3/80)
+ PCACHETAG 0x68000000
+ ECCPARREG 0x6a1e0000
+ IOCTAGS 0x6c000000
+ IOCFLUSH 0x6d000000
+ FDC 0x6e000000 (3/80 Intel 82077)
+ FDC_CNTRL 0x6e000400
+ FDC_VEC 0x6e000800
+ PRINTER 0x6f00003c (3/80)
+
+ The Sun3x System Enable Register controls the function of a few
+ on-board devices and general system operation. It is cleared when
+ the system is reset.
+
+ 15 0
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---.---.---+
+ |BT |FPP|DMA| 0 |VID|RES|FPA|DIA| 0 |CCH|IOC|LBK|DCH| UNUSED |
+ +---+---+---+---+---+---+---+---+---+---+---+---+---+---.---.---+
+
+ Where: DCH = debug mode for system cache
+ LBK = VME loopback
+ IOC = I/O cache enable
+ CCH = system cache enable
+ DIA = diagnostic switch
+ FPA = enable floating-point accelerator
+ RES = 0 for hi-res, 1 for low res
+ VID = enable video display
+ DMA = enable system DVMA
+ FPP = enable 68881/2 FPU
+ BT = 0 for boot state, 1 for normal state
+
+ bad '030 MMU mapping: L fef82000 -> P 00000000
+
+****************************************************************************/
+
+#include "emu.h"
+#include "cpu/m68000/m68000.h"
+#include "machine/timekpr.h"
+#include "machine/z80scc.h"
+#include "bus/scsi/scsi.h"
+#include "bus/scsi/scsihd.h"
+#include "bus/scsi/scsicd.h"
+#include "machine/ncr539x.h"
+#include "machine/upd765.h"
+#include "formats/pc_dsk.h"
+#include "formats/mfi_dsk.h"
+#include "bus/rs232/rs232.h"
+
+#define TIMEKEEPER_TAG "timekpr"
+#define SCC1_TAG "scc1"
+#define SCC2_TAG "scc2"
+#define ESP_TAG "esp"
+#define FDC_TAG "fdc"
+#define RS232A_TAG "rs232a"
+#define RS232B_TAG "rs232b"
+
+class sun3x_state : public driver_device
+{
+public:
+ sun3x_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_scc1(*this, SCC1_TAG),
+ m_scc2(*this, SCC2_TAG),
+ m_fdc(*this, FDC_TAG),
+ m_p_ram(*this, "p_ram"),
+ m_bw2_vram(*this, "bw2_vram")
+ { }
+
+ required_device<cpu_device> m_maincpu;
+ required_device<z80scc_device> m_scc1;
+ required_device<z80scc_device> m_scc2;
+ optional_device<n82077aa_device> m_fdc;
+ virtual void machine_reset() override;
+
+ required_shared_ptr<UINT32> m_p_ram;
+ optional_shared_ptr<UINT32> m_bw2_vram;
+
+ DECLARE_READ32_MEMBER(enable_r);
+ DECLARE_WRITE32_MEMBER(enable_w);
+ DECLARE_READ32_MEMBER(buserr_r);
+ DECLARE_WRITE32_MEMBER(buserr_w);
+ DECLARE_READ32_MEMBER(diag_r);
+ DECLARE_WRITE32_MEMBER(diag_w);
+ DECLARE_READ32_MEMBER(printer_r);
+ DECLARE_WRITE32_MEMBER(printer_w);
+ DECLARE_READ32_MEMBER(iommu_r);
+ DECLARE_WRITE32_MEMBER(iommu_w);
+ DECLARE_READ32_MEMBER(irqctrl_r);
+ DECLARE_WRITE32_MEMBER(irqctrl_w);
+ DECLARE_READ32_MEMBER(memreg_r);
+ DECLARE_WRITE32_MEMBER(memreg_w);
+ DECLARE_READ32_MEMBER(memrerraddr_r);
+ DECLARE_WRITE32_MEMBER(memrerraddr_w);
+ DECLARE_READ32_MEMBER(fdc_control_r);
+ DECLARE_WRITE32_MEMBER(fdc_control_w);
+ DECLARE_READ32_MEMBER(cause_buserr_r);
+ DECLARE_WRITE32_MEMBER(cause_buserr_w);
+ DECLARE_WRITE32_MEMBER(ramwrite_w);
+ DECLARE_READ32_MEMBER(fpa_r);
+ DECLARE_READ32_MEMBER(p4id_r);
+
+ DECLARE_FLOPPY_FORMATS( floppy_formats );
+
+ TIMER_DEVICE_CALLBACK_MEMBER(sun380_timer);
+
+ UINT32 bw2_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+
+private:
+ UINT32 m_enable, m_buserr, m_diag, m_printer, m_irqctrl, m_memreg, m_memerraddr;
+ UINT32 m_iommu[0x800];
+ bool m_bInBusErr;
+};
+
+static ADDRESS_MAP_START(sun3_80_mem, AS_PROGRAM, 32, sun3x_state)
+ AM_RANGE(0x00000000, 0x03ffffff) AM_RAM AM_SHARE("p_ram") AM_WRITE(ramwrite_w)
+ AM_RANGE(0x40000000, 0x40000003) AM_READWRITE(cause_buserr_r, cause_buserr_w)
+ AM_RANGE(0x50300000, 0x50300003) AM_READ(p4id_r)
+ AM_RANGE(0x50400000, 0x504fffff) AM_RAM AM_SHARE("bw2_vram")
+ AM_RANGE(0x60000000, 0x60001fff) AM_READWRITE(iommu_r, iommu_w)
+ AM_RANGE(0x61000000, 0x61000003) AM_READWRITE(enable_r, enable_w)
+ AM_RANGE(0x61000400, 0x61000403) AM_READWRITE(buserr_r, buserr_w)
+ AM_RANGE(0x61000800, 0x61000803) AM_READWRITE(diag_r, diag_w)
+ AM_RANGE(0x61001000, 0x61001003) AM_READWRITE(memreg_r, memreg_w)
+ AM_RANGE(0x61001004, 0x61001007) AM_READWRITE(memrerraddr_r, memrerraddr_w)
+ AM_RANGE(0x61001400, 0x61001403) AM_READWRITE(irqctrl_r, irqctrl_w)
+ AM_RANGE(0x62000000, 0x6200000f) AM_DEVREADWRITE8(SCC1_TAG, z80scc_device, ba_cd_inv_r, ba_cd_inv_w, 0xff00ff00)
+ AM_RANGE(0x62002000, 0x6200200f) AM_DEVREADWRITE8(SCC2_TAG, z80scc_device, ba_cd_inv_r, ba_cd_inv_w, 0xff00ff00)
+ AM_RANGE(0x63000000, 0x6301ffff) AM_ROM AM_REGION("user1",0)
+ AM_RANGE(0x64000000, 0x640007ff) AM_DEVREADWRITE8(TIMEKEEPER_TAG, timekeeper_device, read, write, 0xffffffff)
+ AM_RANGE(0x66000000, 0x6600003f) AM_DEVREADWRITE8(ESP_TAG, ncr539x_device, read, write, 0xff000000)
+ AM_RANGE(0x6e000000, 0x6e000007) AM_DEVICE8(FDC_TAG, n82077aa_device, map, 0xffffffff)
+ AM_RANGE(0x6e000400, 0x6e000403) AM_READWRITE(fdc_control_r, fdc_control_w)
+ AM_RANGE(0x6f00003c, 0x6f00003f) AM_READWRITE(printer_r, printer_w)
+ AM_RANGE(0xfefe0000, 0xfefeffff) AM_ROM AM_REGION("user1",0)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(sun3_460_mem, AS_PROGRAM, 32, sun3x_state)
+ AM_RANGE(0x00000000, 0x03ffffff) AM_RAM AM_SHARE("p_ram") AM_WRITE(ramwrite_w)
+ AM_RANGE(0x09000000, 0x09000003) AM_READWRITE(cause_buserr_r, cause_buserr_w)
+ AM_RANGE(0x50300000, 0x50300003) AM_READ(p4id_r)
+ AM_RANGE(0x50400000, 0x504fffff) AM_RAM AM_SHARE("bw2_vram")
+ AM_RANGE(0x5c000f14, 0x5c000f17) AM_READ(fpa_r)
+ AM_RANGE(0x60000000, 0x60001fff) AM_READWRITE(iommu_r, iommu_w)
+ AM_RANGE(0x61000000, 0x61000003) AM_READWRITE(enable_r, enable_w)
+ AM_RANGE(0x61000400, 0x61000403) AM_READWRITE(buserr_r, buserr_w)
+ AM_RANGE(0x61000800, 0x61000803) AM_READWRITE(diag_r, diag_w)
+ AM_RANGE(0x61001000, 0x61001003) AM_READWRITE(memreg_r, memreg_w)
+ AM_RANGE(0x61001004, 0x61001007) AM_READWRITE(memrerraddr_r, memrerraddr_w)
+ AM_RANGE(0x61001400, 0x61001403) AM_READWRITE(irqctrl_r, irqctrl_w)
+ AM_RANGE(0x62000000, 0x6200000f) AM_DEVREADWRITE8(SCC1_TAG, z80scc_device, ba_cd_inv_r, ba_cd_inv_w, 0xff00ff00)
+ AM_RANGE(0x62002000, 0x6200200f) AM_DEVREADWRITE8(SCC2_TAG, z80scc_device, ba_cd_inv_r, ba_cd_inv_w, 0xff00ff00)
+ AM_RANGE(0x63000000, 0x6301ffff) AM_ROM AM_REGION("user1",0)
+
+ AM_RANGE(0x6f00003c, 0x6f00003f) AM_READWRITE(printer_r, printer_w)
+ AM_RANGE(0xfefe0000, 0xfefeffff) AM_ROM AM_REGION("user1",0)
+ADDRESS_MAP_END
+
+READ32_MEMBER( sun3x_state::p4id_r )
+{
+ return (1<<24); // 0 = hires bw2 1600x1280, 1 = bw2 1152x900, 0x45 is "Ibis" color, blt 0x68 is "Lego" color
+}
+
+WRITE32_MEMBER( sun3x_state::fdc_control_w )
+{
+ logerror("FDC write %02x (%08x)\n", data >> 24, space.device().safe_pc());
+}
+
+READ32_MEMBER( sun3x_state::fdc_control_r )
+{
+ // Type of floppy present
+ // 0 = no floppy in drive
+ // 1 = ed
+ // 2 = hd
+ // 3 = dd
+
+ if(m_fdc) {
+ floppy_image_device *fdev = machine().device<floppy_connector>(":fdc:0")->get_device();
+ if(fdev->exists()) {
+ UINT32 variant = fdev->get_variant();
+ switch(variant) {
+ case floppy_image::SSSD:
+ case floppy_image::SSDD:
+ case floppy_image::DSDD:
+ return 3 << 24;
+
+ case floppy_image::DSHD:
+ return 2 << 24;
+
+ case floppy_image::DSED:
+ return 1 << 24;
+ }
+ }
+ }
+
+ return 0 << 24;
+}
+
+WRITE32_MEMBER(sun3x_state::ramwrite_w)
+{
+ UINT32 *pRAM = (UINT32 *)m_p_ram.target();
+
+ if (((m_memreg & 0xf0000000) == 0x70000000) &&
+ (m_irqctrl & 0x01000000) &&
+ !(m_bInBusErr))
+ {
+ m_memerraddr = offset<<2;
+
+ // low 4 bits of memreg are the byte lane(s) involved, negative logic
+ m_memreg |= 0x0f;
+ switch (mem_mask)
+ {
+ case 0xff000000:
+ m_memreg &= ~0x08;
+ break;
+
+ case 0x00ff0000:
+ m_memerraddr += 1;
+ m_memreg &= ~0x04;
+ break;
+
+ case 0x0000ff00:
+ m_memerraddr += 2;
+ m_memreg &= ~0x02;
+ break;
+
+ case 0x000000ff:
+ m_memerraddr += 3;
+ m_memreg &= ~0x01;
+ break;
+
+ case 0x0000ffff:
+ m_memerraddr += 2;
+ m_memreg &= ~0x03;
+ break;
+
+ case 0xffff0000:
+ m_memreg &= ~0x0c;
+ break;
+
+ case 0xffffffff: // no address adjust, show all 4 lanes as problematic
+ break;
+ }
+
+ m_bInBusErr = true; // prevent recursion
+ m_maincpu->set_input_line_and_vector(M68K_IRQ_7, ASSERT_LINE, 2);
+ }
+
+ COMBINE_DATA(&pRAM[offset]);
+}
+
+READ32_MEMBER(sun3x_state::enable_r)
+{
+ return m_enable;
+}
+
+WRITE32_MEMBER(sun3x_state::enable_w)
+{
+// printf("sun3x: %08x to enable (mask %08x)\n", data, mem_mask);
+ COMBINE_DATA(&m_enable);
+}
+
+READ32_MEMBER(sun3x_state::buserr_r)
+{
+ UINT32 rv = m_buserr;
+ m_buserr = 0;
+ return rv;
+}
+
+WRITE32_MEMBER(sun3x_state::buserr_w)
+{
+// printf("sun3x: %08x to buserr (mask %08x)\n", data, mem_mask);
+ COMBINE_DATA(&m_buserr);
+}
+
+READ32_MEMBER(sun3x_state::diag_r)
+{
+ return m_diag;
+}
+
+WRITE32_MEMBER(sun3x_state::diag_w)
+{
+// printf("sun3x: %08x to diag (mask %08x)\n", data, mem_mask);
+ COMBINE_DATA(&m_diag);
+}
+
+READ32_MEMBER(sun3x_state::printer_r)
+{
+ return m_printer;
+}
+
+WRITE32_MEMBER(sun3x_state::printer_w)
+{
+// printf("sun3x: %08x to printer (mask %08x)\n", data, mem_mask);
+ COMBINE_DATA(&m_printer);
+}
+
+READ32_MEMBER(sun3x_state::irqctrl_r)
+{
+ return m_irqctrl;
+}
+
+WRITE32_MEMBER(sun3x_state::irqctrl_w)
+{
+// printf("sun3x: %08x to interrupt control (mask %08x)\n", data, mem_mask);
+ COMBINE_DATA(&m_irqctrl);
+
+ if (data & 0x01000000)
+ {
+ if (data & 0x02000000)
+ {
+ m_maincpu->set_input_line(M68K_IRQ_1, ASSERT_LINE);
+ }
+ if (data & 0x04000000)
+ {
+ m_maincpu->set_input_line(M68K_IRQ_2, ASSERT_LINE);
+ }
+ if (data & 0x08000000)
+ {
+ m_maincpu->set_input_line(M68K_IRQ_3, ASSERT_LINE);
+ }
+ if (!(data & 0x80000000))
+ {
+ m_maincpu->set_input_line(M68K_IRQ_7, CLEAR_LINE);
+ }
+ }
+ else // master enable clear, clear all interrupts
+ {
+ m_maincpu->set_input_line(M68K_IRQ_1, CLEAR_LINE);
+ m_maincpu->set_input_line(M68K_IRQ_2, CLEAR_LINE);
+ m_maincpu->set_input_line(M68K_IRQ_3, CLEAR_LINE);
+ m_maincpu->set_input_line(M68K_IRQ_4, CLEAR_LINE);
+ m_maincpu->set_input_line(M68K_IRQ_5, CLEAR_LINE);
+ m_maincpu->set_input_line(M68K_IRQ_6, CLEAR_LINE);
+ m_maincpu->set_input_line(M68K_IRQ_7, CLEAR_LINE);
+ }
+}
+
+READ32_MEMBER(sun3x_state::memreg_r)
+{
+ return m_memreg;
+}
+
+WRITE32_MEMBER(sun3x_state::memreg_w)
+{
+// printf("sun3x: %08x to memory control (mask %08x)\n", data, mem_mask);
+ COMBINE_DATA(&m_memreg);
+}
+
+READ32_MEMBER(sun3x_state::memrerraddr_r)
+{
+ m_bInBusErr = false;
+ m_maincpu->set_input_line(M68K_IRQ_7, CLEAR_LINE);
+ return m_memerraddr;
+}
+
+WRITE32_MEMBER(sun3x_state::memrerraddr_w)
+{
+// printf("sun3x: %08x to memory error address (mask %08x)\n", data, mem_mask);
+ COMBINE_DATA(&m_memerraddr);
+}
+
+READ32_MEMBER(sun3x_state::iommu_r)
+{
+ return m_iommu[offset];
+}
+
+// IOMMU entry defs:
+// address mask: 0x03ffe000
+// cache inhibit: 0x00000040
+// full block: 0x00000020
+// modified: 0x00000010
+// used: 0x00000008
+// write prot: 0x00000004
+// bad: 0x00000002
+// valid: 0x00000001
+WRITE32_MEMBER(sun3x_state::iommu_w)
+{
+ COMBINE_DATA(&m_iommu[offset]);
+}
+
+READ32_MEMBER(sun3x_state::fpa_r)
+{
+ m_buserr |= 0x04000000;
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
+ return 0xffffffff;
+}
+
+READ32_MEMBER(sun3x_state::cause_buserr_r)
+{
+ m_buserr |= 0x20000000;
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
+ return 0xffffffff;
+}
+
+WRITE32_MEMBER(sun3x_state::cause_buserr_w)
+{
+ m_buserr |= 0x20000000;
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
+ m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(sun3x_state::sun380_timer)
+{
+ if ((m_irqctrl & 0x81000000) == 0x81000000)
+ {
+ m_maincpu->set_input_line(M68K_IRQ_7, CLEAR_LINE);
+ m_maincpu->set_input_line(M68K_IRQ_7, ASSERT_LINE);
+ }
+}
+
+UINT32 sun3x_state::bw2_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ UINT32 *scanline;
+ int x, y;
+ UINT8 pixels;
+ static const UINT32 palette[2] = { 0, 0xffffff };
+ UINT8 *m_vram = (UINT8 *)m_bw2_vram.target();
+
+ for (y = 0; y < 900; y++)
+ {
+ scanline = &bitmap.pix32(y);
+ for (x = 0; x < 1152/8; x++)
+ {
+ pixels = m_vram[(y * (1152/8)) + (BYTE4_XOR_BE(x))];
+
+ *scanline++ = palette[(pixels>>7)&1];
+ *scanline++ = palette[(pixels>>6)&1];
+ *scanline++ = palette[(pixels>>5)&1];
+ *scanline++ = palette[(pixels>>4)&1];
+ *scanline++ = palette[(pixels>>3)&1];
+ *scanline++ = palette[(pixels>>2)&1];
+ *scanline++ = palette[(pixels>>1)&1];
+ *scanline++ = palette[(pixels&1)];
+ }
+ }
+
+ return 0;
+}
+
+/* Input ports */
+static INPUT_PORTS_START( sun3x )
+INPUT_PORTS_END
+
+
+void sun3x_state::machine_reset()
+{
+ UINT8* user1 = memregion("user1")->base();
+
+ memcpy((UINT8*)m_p_ram.target(),user1,0x10000);
+
+ m_maincpu->reset();
+
+ memset(m_iommu, 0, sizeof(m_iommu));
+
+ m_enable = 0;
+ m_buserr = 0;
+ m_diag = 0;
+ m_printer = 0;
+ m_irqctrl = 0;
+ m_memreg = 0;
+ m_memerraddr = 0;
+ m_bInBusErr = false;
+}
+
+FLOPPY_FORMATS_MEMBER( sun3x_state::floppy_formats )
+ FLOPPY_PC_FORMAT
+FLOPPY_FORMATS_END
+
+static SLOT_INTERFACE_START( sun_floppies )
+ SLOT_INTERFACE( "35hd", FLOPPY_35_HD )
+SLOT_INTERFACE_END
+
+static MACHINE_CONFIG_START( sun3_80, sun3x_state )
+ /* basic machine hardware */
+ MCFG_CPU_ADD("maincpu", M68030, 20000000)
+ MCFG_CPU_PROGRAM_MAP(sun3_80_mem)
+
+ MCFG_M48T02_ADD(TIMEKEEPER_TAG)
+
+ MCFG_SCC8530_ADD(SCC1_TAG, XTAL_4_9152MHz, 0, 0, 0, 0)
+ MCFG_SCC8530_ADD(SCC2_TAG, XTAL_4_9152MHz, 0, 0, 0, 0)
+ MCFG_Z80SCC_OUT_TXDA_CB(DEVWRITELINE(RS232A_TAG, rs232_port_device, write_txd))
+ MCFG_Z80SCC_OUT_TXDB_CB(DEVWRITELINE(RS232B_TAG, rs232_port_device, write_txd))
+
+ MCFG_RS232_PORT_ADD(RS232A_TAG, default_rs232_devices, nullptr)
+ MCFG_RS232_RXD_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, rxa_w))
+ MCFG_RS232_DCD_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, dcda_w))
+ MCFG_RS232_CTS_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, ctsa_w))
+
+ MCFG_RS232_PORT_ADD(RS232B_TAG, default_rs232_devices, nullptr)
+ MCFG_RS232_RXD_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, rxb_w))
+ MCFG_RS232_DCD_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, dcdb_w))
+ MCFG_RS232_CTS_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, ctsb_w))
+
+ MCFG_DEVICE_ADD("scsi", SCSI_PORT, 0)
+ MCFG_SCSIDEV_ADD("scsi:" SCSI_PORT_DEVICE1, "harddisk", SCSIHD, SCSI_ID_6)
+ MCFG_SCSIDEV_ADD("scsi:" SCSI_PORT_DEVICE2, "harddisk", SCSIHD, SCSI_ID_5)
+
+ MCFG_DEVICE_ADD(ESP_TAG, NCR539X, 20000000/2)
+ MCFG_LEGACY_SCSI_PORT("scsi")
+
+ MCFG_N82077AA_ADD("fdc", n82077aa_device::MODE_PS2)
+ MCFG_FLOPPY_DRIVE_ADD("fdc:0", sun_floppies, "35hd", sun3x_state::floppy_formats)
+
+ // the timekeeper has no interrupt output, so 3/80 includes a dedicated timer circuit
+ MCFG_TIMER_DRIVER_ADD_PERIODIC("timer", sun3x_state, sun380_timer, attotime::from_hz(100))
+
+ MCFG_SCREEN_ADD("bwtwo", RASTER)
+ MCFG_SCREEN_UPDATE_DRIVER(sun3x_state, bw2_update)
+ MCFG_SCREEN_SIZE(1152,900)
+ MCFG_SCREEN_VISIBLE_AREA(0, 1152-1, 0, 900-1)
+ MCFG_SCREEN_REFRESH_RATE(72)
+MACHINE_CONFIG_END
+
+static MACHINE_CONFIG_START( sun3_460, sun3x_state )
+ /* basic machine hardware */
+ MCFG_CPU_ADD("maincpu", M68030, 33000000)
+ MCFG_CPU_PROGRAM_MAP(sun3_460_mem)
+
+ MCFG_M48T02_ADD(TIMEKEEPER_TAG)
+
+ MCFG_SCC8530_ADD(SCC1_TAG, XTAL_4_9152MHz, 0, 0, 0, 0)
+ MCFG_SCC8530_ADD(SCC2_TAG, XTAL_4_9152MHz, 0, 0, 0, 0)
+ MCFG_Z80SCC_OUT_TXDA_CB(DEVWRITELINE(RS232A_TAG, rs232_port_device, write_txd))
+ MCFG_Z80SCC_OUT_TXDB_CB(DEVWRITELINE(RS232B_TAG, rs232_port_device, write_txd))
+
+ MCFG_RS232_PORT_ADD(RS232A_TAG, default_rs232_devices, nullptr)
+ MCFG_RS232_RXD_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, rxa_w))
+ MCFG_RS232_DCD_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, dcda_w))
+ MCFG_RS232_CTS_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, ctsa_w))
+
+ MCFG_RS232_PORT_ADD(RS232B_TAG, default_rs232_devices, nullptr)
+ MCFG_RS232_RXD_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, rxb_w))
+ MCFG_RS232_DCD_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, dcdb_w))
+ MCFG_RS232_CTS_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, ctsb_w))
+MACHINE_CONFIG_END
+
+/* ROM definition */
+
+ROM_START( sun3_80 )
+ ROM_REGION32_BE( 0x20000, "user1", ROMREGION_ERASEFF )
+/*
+Sun 3/80 V1.0 Bootprom
+Sun 3/80 V2.2 Bootprom
+Sun 3/80 V2.3 Bootprom
+Sun 3/80 V2.9.2 Bootprom
+Sun 3/80 V3.0 Bootprom
+Sun 3/80 V3.0.2 Bootprom
+Sun 3/80 V3.0.3 Bootprom
+*/
+ ROM_SYSTEM_BIOS(0, "rev303", "Rev 3.0.3")
+ ROMX_LOAD( "sun3_80_v3.0.3", 0x0000, 0x20000, CRC(8f983115) SHA1(e4be2dcbb29fc5c60ed9d838ab241c634fdd24e5), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(1, "rev302", "Rev 3.0.2")
+ ROMX_LOAD( "sun3_80_v3.0.2", 0x0000, 0x20000, CRC(c09a3592) SHA1(830187dfe58e65289533717a797d2c42da86ac4e), ROM_BIOS(2))
+ ROM_SYSTEM_BIOS(2, "rev30", "Rev 3.0")
+ ROMX_LOAD( "sun3_80_v3.0", 0x0000, 0x20000, CRC(47e3b012) SHA1(1e045b6f542aaf7808d6567c28a9e734a8c5d815), ROM_BIOS(3))
+ ROM_SYSTEM_BIOS(3, "rev292", "Rev 2.9.2")
+ ROMX_LOAD( "sun3_80_v2.9.2", 0x0000, 0x20000, CRC(32bcf711) SHA1(7ecd4a0d0988c1d1d53fd79ac16c8456ed73ace1), ROM_BIOS(4))
+
+ // default NVRAM: includes valid settings for console on framebuffer, boot from SCSI disk, Ethernet ID, more
+ ROM_REGION( 0x800, TIMEKEEPER_TAG, 0 )
+ ROM_LOAD( "timekpr_380.bin", 0x000000, 0x000800, CRC(e76f1aae) SHA1(8e7c36e3928887a94a8133e8416ee4126c31edd7) )
+ROM_END
+
+ROM_START( sun3_460 )
+ ROM_REGION32_BE( 0x20000, "user1", ROMREGION_ERASEFF )
+/*
+Sun 3/460/480 V1.2.3 Bootprom
+Sun 3/460/480 V2.9.1 Bootprom (2 Files, one for odd and one for even addresses)
+Sun 3/460/480 V2.9.2 Bootprom
+Sun 3/460/480 V2.9.3 Bootprom
+Sun 3/460/480 V3.0 Bootprom (2 Files, one for odd and one for even addresses)
+*/
+ ROM_SYSTEM_BIOS(0, "rev30", "Rev 3.0")
+ ROMX_LOAD( "3_400_l.300", 0x00000, 0x10000, CRC(1312a04b) SHA1(6c3b67ba3567991897a48fe20f589ebbfcf0a35d), ROM_BIOS(1))
+ ROMX_LOAD( "3_400_h.300", 0x10000, 0x10000, CRC(8d688672) SHA1(a5593844ce6af6c4f7f39bb653dc8f964b73b095), ROM_BIOS(1))
+ ROM_SYSTEM_BIOS(1, "rev291", "Rev 2.9.1")
+ ROMX_LOAD( "sun3_460_v2.9.1_0", 0x00000, 0x10000, CRC(d62dbf09) SHA1(4a6b5fd7840b44fe93c9058a8973d8dd3c9f7d24), ROM_BIOS(2))
+ ROMX_LOAD( "sun3_460_v2.9.1_1", 0x10000, 0x10000, CRC(3b5a5942) SHA1(ed6250e3c07d7cb62d4dd517a8637c8d37e16dc5), ROM_BIOS(2))
+ROM_END
+
+/* Driver */
+
+/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */
+COMP( 198?, sun3_80, 0, 0, sun3_80, sun3x, driver_device, 0, "Sun Microsystems", "Sun 3/80", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) // Hydra
+COMP( 198?, sun3_460, 0, 0, sun3_460, sun3x, driver_device, 0, "Sun Microsystems", "Sun 3/460/470/480", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) // Pegasus
diff --git a/src/mame/includes/electron.h b/src/mame/includes/electron.h
index bfa6de0f5a7..a2c616c7954 100644
--- a/src/mame/includes/electron.h
+++ b/src/mame/includes/electron.h
@@ -16,6 +16,7 @@
#include "imagedev/cassette.h"
#include "sound/beep.h"
+#include "bus/electron/exp.h"
#include "bus/generic/slot.h"
#include "bus/generic/carts.h"
diff --git a/src/mame/includes/sorcerer.h b/src/mame/includes/sorcerer.h
index caead4ebb48..fcc64a275df 100644
--- a/src/mame/includes/sorcerer.h
+++ b/src/mame/includes/sorcerer.h
@@ -15,6 +15,7 @@
#include "sound/wave.h"
#include "machine/ay31015.h"
#include "bus/centronics/ctronics.h"
+#include "bus/rs232/rs232.h"
#include "machine/ram.h"
#include "imagedev/cassette.h"
#include "imagedev/snapquik.h"
@@ -25,8 +26,6 @@
#include "bus/generic/slot.h"
#include "bus/generic/carts.h"
-#define SORCERER_USING_RS232 0
-
#define ES_CPU_CLOCK (12638000 / 6)
#define ES_UART_CLOCK (ES_CPU_CLOCK / 440)
@@ -62,6 +61,7 @@ public:
, m_wave1(*this, WAVE_TAG)
, m_wave2(*this, WAVE2_TAG)
, m_uart(*this, "uart")
+ , m_rs232(*this, "rs232")
, m_centronics(*this, "centronics")
, m_cart(*this, "cartslot")
, m_ram(*this, RAM_TAG)
@@ -80,6 +80,7 @@ public:
DECLARE_MACHINE_START(sorcererd);
DECLARE_DRIVER_INIT(sorcerer);
TIMER_CALLBACK_MEMBER(sorcerer_cassette_tc);
+ TIMER_CALLBACK_MEMBER(sorcerer_serial_tc);
TIMER_CALLBACK_MEMBER(sorcerer_reset);
DECLARE_SNAPSHOT_LOAD_MEMBER( sorcerer );
DECLARE_QUICKLOAD_LOAD_MEMBER( sorcerer);
@@ -101,6 +102,7 @@ private:
required_device<wave_device> m_wave1;
required_device<wave_device> m_wave2;
required_device<ay31015_device> m_uart;
+ required_device<rs232_port_device> m_rs232;
required_device<centronics_device> m_centronics;
required_device<generic_slot_device> m_cart;
required_device<ram_device> m_ram;
diff --git a/src/mame/machine/dec_lk201.cpp b/src/mame/machine/dec_lk201.cpp
index a25facd0e67..d120e3ff46a 100644
--- a/src/mame/machine/dec_lk201.cpp
+++ b/src/mame/machine/dec_lk201.cpp
@@ -202,7 +202,7 @@ ADDRESS_MAP_END
//-------------------------------------------------
static MACHINE_CONFIG_FRAGMENT( lk201 )
- MCFG_CPU_ADD(LK201_CPU_TAG, M68HC05EG, 2000000) // actually 68HC05C4
+ MCFG_CPU_ADD(LK201_CPU_TAG, M68HC05EG, 4000000) // actually 68HC05C4, clock verified by Lord_Nightmare
MCFG_CPU_PROGRAM_MAP(lk201_map)
MCFG_SPEAKER_STANDARD_MONO("mono")
diff --git a/src/mame/machine/sorcerer.cpp b/src/mame/machine/sorcerer.cpp
index 7cf0db6bd8f..b64c86eae9a 100644
--- a/src/mame/machine/sorcerer.cpp
+++ b/src/mame/machine/sorcerer.cpp
@@ -9,24 +9,22 @@
#include "includes/sorcerer.h"
#include "machine/z80bin.h"
-#if SORCERER_USING_RS232
-
-/* The serial code (which was never connected to the outside) is disabled for now. */
/* timer for sorcerer serial chip transmit and receive */
TIMER_CALLBACK_MEMBER(sorcerer_state::sorcerer_serial_tc)
{
/* if rs232 is enabled, uart is connected to clock defined by bit6 of port fe.
- Transmit and receive clocks are connected to the same clock */
+ Transmit and receive clocks are connected to the same clock. */
/* if rs232 is disabled, receive clock is linked to cassette hardware */
- if (m_fe & 0x80)
+ if BIT(m_fe, 7)
{
/* connect to rs232 */
+ m_rs232->write_txd(m_uart->get_output_pin(AY31015_SO));
+ m_uart->set_input_pin(AY31015_SI, m_rs232->rxd_r());
}
}
-#endif
void sorcerer_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
@@ -34,9 +32,7 @@ void sorcerer_state::device_timer(emu_timer &timer, device_timer_id id, int para
switch (id)
{
case TIMER_SERIAL:
-#if SORCERER_USING_RS232
sorcerer_serial_tc(ptr, param);
-#endif
break;
case TIMER_CASSETTE:
sorcerer_cassette_tc(ptr, param);
@@ -181,9 +177,7 @@ WRITE8_MEMBER(sorcerer_state::sorcerer_fe_w)
if (!BIT(data, 7)) // cassette operations
{
-#if SORCERER_USING_RS232
m_serial_timer->adjust(attotime::zero);
-#endif
bool sound = BIT(m_iop_config->read(), 3);
@@ -206,13 +200,11 @@ WRITE8_MEMBER(sorcerer_state::sorcerer_fe_w)
else
m_cassette_timer->adjust(attotime::zero);
}
-#if SORCERER_USING_RS232
else
{
m_serial_timer->adjust(attotime::zero, 0, attotime::from_hz(ES_UART_CLOCK*4));
m_cassette_timer->adjust(attotime::zero);
}
-#endif
// bit 6 baud rate */
if (BIT(changed_bits, 6))
@@ -349,9 +341,7 @@ SNAPSHOT_LOAD_MEMBER( sorcerer_state,sorcerer)
void sorcerer_state::machine_start()
{
m_cassette_timer = timer_alloc(TIMER_CASSETTE);
-#if SORCERER_USING_RS232
m_serial_timer = timer_alloc(TIMER_SERIAL);
-#endif
UINT16 endmem = 0xbfff;
@@ -379,9 +369,7 @@ void sorcerer_state::machine_start()
MACHINE_START_MEMBER(sorcerer_state,sorcererd)
{
m_cassette_timer = timer_alloc(TIMER_CASSETTE);
-#if SORCERER_USING_RS232
m_serial_timer = timer_alloc(TIMER_SERIAL);
-#endif
UINT16 endmem = 0xbbff;
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index fcd4d5a61cc..b077637a273 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -28125,8 +28125,11 @@ vtenis2c // 2001.10 Virtua Tennis 2 / Power Smash 2 (Rev
vtennis // 1999.12 Virtua Tennis / Power Smash (cartridge)
vtennis2 // 2001.08.27 Virtua Tennis 2 / Power Smash 2 (GD-ROM)
vtennisg // 1999.?? Virtua Tennis / Power Smash (GD-ROM)
+wccf116 // 2003.?? World Club Champion Football Serie A 2001-2002 Ver. 2
+wccf1dup // 2002.?? World Club Champion Football Serie A 2001-2002 DIMM FIRM Ver.3.03
wccf212e // 2004.12 World Club Champion Football Serie A 2002-2003 Ver.2.12
wccf234j // 2004.12 World Club Champion Football Serie A 2002-2003 Ver.2.34
+wccf2chk // 2004.?? World Club Champion Football Serie A 2002-2003 Drive Checker
wccf310j // 2005.06 World Club Champion Football European Clubs 2004-2005
wccf322e // 2005.11 World Club Champion Football European Clubs 2004-2005 Ver.3.22
wccf331e // 2005.06 World Club Champion Football European Clubs 2004-2005 Ver.1.1
@@ -33969,12 +33972,14 @@ sun2_50 //
sun3_110 //
sun3_150 //
sun3_260 //
-sun3_460 //
sun3_50 //
sun3_60 //
-sun3_80 //
sun3_e //
+@source:sun3x.cpp
+sun3_80 //
+sun3_460 //
+
@source:sun4.cpp
sun_s10 //
sun_s20 //
diff --git a/src/mame/mess.flt b/src/mame/mess.flt
index 935d993d3ef..3cf1a404654 100644
--- a/src/mame/mess.flt
+++ b/src/mame/mess.flt
@@ -545,6 +545,7 @@ studio2.cpp
sun1.cpp
sun2.cpp
sun3.cpp
+sun3x.cpp
sun4.cpp
super6.cpp
super80.cpp
diff --git a/src/mame/video/powervr2.cpp b/src/mame/video/powervr2.cpp
index b4cade60de7..0c31ce84e22 100644
--- a/src/mame/video/powervr2.cpp
+++ b/src/mame/video/powervr2.cpp
@@ -1024,7 +1024,7 @@ WRITE32_MEMBER( powervr2_device::startrender_w )
}
// printf("ISP START %d %d\n",sanitycount,m_screen->vpos());
/* Fire ISP irq after a set amount of time TODO: timing of this */
- endofrender_timer_isp->adjust(state->m_maincpu->cycles_to_attotime(sanitycount*25));
+ endofrender_timer_isp->adjust(state->m_maincpu->cycles_to_attotime(sanitycount*25 + 500000)); // hacky end of render delay for Capcom games, otherwise they works at ~1/10 speed
break;
}
}
diff --git a/src/osd/modules/debugger/debugimgui.cpp b/src/osd/modules/debugger/debugimgui.cpp
index 76737012076..25f6938f4fa 100644
--- a/src/osd/modules/debugger/debugimgui.cpp
+++ b/src/osd/modules/debugger/debugimgui.cpp
@@ -261,47 +261,16 @@ void debug_imgui::handle_keys()
{
ImGuiIO& io = ImGui::GetIO();
ui_event event;
+ debug_area* focus_view = nullptr;
- // global keys
- if(m_machine->input().code_pressed_once(KEYCODE_F3))
- {
- if(m_machine->input().code_pressed(KEYCODE_LSHIFT))
- m_machine->schedule_hard_reset();
- else
- {
- m_machine->schedule_soft_reset();
- debug_cpu_get_visible_cpu(*m_machine)->debug()->go();
- }
- }
+ // find view that has focus (should only be one at a time)
+ for(std::vector<debug_area*>::iterator view_ptr = view_list.begin();view_ptr != view_list.end();++view_ptr)
+ if((*view_ptr)->has_focus)
+ focus_view = *view_ptr;
- if(m_machine->input().code_pressed_once(KEYCODE_F5))
- {
- debug_cpu_get_visible_cpu(*m_machine)->debug()->go();
- m_running = true;
- }
- if(m_machine->input().code_pressed_once(KEYCODE_F6))
- {
- debug_cpu_get_visible_cpu(*m_machine)->debug()->go_next_device();
- m_running = true;
- }
- if(m_machine->input().code_pressed_once(KEYCODE_F7))
- {
- debug_cpu_get_visible_cpu(*m_machine)->debug()->go_interrupt();
- m_running = true;
- }
- if(m_machine->input().code_pressed_once(KEYCODE_F8))
- debug_cpu_get_visible_cpu(*m_machine)->debug()->go_vblank();
- if(m_machine->input().code_pressed_once(KEYCODE_F9))
- debug_cpu_get_visible_cpu(*m_machine)->debug()->single_step_out();
- if(m_machine->input().code_pressed_once(KEYCODE_F10))
- debug_cpu_get_visible_cpu(*m_machine)->debug()->single_step_over();
- if(m_machine->input().code_pressed_once(KEYCODE_F11))
- debug_cpu_get_visible_cpu(*m_machine)->debug()->single_step();
- if(m_machine->input().code_pressed_once(KEYCODE_F12))
- {
- debug_cpu_get_visible_cpu(*m_machine)->debug()->go();
- m_hide = true;
- }
+ // check views in main views also (only the disassembler view accepts inputs)
+ if(view_main_disasm->has_focus)
+ focus_view = view_main_disasm;
if(m_machine->input().code_pressed(KEYCODE_LCONTROL))
io.KeyCtrl = true;
@@ -331,21 +300,64 @@ void debug_imgui::handle_keys()
{
case UI_EVENT_CHAR:
m_key_char = event.ch;
+ if(focus_view != nullptr)
+ focus_view->view->process_char(m_key_char);
return;
default:
break;
}
}
- if(ImGui::IsKeyPressed(ITEM_ID_D) && ImGui::IsKeyDown(ITEM_ID_LCONTROL))
+ // global keys
+ if(ImGui::IsKeyPressed(ITEM_ID_F3,false))
+ {
+ if(ImGui::IsKeyDown(ITEM_ID_LSHIFT))
+ m_machine->schedule_hard_reset();
+ else
+ {
+ m_machine->schedule_soft_reset();
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->go();
+ }
+ }
+
+ if(ImGui::IsKeyPressed(ITEM_ID_F5,false))
+ {
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->go();
+ m_running = true;
+ }
+ if(ImGui::IsKeyPressed(ITEM_ID_F6,false))
+ {
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->go_next_device();
+ m_running = true;
+ }
+ if(ImGui::IsKeyPressed(ITEM_ID_F7,false))
+ {
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->go_interrupt();
+ m_running = true;
+ }
+ if(ImGui::IsKeyPressed(ITEM_ID_F8,false))
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->go_vblank();
+ if(ImGui::IsKeyPressed(ITEM_ID_F9,false))
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->single_step_out();
+ if(ImGui::IsKeyPressed(ITEM_ID_F10,false))
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->single_step_over();
+ if(ImGui::IsKeyPressed(ITEM_ID_F11,false))
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->single_step();
+ if(ImGui::IsKeyPressed(ITEM_ID_F12,false))
+ {
+ debug_cpu_get_visible_cpu(*m_machine)->debug()->go();
+ m_hide = true;
+ }
+
+ if(ImGui::IsKeyPressed(ITEM_ID_D,false) && ImGui::IsKeyDown(ITEM_ID_LCONTROL))
add_disasm(++m_win_count);
- if(ImGui::IsKeyPressed(ITEM_ID_M) && ImGui::IsKeyDown(ITEM_ID_LCONTROL))
+ if(ImGui::IsKeyPressed(ITEM_ID_M,false) && ImGui::IsKeyDown(ITEM_ID_LCONTROL))
add_memory(++m_win_count);
- if(ImGui::IsKeyPressed(ITEM_ID_B) && ImGui::IsKeyDown(ITEM_ID_LCONTROL))
+ if(ImGui::IsKeyPressed(ITEM_ID_B,false) && ImGui::IsKeyDown(ITEM_ID_LCONTROL))
add_bpoints(++m_win_count);
- if(ImGui::IsKeyPressed(ITEM_ID_W) && ImGui::IsKeyDown(ITEM_ID_LCONTROL))
+ if(ImGui::IsKeyPressed(ITEM_ID_W,false) && ImGui::IsKeyDown(ITEM_ID_LCONTROL))
add_wpoints(++m_win_count);
- if(ImGui::IsKeyPressed(ITEM_ID_L) && ImGui::IsKeyDown(ITEM_ID_LCONTROL))
+ if(ImGui::IsKeyPressed(ITEM_ID_L,false) && ImGui::IsKeyDown(ITEM_ID_LCONTROL))
add_log(++m_win_count);
}
diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp
index a709a9a8c52..9ba54892f51 100644
--- a/src/osd/modules/lib/osdobj_common.cpp
+++ b/src/osd/modules/lib/osdobj_common.cpp
@@ -255,6 +255,7 @@ void osd_common_t::register_options()
REGISTER_MODULE(m_mod_man, OUTPUT_NONE);
REGISTER_MODULE(m_mod_man, OUTPUT_CONSOLE);
REGISTER_MODULE(m_mod_man, OUTPUT_NETWORK);
+ REGISTER_MODULE(m_mod_man, OUTPUT_WIN32);
// after initialization we know which modules are supported
@@ -643,6 +644,7 @@ void osd_common_t::init_subsystems()
m_midi = select_module_options<midi_module *>(options(), OSD_MIDI_PROVIDER);
m_output = select_module_options<output_module *>(options(), OSD_OUTPUT_PROVIDER);
+ m_output->set_machine(&machine());
machine().output().set_notifier(nullptr, output_notifier_callback, this);
m_mod_man.init(options());
diff --git a/src/osd/modules/output/output_module.h b/src/osd/modules/output/output_module.h
index 81fcaae2cce..f3461d3e1f6 100644
--- a/src/osd/modules/output/output_module.h
+++ b/src/osd/modules/output/output_module.h
@@ -20,11 +20,16 @@
class output_module
{
public:
- output_module() { }
+ output_module(): m_machine(nullptr) { }
virtual ~output_module() { }
virtual void notify(const char *outname, INT32 value) = 0;
+
+ void set_machine(running_machine *machine) { m_machine = machine; };
+ running_machine &machine() const { return *m_machine; }
+private:
+ running_machine *m_machine;
};
#endif /* OUTPUT_MODULE_H_ */
diff --git a/src/osd/modules/output/win32_output.cpp b/src/osd/modules/output/win32_output.cpp
new file mode 100644
index 00000000000..2525dfa2bb9
--- /dev/null
+++ b/src/osd/modules/output/win32_output.cpp
@@ -0,0 +1,340 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+//============================================================
+//
+// output.c - Win32 implementation of MAME output routines
+//
+//============================================================
+
+#include "output_module.h"
+#include "modules/osdmodule.h"
+#include "modules/lib/osdobj_common.h"
+
+#if defined(OSD_WINDOWS)
+
+// standard windows headers
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+// MAME headers
+#include "emu.h"
+#include "winmain.h"
+
+#include "winutil.h"
+#include "win32_output.h"
+
+
+//============================================================
+// CONSTANTS
+//============================================================
+
+// window styles
+#define WINDOW_STYLE WS_OVERLAPPEDWINDOW
+#define WINDOW_STYLE_EX 0
+
+
+
+//============================================================
+// TYPEDEFS
+//============================================================
+
+struct registered_client
+{
+ registered_client * next; // next client in the list
+ LPARAM id; // client-specified ID
+ HWND hwnd; // client HWND
+ running_machine * machine;
+};
+
+
+// message IDs
+static UINT om_mame_start;
+static UINT om_mame_stop;
+static UINT om_mame_update_state;
+static UINT om_mame_register_client;
+static UINT om_mame_unregister_client;
+static UINT om_mame_get_id_string;
+
+
+
+//============================================================
+// FUNCTION PROTOTYPES
+//============================================================
+
+static LRESULT CALLBACK output_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
+
+class output_win32 : public osd_module, public output_module
+{
+public:
+ output_win32()
+ : osd_module(OSD_OUTPUT_PROVIDER, "windows"), output_module()
+ {
+ }
+ virtual ~output_win32() { }
+
+ virtual int init(const osd_options &options) override;
+ virtual void exit() override;
+
+ // output_module
+
+ virtual void notify(const char *outname, INT32 value) override;
+
+ int create_window_class(void);
+ LRESULT register_client(HWND hwnd, LPARAM id);
+ LRESULT unregister_client(HWND hwnd, LPARAM id);
+ LRESULT send_id_string(HWND hwnd, LPARAM id);
+
+private:
+ // our HWND
+ HWND m_output_hwnd;
+
+ // client list
+ registered_client * m_clientlist;
+
+};
+
+
+//============================================================
+// output_init
+//============================================================
+
+int output_win32::init(const osd_options &options)
+{
+ int result;
+
+ // reset globals
+ m_clientlist = nullptr;
+
+ // create our window class
+ result = create_window_class();
+ assert(result == 0);
+ (void)result; // to silence gcc 4.6
+
+ // create a window
+ m_output_hwnd = CreateWindowEx(
+ WINDOW_STYLE_EX,
+ OUTPUT_WINDOW_CLASS,
+ OUTPUT_WINDOW_NAME,
+ WINDOW_STYLE,
+ 0, 0,
+ 1, 1,
+ nullptr,
+ nullptr,
+ GetModuleHandleUni(),
+ nullptr);
+ assert(m_output_hwnd != nullptr);
+
+ // set a pointer to the running machine
+ SetWindowLongPtr(m_output_hwnd, GWLP_USERDATA, (LONG_PTR)this);
+
+ // allocate message ids
+ om_mame_start = RegisterWindowMessage(OM_MAME_START);
+ assert(om_mame_start != 0);
+ om_mame_stop = RegisterWindowMessage(OM_MAME_STOP);
+ assert(om_mame_stop != 0);
+ om_mame_update_state = RegisterWindowMessage(OM_MAME_UPDATE_STATE);
+ assert(om_mame_update_state != 0);
+
+ om_mame_register_client = RegisterWindowMessage(OM_MAME_REGISTER_CLIENT);
+ assert(om_mame_register_client != 0);
+ om_mame_unregister_client = RegisterWindowMessage(OM_MAME_UNREGISTER_CLIENT);
+ assert(om_mame_unregister_client != 0);
+ om_mame_get_id_string = RegisterWindowMessage(OM_MAME_GET_ID_STRING);
+ assert(om_mame_get_id_string != 0);
+
+ // broadcast a startup message
+ PostMessage(HWND_BROADCAST, om_mame_start, (WPARAM)m_output_hwnd, 0);
+
+ return 0;
+}
+
+
+//============================================================
+// output_exit
+//============================================================
+
+void output_win32::exit()
+{
+ // free all the clients
+ while (m_clientlist != nullptr)
+ {
+ registered_client *temp = m_clientlist;
+ m_clientlist = temp->next;
+ global_free(temp);
+ }
+
+ // broadcast a shutdown message
+ PostMessage(HWND_BROADCAST, om_mame_stop, (WPARAM)m_output_hwnd, 0);
+}
+
+
+//============================================================
+// create_window_class
+//============================================================
+
+int output_win32::create_window_class(void)
+{
+ static UINT8 classes_created = FALSE;
+
+ /* only do this once */
+ if (!classes_created)
+ {
+ WNDCLASS wc = { 0 };
+
+ // initialize the description of the window class
+ wc.lpszClassName = OUTPUT_WINDOW_CLASS;
+ wc.hInstance = GetModuleHandleUni();
+ wc.lpfnWndProc = output_window_proc;
+
+ UnregisterClass(wc.lpszClassName, wc.hInstance);
+
+ // register the class; fail if we can't
+ if (!RegisterClass(&wc))
+ return 1;
+ classes_created = TRUE;
+ }
+
+ return 0;
+}
+
+
+//============================================================
+// output_window_proc
+//============================================================
+
+static LRESULT CALLBACK output_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
+{
+ LONG_PTR ptr = GetWindowLongPtr(wnd, GWLP_USERDATA);
+ output_win32 &output = *(output_win32 *)ptr;
+
+ // register a new client
+ if (message == om_mame_register_client)
+ return output.register_client((HWND)wparam, lparam);
+
+ // unregister a client
+ else if (message == om_mame_unregister_client)
+ return output.unregister_client((HWND)wparam, lparam);
+
+ // get a string for an ID
+ else if (message == om_mame_get_id_string)
+ return output.send_id_string((HWND)wparam, lparam);
+
+ else
+ return DefWindowProc(wnd, message, wparam, lparam);
+}
+
+
+//============================================================
+// register_client
+//============================================================
+
+LRESULT output_win32::register_client(HWND hwnd, LPARAM id)
+{
+ registered_client **client;
+
+ // find the end of the list; if we find ourself already registered,
+ // return 1
+ for (client = &m_clientlist; *client != nullptr; client = &(*client)->next)
+ if ((*client)->id == id)
+ {
+ (*client)->hwnd = hwnd;
+ machine().output().notify_all(this);
+ return 1;
+ }
+
+ // add us to the end
+ *client = global_alloc(registered_client);
+ (*client)->next = nullptr;
+ (*client)->id = id;
+ (*client)->hwnd = hwnd;
+ (*client)->machine = &machine();
+
+ // request a notification for all outputs
+ machine().output().notify_all(this);
+ return 0;
+}
+
+
+//============================================================
+// unregister_client
+//============================================================
+
+LRESULT output_win32::unregister_client(HWND hwnd, LPARAM id)
+{
+ registered_client **client;
+ int found = FALSE;
+
+ // find any matching IDs in the list and remove them
+ for (client = &m_clientlist; *client != nullptr; client = &(*client)->next)
+ if ((*client)->id == id)
+ {
+ registered_client *temp = *client;
+ *client = (*client)->next;
+ global_free(temp);
+ found = TRUE;
+ break;
+ }
+
+ // return an error if not found
+ return found ? 0 : 1;
+}
+
+
+//============================================================
+// send_id_string
+//============================================================
+
+LRESULT output_win32::send_id_string(HWND hwnd, LPARAM id)
+{
+ COPYDATASTRUCT copydata;
+ const char *name;
+ int datalen;
+
+ // id 0 is the name of the game
+ if (id == 0)
+ name = machine().system().name;
+ else
+ name = machine().output().id_to_name(id);
+
+ // a NULL name is an empty string
+ if (name == nullptr)
+ name = "";
+
+ // allocate memory for the message
+ datalen = sizeof(copydata_id_string) + strlen(name) + 1;
+ dynamic_buffer buffer(datalen);
+ copydata_id_string *temp = (copydata_id_string *)&buffer[0];
+ temp->id = id;
+ strcpy(temp->string, name);
+
+ // reply by using SendMessage with WM_COPYDATA
+ copydata.dwData = COPYDATA_MESSAGE_ID_STRING;
+ copydata.cbData = datalen;
+ copydata.lpData = temp;
+ SendMessage(hwnd, WM_COPYDATA, (WPARAM)m_output_hwnd, (LPARAM)&copydata);
+
+ return 0;
+}
+
+
+//============================================================
+// notifier_callback
+//============================================================
+
+void output_win32::notify(const char *outname, INT32 value)
+{
+ registered_client *client;
+ // loop over clients and notify them
+ for (client = m_clientlist; client != nullptr; client = client->next)
+ {
+ PostMessage(client->hwnd, om_mame_update_state, client->machine->output().name_to_id(outname), value);
+ }
+}
+
+
+
+#else
+ MODULE_NOT_SUPPORTED(output_win32, OSD_OUTPUT_PROVIDER, "windows")
+#endif
+
+MODULE_DEFINITION(OUTPUT_WIN32, output_win32)
diff --git a/src/osd/modules/output/win32_output.h b/src/osd/modules/output/win32_output.h
new file mode 100644
index 00000000000..9d71332b44b
--- /dev/null
+++ b/src/osd/modules/output/win32_output.h
@@ -0,0 +1,86 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+//============================================================
+//
+// output.h - Win32 implementation of MAME output routines
+//
+//============================================================
+
+#ifndef __WINDOWS_OUTPUT_H__
+#define __WINDOWS_OUTPUT_H__
+
+
+//============================================================
+// CONSTANTS
+//============================================================
+
+// window parameters
+#define OUTPUT_WINDOW_CLASS TEXT("MAMEOutput")
+#define OUTPUT_WINDOW_NAME TEXT("MAMEOutput")
+
+//
+// These messages are sent by MAME:
+//
+
+// OM_MAME_START: broadcast when MAME initializes
+// WPARAM = HWND of MAME's output window
+// LPARAM = unused
+#define OM_MAME_START TEXT("MAMEOutputStart")
+
+// OM_MAME_STOP: broadcast when MAME shuts down
+// WPARAM = HWND of MAME's output window
+// LPARAM = unused
+#define OM_MAME_STOP TEXT("MAMEOutputStop")
+
+// OM_MAME_UPDATE_STATE: sent to registered clients when the state
+// of an output changes
+// WPARAM = ID of the output
+// LPARAM = new value for the output
+#define OM_MAME_UPDATE_STATE TEXT("MAMEOutputUpdateState")
+
+
+//
+// These messages are sent by external clients to MAME:
+//
+
+// OM_MAME_REGISTER_CLIENT: sent to MAME to register a client
+// WPARAM = HWND of client's listener window
+// LPARAM = client-specified ID (must be unique)
+#define OM_MAME_REGISTER_CLIENT TEXT("MAMEOutputRegister")
+
+// OM_MAME_UNREGISTER_CLIENT: sent to MAME to unregister a client
+// WPARAM = HWND of client's listener window
+// LPARAM = client-specified ID (must match registration)
+#define OM_MAME_UNREGISTER_CLIENT TEXT("MAMEOutputUnregister")
+
+// OM_MAME_GET_ID_STRING: requests the string associated with a
+// given ID. ID=0 is always the name of the game. Other IDs are
+// only discoverable from a OM_MAME_UPDATE_STATE message. The
+// result will be sent back as a WM_COPYDATA message with MAME's
+// output window as the sender, dwData = the ID of the string,
+// and lpData pointing to a NULL-terminated string.
+// WPARAM = HWND of client's listener window
+// LPARAM = ID you wish to know about
+#define OM_MAME_GET_ID_STRING TEXT("MAMEOutputGetIDString")
+
+
+//
+// These constants are used to identify WM_COPYDATA messages
+// coming from MAME:
+//
+
+#define COPYDATA_MESSAGE_ID_STRING 1
+
+
+
+//============================================================
+// TYPE DEFINITIONS
+//============================================================
+
+struct copydata_id_string
+{
+ UINT32 id; // ID that was requested
+ char string[1]; // string array containing the data
+};
+
+#endif /* __WINDOWS_OUTPUT_H__ */
diff --git a/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_distortion.sc b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_distortion.sc
index d7e1acf8494..be1f6ef43f6 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_distortion.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/hlsl/fs_distortion.sc
@@ -97,19 +97,18 @@ float GetSpotAddend(vec2 coord, float amount)
return saturate(SigmoidSpot);
}
-float GetRoundCornerFactor(vec2 coord, float radiusAmount, float smoothAmount)
+float GetRoundCornerFactor(vec2 coord, vec2 bounds, float radiusAmount, float smoothAmount)
{
// reduce smooth amount down to radius amount
smoothAmount = min(smoothAmount, radiusAmount);
- vec2 quadDims = (u_swap_xy.x > 0.0) ? u_quad_dims.yx : u_quad_dims.xy;
-
- float range = min(quadDims.x, quadDims.y) * 0.5;
- float radius = range * max(radiusAmount, 0.0025);
- float smooth_val = 1.0 / (range * max(smoothAmount, 0.0025));
+ float range = min(bounds.x, bounds.y);
+ float amountMinimum = range > 0.0f ? 1.0f / range : 0.0f;
+ float radius = range * max(radiusAmount, amountMinimum);
+ float smooth_val = 1.0f / (range * max(smoothAmount, amountMinimum * 3.0f));
// compute box
- float box = roundBox(quadDims * (coord * 2.0f), quadDims, radius);
+ float box = roundBox(bounds * (coord * 2.0f), bounds, radius);
// apply smooth
box *= smooth_val;
@@ -206,8 +205,11 @@ void main()
// Round Corners Simulation
vec2 RoundCornerCoord = CornerCoordCentered;
+ vec2 RoundCornerBounds = (u_swap_xy.x > 0.0)
+ ? u_quad_dims.yx
+ : u_quad_dims.xy;
- float roundCornerFactor = GetRoundCornerFactor(RoundCornerCoord, u_round_corner.x, u_smooth_border.x);
+ float roundCornerFactor = GetRoundCornerFactor(RoundCornerCoord, RoundCornerBounds, u_round_corner.x * 0.5f, u_smooth_border.x * 0.5f);
BaseColor.rgb *= roundCornerFactor;
gl_FragColor = BaseColor;
diff --git a/src/osd/modules/render/d3d/d3dhlsl.cpp b/src/osd/modules/render/d3d/d3dhlsl.cpp
index 2864d740bb7..5c1bef296cf 100644
--- a/src/osd/modules/render/d3d/d3dhlsl.cpp
+++ b/src/osd/modules/render/d3d/d3dhlsl.cpp
@@ -722,6 +722,7 @@ void shaders::init(d3d_base *d3dintf, running_machine *machine, renderer_d3d9 *r
options->yiq_q = winoptions.screen_yiq_q();
options->yiq_scan_time = winoptions.screen_yiq_scan_time();
options->yiq_phase_count = winoptions.screen_yiq_phase_count();
+ options->vector_beam_smooth = winoptions.screen_vector_beam_smooth();
options->vector_length_scale = winoptions.screen_vector_length_scale();
options->vector_length_ratio = winoptions.screen_vector_length_ratio();
options->bloom_blend_mode = winoptions.screen_bloom_blend_mode();
@@ -1524,6 +1525,7 @@ int shaders::vector_pass(d3d_render_target *rt, int source_index, poly_info *pol
// curr_effect->set_float("TimeScale", options->vector_time_scale);
curr_effect->set_float("LengthRatio", options->vector_length_ratio);
curr_effect->set_float("LengthScale", options->vector_length_scale);
+ curr_effect->set_float("BeamSmooth", options->vector_beam_smooth);
blit(rt->target_surface[next_index], true, poly->get_type(), vertnum, poly->get_count());
@@ -2285,7 +2287,8 @@ hlsl_options shaders::last_options = { false };
enum slider_option
{
- SLIDER_VECTOR_ATT_MAX = 0,
+ SLIDER_VECTOR_BEAM_SMOOTH = 0,
+ SLIDER_VECTOR_ATT_MAX,
SLIDER_VECTOR_ATT_LEN_MIN,
SLIDER_SHADOW_MASK_TILE_MODE,
SLIDER_SHADOW_MASK_ALPHA,
@@ -2362,6 +2365,7 @@ enum slider_screen_type
slider_desc shaders::s_sliders[] =
{
+ { "Vector Beam Smooth Amount", 0, 0, 100, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_VECTOR, SLIDER_VECTOR_BEAM_SMOOTH, 0.01f, "%1.2f", {} },
{ "Vector Attenuation Maximum", 0, 50, 100, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_VECTOR, SLIDER_VECTOR_ATT_MAX, 0.01f, "%1.2f", {} },
{ "Vector Attenuation Length Minimum", 1, 500, 1000, 1, SLIDER_FLOAT, SLIDER_SCREEN_TYPE_VECTOR, SLIDER_VECTOR_ATT_LEN_MIN, 0.001f, "%1.3f", {} },
{ "Shadow Mask Tile Mode", 0, 0, 1, 1, SLIDER_INT_ENUM, SLIDER_SCREEN_TYPE_ANY, SLIDER_SHADOW_MASK_TILE_MODE, 0, "%s", { "Screen", "Source" } },
@@ -2433,6 +2437,7 @@ void *shaders::get_slider_option(int id, int index)
{
switch (id)
{
+ case SLIDER_VECTOR_BEAM_SMOOTH: return &(options->vector_beam_smooth);
case SLIDER_VECTOR_ATT_MAX: return &(options->vector_length_scale);
case SLIDER_VECTOR_ATT_LEN_MIN: return &(options->vector_length_ratio);
case SLIDER_SHADOW_MASK_TILE_MODE: return &(options->shadow_mask_tile_mode);
diff --git a/src/osd/modules/render/d3d/d3dhlsl.h b/src/osd/modules/render/d3d/d3dhlsl.h
index abf1e48a549..6f6e31f1933 100644
--- a/src/osd/modules/render/d3d/d3dhlsl.h
+++ b/src/osd/modules/render/d3d/d3dhlsl.h
@@ -245,6 +245,7 @@ struct hlsl_options
int yiq_phase_count;
// Vectors
+ float vector_beam_smooth;
float vector_length_scale;
float vector_length_ratio;
diff --git a/src/osd/modules/render/drawbgfx.cpp b/src/osd/modules/render/drawbgfx.cpp
index e0966fdbd62..dec0110157a 100644
--- a/src/osd/modules/render/drawbgfx.cpp
+++ b/src/osd/modules/render/drawbgfx.cpp
@@ -624,6 +624,13 @@ void renderer_bgfx::put_line(float x0, float y0, float x1, float y1, float r, UI
dy *= d;
}
+ // create diamond shape for points
+ else
+ {
+ // set distance to unit vector length (1,1)
+ dx = dy = 0.70710678f;
+ }
+
float nx = dy;
float ny = -dx;
float verts[4 * 3];
diff --git a/src/osd/modules/render/drawd3d.cpp b/src/osd/modules/render/drawd3d.cpp
index 4490a8c327e..44dd1b10600 100644
--- a/src/osd/modules/render/drawd3d.cpp
+++ b/src/osd/modules/render/drawd3d.cpp
@@ -42,33 +42,6 @@ enum
//============================================================
-// MACROS
-//============================================================
-
-#define FSWAP(var1, var2) do { float temp = var1; var1 = var2; var2 = temp; } while (0)
-
-
-//============================================================
-// GLOBALS
-//============================================================
-
-static const line_aa_step line_aa_1step[] =
-{
- { 0.00f, 0.00f, 1.00f },
- { 0 }
-};
-
-static const line_aa_step line_aa_4step[] =
-{
- { -0.25f, 0.00f, 0.25f },
- { 0.25f, 0.00f, 0.25f },
- { 0.00f, -0.25f, 0.25f },
- { 0.00f, 0.25f, 0.25f },
- { 0 }
-};
-
-
-//============================================================
// INLINES
//============================================================
@@ -1388,13 +1361,11 @@ void renderer_d3d9::batch_vectors(int vector_count)
{
auto win = assert_window();
- windows_options &options = downcast<windows_options &>(win->machine().options());
-
float quad_width = 0.0f;
float quad_height = 0.0f;
- int vertex_count = vector_count * (options.antialias() ? 24 : 6);
- int triangle_count = vector_count * (options.antialias() ? 8 : 2);
+ int vertex_count = vector_count * 6;
+ int triangle_count = vector_count * 2;
m_vectorbatch = mesh_alloc(vertex_count);
m_batchindex = 0;
@@ -1499,71 +1470,103 @@ void renderer_d3d9::batch_vectors(int vector_count)
void renderer_d3d9::batch_vector(const render_primitive &prim)
{
+ // get a pointer to the vertex buffer
+ if (m_vectorbatch == nullptr)
+ {
+ return;
+ }
+
// compute the effective width based on the direction of the line
float effwidth = prim.width;
- if (effwidth < 0.5f)
+ if (effwidth < 2.0f)
{
- effwidth = 0.5f;
+ effwidth = 2.0f;
}
// determine the bounds of a quad to draw this line
render_bounds b0, b1;
render_line_to_quad(&prim.bounds, effwidth, effwidth, &b0, &b1);
- float dx = b1.x1 - b0.x1;
- float dy = b1.y1 - b0.y1;
- float line_length = sqrtf(dx * dx + dy * dy);
+ float lx = b1.x1 - b0.x1;
+ float ly = b1.y1 - b0.y1;
+ float wx = b1.x1 - b1.x0;
+ float wy = b1.y1 - b1.y0;
+ float line_length = sqrtf(lx * lx + ly * ly);
+ float line_width = sqrtf(wx * wx + wy * wy);
+
+ m_vectorbatch[m_batchindex + 0].x = b0.x0;
+ m_vectorbatch[m_batchindex + 0].y = b0.y0;
+ m_vectorbatch[m_batchindex + 1].x = b0.x1;
+ m_vectorbatch[m_batchindex + 1].y = b0.y1;
+ m_vectorbatch[m_batchindex + 2].x = b1.x0;
+ m_vectorbatch[m_batchindex + 2].y = b1.y0;
+
+ m_vectorbatch[m_batchindex + 3].x = b0.x1;
+ m_vectorbatch[m_batchindex + 3].y = b0.y1;
+ m_vectorbatch[m_batchindex + 4].x = b1.x0;
+ m_vectorbatch[m_batchindex + 4].y = b1.y0;
+ m_vectorbatch[m_batchindex + 5].x = b1.x1;
+ m_vectorbatch[m_batchindex + 5].y = b1.y1;
- // iterate over AA steps
- for (const line_aa_step *step = PRIMFLAG_GET_ANTIALIAS(prim.flags) ? line_aa_4step : line_aa_1step;
- step->weight != 0; step++)
+ if (m_shaders->enabled())
{
- // get a pointer to the vertex buffer
- if (m_vectorbatch == nullptr)
- {
- return;
- }
-
- m_vectorbatch[m_batchindex + 0].x = b0.x0 + step->xoffs;
- m_vectorbatch[m_batchindex + 0].y = b0.y0 + step->yoffs;
- m_vectorbatch[m_batchindex + 1].x = b0.x1 + step->xoffs;
- m_vectorbatch[m_batchindex + 1].y = b0.y1 + step->yoffs;
- m_vectorbatch[m_batchindex + 2].x = b1.x0 + step->xoffs;
- m_vectorbatch[m_batchindex + 2].y = b1.y0 + step->yoffs;
-
- m_vectorbatch[m_batchindex + 3].x = b0.x1 + step->xoffs;
- m_vectorbatch[m_batchindex + 3].y = b0.y1 + step->yoffs;
- m_vectorbatch[m_batchindex + 4].x = b1.x0 + step->xoffs;
- m_vectorbatch[m_batchindex + 4].y = b1.y0 + step->yoffs;
- m_vectorbatch[m_batchindex + 5].x = b1.x1 + step->xoffs;
- m_vectorbatch[m_batchindex + 5].y = b1.y1 + step->yoffs;
+ // procedural generated texture
+ m_vectorbatch[m_batchindex + 0].u0 = 0.0f;
+ m_vectorbatch[m_batchindex + 0].v0 = 0.0f;
+ m_vectorbatch[m_batchindex + 1].u0 = 0.0f;
+ m_vectorbatch[m_batchindex + 1].v0 = 1.0f;
+ m_vectorbatch[m_batchindex + 2].u0 = 1.0f;
+ m_vectorbatch[m_batchindex + 2].v0 = 0.0f;
+
+ m_vectorbatch[m_batchindex + 3].u0 = 0.0f;
+ m_vectorbatch[m_batchindex + 3].v0 = 1.0f;
+ m_vectorbatch[m_batchindex + 4].u0 = 1.0f;
+ m_vectorbatch[m_batchindex + 4].v0 = 0.0f;
+ m_vectorbatch[m_batchindex + 5].u0 = 1.0f;
+ m_vectorbatch[m_batchindex + 5].v0 = 1.0f;
+ }
+ else
+ {
+ vec2f& start = get_default_texture()->get_uvstart();
+ vec2f& stop = get_default_texture()->get_uvstop();
- // determine the color of the line
- INT32 r = (INT32)(prim.color.r * step->weight * 255.0f);
- INT32 g = (INT32)(prim.color.g * step->weight * 255.0f);
- INT32 b = (INT32)(prim.color.b * step->weight * 255.0f);
- INT32 a = (INT32)(prim.color.a * 255.0f);
- DWORD color = D3DCOLOR_ARGB(a, r, g, b);
+ m_vectorbatch[m_batchindex + 0].u0 = start.c.x;
+ m_vectorbatch[m_batchindex + 0].v0 = start.c.y;
+ m_vectorbatch[m_batchindex + 1].u0 = start.c.x;
+ m_vectorbatch[m_batchindex + 1].v0 = stop.c.y;
+ m_vectorbatch[m_batchindex + 2].u0 = stop.c.x;
+ m_vectorbatch[m_batchindex + 2].v0 = start.c.y;
- // set the color, Z parameters to standard values
- for (int i = 0; i < 6; i++)
- {
- m_vectorbatch[m_batchindex + i].x -= 0.5f;
- m_vectorbatch[m_batchindex + i].y -= 0.5f;
- m_vectorbatch[m_batchindex + i].z = 0.0f;
- m_vectorbatch[m_batchindex + i].rhw = 1.0f;
- m_vectorbatch[m_batchindex + i].color = color;
+ m_vectorbatch[m_batchindex + 3].u0 = start.c.x;
+ m_vectorbatch[m_batchindex + 3].v0 = stop.c.y;
+ m_vectorbatch[m_batchindex + 4].u0 = stop.c.x;
+ m_vectorbatch[m_batchindex + 4].v0 = start.c.y;
+ m_vectorbatch[m_batchindex + 5].u0 = stop.c.x;
+ m_vectorbatch[m_batchindex + 5].v0 = stop.c.y;
+ }
- // no texture mapping
- m_vectorbatch[m_batchindex + i].u0 = 0.0f;
- m_vectorbatch[m_batchindex + i].v0 = 0.0f;
+ // determine the color of the line
+ INT32 r = (INT32)(prim.color.r * 255.0f);
+ INT32 g = (INT32)(prim.color.g * 255.0f);
+ INT32 b = (INT32)(prim.color.b * 255.0f);
+ INT32 a = (INT32)(prim.color.a * 255.0f);
+ DWORD color = D3DCOLOR_ARGB(a, r, g, b);
- // line length
- m_vectorbatch[m_batchindex + i].u1 = line_length;
- }
+ // set the color, Z parameters to standard values
+ for (int i = 0; i < 6; i++)
+ {
+ m_vectorbatch[m_batchindex + i].x -= 0.5f;
+ m_vectorbatch[m_batchindex + i].y -= 0.5f;
+ m_vectorbatch[m_batchindex + i].z = 0.0f;
+ m_vectorbatch[m_batchindex + i].rhw = 1.0f;
+ m_vectorbatch[m_batchindex + i].color = color;
- m_batchindex += 6;
+ // vector length/width
+ m_vectorbatch[m_batchindex + i].u1 = line_length;
+ m_vectorbatch[m_batchindex + i].v1 = line_width;
}
+
+ m_batchindex += 6;
}
@@ -1573,38 +1576,45 @@ void renderer_d3d9::batch_vector(const render_primitive &prim)
void renderer_d3d9::draw_line(const render_primitive &prim)
{
+ // get a pointer to the vertex buffer
+ vertex *vertex = mesh_alloc(4);
+ if (vertex == nullptr)
+ {
+ return;
+ }
+
// compute the effective width based on the direction of the line
float effwidth = prim.width;
- if (effwidth < 0.5f)
+ if (effwidth < 1.0f)
{
- effwidth = 0.5f;
+ effwidth = 1.0f;
}
// determine the bounds of a quad to draw this line
render_bounds b0, b1;
render_line_to_quad(&prim.bounds, effwidth, 0.0f, &b0, &b1);
- // get a pointer to the vertex buffer
- vertex *vertex = mesh_alloc(4);
- if (vertex == nullptr)
- return;
-
- // rotate the unit vector by 135 degrees and add to point 0
vertex[0].x = b0.x0;
vertex[0].y = b0.y0;
-
- // rotate the unit vector by -135 degrees and add to point 0
vertex[1].x = b0.x1;
vertex[1].y = b0.y1;
-
- // rotate the unit vector by 45 degrees and add to point 1
vertex[2].x = b1.x0;
vertex[2].y = b1.y0;
-
- // rotate the unit vector by -45 degrees and add to point 1
vertex[3].x = b1.x1;
vertex[3].y = b1.y1;
+ vec2f& start = get_default_texture()->get_uvstart();
+ vec2f& stop = get_default_texture()->get_uvstop();
+
+ vertex[0].u0 = start.c.x;
+ vertex[0].v0 = start.c.y;
+ vertex[2].u0 = stop.c.x;
+ vertex[2].v0 = start.c.y;
+ vertex[1].u0 = start.c.x;
+ vertex[1].v0 = stop.c.y;
+ vertex[3].u0 = stop.c.x;
+ vertex[3].v0 = stop.c.y;
+
// determine the color of the line
INT32 r = (INT32)(prim.color.r * 255.0f);
INT32 g = (INT32)(prim.color.g * 255.0f);
@@ -1618,10 +1628,6 @@ void renderer_d3d9::draw_line(const render_primitive &prim)
vertex[i].z = 0.0f;
vertex[i].rhw = 1.0f;
vertex[i].color = color;
-
- // no texture mapping
- vertex[i].u0 = 0.0f;
- vertex[i].v0 = 0.0f;
}
// now add a polygon entry
diff --git a/src/osd/modules/render/drawogl.cpp b/src/osd/modules/render/drawogl.cpp
index 57173e8e2a4..77acf017790 100644
--- a/src/osd/modules/render/drawogl.cpp
+++ b/src/osd/modules/render/drawogl.cpp
@@ -1085,22 +1085,14 @@ int renderer_ogl::draw(const int update)
// we're doing nothing 3d, so the Z-buffer is currently not interesting
glDisable(GL_DEPTH_TEST);
- if (win->machine().options().antialias())
- {
- // enable antialiasing for lines
- glEnable(GL_LINE_SMOOTH);
- // enable antialiasing for points
- glEnable(GL_POINT_SMOOTH);
-
- // prefer quality to speed
- glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
- glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
- }
- else
- {
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_POINT_SMOOTH);
- }
+ // enable antialiasing for lines
+ glEnable(GL_LINE_SMOOTH);
+ // enable antialiasing for points
+ glEnable(GL_POINT_SMOOTH);
+
+ // prefer quality to speed
+ glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
+ glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
// enable blending
glEnable(GL_BLEND);
diff --git a/src/osd/windows/ledutil.cpp b/src/osd/windows/ledutil.cpp
new file mode 100644
index 00000000000..60427b4ef8e
--- /dev/null
+++ b/src/osd/windows/ledutil.cpp
@@ -0,0 +1,709 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles,Paul Priest
+//============================================================
+//
+// ledutil.c - Win32 example code that tracks changing
+// outputs and updates the keyboard LEDs in response
+//
+//============================================================
+//
+// This is sample code. To use it as a starting point, you
+// should do the following:
+//
+// 1. Change the CLIENT_ID define to something unique.
+//
+// 2. Change the WINDOW_CLASS and WINDOW_NAME defines to
+// something unique.
+//
+// 3. Delete all the code from the >8 snip 8< comment and
+// downward.
+//
+// 4. Implement the following functions:
+//
+// output_startup - called at app init time
+// output_shutdown - called before the app exits
+// output_mame_start - called when MAME starts
+// output_mame_stop - called when MAME exits
+// output_set_state - called whenever state changes
+//
+//============================================================
+
+// standard windows headers
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <winioctl.h>
+
+// standard C headers
+#include <conio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// MAME output header file
+typedef int running_machine;
+#include "osdcomm.h"
+#include "modules/output/win32_output.h"
+
+
+//============================================================
+// DEBUGGING
+//============================================================
+
+// note you need to compile as a console app to have any of
+// these printfs show up
+#define DEBUG_VERSION 0
+
+#if DEBUG_VERSION
+#define DEBUG_PRINTF(x) printf x
+#else
+#define DEBUG_PRINTF(x)
+#endif
+
+
+//============================================================
+// CONSTANTS
+//============================================================
+
+// unique client ID
+#define CLIENT_ID (('M' << 24) | ('L' << 16) | ('E' << 8) | ('D' << 0))
+
+// LED methods
+#define LED_METHOD_PS2 0
+#define LED_METHOD_USB 1
+
+// window parameters
+#define WINDOW_CLASS TEXT("LEDSample")
+#define WINDOW_NAME TEXT("LEDSample")
+
+// window styles
+#define WINDOW_STYLE WS_OVERLAPPEDWINDOW
+#define WINDOW_STYLE_EX 0
+
+// Define the keyboard indicators.
+// (Definitions borrowed from ntddkbd.h)
+
+#define IOCTL_KEYBOARD_SET_INDICATORS CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0002, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_KEYBOARD_QUERY_TYPEMATIC CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0008, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_KEYBOARD_QUERY_INDICATORS CTL_CODE(FILE_DEVICE_KEYBOARD, 0x0010, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define KEYBOARD_SCROLL_LOCK_ON 1
+#define KEYBOARD_NUM_LOCK_ON 2
+#define KEYBOARD_CAPS_LOCK_ON 4
+
+
+
+//============================================================
+// TYPE DEFINITIONS
+//============================================================
+
+struct KEYBOARD_INDICATOR_PARAMETERS
+{
+ USHORT UnitId; // Unit identifier.
+ USHORT LedFlags; // LED indicator state.
+};
+
+
+struct id_map_entry
+{
+ id_map_entry * next;
+ const char * name;
+ WPARAM id;
+};
+
+
+
+//============================================================
+// GLOBAL VARIABLES
+//============================================================
+
+static int ledmethod;
+static int original_state;
+static int current_state;
+static int pause_state;
+static HANDLE hKbdDev;
+
+static HWND mame_target;
+static HWND listener_hwnd;
+
+static id_map_entry * idmaplist;
+
+// message IDs
+static UINT om_mame_start;
+static UINT om_mame_stop;
+static UINT om_mame_update_state;
+static UINT om_mame_register_client;
+static UINT om_mame_unregister_client;
+static UINT om_mame_get_id_string;
+
+
+
+//============================================================
+// FUNCTION PROTOTYPES
+//============================================================
+
+static int create_window_class(void);
+static LRESULT CALLBACK listener_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
+static LRESULT handle_mame_start(WPARAM wparam, LPARAM lparam);
+static LRESULT handle_mame_stop(WPARAM wparam, LPARAM lparam);
+static LRESULT handle_copydata(WPARAM wparam, LPARAM lparam);
+static void reset_id_to_outname_cache(void);
+static const char *map_id_to_outname(WPARAM id);
+static LRESULT handle_update_state(WPARAM wparam, LPARAM lparam);
+
+// these functions provide the meat
+static void output_startup(const char *commandline);
+static void output_mame_start(void);
+static void output_set_state(const char *name, INT32 state);
+static void output_mame_stop(void);
+static void output_shutdown(void);
+
+static int led_get_state(void);
+static void led_set_state(int state);
+
+
+//============================================================
+// main
+//============================================================
+
+int main(int argc, char *argv[])
+{
+ const char *arg = (argc > 1) ? argv[1] : "";
+ int exitcode = 1;
+ HWND otherwnd;
+ MSG message;
+ int result;
+
+ // see if there is another instance of us running
+ otherwnd = FindWindow(WINDOW_CLASS, WINDOW_NAME);
+
+ // if the argument is "-kill", post a close message
+ if (strcmp(arg, "-kill") == 0)
+ {
+ if (otherwnd != nullptr)
+ PostMessage(otherwnd, WM_QUIT, 0, 0);
+ return (otherwnd != nullptr) ? 1 : 0;
+ }
+
+ // if we had another instance, defer to it
+ if (otherwnd != nullptr)
+ return 0;
+
+ // call the startup code
+ output_startup(arg);
+
+ // create our window class
+ result = create_window_class();
+ if (result != 0)
+ goto error;
+
+ // create a window
+ listener_hwnd = CreateWindowEx(
+ WINDOW_STYLE_EX,
+ WINDOW_CLASS,
+ WINDOW_NAME,
+ WINDOW_STYLE,
+ 0, 0,
+ 1, 1,
+ nullptr,
+ nullptr,
+ GetModuleHandle(nullptr),
+ nullptr);
+ if (listener_hwnd == nullptr)
+ goto error;
+
+ // allocate message ids
+ om_mame_start = RegisterWindowMessage(OM_MAME_START);
+ if (om_mame_start == 0)
+ goto error;
+ om_mame_stop = RegisterWindowMessage(OM_MAME_STOP);
+ if (om_mame_stop == 0)
+ goto error;
+ om_mame_update_state = RegisterWindowMessage(OM_MAME_UPDATE_STATE);
+ if (om_mame_update_state == 0)
+ goto error;
+
+ om_mame_register_client = RegisterWindowMessage(OM_MAME_REGISTER_CLIENT);
+ if (om_mame_register_client == 0)
+ goto error;
+ om_mame_unregister_client = RegisterWindowMessage(OM_MAME_UNREGISTER_CLIENT);
+ if (om_mame_unregister_client == 0)
+ goto error;
+ om_mame_get_id_string = RegisterWindowMessage(OM_MAME_GET_ID_STRING);
+ if (om_mame_get_id_string == 0)
+ goto error;
+
+ // see if MAME is already running
+ otherwnd = FindWindow(OUTPUT_WINDOW_CLASS, OUTPUT_WINDOW_NAME);
+ if (otherwnd != nullptr)
+ handle_mame_start((WPARAM)otherwnd, 0);
+
+ // process messages
+ while (GetMessage(&message, nullptr, 0, 0))
+ {
+ TranslateMessage(&message);
+ DispatchMessage(&message);
+ }
+
+ // reset on the way out if still live
+ if (mame_target != nullptr)
+ handle_mame_stop((WPARAM)mame_target, 0);
+ exitcode = 0;
+
+error:
+ // call the shutdown code
+ output_shutdown();
+
+ return exitcode;
+}
+
+
+//============================================================
+// create_window_class
+//============================================================
+
+static int create_window_class(void)
+{
+ static int classes_created = FALSE;
+
+ /* only do this once */
+ if (!classes_created)
+ {
+ WNDCLASS wc = { 0 };
+
+ // initialize the description of the window class
+ wc.lpszClassName = WINDOW_CLASS;
+ wc.hInstance = GetModuleHandle(nullptr);
+ wc.lpfnWndProc = listener_window_proc;
+
+ // register the class; fail if we can't
+ if (!RegisterClass(&wc))
+ return 1;
+ classes_created = TRUE;
+ }
+
+ return 0;
+}
+
+
+//============================================================
+// window_proc
+//============================================================
+
+static LRESULT CALLBACK listener_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
+{
+ // OM_MAME_START: register ourselves with the new MAME (first instance only)
+ if (message == om_mame_start)
+ return handle_mame_start(wparam, lparam);
+
+ // OM_MAME_STOP: no need to unregister, just note that we've stopped caring and reset the LEDs
+ else if (message == om_mame_stop)
+ return handle_mame_stop(wparam, lparam);
+
+ // OM_MAME_UPDATE_STATE: update the state of this item if we care
+ else if (message == om_mame_update_state)
+ return handle_update_state(wparam, lparam);
+
+ // WM_COPYDATA: extract the string and create an ID map entry
+ else if (message == WM_COPYDATA)
+ return handle_copydata(wparam, lparam);
+
+ // everything else is default
+ else
+ return DefWindowProc(wnd, message, wparam, lparam);
+}
+
+
+//============================================================
+// handle_mame_start
+//============================================================
+
+static LRESULT handle_mame_start(WPARAM wparam, LPARAM lparam)
+{
+ DEBUG_PRINTF(("mame_start (%08X)\n", (UINT32)wparam));
+
+ // make this the targeted version of MAME
+ mame_target = (HWND)wparam;
+
+ // initialize the LED states
+ output_mame_start();
+ reset_id_to_outname_cache();
+
+ // register ourselves as a client
+ PostMessage(mame_target, om_mame_register_client, (WPARAM)listener_hwnd, CLIENT_ID);
+
+ // get the game name
+ map_id_to_outname(0);
+ return 0;
+}
+
+
+//============================================================
+// handle_mame_stop
+//============================================================
+
+static LRESULT handle_mame_stop(WPARAM wparam, LPARAM lparam)
+{
+ DEBUG_PRINTF(("mame_stop (%08X)\n", (UINT32)wparam));
+
+ // ignore if this is not the instance we care about
+ if (mame_target != (HWND)wparam)
+ return 1;
+
+ // clear our target out
+ mame_target = nullptr;
+ reset_id_to_outname_cache();
+
+ // reset the LED states
+ output_mame_stop();
+ return 0;
+}
+
+
+//============================================================
+// handle_copydata
+//============================================================
+
+static LRESULT handle_copydata(WPARAM wparam, LPARAM lparam)
+{
+ COPYDATASTRUCT *copydata = (COPYDATASTRUCT *)lparam;
+ copydata_id_string *data = (copydata_id_string *)copydata->lpData;
+ id_map_entry *entry;
+ char *string;
+
+ DEBUG_PRINTF(("copydata (%08X)\n", (UINT32)wparam));
+
+ // ignore requests we don't care about
+ if (mame_target != (HWND)wparam)
+ return 1;
+
+ // allocate memory
+ entry = (id_map_entry *)malloc(sizeof(*entry));
+ if (entry == nullptr)
+ return 0;
+
+ string = (char *)malloc(strlen(data->string) + 1);
+ if (string == nullptr)
+ {
+ free(entry);
+ return 0;
+ }
+
+ // if all allocations worked, make a new entry
+ entry->next = idmaplist;
+ entry->name = string;
+ entry->id = data->id;
+
+ // copy the string and hook us into the list
+ strcpy(string, data->string);
+ idmaplist = entry;
+
+ DEBUG_PRINTF((" id %d = '%s'\n", (int)entry->id, entry->name));
+
+ return 0;
+}
+
+
+//============================================================
+// reset_id_to_outname_cache
+//============================================================
+
+static void reset_id_to_outname_cache(void)
+{
+ // free our ID list
+ while (idmaplist != nullptr)
+ {
+ id_map_entry *temp = idmaplist;
+ idmaplist = temp->next;
+ free((void*)temp->name);
+ free(temp);
+ }
+}
+
+
+//============================================================
+// map_id_to_outname
+//============================================================
+
+static const char *map_id_to_outname(WPARAM id)
+{
+ id_map_entry *entry;
+
+ // see if we have an entry in our map
+ for (entry = idmaplist; entry != nullptr; entry = entry->next)
+ if (entry->id == id)
+ return entry->name;
+
+ // no entry yet; we have to ask
+ SendMessage(mame_target, om_mame_get_id_string, (WPARAM)listener_hwnd, id);
+
+ // now see if we have the entry in our map
+ for (entry = idmaplist; entry != nullptr; entry = entry->next)
+ if (entry->id == id)
+ return entry->name;
+
+ // if not, use an empty string
+ return "";
+}
+
+
+//============================================================
+// handle_update_state
+//============================================================
+
+static LRESULT handle_update_state(WPARAM wparam, LPARAM lparam)
+{
+ DEBUG_PRINTF(("update_state: id=%d state=%d\n", (UINT32)wparam, (UINT32)lparam));
+ output_set_state(map_id_to_outname(wparam), lparam);
+ return 0;
+}
+
+
+//
+// END BOILERPLATE CODE
+//
+// ------------------------>8 snip 8<-------------------------
+//
+// BEGIN LED-SPECIFIC CODE
+//
+
+
+//============================================================
+// output_startup
+//============================================================
+
+static void output_startup(const char *commandline)
+{
+ // default to PS/2, override if USB is specified as a parameter
+ ledmethod = LED_METHOD_PS2;
+ if (commandline != nullptr && strcmp(commandline, "-usb") == 0)
+ ledmethod = LED_METHOD_USB;
+
+ // output the method
+ switch (ledmethod)
+ {
+ case LED_METHOD_PS2:
+ DEBUG_PRINTF(("Using PS/2 method\n"));
+ break;
+
+ case LED_METHOD_USB:
+ DEBUG_PRINTF(("Using USB method\n"));
+ break;
+ }
+}
+
+
+//============================================================
+// output_shutdown
+//============================================================
+
+static void output_shutdown(void)
+{
+ // nothing to do here
+}
+
+
+//============================================================
+// output_mame_start
+//============================================================
+
+static void output_mame_start(void)
+{
+ HRESULT error_number;
+
+ // initialize the system based on the method
+ switch (ledmethod)
+ {
+ case LED_METHOD_PS2:
+ if (!DefineDosDevice(DDD_RAW_TARGET_PATH, TEXT("Kbd"), TEXT("\\Device\\KeyboardClass0")))
+ {
+ error_number = GetLastError();
+ fprintf(stderr, "Unable to open the keyboard device. (error %d)\n", (UINT32)error_number);
+ return;
+ }
+
+ hKbdDev = CreateFile(TEXT("\\\\.\\Kbd"), GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
+ if (hKbdDev == INVALID_HANDLE_VALUE)
+ {
+ error_number = GetLastError();
+ fprintf(stderr, "Unable to open the keyboard device. (error %d)\n", (UINT32)error_number);
+ return;
+ }
+ break;
+ }
+
+ // remember the initial LED states
+ original_state = current_state = led_get_state();
+}
+
+
+//============================================================
+// output_mame_stop
+//============================================================
+
+static void output_mame_stop(void)
+{
+ int error_number = 0;
+
+ // restore the initial LED states
+ led_set_state(original_state);
+
+ switch (ledmethod)
+ {
+ case LED_METHOD_PS2:
+ if (!DefineDosDevice(DDD_REMOVE_DEFINITION, TEXT("Kbd"), nullptr))
+ {
+ error_number = GetLastError();
+ fprintf(stderr, "Unable to close the keyboard device. (error %d)\n", error_number);
+ return;
+ }
+ if (!CloseHandle(hKbdDev))
+ {
+ error_number = GetLastError();
+ fprintf(stderr, "Unable to close the keyboard device. (error %d)\n", error_number);
+ return;
+ }
+ break;
+ }
+}
+
+
+//============================================================
+// output_set_state
+//============================================================
+
+static void output_set_state(const char *outname, INT32 state)
+{
+ // look for pause state
+ if (strcmp(outname, "pause") == 0)
+ {
+ if (state)
+ {
+ pause_state = led_get_state();
+ led_set_state(original_state);
+ }
+ else
+ {
+ original_state = led_get_state();
+ led_set_state(pause_state);
+ }
+ }
+ // look for LED0/LED1/LED2 states and update accordingly
+ else if (strcmp(outname, "led0") == 0)
+ led_set_state((current_state & ~1) | (state & 1));
+ else if (strcmp(outname, "led1") == 0)
+ led_set_state((current_state & ~2) | ((state & 1) << 1));
+ else if (strcmp(outname, "led2") == 0)
+ led_set_state((current_state & ~4) | ((state & 1) << 2));
+}
+
+
+//============================================================
+// led_get_state
+//============================================================
+
+static int led_get_state(void)
+{
+ int result = 0;
+
+ switch (ledmethod)
+ {
+ case LED_METHOD_USB:
+ {
+ BYTE key_states[256];
+
+ // get the current state
+ GetKeyboardState(&key_states[0]);
+
+ // set the numlock bit
+ result |= (key_states[VK_NUMLOCK] & 1);
+ result |= (key_states[VK_CAPITAL] & 1) << 1;
+ result |= (key_states[VK_SCROLL] & 1) << 2;
+ break;
+ }
+
+ case LED_METHOD_PS2:
+ {
+ KEYBOARD_INDICATOR_PARAMETERS OutputBuffer; // Output buffer for DeviceIoControl
+ ULONG DataLength = sizeof(KEYBOARD_INDICATOR_PARAMETERS);
+ ULONG ReturnedLength; // Number of bytes returned in output buffer
+
+ // Address first keyboard
+ OutputBuffer.UnitId = 0;
+
+ DeviceIoControl(hKbdDev, IOCTL_KEYBOARD_QUERY_INDICATORS,
+ nullptr, 0,
+ &OutputBuffer, DataLength,
+ &ReturnedLength, nullptr);
+
+ // Demangle lights to match 95/98
+ if (OutputBuffer.LedFlags & KEYBOARD_NUM_LOCK_ON) result |= 0x1;
+ if (OutputBuffer.LedFlags & KEYBOARD_CAPS_LOCK_ON) result |= 0x2;
+ if (OutputBuffer.LedFlags & KEYBOARD_SCROLL_LOCK_ON) result |= 0x4;
+ break;
+ }
+ }
+
+ return result;
+}
+
+
+//============================================================
+// led_set_state
+//============================================================
+
+static void led_set_state(int state)
+{
+ current_state = state;
+
+ switch (ledmethod)
+ {
+ case LED_METHOD_USB:
+ {
+ static const BYTE vk[3] = { VK_NUMLOCK, VK_CAPITAL, VK_SCROLL };
+ BYTE keyState[256];
+ int k;
+
+ GetKeyboardState((LPBYTE)&keyState);
+ for (k = 0; k < 3; k++)
+ {
+ if ((((state >> k) & 1) && !(keyState[vk[k]] & 1)) ||
+ (!((state >> k) & 1) && (keyState[vk[k]] & 1)))
+ {
+ // Simulate a key press
+ keybd_event(vk[k], 0x45, KEYEVENTF_EXTENDEDKEY | 0, 0);
+
+ // Simulate a key release
+ keybd_event(vk[k], 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
+ }
+ }
+
+ keyState[VK_NUMLOCK] = (keyState[VK_NUMLOCK] & ~1) | ((state >> 0) & 1);
+ keyState[VK_CAPITAL] = (keyState[VK_CAPITAL] & ~1) | ((state >> 1) & 1);
+ keyState[VK_SCROLL] = (keyState[VK_SCROLL] & ~1) | ((state >> 2) & 1);
+ SetKeyboardState(&keyState[0]);
+ break;
+ }
+
+ case LED_METHOD_PS2:
+ {
+ KEYBOARD_INDICATOR_PARAMETERS InputBuffer; // Input buffer for DeviceIoControl
+ ULONG DataLength = sizeof(KEYBOARD_INDICATOR_PARAMETERS);
+ ULONG ReturnedLength; // Number of bytes returned in output buffer
+ UINT LedFlags=0;
+
+ // Demangle lights to match 95/98
+ if (state & 0x1) LedFlags |= KEYBOARD_NUM_LOCK_ON;
+ if (state & 0x2) LedFlags |= KEYBOARD_CAPS_LOCK_ON;
+ if (state & 0x4) LedFlags |= KEYBOARD_SCROLL_LOCK_ON;
+
+ // Address first keyboard
+ InputBuffer.UnitId = 0;
+ InputBuffer.LedFlags = LedFlags;
+ DeviceIoControl(hKbdDev, IOCTL_KEYBOARD_SET_INDICATORS,
+ &InputBuffer, DataLength,
+ nullptr, 0,
+ &ReturnedLength, nullptr);
+ break;
+ }
+ }
+}
diff --git a/src/osd/windows/winmain.cpp b/src/osd/windows/winmain.cpp
index ab8e99b6038..32adaa3156c 100644
--- a/src/osd/windows/winmain.cpp
+++ b/src/osd/windows/winmain.cpp
@@ -217,6 +217,7 @@ const options_entry windows_options::s_option_entries[] =
{ WINOPTION_YIQ_PHASE_COUNT";yiqp", "2", OPTION_INTEGER, "Phase Count value for NTSC signal processing" },
/* Vector simulation below this line */
{ nullptr, nullptr, OPTION_HEADER, "VECTOR POST-PROCESSING OPTIONS" },
+ { WINOPTION_VECTOR_BEAM_SMOOTH";vecsmooth", "0.0", OPTION_FLOAT, "The vector beam smoothness" },
{ WINOPTION_VECTOR_LENGTH_SCALE";vecscale", "0.5", OPTION_FLOAT, "The maximum vector attenuation" },
{ WINOPTION_VECTOR_LENGTH_RATIO";vecratio", "0.5", OPTION_FLOAT, "The minimum vector length (vector length to screen size ratio) that is affected by the attenuation" },
/* Bloom below this line */
diff --git a/src/osd/windows/winmain.h b/src/osd/windows/winmain.h
index 6935130c30f..f7774922223 100644
--- a/src/osd/windows/winmain.h
+++ b/src/osd/windows/winmain.h
@@ -83,6 +83,7 @@
#define WINOPTION_YIQ_QVALUE "yiq_q"
#define WINOPTION_YIQ_SCAN_TIME "yiq_scan_time"
#define WINOPTION_YIQ_PHASE_COUNT "yiq_phase_count"
+#define WINOPTION_VECTOR_BEAM_SMOOTH "vector_beam_smooth"
#define WINOPTION_VECTOR_LENGTH_SCALE "vector_length_scale"
#define WINOPTION_VECTOR_LENGTH_RATIO "vector_length_ratio"
#define WINOPTION_BLOOM_BLEND_MODE "bloom_blend_mode"
@@ -177,6 +178,7 @@ public:
float screen_yiq_q() const { return float_value(WINOPTION_YIQ_QVALUE); }
float screen_yiq_scan_time() const { return float_value(WINOPTION_YIQ_SCAN_TIME); }
int screen_yiq_phase_count() const { return int_value(WINOPTION_YIQ_PHASE_COUNT); }
+ float screen_vector_beam_smooth() const { return float_value(WINOPTION_VECTOR_BEAM_SMOOTH); }
float screen_vector_length_scale() const { return float_value(WINOPTION_VECTOR_LENGTH_SCALE); }
float screen_vector_length_ratio() const { return float_value(WINOPTION_VECTOR_LENGTH_RATIO); }
int screen_bloom_blend_mode() const { return int_value(WINOPTION_BLOOM_BLEND_MODE); }