summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
author Robbbert <Robbbert@users.noreply.github.com>2022-06-24 16:28:20 +1000
committer Robbbert <Robbbert@users.noreply.github.com>2022-06-24 16:28:20 +1000
commit2b45f3cefc9a7492f3e11306ff2cb260852eb923 (patch)
tree5509a2b068317fbf6a9b772581421bc4128462cc
parentcac7854ef867fc08f0978ed874d0375f3e85b9c6 (diff)
parentae46009f50f2edcf52448858c442b24ba75a2145 (diff)
Merge remote-tracking branch 'upstream/master'
-rw-r--r--scripts/src/bus.lua2
-rw-r--r--scripts/src/emu.lua6
-rw-r--r--src/devices/bus/nubus/nubus.cpp11
-rw-r--r--src/devices/bus/nubus/nubus.h2
-rw-r--r--src/devices/bus/nubus/nubus_48gc.cpp519
-rw-r--r--src/devices/bus/nubus/nubus_48gc.h56
-rw-r--r--src/devices/bus/nubus/nubus_spec8.cpp62
-rw-r--r--src/devices/bus/nubus/nubus_specpdq.cpp198
-rw-r--r--src/devices/bus/nubus/nubus_specpdq.h15
-rw-r--r--src/devices/bus/nubus/supermac.cpp7
-rw-r--r--src/devices/bus/nubus/supermac.h10
-rw-r--r--src/devices/bus/pc_kbd/cherry_mx1500.cpp333
-rw-r--r--src/devices/bus/pc_kbd/cherry_mx1500.h44
-rw-r--r--src/devices/bus/pc_kbd/keyboards.cpp2
-rw-r--r--src/devices/bus/pc_kbd/keyboards.h1
-rw-r--r--src/emu/layout/generic.h3
-rw-r--r--src/emu/layout/monitors.lay41
-rw-r--r--src/emu/rendlay.cpp3
-rw-r--r--src/mame/drivers/mac.cpp17
-rw-r--r--src/mame/drivers/macquadra700.cpp9
-rw-r--r--src/mame/layout/mac.lay16
21 files changed, 1074 insertions, 283 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua
index 47efc8ad839..29ac16ff758 100644
--- a/scripts/src/bus.lua
+++ b/scripts/src/bus.lua
@@ -2002,6 +2002,8 @@ if (BUSES["PC_KBD"]~=null) then
MAME_DIR .. "src/devices/bus/pc_kbd/pc_kbdc.h",
MAME_DIR .. "src/devices/bus/pc_kbd/keyboards.cpp",
MAME_DIR .. "src/devices/bus/pc_kbd/keyboards.h",
+ MAME_DIR .. "src/devices/bus/pc_kbd/cherry_mx1500.cpp",
+ MAME_DIR .. "src/devices/bus/pc_kbd/cherry_mx1500.h",
MAME_DIR .. "src/devices/bus/pc_kbd/ec1841.cpp",
MAME_DIR .. "src/devices/bus/pc_kbd/ec1841.h",
MAME_DIR .. "src/devices/bus/pc_kbd/iskr1030.cpp",
diff --git a/scripts/src/emu.lua b/scripts/src/emu.lua
index 06b92469c25..ef708b93d03 100644
--- a/scripts/src/emu.lua
+++ b/scripts/src/emu.lua
@@ -281,12 +281,13 @@ dependency {
-------------------------------------------------
-- core layouts
--------------------------------------------------
+ { MAME_DIR .. "src/emu/rendlay.cpp", GEN_DIR .. "emu/layout/noscreens.lh" },
+ { MAME_DIR .. "src/emu/rendlay.cpp", GEN_DIR .. "emu/layout/monitors.lh" },
{ MAME_DIR .. "src/emu/rendlay.cpp", GEN_DIR .. "emu/layout/dualhovu.lh" },
{ MAME_DIR .. "src/emu/rendlay.cpp", GEN_DIR .. "emu/layout/dualhsxs.lh" },
{ MAME_DIR .. "src/emu/rendlay.cpp", GEN_DIR .. "emu/layout/dualhuov.lh" },
{ MAME_DIR .. "src/emu/rendlay.cpp", GEN_DIR .. "emu/layout/triphsxs.lh" },
{ MAME_DIR .. "src/emu/rendlay.cpp", GEN_DIR .. "emu/layout/quadhsxs.lh" },
- { MAME_DIR .. "src/emu/rendlay.cpp", GEN_DIR .. "emu/layout/noscreens.lh" },
}
custombuildtask {
@@ -296,12 +297,13 @@ custombuildtask {
custombuildtask {
{ MAME_DIR .. "src/frontend/mame/ui/uicmd14.png", GEN_DIR .. "emu/ui/uicmd14.fh", { MAME_DIR.. "scripts/build/png2bdc.py", MAME_DIR .. "scripts/build/file2str.py" }, { "@echo Converting uicmd14.png...", PYTHON .. " $(1) $(<) temp_cmd.bdc", PYTHON .. " $(2) temp_cmd.bdc $(@) font_uicmd14 uint8_t" } },
+ layoutbuildtask("emu/layout", "noscreens"),
+ layoutbuildtask("emu/layout", "monitors"),
layoutbuildtask("emu/layout", "dualhovu"),
layoutbuildtask("emu/layout", "dualhsxs"),
layoutbuildtask("emu/layout", "dualhuov"),
layoutbuildtask("emu/layout", "triphsxs"),
layoutbuildtask("emu/layout", "quadhsxs"),
- layoutbuildtask("emu/layout", "noscreens"),
}
project ("precompile")
diff --git a/src/devices/bus/nubus/nubus.cpp b/src/devices/bus/nubus/nubus.cpp
index 4cf28122207..4f712861714 100644
--- a/src/devices/bus/nubus/nubus.cpp
+++ b/src/devices/bus/nubus/nubus.cpp
@@ -193,6 +193,12 @@ void nubus_device::install_bank(offs_t start, offs_t end, void *data)
m_space->install_ram(start, end, data);
}
+void nubus_device::install_view(offs_t start, offs_t end, memory_view &view)
+{
+// printf("install_view: %s @ %x->%x\n", tag, start, end);
+ m_space->install_view(start, end, view);
+}
+
void nubus_device::set_irq_line(int slot, int state)
{
switch (slot)
@@ -284,6 +290,11 @@ void device_nubus_card_interface::install_bank(offs_t start, offs_t end, void *d
nubus().install_bank(start, end, data);
}
+void device_nubus_card_interface::install_view(offs_t start, offs_t end, memory_view &view)
+{
+ nubus().install_view(start, end, view);
+}
+
void device_nubus_card_interface::install_declaration_rom(const char *romregion, bool mirror_all_mb, bool reverse_rom)
{
bool inverted = false;
diff --git a/src/devices/bus/nubus/nubus.h b/src/devices/bus/nubus/nubus.h
index cc9a434d205..198f5b115eb 100644
--- a/src/devices/bus/nubus/nubus.h
+++ b/src/devices/bus/nubus/nubus.h
@@ -38,6 +38,7 @@ public:
// helper functions for card devices
void install_declaration_rom(const char *romregion, bool mirror_all_mb = false, bool reverse_rom = false);
void install_bank(offs_t start, offs_t end, void *data);
+ void install_view(offs_t start, offs_t end, memory_view &view);
uint32_t get_slotspace() { return 0xf0000000 | (m_slot<<24); }
uint32_t get_super_slotspace() { return m_slot<<28; }
@@ -126,6 +127,7 @@ public:
void install_readonly_device(offs_t start, offs_t end, read32_delegate rhandler, uint32_t mask=0xffffffff);
void install_writeonly_device(offs_t start, offs_t end, write32_delegate whandler, uint32_t mask=0xffffffff);
void install_bank(offs_t start, offs_t end, void *data);
+ void install_view(offs_t start, offs_t end, memory_view &view);
void set_irq_line(int slot, int state);
DECLARE_WRITE_LINE_MEMBER( irq9_w );
diff --git a/src/devices/bus/nubus/nubus_48gc.cpp b/src/devices/bus/nubus/nubus_48gc.cpp
index 3b6896e578d..899910b52c6 100644
--- a/src/devices/bus/nubus/nubus_48gc.cpp
+++ b/src/devices/bus/nubus/nubus_48gc.cpp
@@ -1,15 +1,27 @@
// license:BSD-3-Clause
-// copyright-holders:R. Belmont
+// copyright-holders:R. Belmont, Vas Crabb
/***************************************************************************
Apple 4*8 Graphics Card (model 630-0400) emulation
Apple 8*24 Graphics Card emulation (cards have the same framebuffer chip
w/different ROMs and RAMDACs, apparently)
+ TODO:
+ * Work out why some monitors need magic multiply or divide by two to
+ get the right RAMDAC clock - inferring it from the reference clock
+ modulus is definitely wrong.
+ * When a monochrome monitor is connected, it sends the intensity to the
+ blue channel - maybe detect this and map blue channel to white?
+ * The 8•24 card uses a strange off-white palette with some monitors,
+ including the 21" and 16" RGB displays.
+ * Interlaced modes.
+
***************************************************************************/
#include "emu.h"
#include "nubus_48gc.h"
+
+#include "layout/generic.h"
#include "screen.h"
#include <algorithm>
@@ -18,11 +30,38 @@
#include "logmacro.h"
-#define VRAM_SIZE (0x200000) // 2 megs, maxed out
+#define VRAM_SIZE (0x20'0000) // 2 megs, maxed out
-#define GC48_SCREEN_NAME "48gc_screen"
+#define GC48_SCREEN_NAME "screen"
#define GC48_ROM_REGION "48gc_rom"
+
+static INPUT_PORTS_START( 48gc )
+ PORT_START("MONITOR")
+ PORT_CONFNAME(0x07, 0x06, u8"Attached monitor")
+ PORT_CONFSETTING( 0x00, u8"Macintosh Two-Page Monitor (1152\u00d7870)")
+ PORT_CONFSETTING( 0x01, u8"Macintosh Portrait Display (B&W 15\" 640\u00d7870)")
+ PORT_CONFSETTING( 0x02, u8"Macintosh RGB Display (12\" 512\u00d7384)")
+ PORT_CONFSETTING( 0x03, u8"Macintosh Two-Page Monitor (B&W 21\" 1152\u00d7870)")
+ //PORT_CONFSETTING( 0x04, u8"NTSC Monitor") requires implementing interlace modes
+ PORT_CONFSETTING( 0x05, u8"Macintosh Portrait Display (640\u00d7870)")
+ PORT_CONFSETTING( 0x06, u8"Macintosh Hi-Res Display (12-14\" 640\u00d7480)")
+INPUT_PORTS_END
+
+
+static INPUT_PORTS_START( 824gc )
+ PORT_START("MONITOR")
+ PORT_CONFNAME(0x07, 0x06, u8"Attached monitor")
+ PORT_CONFSETTING( 0x00, u8"Mac 21\" Color Display (1152\u00d7870)")
+ PORT_CONFSETTING( 0x01, u8"Mac Portrait Display (B&W 15\" 640\u00d7870)")
+ PORT_CONFSETTING( 0x02, u8"Mac RGB Display (12\" 512\u00d7384)")
+ PORT_CONFSETTING( 0x03, u8"Mac Two-Page Display (B&W 21\" 1152\u00d7870)")
+ //PORT_CONFSETTING( 0x04, u8"NTSC Monitor") requires implementing interlace modes
+ PORT_CONFSETTING( 0x05, u8"Mac 16\" Color Display (832\u00d7624)")
+ PORT_CONFSETTING( 0x06, u8"Mac Hi-Res Display (12-14\" 640\u00d7480)")
+INPUT_PORTS_END
+
+
ROM_START( gc48 )
ROM_REGION(0x8000, GC48_ROM_REGION, 0)
ROM_LOAD( "3410801.bin", 0x0000, 0x8000, CRC(e283da91) SHA1(4ae21d6d7bbaa6fc7aa301bee2b791ed33b1dcf9) )
@@ -47,20 +86,20 @@ DEFINE_DEVICE_TYPE(NUBUS_824GC, nubus_824gc_device, "nb_824gc", "Apple Macintosh
void jmfb_device::device_add_mconfig(machine_config &config)
{
+ config.set_default_layout(layout_monitors);
+
screen_device &screen(SCREEN(config, GC48_SCREEN_NAME, SCREEN_TYPE_RASTER));
screen.set_screen_update(FUNC(jmfb_device::screen_update));
- screen.set_raw(25175000, 800, 0, 640, 525, 0, 480);
-// screen.set_size(1152, 870);
-// screen.set_visarea(0, 1152-1, 0, 870-1);
-// screen.set_refresh_hz(75);
-// screen.set_vblank_time(ATTOSECONDS_IN_USEC(1260));
+ screen.set_raw(20_MHz_XTAL / 21 * 127 / 4, 864, 0, 640, 525, 0, 480);
+ //screen.set_raw(20_MHz_XTAL / 19 * 190 / 2, 1'456, 0, 1'152, 915, 0, 870);
+ screen.set_video_attributes(VIDEO_UPDATE_SCANLINE);
}
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
-const tiny_rom_entry *jmfb_device::device_rom_region() const
+const tiny_rom_entry *nubus_48gc_device::device_rom_region() const
{
return ROM_NAME( gc48 );
}
@@ -71,6 +110,20 @@ const tiny_rom_entry *nubus_824gc_device::device_rom_region() const
}
//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor nubus_48gc_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( 48gc );
+}
+
+ioport_constructor nubus_824gc_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( 824gc );
+}
+
+//-------------------------------------------------
// palette_entries - entries in color palette
//-------------------------------------------------
@@ -88,26 +141,27 @@ uint32_t jmfb_device::palette_entries() const
// jmfb_device - constructor
//-------------------------------------------------
-jmfb_device::jmfb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool is824) :
+jmfb_device::jmfb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, type, tag, owner, clock),
device_nubus_card_interface(mconfig, *this),
device_video_interface(mconfig, *this),
device_palette_interface(mconfig, *this),
- m_timer(nullptr), m_mode(0), m_vbl_disable(0), m_toggle(0), m_stride(0), m_base(0),
- m_count(0), m_clutoffs(0),
- m_xres(0), m_yres(0),
- m_is824(is824)
+ m_monitor(*this, "MONITOR"),
+ m_vram_view(*this, "vram"),
+ m_timer(nullptr),
+ m_vbl_disable(0), m_toggle(0), m_stride(0), m_base(0),
+ m_count(0), m_clutoffs(0), m_mode(0)
{
set_screen(*this, GC48_SCREEN_NAME);
}
nubus_48gc_device::nubus_48gc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- jmfb_device(mconfig, NUBUS_48GC, tag, owner, clock, false)
+ jmfb_device(mconfig, NUBUS_48GC, tag, owner, clock)
{
}
nubus_824gc_device::nubus_824gc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- jmfb_device(mconfig, NUBUS_824GC, tag, owner, clock, true)
+ jmfb_device(mconfig, NUBUS_824GC, tag, owner, clock)
{
}
@@ -117,20 +171,68 @@ nubus_824gc_device::nubus_824gc_device(const machine_config &mconfig, const char
void jmfb_device::device_start()
{
- uint32_t slotspace;
-
install_declaration_rom(GC48_ROM_REGION);
- slotspace = get_slotspace();
+ uint32_t const slotspace = get_slotspace();
-// printf("[JMFB %p] slotspace = %x\n", this, slotspace);
+ LOG("[JMFB %p] slotspace = %x\n", this, slotspace);
m_vram.resize(VRAM_SIZE / sizeof(uint32_t));
- install_bank(slotspace, slotspace+VRAM_SIZE-1, &m_vram[0]);
-
- nubus().install_device(slotspace+0x200000, slotspace+0x2003ff, read32s_delegate(*this, FUNC(jmfb_device::mac_48gc_r)), write32s_delegate(*this, FUNC(jmfb_device::mac_48gc_w)));
+ install_view(
+ slotspace, slotspace + VRAM_SIZE - 1,
+ m_vram_view);
+ m_vram_view[0].install_ram(
+ slotspace, slotspace + VRAM_SIZE - 1,
+ &m_vram[0]);
+ m_vram_view[1].install_readwrite_handler(
+ slotspace, slotspace + VRAM_SIZE - 1,
+ read32s_delegate(*this, FUNC(jmfb_device::rgb_unpack)), write32s_delegate(*this, FUNC(jmfb_device::rgb_pack)));
+ m_vram_view.select(0);
m_timer = timer_alloc(FUNC(jmfb_device::vbl_tick), this);
+
+ save_item(NAME(m_vram));
+ save_item(NAME(m_vbl_disable));
+ save_item(NAME(m_toggle));
+ save_item(NAME(m_stride));
+ save_item(NAME(m_base));
+ save_item(NAME(m_registers));
+ save_item(NAME(m_preload));
+ save_item(NAME(m_colors));
+ save_item(NAME(m_count));
+ save_item(NAME(m_clutoffs));
+ save_item(NAME(m_mode));
+ save_item(NAME(m_hactive));
+ save_item(NAME(m_hbporch));
+ save_item(NAME(m_hsync));
+ save_item(NAME(m_hfporch));
+ save_item(NAME(m_vactive));
+ save_item(NAME(m_vbporch));
+ save_item(NAME(m_vsync));
+ save_item(NAME(m_vfporch));
+ save_item(NAME(m_multiplier));
+ save_item(NAME(m_modulus));
+ save_item(NAME(m_pdiv));
+}
+
+void nubus_48gc_device::device_start()
+{
+ jmfb_device::device_start();
+
+ uint32_t const slotspace = get_slotspace();
+ nubus().install_device(
+ slotspace + 0x200000, slotspace + 0x2003ff,
+ read32s_delegate(*this, FUNC(nubus_48gc_device::jmfb_r)), write32s_delegate(*this, FUNC(nubus_48gc_device::mac_48gc_w)));
+}
+
+void nubus_824gc_device::device_start()
+{
+ jmfb_device::device_start();
+
+ uint32_t const slotspace = get_slotspace();
+ nubus().install_device(
+ slotspace + 0x200000, slotspace + 0x2003ff,
+ read32s_delegate(*this, FUNC(nubus_824gc_device::jmfb_r)), write32s_delegate(*this, FUNC(nubus_824gc_device::mac_824gc_w)));
}
//-------------------------------------------------
@@ -139,18 +241,31 @@ void jmfb_device::device_start()
void jmfb_device::device_reset()
{
+ m_vram_view.select(0);
+
+ std::fill(m_vram.begin(), m_vram.end(), 0);
+ m_vbl_disable = 1;
m_toggle = 0;
+ m_stride = 80 / 4;
+ m_base = 0;
+ m_preload = 256 - 8;
+
m_clutoffs = 0;
m_count = 0;
- m_vbl_disable = 1;
- m_stride = 80/4;
- m_base = 0;
- m_xres = 640;
- m_yres = 480;
m_mode = 0;
- std::fill(m_vram.begin(), m_vram.end(), 0);
- m_timer->adjust(screen().time_until_pos(479, 0), 0);
+ m_hactive = 286;
+ m_hbporch = 22;
+ m_hsync = 30;
+ m_hfporch = 18;
+
+ m_vactive = 1740;
+ m_vbporch = 78;
+ m_vsync = 6;
+ m_vfporch = 6;
+ m_multiplier = 190;
+ m_modulus = 19;
+ m_pdiv = 1;
}
/***************************************************************************
@@ -166,22 +281,25 @@ TIMER_CALLBACK_MEMBER(jmfb_device::vbl_tick)
raise_slot_irq();
}
- m_timer->adjust(screen().time_until_pos(479, 0), 0);
+ // TODO: determine correct timing for vertical blanking interrupt
+ m_timer->adjust(screen().time_until_pos(screen().visible_area().bottom()));
}
uint32_t jmfb_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
- auto const vram8 = util::big_endian_cast<uint8_t const>(&m_vram[0]) + (m_base << 5);
+ auto const screenbase = util::big_endian_cast<uint8_t const>(&m_vram[0]) + (m_base << 5);
+ int const xres = screen.visible_area().right();
switch (m_mode)
{
case 0: // 1bpp
- for (int y = 0; y < m_yres; y++)
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
+ auto const rowbase = screenbase + (y * m_stride * 4);
uint32_t *scanline = &bitmap.pix(y);
- for (int x = 0; x < m_xres/8; x++)
+ for (int x = 0; x <= xres/8; x++)
{
- uint8_t const pixels = vram8[(y * m_stride * 4) + x];
+ uint8_t const pixels = rowbase[x];
*scanline++ = pen_color(BIT(pixels, 7));
*scanline++ = pen_color(BIT(pixels, 6));
@@ -196,12 +314,13 @@ uint32_t jmfb_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap,
break;
case 1: // 2bpp
- for (int y = 0; y < m_yres; y++)
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
+ auto const rowbase = screenbase + (y * m_stride * 4);
uint32_t *scanline = &bitmap.pix(y);
- for (int x = 0; x < m_xres/4; x++)
+ for (int x = 0; x <= xres/4; x++)
{
- uint8_t const pixels = vram8[(y * m_stride * 4) + x];
+ uint8_t const pixels = rowbase[x];
*scanline++ = pen_color(BIT(pixels, 6, 2));
*scanline++ = pen_color(BIT(pixels, 4, 2));
@@ -212,12 +331,13 @@ uint32_t jmfb_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap,
break;
case 2: // 4 bpp
- for (int y = 0; y < m_yres; y++)
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
+ auto const rowbase = screenbase + (y * m_stride * 4);
uint32_t *scanline = &bitmap.pix(y);
- for (int x = 0; x < m_xres/2; x++)
+ for (int x = 0; x <= xres/2; x++)
{
- uint8_t const pixels = vram8[(y * m_stride * 4) + x];
+ uint8_t const pixels = rowbase[x];
*scanline++ = pen_color(BIT(pixels, 4, 4));
*scanline++ = pen_color(BIT(pixels, 0, 4));
@@ -226,24 +346,26 @@ uint32_t jmfb_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap,
break;
case 3: // 8 bpp
- for (int y = 0; y < m_yres; y++)
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
+ auto const rowbase = screenbase + (y * m_stride * 4);
uint32_t *scanline = &bitmap.pix(y);
- for (int x = 0; x < m_xres; x++)
+ for (int x = 0; x <= xres; x++)
{
- uint8_t const pixels = vram8[(y * m_stride * 4) + x];
- *scanline++ = pen_color(pixels);
+ *scanline++ = pen_color(rowbase[x]);
}
}
break;
case 4: // 24 bpp
+ for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
{
- uint32_t const base = (m_base * 8 / 3) << 3;
- uint32_t const stride = m_stride * 8 / 3;
- for (int y = 0; y < m_yres; y++)
+ auto source = util::big_endian_cast<uint8_t const>(&m_vram[0]) + (m_base << 6) + (y * m_stride * 8);
+ uint32_t *scanline = &bitmap.pix(y);
+ for (int x = 0; x <= xres; x++)
{
- std::copy_n(&m_vram[base + (y * stride)], m_xres, &bitmap.pix(y));
+ *scanline++ = rgb_t(source[0], source[1], source[2]);
+ source += 3;
}
}
break;
@@ -252,12 +374,102 @@ uint32_t jmfb_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap,
return 0;
}
-void jmfb_device::mac_48gc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+void jmfb_device::update_crtc()
+{
+ int const vtotal = (m_vactive + m_vbporch + m_vsync + m_vfporch) / 2;
+ int const height = m_vactive / 2;
+ if (vtotal && height && m_multiplier)
+ {
+ // FIXME: where does this multiply/divide by 2 come from?
+ // This is obviously not correct by any definition.
+ int scale = 0;
+ switch (m_modulus)
+ {
+ case 15:
+ scale = -1;
+ break;
+ case 21:
+ scale = 0;
+ break;
+ case 19:
+ case 22:
+ scale = 1;
+ break;
+ default:
+ throw emu_fatalerror("%s: Unknown clock modulus %d\n", tag(), m_modulus);
+ }
+ int const divider = 256 - unsigned(m_preload);
+ int htotal = ((m_hactive + m_hbporch + m_hsync + m_hfporch + 8) << (m_pdiv + scale)) / divider;
+ int width = ((m_hactive + 2) << (m_pdiv + scale)) / divider;
+ switch (m_mode)
+ {
+ case 0: // 1bpp:
+ htotal <<= 3;
+ width <<= 3;
+ break;
+ case 1: // 2bpp:
+ htotal <<= 2;
+ width <<= 2;
+ break;
+ case 2: // 4bpp:
+ htotal <<= 1;
+ width <<= 1;
+ break;
+ case 3: // 8bpp:
+ break;
+ case 4: // 24bpp:
+ htotal >>= 2;
+ width >>= 2;
+ break;
+ }
+ XTAL const pixclock = 20_MHz_XTAL / m_modulus * m_multiplier / (1 << m_pdiv);
+ screen().configure(
+ htotal, vtotal,
+ rectangle(0, width - 1, 0, height - 1),
+ attotime::from_ticks(htotal * vtotal, pixclock).attoseconds());
+
+ // TODO: determine correct timing for vertical blanking interrupt
+ m_timer->adjust(screen().time_until_pos(height - 1, 0));
+ }
+}
+
+uint32_t jmfb_device::jmfb_r(offs_t offset, uint32_t mem_mask)
+{
+// printf("%s 48gc_r: @ %x, mask %08x\n", machine().describe_context().c_str(), offset, mem_mask);
+
+ switch (offset)
+ {
+ case 0x000/4:
+ return m_monitor->read() << 9;
+
+ case 0x1c0/4:
+ m_toggle ^= 0xffffffff;
+ return m_toggle;
+ }
+
+ return 0;
+}
+
+void jmfb_device::jmfb_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
COMBINE_DATA(&m_registers[offset & 0xff]);
switch (offset)
{
+ case 0x000/4: // control
+ LOG("%s: %04x to control\n", machine().describe_context(), data);
+ if (BIT(data, 7))
+ {
+ m_vram_view.select(BIT(data, 2)); // packed RGB mode
+ }
+ break;
+
+ case 0x004/4:
+ LOG("%s: %02x to preload\n", machine().describe_context(), data);
+ m_preload = data;
+ update_crtc();
+ break;
+
case 0x008/4: // base
LOG("%s: %x to base\n", machine().describe_context(), data);
m_base = data;
@@ -269,91 +481,180 @@ void jmfb_device::mac_48gc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
m_stride = data;
break;
- case 0x200/4: // DAC control
- LOG("%s: %08x to DAC control\n", machine().describe_context(), data);
- if (m_is824)
- {
- m_clutoffs = data & 0xff;
- }
- else
- {
- m_clutoffs = data >> 24;
- }
- m_count = 0;
+ case 0x10c/4: // active pixel cells - 2
+ LOG("%s: %d-2 to active cells\n", machine().describe_context(), data + 2);
+ m_hactive = data;
+ update_crtc();
break;
- case 0x204/4: // DAC data
- if (m_is824)
- {
- m_colors[m_count++] = data & 0xff;
- }
- else
- {
- m_colors[m_count++] = data >> 24;
- }
+ case 0x110/4: // horizontal back porch
+ LOG("%s: %d to horizontal back porch\n", machine().describe_context(), data + 2);
+ m_hbporch = data;
+ update_crtc();
+ break;
- if (m_count == 3)
- {
- LOG("%s: RAMDAC: color %d = %02x %02x %02x\n", machine().describe_context(), m_clutoffs, m_colors[0], m_colors[1], m_colors[2]);
- set_pen_color(m_clutoffs, rgb_t(m_colors[0], m_colors[1], m_colors[2]));
- m_clutoffs++;
- m_count = 0;
- }
+ case 0x114/4: // horizontal sync pulse
+ LOG("%s: %d-2 to horizontal sync pulse\n", machine().describe_context(), data + 2);
+ m_hsync = data;
+ update_crtc();
break;
- case 0x208/4: // mode control
- m_mode = (data>>3)&3;
- if (m_mode == 3) // this can be 8 or 24 bpp
- {
- // check pixel format for 24bpp
- if (m_is824)
- {
- if (data & 2)
- {
- m_mode = 4; // 24bpp
- }
- }
- else
- {
- if (((data>>5)&3) == 0)
- {
- m_mode = 4; // 24bpp
- }
- }
- }
-// printf("%02x to mode (m_mode = %d)\n", data, m_mode);
+ case 0x118/4: // horizontal front porch
+ LOG("%s: %d-2 to horizontal front porch\n", machine().describe_context(), data + 2);
+ m_hfporch = data;
+ update_crtc();
+ break;
+
+ case 0x124/4: // active lines * 2
+ LOG("%s: %d*2 to active lines\n", machine().describe_context(), data / 2);
+ m_vactive = data;
+ update_crtc();
+ break;
+
+ case 0x128/4: // vertical back porch * 2
+ LOG("%s: %d*2 to vertical back porch\n", machine().describe_context(), data / 2);
+ m_vbporch = data;
+ update_crtc();
+ break;
+
+ case 0x12c/4: // vertical sync width * 2
+ LOG("%s: %d*2 to vertical sync pulse width\n", machine().describe_context(), data / 2);
+ m_vsync = data;
+ update_crtc();
+ break;
+
+ case 0x130/4: // vertical front porch * 2
+ LOG("%s: %d*2 to vertical front porch\n", machine().describe_context(), data / 2);
+ m_vfporch = data;
+ update_crtc();
break;
- case 0x13c/4: // bit 1 = VBL disable (1=no interrupts)
+ case 0x13c/4: // bit 1 = VBL disable (1=no interrupts)
m_vbl_disable = (data & 2) ? 1 : 0;
break;
- case 0x148/4: // write 1 here to clear interrupt
+ case 0x148/4: // write 1 here to clear interrupt
if (data == 1)
{
lower_slot_irq();
}
break;
+ case 0x300/4:
+ case 0x304/4:
+ case 0x308/4:
+ case 0x30c/4:
+ m_multiplier &= ~(0x0f << ((offset & 3) * 4));
+ m_multiplier |= (data & 0x0f) << ((offset & 3) * 4);
+ LOG("%s: %d to multiplier\n", machine().describe_context(), m_multiplier);
+ update_crtc();
+ break;
+
+ case 0x310/4:
+ case 0x314/4:
+ case 0x318/4:
+ m_modulus &= ~(0x0f << ((offset & 3) * 4));
+ m_modulus |= (data & 0x0f) << ((offset & 3) * 4);
+ LOG("%s: %d to modulus\n", machine().describe_context(), m_modulus);
+ if (offset == 0x318/4) // avoid bad intermediate values
+ update_crtc();
+ break;
+
+ case 0x324/4:
+ LOG("%s: 1<<%d to pixel cell divider\n", machine().describe_context(), data);
+ m_pdiv = data & 0x0f;
+ update_crtc();
+ break;
+
default:
break;
}
}
-uint32_t jmfb_device::mac_48gc_r(offs_t offset, uint32_t mem_mask)
+void nubus_48gc_device::mac_48gc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
-// printf("%s 48gc_r: @ %x, mask %08x\n", machine().describe_context().c_str(), offset, mem_mask);
+ switch (offset)
+ {
+ case 0x200/4: // DAC control
+ dac_ctrl_w(data >> 24);
+ break;
+
+ case 0x204/4: // DAC data
+ dac_data_w(data >> 24);
+ break;
+
+ case 0x208/4: // mode control
+ mode_w(data, !((data >> 5) & 0x3));
+ break;
+ default:
+ jmfb_w(offset, data, mem_mask);
+ }
+}
+
+void nubus_824gc_device::mac_824gc_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
switch (offset)
{
- case 0:
- return 0x0c00; // sense 13" RGB for now
-// return 0x0000; // sense "RGB Kong" monitor
+ case 0x200/4: // DAC control
+ dac_ctrl_w(data & 0xff);
+ break;
- case 0x1c0/4:
- m_toggle ^= 0xffffffff;
- return m_toggle;
+ case 0x204/4: // DAC data
+ dac_data_w(data & 0xff);
+ break;
+
+ case 0x208/4: // mode control
+ mode_w(data, BIT(data, 1));
+ break;
+
+ default:
+ jmfb_w(offset, data, mem_mask);
+ }
+}
+
+void jmfb_device::dac_ctrl_w(uint8_t data)
+{
+ LOG("%s: %02x to DAC control\n", machine().describe_context(), data);
+ m_clutoffs = data;
+ m_count = 0;
+}
+
+void jmfb_device::dac_data_w(uint8_t data)
+{
+ m_colors[m_count++] = data;
+
+ if (m_count == 3)
+ {
+ LOG("%s: RAMDAC: color %d = %02x %02x %02x\n", machine().describe_context(), m_clutoffs, m_colors[0], m_colors[1], m_colors[2]);
+ set_pen_color(m_clutoffs, rgb_t(m_colors[0], m_colors[1], m_colors[2]));
+ m_clutoffs++;
+ m_count = 0;
}
+}
- return 0;
+void jmfb_device::mode_w(uint32_t data, bool rgb)
+{
+ m_mode = (data >> 3) & 0x3;
+ if ((m_mode == 3) & rgb) // mode 3 can be 8 or 24 bpp
+ m_mode = 4;
+ LOG("%s: %02x to mode (m_mode = %d)\n", machine().describe_context(), data, m_mode);
+ update_crtc();
+}
+
+uint32_t jmfb_device::rgb_unpack(offs_t offset, uint32_t mem_mask)
+{
+ auto const color = util::big_endian_cast<uint8_t const>(&m_vram[0]) + (offset * 3);
+ return (uint32_t(color[0]) << 16) | (uint32_t(color[1]) << 8) | uint32_t(color[2]);
+}
+
+void jmfb_device::rgb_pack(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ auto const color = util::big_endian_cast<uint8_t>(&m_vram[0]) + (offset * 3);
+ if (ACCESSING_BITS_16_23)
+ color[0] = uint8_t(data >> 16);
+ if (ACCESSING_BITS_8_15)
+ color[1] = uint8_t(data >> 8);
+ if (ACCESSING_BITS_0_7)
+ color[2] = uint8_t(data);
}
diff --git a/src/devices/bus/nubus/nubus_48gc.h b/src/devices/bus/nubus/nubus_48gc.h
index 78cf5f6d90e..d0b433bf1a6 100644
--- a/src/devices/bus/nubus/nubus_48gc.h
+++ b/src/devices/bus/nubus/nubus_48gc.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:R. Belmont
+// copyright-holders:R. Belmont, Vas Crabb
#ifndef MAME_BUS_NUBUS_NUBUS_48GC_H
#define MAME_BUS_NUBUS_NUBUS_48GC_H
@@ -21,7 +21,7 @@ class jmfb_device :
{
protected:
// construction/destruction
- jmfb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool is824);
+ jmfb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override;
@@ -29,40 +29,76 @@ protected:
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
- virtual const tiny_rom_entry *device_rom_region() const override;
// palette implementation
uint32_t palette_entries() const override;
TIMER_CALLBACK_MEMBER(vbl_tick);
-private:
- uint32_t mac_48gc_r(offs_t offset, uint32_t mem_mask = ~0);
- void mac_48gc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t jmfb_r(offs_t offset, uint32_t mem_mask = ~0);
+ void jmfb_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+
+ void dac_ctrl_w(uint8_t data);
+ void dac_data_w(uint8_t data);
+ void mode_w(uint32_t data, bool rgb);
+private:
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ void update_crtc();
+
+ uint32_t rgb_unpack(offs_t offset, uint32_t mem_mask = ~0);
+ void rgb_pack(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ required_ioport m_monitor;
+ memory_view m_vram_view;
emu_timer *m_timer;
std::vector<uint32_t> m_vram;
- uint32_t m_mode, m_vbl_disable, m_toggle, m_stride, m_base;
- uint32_t m_colors[3], m_count, m_clutoffs;
+ uint32_t m_vbl_disable, m_toggle, m_stride, m_base;
uint32_t m_registers[0x100];
- int m_xres, m_yres;
- const bool m_is824;
+ uint8_t m_preload;
+
+ uint8_t m_colors[3], m_count, m_clutoffs, m_mode;
+
+ uint16_t m_hactive, m_hbporch, m_hsync, m_hfporch;
+ uint16_t m_vactive, m_vbporch, m_vsync, m_vfporch;
+ uint16_t m_multiplier;
+ uint16_t m_modulus;
+ uint8_t m_pdiv;
};
class nubus_48gc_device : public jmfb_device
{
public:
nubus_48gc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+
+private:
+ void mac_48gc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
};
class nubus_824gc_device : public jmfb_device
{
public:
nubus_824gc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual ioport_constructor device_input_ports() const override;
+
+private:
+ void mac_824gc_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
};
// device type definition
diff --git a/src/devices/bus/nubus/nubus_spec8.cpp b/src/devices/bus/nubus/nubus_spec8.cpp
index 1135a3bd442..ee3549a2572 100644
--- a/src/devices/bus/nubus/nubus_spec8.cpp
+++ b/src/devices/bus/nubus/nubus_spec8.cpp
@@ -21,17 +21,34 @@
Configuration settings, you need to zap the PRAM before it will be
recognised properly.
+ Set breakpoint at 0x2d1e on Mac II with Ver. 1.3 card in slot 9 to catch
+ user oscillator measurement. See the measured value in D0.b when
+ PC = 0x2d6c.
+
+ Expected:
+ 2- 5 57.28 MHz
+ 6-19 bad
+ 20-22 14.32 MHz
+ 23-24 15.67 MHz
+ 25-27 17.73 MHz
+ 27- bad
+
+ Measured:
+ 14.32 MHz 20
+ 15.67 MHz 23
+ 17.73 MHz 26
+ 57.28 MHz 5
+
TODO:
* Having no oscillator installed at Y1 is not emulated.
* Interlaced modes are not understood.
- * There are lines of garbage at the bottom of the screen in some high-
- resolution modes (bottom of the virtual desktop if virtual desktop is
- enabled).
***************************************************************************/
#include "emu.h"
#include "nubus_spec8.h"
+
+#include "layout/generic.h"
#include "screen.h"
#include <algorithm>
@@ -40,10 +57,10 @@
#include "logmacro.h"
-#define SPEC8S3_SCREEN_NAME "spec8s3_screen"
+#define SPEC8S3_SCREEN_NAME "screen"
#define SPEC8S3_ROM_REGION "spec8s3_rom"
-#define VRAM_SIZE (0xc0000) // 768k of VRAM for 1024x768 @ 8 bit
+#define VRAM_SIZE (0x10'0000) // 1M of VRAM for 1024x768 @ 8 bit
static INPUT_PORTS_START( spec8s3 )
@@ -79,9 +96,12 @@ DEFINE_DEVICE_TYPE(NUBUS_SPEC8S3, nubus_spec8s3_device, "nb_sp8s3", "SuperMac Sp
void nubus_spec8s3_device::device_add_mconfig(machine_config &config)
{
+ config.set_default_layout(layout_monitors);
+
screen_device &screen(SCREEN(config, SPEC8S3_SCREEN_NAME, SCREEN_TYPE_RASTER));
screen.set_screen_update(FUNC(nubus_spec8s3_device::screen_update));
screen.set_raw(80.000_MHz_XTAL, 332*4, 64*4, 320*4, 804, 33, 801);
+ screen.set_video_attributes(VIDEO_UPDATE_SCANLINE);
}
//-------------------------------------------------
@@ -496,38 +516,10 @@ uint32_t nubus_spec8s3_device::spec8s3_r(offs_t offset, uint32_t mem_mask)
case 0x382c:
case 0x382e:
{
- /*
- * Set breakpoint at 0x2d1e on Mac II with Ver. 1.3 card in
- * slot 9 to catch user oscillator measurement. See the
- * measured value in D0.b when PC = 0x2d6c.
- *
- * Expected:
- * 2- 5 57.28 MHz
- * 6-19 bad
- * 20-22 14.32 MHz
- * 23-24 15.67 MHz
- * 25-27 17.73 MHz
- * 27- bad
- *
- * Measured:
- * 14.32 MHz 20
- * 15.67 MHz 23
- * 17.73 MHz 26
- * 57.28 MHz 5
- */
- int vpos;
+ // hack for interlace modes because screen_device doesn't support them
+ int vpos = screen().vpos();
if (m_interlace)
- {
- // hack for interlace modes because screen_device doesn't support them
- vpos = screen().vpos() - (m_crtc.v_sync() * 2);
- if (vpos >= (m_crtc.v_total() * 2))
- vpos -= m_crtc.v_total() * 2;
vpos /= 2;
- }
- else
- {
- vpos = m_crtc.v_pos(screen());
- }
return ~((vpos >> (BIT(offset, 1) ? 8 : 0)) & 0xff);
}
diff --git a/src/devices/bus/nubus/nubus_specpdq.cpp b/src/devices/bus/nubus/nubus_specpdq.cpp
index 651d7b19023..62c1aec9e29 100644
--- a/src/devices/bus/nubus/nubus_specpdq.cpp
+++ b/src/devices/bus/nubus/nubus_specpdq.cpp
@@ -21,10 +21,18 @@
There is 256 bytes of pattern RAM arranged as 32 pixels horizontally by
8 vertically.
+ TODO:
+ * Having no alternate oscillator installed is not emulated.
+ * Work out how active line length is configured.
+ * Alternate oscillator calibration is currently failing. Fixing this
+ probably requires a complete cycle-accurate Mac II.
+
***************************************************************************/
#include "emu.h"
#include "nubus_specpdq.h"
+
+#include "layout/generic.h"
#include "screen.h"
#include <algorithm>
@@ -33,10 +41,10 @@
#include "logmacro.h"
-#define SPECPDQ_SCREEN_NAME "specpdq_screen"
+#define SPECPDQ_SCREEN_NAME "screen"
#define SPECPDQ_ROM_REGION "specpdq_rom"
-#define VRAM_SIZE (0x400000)
+#define VRAM_SIZE (0x40'0000)
static INPUT_PORTS_START( specpdq )
@@ -65,9 +73,12 @@ DEFINE_DEVICE_TYPE(NUBUS_SPECPDQ, nubus_specpdq_device, "nb_spdq", "SuperMac Spe
void nubus_specpdq_device::device_add_mconfig(machine_config &config)
{
+ config.set_default_layout(layout_monitors);
+
screen_device &screen(SCREEN(config, SPECPDQ_SCREEN_NAME, SCREEN_TYPE_RASTER));
screen.set_screen_update(FUNC(nubus_specpdq_device::screen_update));
screen.set_raw(100.000_MHz_XTAL, 1'456, 108, 1'260, 915, 39, 909);
+ screen.set_video_attributes(VIDEO_UPDATE_SCANLINE);
}
//-------------------------------------------------
@@ -118,9 +129,7 @@ nubus_specpdq_device::nubus_specpdq_device(const machine_config &mconfig, device
device_palette_interface(mconfig, *this),
m_userosc(*this, "USEROSC"),
m_timer(nullptr),
- m_mode(0), m_vbl_disable(0),
- m_count(0), m_clutoffs(0),
- m_width(0), m_height(0), m_patofsx(0), m_patofsy(0), m_vram_addr(0), m_vram_src(0)
+ m_mode(0)
{
set_screen(*this, SPECPDQ_SCREEN_NAME);
}
@@ -155,14 +164,14 @@ void nubus_specpdq_device::device_start()
save_item(NAME(m_vint));
save_item(NAME(m_hdelay));
save_item(NAME(m_osc));
+ save_item(NAME(m_blit_stride));
+ save_item(NAME(m_blit_src));
+ save_item(NAME(m_blit_dst));
+ save_item(NAME(m_blit_width));
+ save_item(NAME(m_blit_height));
+ save_item(NAME(m_blit_patoffs));
+ save_item(NAME(m_blit_pat));
save_item(NAME(m_7xxxxx_regs));
- save_item(NAME(m_width));
- save_item(NAME(m_height));
- save_item(NAME(m_patofsx));
- save_item(NAME(m_patofsy));
- save_item(NAME(m_vram_addr));
- save_item(NAME(m_vram_src));
- save_item(NAME(m_pattern));
}
//-------------------------------------------------
@@ -180,18 +189,21 @@ void nubus_specpdq_device::device_reset()
std::fill(std::begin(m_colors), std::end(m_colors), 0);
m_count = 0;
m_clutoffs = 0;
- m_stride = 512 / 4;
+
+ m_stride = 0;
m_vint = 0;
m_hdelay = 0;
m_osc = 0;
+ m_blit_stride = 0;
+ m_blit_src = 0;
+ m_blit_dst = 0;
+ m_blit_width = 0;
+ m_blit_height = 0;
+ m_blit_patoffs = 0;
+ std::fill(std::begin(m_blit_pat), std::end(m_blit_pat), 0);
+
std::fill(std::begin(m_7xxxxx_regs), std::end(m_7xxxxx_regs), 0);
- m_width = 0;
- m_height = 0;
- m_patofsx = 0;
- m_patofsy = 0;
- m_vram_addr = 0;
- m_vram_src = 0;
}
@@ -202,10 +214,7 @@ TIMER_CALLBACK_MEMBER(nubus_specpdq_device::vbl_tick)
raise_slot_irq();
}
- m_timer->adjust(
- screen().time_until_pos(
- m_vint + m_crtc.v_start() - 1,
- m_crtc.h_total(16) - m_crtc.h_sync(16)));
+ m_timer->adjust(screen().time_until_pos(m_vint));
}
/***************************************************************************
@@ -272,10 +281,7 @@ void nubus_specpdq_device::update_crtc()
active,
m_crtc.frame_time(16, oscillator));
- m_timer->adjust(
- screen().time_until_pos(
- m_vint + m_crtc.v_start() - 1,
- m_crtc.h_total(16) - m_crtc.h_sync(16)));
+ m_timer->adjust(screen().time_until_pos(m_vint + m_crtc.v_start() - 1));
}
}
@@ -410,7 +416,7 @@ void nubus_specpdq_device::specpdq_w(offs_t offset, uint32_t data, uint32_t mem_
else if ((offset >= 0x181000) && (offset <= 0x18103f))
{
// 256 pixels worth at 8 bpp
- m_pattern[offset & 0x3f] = ~data;
+ m_blit_pat[offset & 0x3f] = ~data;
}
else switch (offset)
{
@@ -424,7 +430,6 @@ void nubus_specpdq_device::specpdq_w(offs_t offset, uint32_t data, uint32_t mem_
case 0xc0054:
case 0xc0056:
- // same value written here and to c007a:c0078
m_stride &= BIT(offset, 1) ? 0x00ff : 0xff00;
m_stride |= (~data & 0xff000000) >> (BIT(offset, 1) ? 16 : 24);
LOG("%s: %u to stride\n", machine().describe_context(), m_stride);
@@ -451,6 +456,13 @@ void nubus_specpdq_device::specpdq_w(offs_t offset, uint32_t data, uint32_t mem_
update_crtc();
break;
+ case 0xc0078:
+ case 0xc007a:
+ m_blit_stride &= BIT(offset, 1) ? 0x00ff : 0xff00;
+ m_blit_stride |= (~data & 0xff000000) >> (BIT(offset, 1) ? 16 : 24);
+ LOG("%s: %u to blitter stride\n", machine().describe_context(), m_blit_stride);
+ break;
+
case 0x120000: // DAC address
LOG("%s: %08x to DAC control\n", machine().describe_context(), data);
m_clutoffs = ~data & 0xff;
@@ -496,7 +508,6 @@ void nubus_specpdq_device::specpdq_w(offs_t offset, uint32_t data, uint32_t mem_
m_shiftreg.write_control(*this, data);
break;
- // blitter control
case 0x182006:
data = ~data;
LOG("%08x (%d) to blitter ctrl 1 %s rectangle\n", data, data, machine().describe_context());
@@ -505,55 +516,18 @@ void nubus_specpdq_device::specpdq_w(offs_t offset, uint32_t data, uint32_t mem_
case 0x182007:
data = ~data;
LOG("%s: %08x to blitter command\n", machine().describe_context(), data);
-
- if (data == 2)
- {
- // fill rectangle
- auto const source = util::big_endian_cast<uint8_t const>(m_pattern);
- auto dest = util::big_endian_cast<uint8_t>(&m_vram[0]) + m_vram_addr;
- uint32_t const patofsx = (m_vram_addr & 0x3) + m_patofsx;
- LOG("Fill rectangle with %02x %02x %02x %02x, adr %x (%d, %d) width %d height %d delta %d %d\n", source[0], source[1], source[2], source[3], m_vram_addr, m_vram_addr % 1152, m_vram_addr / 1152, m_width, m_height, m_patofsx, m_patofsy);
- for (int y = 0; y <= m_height; y++)
- {
- for (int x = 0; x < m_width; x++)
- {
- dest[x] = source[(((m_patofsy + y) & 0x7) << 5) + ((patofsx + x) & 0x1f)];
- }
- dest += m_stride * 4;
- }
- }
- else if (data == 0x100)
- {
- LOG("Copy rectangle forwards, width %d height %d dst %x (%d, %d) src %x (%d, %d)\n", m_width, m_height, m_vram_addr, m_vram_addr % 1152, m_vram_addr / 1152, m_vram_src, m_vram_src % 1152, m_vram_src / 1152);
- auto source = util::big_endian_cast<uint8_t const>(&m_vram[0]) + m_vram_src;
- auto dest = util::big_endian_cast<uint8_t>(&m_vram[0]) + m_vram_addr;
- for (int y = 0; y <= m_height; y++)
- {
- for (int x = 0; x < m_width; x++)
- {
- dest[x] = source[x];
- }
- source += m_stride * 4;
- dest += m_stride * 4;
- }
- }
- else if (data == 0x101)
- {
- LOG("Copy rectangle backwards, width %d height %d dst %x (%d, %d) src %x (%d, %d)\n", m_width, m_height, m_vram_addr, m_vram_addr % 1152, m_vram_addr / 1152, m_vram_src, m_vram_src % 1152, m_vram_src / 1152);
- auto source = util::big_endian_cast<uint8_t const>(&m_vram[0]) + m_vram_src;
- auto dest = util::big_endian_cast<uint8_t>(&m_vram[0]) + m_vram_addr;
- for (int y = 0; y <= m_height; y++)
- {
- for (int x = 0; x < m_width; x++)
- {
- dest[-x] = source[-x];
- }
- source -= m_stride * 4;
- dest -= m_stride * 4;
- }
- }
- else
+ switch (data)
{
+ case 0x002:
+ blitter_pattern_fill();
+ break;
+ case 0x100:
+ blitter_copy_forward();
+ break;
+ case 0x101:
+ blitter_copy_backward();
+ break;
+ default:
logerror("Unknown blitter command %08x\n", data);
}
break;
@@ -561,32 +535,31 @@ void nubus_specpdq_device::specpdq_w(offs_t offset, uint32_t data, uint32_t mem_
case 0x182008:
data = ~data;
LOG("%s: %08x (%d) to blitter ctrl 2 rectangle\n", machine().describe_context(), data, data);
- m_patofsx = BIT(data, 0, 3);
- m_patofsy = BIT(data, 3, 3);
+ m_blit_patoffs = (data >> 3) & 0x1fff;
break;
case 0x182009:
data = ~data;
LOG("%s: %08x to blitter destination\n", machine().describe_context(), data);
- m_vram_addr = data >> 2;
+ m_blit_dst = (data >> 2) & 0x3fffff;
break;
case 0x18200a:
data = ~data;
LOG("%s: %08x to blitter source\n", machine().describe_context(), data);
- m_vram_src = data >> 2;
+ m_blit_src = (data >> 2) & 0x3fffff;
break;
case 0x18200b:
data = ~data;
LOG("%s: %08x (%d) to blitter height\n", machine().describe_context(), data, data);
- m_height = data & 0xffff;
+ m_blit_height = data;
break;
case 0x18200e:
data = ~data;
LOG("%s: %08x (%d) to blitter width\n", machine().describe_context(), data, data);
- m_width = data;
+ m_blit_width = data;
break;
default:
@@ -614,7 +587,7 @@ uint32_t nubus_specpdq_device::specpdq_r(offs_t offset, uint32_t mem_mask)
* 57.28 MHz 1 detected as 55.00 MHz
* 64.00 MHz 9 detected as 57.28 MHz
*/
- return ~((u32(m_crtc.v_pos(screen())) << (BIT(offset, 1) ? 16 : 24)) & 0xff000000);
+ return ~((u32(screen().vpos()) << (BIT(offset, 1) ? 16 : 24)) & 0xff000000);
}
if (offset >= 0xc0000 && offset < 0x100000)
@@ -635,3 +608,58 @@ uint32_t nubus_specpdq_device::vram_r(offs_t offset, uint32_t mem_mask)
{
return ~m_vram[offset];
}
+
+void nubus_specpdq_device::blitter_pattern_fill()
+{
+ auto const source = util::big_endian_cast<uint8_t const>(m_blit_pat);
+ auto const dest = util::big_endian_cast<uint8_t>(&m_vram[0]);
+ uint32_t const patofsx = m_blit_dst & 0x3;
+ uint32_t const stride = m_blit_stride * 4;
+ LOG("Fill rectangle with %02x %02x %02x %02x, adr %x (%d, %d) width %d height %d delta %d\n",
+ source[0], source[1], source[2], source[3],
+ m_blit_dst, m_blit_dst % (m_blit_stride * 4), m_blit_dst / (m_blit_stride * 4),
+ m_blit_width, m_blit_height, m_blit_patoffs);
+ for (int y = 0; y <= m_blit_height; y++)
+ {
+ for (int x = 0; x < m_blit_width; x++)
+ {
+ dest[(m_blit_dst + (y * stride) + x) & (VRAM_SIZE - 1)] = source[(((m_blit_patoffs + y) & 0x7) << 5) | ((patofsx + x) & 0x1f)];
+ }
+ }
+}
+
+void nubus_specpdq_device::blitter_copy_forward()
+{
+ LOG("Copy rectangle forwards, width %d height %d dst %x (%d, %d) src %x (%d, %d)\n",
+ m_blit_width, m_blit_height,
+ m_blit_dst, m_blit_dst % (m_blit_stride * 4), m_blit_dst / (m_blit_stride * 4),
+ m_blit_src, m_blit_src % (m_blit_stride * 4), m_blit_src / (m_blit_stride * 4));
+ auto const source = util::big_endian_cast<uint8_t const>(&m_vram[0]);
+ auto const dest = util::big_endian_cast<uint8_t>(&m_vram[0]);
+ uint32_t const stride = m_blit_stride * 4;
+ for (int y = 0; y <= m_blit_height; y++)
+ {
+ for (int x = 0; x < m_blit_width; x++)
+ {
+ dest[(m_blit_dst + (y * stride) + x) & (VRAM_SIZE - 1)] = source[(m_blit_src + (y * stride) + x) & (VRAM_SIZE - 1)];
+ }
+ }
+}
+
+void nubus_specpdq_device::blitter_copy_backward()
+{
+ LOG("Copy rectangle backwards, width %d height %d dst %x (%d, %d) src %x (%d, %d)\n",
+ m_blit_width, m_blit_height,
+ m_blit_dst, m_blit_dst % (m_blit_stride * 4), m_blit_dst / (m_blit_stride * 4),
+ m_blit_src, m_blit_src % (m_blit_stride * 4), m_blit_src / (m_blit_stride * 4));
+ auto const source = util::big_endian_cast<uint8_t const>(&m_vram[0]);
+ auto const dest = util::big_endian_cast<uint8_t>(&m_vram[0]);
+ uint32_t const stride = m_blit_stride * 4;
+ for (int y = 0; y <= m_blit_height; y++)
+ {
+ for (int x = 0; x < m_blit_width; x++)
+ {
+ dest[(m_blit_dst - (y * stride) - x) & (VRAM_SIZE - 1)] = source[(m_blit_src - (y * stride) - x) & (VRAM_SIZE - 1)];
+ }
+ }
+}
diff --git a/src/devices/bus/nubus/nubus_specpdq.h b/src/devices/bus/nubus/nubus_specpdq.h
index 53c3b9feb30..62b24c062b5 100644
--- a/src/devices/bus/nubus/nubus_specpdq.h
+++ b/src/devices/bus/nubus/nubus_specpdq.h
@@ -46,6 +46,10 @@ private:
uint32_t vram_r(offs_t offset, uint32_t mem_mask = ~0);
void vram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ void blitter_pattern_fill();
+ void blitter_copy_forward();
+ void blitter_copy_backward();
+
void update_crtc();
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
@@ -65,10 +69,13 @@ private:
uint8_t m_hdelay;
uint8_t m_osc;
- uint32_t m_7xxxxx_regs[0x100000/4];
- uint32_t m_width, m_height, m_patofsx, m_patofsy;
- uint32_t m_vram_addr, m_vram_src;
- uint32_t m_pattern[64];
+ uint16_t m_blit_stride;
+ uint32_t m_blit_src, m_blit_dst;
+ uint32_t m_blit_width, m_blit_height;
+ uint8_t m_blit_patoffs;
+ uint32_t m_blit_pat[64];
+
+ uint32_t m_7xxxxx_regs[0x100000 / 4];
};
diff --git a/src/devices/bus/nubus/supermac.cpp b/src/devices/bus/nubus/supermac.cpp
index af7ba20e9c1..c8f00e81003 100644
--- a/src/devices/bus/nubus/supermac.cpp
+++ b/src/devices/bus/nubus/supermac.cpp
@@ -131,13 +131,6 @@ bool supermac_spec_crtc::valid(device_t &device) const
}
-int supermac_spec_crtc::v_pos(screen_device const &screen) const
-{
- int const vpos = screen.vpos() + m_vsync + 1;
- return (vpos <= m_vtotal) ? vpos : (vpos - m_vtotal - 1);
-}
-
-
void supermac_spec_shift_reg::register_save(device_t &device)
{
device.save_item(NAME(m_shift_data));
diff --git a/src/devices/bus/nubus/supermac.h b/src/devices/bus/nubus/supermac.h
index d656eb6c4af..9fb4c93f326 100644
--- a/src/devices/bus/nubus/supermac.h
+++ b/src/devices/bus/nubus/supermac.h
@@ -24,9 +24,9 @@ public:
uint32_t h_active(uint32_t scale) const noexcept
{ return (m_hend - m_hstart) * scale; }
uint32_t h_start(uint32_t scale) const noexcept
- { return (m_hstart - m_hsync) * scale; }
+ { return (m_hstart + 1) * scale; }
uint32_t h_end(uint32_t scale) const noexcept
- { return (m_hend - m_hsync) * scale; }
+ { return (m_hend + 1) * scale; }
uint16_t v_sync() const noexcept
{ return m_vsync + 1; }
@@ -35,15 +35,13 @@ public:
uint32_t v_active() const noexcept
{ return (m_vend - m_vstart); }
uint16_t v_start() const noexcept
- { return m_vstart - m_vsync; }
+ { return m_vstart + 1; }
uint16_t v_end() const noexcept
- { return m_vend - m_vsync; }
+ { return m_vend + 1; }
attoseconds_t frame_time(uint32_t scale, XTAL const &osc) const noexcept
{ return attotime::from_ticks((m_htotal + 1) * (m_vtotal + 1) * scale, osc).attoseconds(); }
- int v_pos(screen_device const &screen) const;
-
private:
uint16_t m_hsync, m_hstart, m_hend, m_htotal;
uint16_t m_vsync, m_vstart, m_vend, m_vtotal;
diff --git a/src/devices/bus/pc_kbd/cherry_mx1500.cpp b/src/devices/bus/pc_kbd/cherry_mx1500.cpp
new file mode 100644
index 00000000000..4fc451d8354
--- /dev/null
+++ b/src/devices/bus/pc_kbd/cherry_mx1500.cpp
@@ -0,0 +1,333 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Cherry MX 1500 101/102-key keyboards
+
+ These AT and PS/2-compatible keyboards have a built-in smartcard reader
+ programmed to read medical cards. The electrical interface is nominally
+ ISO 7816-2 compliant, but none of the three supported synchronous
+ protocols adheres to the ISO 7816-3 standard. (One of these formats
+ appears to be simply a 24C04 I²C EEPROM.) The three LEDs at the top
+ right of the keyboard (Error, Data, Power) are related to the smartcard
+ reader, as are several undocumented keyboard commands. All this
+ additional functionality is currently unemulated.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cherry_mx1500.h"
+
+#include "cpu/mcs51/mcs51.h"
+
+
+// device type definition
+DEFINE_DEVICE_TYPE(CHERRY_G80_1500, cherry_g80_1500_device, "g80_1500", "Cherry G80-1500 Multi-Function Keyboard")
+
+cherry_g80_1500_device::cherry_g80_1500_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, CHERRY_G80_1500, tag, owner, clock)
+ , device_pc_kbd_interface(mconfig, *this)
+ , m_mcu(*this, "mcu")
+ , m_keys(*this, "ROW%u", 0U)
+ , m_leds(*this, "led%u", 0U)
+ , m_p1(0xff)
+{
+}
+
+void cherry_g80_1500_device::device_start()
+{
+ m_leds.resolve();
+
+ set_pc_kbdc_device();
+
+ save_item(NAME(m_p1));
+}
+
+
+static INPUT_PORTS_START(g80_1500)
+ PORT_START("CONFIG")
+ PORT_CONFNAME(3, 0, "Layout")
+ PORT_CONFSETTING(0, "US-International (G80-1500 HAU)")
+ PORT_CONFSETTING(1, "German (G80-1500 HAD)")
+ PORT_CONFSETTING(2, "French (G80-1500 HAF)")
+ //PORT_CONFSETTING(3, "UK-English (G80-1500 HAG)")
+
+ PORT_START("ROW0")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_CODE(KEYCODE_F7)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK)) PORT_CODE(KEYCODE_ASTERISK)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD)) PORT_CODE(KEYCODE_PLUS_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR('<') PORT_CODE(KEYCODE_COMMA) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR(';') PORT_CODE(KEYCODE_COMMA) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(';') PORT_CHAR('.') PORT_CODE(KEYCODE_COMMA) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CHAR('l') PORT_CHAR('L') PORT_CODE(KEYCODE_L)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CHAR('o') PORT_CHAR('O') PORT_CODE(KEYCODE_O)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('9') PORT_CHAR('(') PORT_CODE(KEYCODE_9) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('9') PORT_CHAR(')') PORT_CHAR(']') PORT_CODE(KEYCODE_9) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x00e7) PORT_CHAR('9') PORT_CHAR('^') PORT_CODE(KEYCODE_9) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_CODE(KEYCODE_ENTER_PAD)
+
+ PORT_START("ROW1")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_CODE(KEYCODE_F6)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) PORT_CODE(KEYCODE_MINUS_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) PORT_CODE(KEYCODE_3_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CHAR('m') PORT_CHAR('M') PORT_CODE(KEYCODE_M) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M \xCE\xBC") PORT_CHAR('m') PORT_CHAR('M') PORT_CHAR(0x03bc) PORT_CODE(KEYCODE_M) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(',') PORT_CHAR('?') PORT_CODE(KEYCODE_M) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("K") PORT_CHAR('k') PORT_CHAR('K') PORT_CODE(KEYCODE_K)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("I") PORT_CHAR('i') PORT_CHAR('I') PORT_CODE(KEYCODE_I)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('8') PORT_CHAR('*') PORT_CODE(KEYCODE_8) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('8') PORT_CHAR('(') PORT_CHAR('[') PORT_CODE(KEYCODE_8) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('_') PORT_CHAR('8') PORT_CHAR('\\') PORT_CODE(KEYCODE_8) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) PORT_CODE(KEYCODE_DEL_PAD)
+
+ PORT_START("ROW2")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F10)) PORT_CODE(KEYCODE_F10)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(PGUP)) PORT_CODE(KEYCODE_PGUP)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(PGDN)) PORT_CODE(KEYCODE_PGDN)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RSHIFT)) PORT_CODE(KEYCODE_RSHIFT)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_UNUSED) PORT_CONDITION("CONFIG", 3, EQUALS, 0) // INT 2 key
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('#') PORT_CHAR('\'') PORT_CODE(KEYCODE_BACKSLASH) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('*') PORT_CHAR(0x03bc) PORT_CODE(KEYCODE_BACKSLASH) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(']') PORT_CHAR('}') PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('+') PORT_CHAR('*') PORT_CHAR('~') PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('$') PORT_CHAR(0x00a3) PORT_CHAR(0x00a4) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('=') PORT_CHAR('+') PORT_CODE(KEYCODE_EQUALS) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\xC2\xB4 `") PORT_CODE(KEYCODE_EQUALS) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('=') PORT_CHAR('+') PORT_CHAR('}') PORT_CODE(KEYCODE_EQUALS) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_CODE(KEYCODE_DOWN)
+
+ PORT_START("ROW3")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_CODE(KEYCODE_F9)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(HOME)) PORT_CODE(KEYCODE_HOME)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(END)) PORT_CODE(KEYCODE_END)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('/') PORT_CHAR('?') PORT_CODE(KEYCODE_SLASH) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('_') PORT_CODE(KEYCODE_SLASH) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('!') PORT_CHAR(0x00a7) PORT_CODE(KEYCODE_SLASH) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\'') PORT_CHAR('"') PORT_CODE(KEYCODE_QUOTE) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\xC3\x84") PORT_CHAR(0x00e4) PORT_CHAR(0x00c4) PORT_CODE(KEYCODE_QUOTE) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x00f9) PORT_CHAR('%') PORT_CODE(KEYCODE_QUOTE) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('[') PORT_CHAR('{') PORT_CODE(KEYCODE_OPENBRACE) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\xC3\x9C") PORT_CHAR(0x00fc) PORT_CHAR(0x00dc) PORT_CODE(KEYCODE_OPENBRACE) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("^ \xC2\xA8") PORT_CODE(KEYCODE_OPENBRACE) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('_') PORT_CODE(KEYCODE_MINUS) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x00df) PORT_CHAR('?') PORT_CHAR('\\') PORT_CODE(KEYCODE_MINUS) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(')') PORT_CHAR(0x00b0) PORT_CHAR(']') PORT_CODE(KEYCODE_MINUS) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) PORT_CODE(KEYCODE_LEFT)
+
+ PORT_START("ROW4")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_CODE(KEYCODE_F8)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD)) PORT_CODE(KEYCODE_SLASH_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) PORT_CODE(KEYCODE_1_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('.') PORT_CHAR('>') PORT_CODE(KEYCODE_STOP) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('.') PORT_CHAR(':') PORT_CODE(KEYCODE_STOP) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(':') PORT_CHAR('/') PORT_CODE(KEYCODE_STOP) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(';') PORT_CHAR(':') PORT_CODE(KEYCODE_COLON) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("\xC3\x96") PORT_CHAR(0x00f6) PORT_CHAR(0x00d6) PORT_CODE(KEYCODE_COLON) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("M") PORT_CHAR('m') PORT_CHAR('M') PORT_CODE(KEYCODE_COLON) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("P") PORT_CHAR('p') PORT_CHAR('P') PORT_CODE(KEYCODE_P)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('0') PORT_CHAR(')') PORT_CODE(KEYCODE_0) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('0') PORT_CHAR('=') PORT_CHAR('}') PORT_CODE(KEYCODE_0) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x00e0) PORT_CHAR('0') PORT_CHAR('@') PORT_CODE(KEYCODE_0) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RCONTROL)) PORT_CODE(KEYCODE_RCONTROL)
+
+ PORT_START("ROW5")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_CODE(KEYCODE_F5)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) PORT_CODE(KEYCODE_9_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) PORT_CODE(KEYCODE_6_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("N") PORT_CHAR('n') PORT_CHAR('N') PORT_CODE(KEYCODE_N)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("J") PORT_CHAR('j') PORT_CHAR('J') PORT_CODE(KEYCODE_J)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("U") PORT_CHAR('u') PORT_CHAR('U') PORT_CODE(KEYCODE_U)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('7') PORT_CHAR('&') PORT_CODE(KEYCODE_7) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('7') PORT_CHAR('/') PORT_CHAR('{') PORT_CODE(KEYCODE_7) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x00e8) PORT_CHAR('7') PORT_CHAR('`') PORT_CODE(KEYCODE_7) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CHAR(0x1b) PORT_CODE(KEYCODE_ESC)
+
+ PORT_START("ROW6")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_CODE(KEYCODE_F2)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) PORT_CODE(KEYCODE_7_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_CODE(KEYCODE_UP)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("C") PORT_CHAR('c') PORT_CHAR('C') PORT_CODE(KEYCODE_C)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("F") PORT_CHAR('f') PORT_CHAR('F') PORT_CODE(KEYCODE_F)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("R") PORT_CHAR('r') PORT_CHAR('R') PORT_CODE(KEYCODE_R)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('4') PORT_CHAR('$') PORT_CODE(KEYCODE_4) PORT_CONDITION("CONFIG", 3, NOTEQUALS, 2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\'') PORT_CHAR('4') PORT_CHAR('{') PORT_CODE(KEYCODE_4) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_CODE(KEYCODE_F1)
+
+ PORT_START("ROW7")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(PRTSCR)) PORT_CODE(KEYCODE_PRTSCR)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) PORT_CODE(KEYCODE_8_PAD)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) PORT_CODE(KEYCODE_2_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("X") PORT_CHAR('x') PORT_CHAR('X') PORT_CODE(KEYCODE_X)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("D") PORT_CHAR('d') PORT_CHAR('D') PORT_CODE(KEYCODE_D)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("E") PORT_CHAR('e') PORT_CHAR('E') PORT_CODE(KEYCODE_E)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('3') PORT_CHAR('#') PORT_CODE(KEYCODE_3) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('3') PORT_CHAR(0x00a7) PORT_CHAR(0x00b3) PORT_CODE(KEYCODE_3) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('"') PORT_CHAR('3') PORT_CHAR('#') PORT_CODE(KEYCODE_3) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) PORT_CODE(KEYCODE_0_PAD)
+
+ PORT_START("ROW8")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK)) PORT_CODE(KEYCODE_SCRLOCK)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(PAUSE)) PORT_CODE(KEYCODE_PAUSE)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) PORT_CODE(KEYCODE_5_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_Z) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CHAR('y') PORT_CHAR('Y') PORT_CODE(KEYCODE_Z) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CHAR('w') PORT_CHAR('W') PORT_CODE(KEYCODE_Z) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("S") PORT_CHAR('s') PORT_CHAR('S') PORT_CODE(KEYCODE_S)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("W") PORT_CHAR('w') PORT_CHAR('W') PORT_CODE(KEYCODE_W) PORT_CONDITION("CONFIG", 3, NOTEQUALS, 2)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_W) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('2') PORT_CHAR('@') PORT_CODE(KEYCODE_2) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('2') PORT_CHAR('"') PORT_CHAR(0x00b2) PORT_CODE(KEYCODE_2) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x00e9) PORT_CHAR('2') PORT_CHAR('~') PORT_CODE(KEYCODE_2) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) PORT_CODE(KEYCODE_RIGHT)
+
+ PORT_START("ROW9")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F12)) PORT_CODE(KEYCODE_F12)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(INSERT)) PORT_CODE(KEYCODE_INSERT)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(DEL)) PORT_CODE(KEYCODE_DEL)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_UNUSED) PORT_CONDITION("CONFIG", 3, EQUALS, 0) // INT 1 key
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('<') PORT_CHAR('>') PORT_CHAR('|') PORT_CODE(KEYCODE_BACKSLASH2) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('<') PORT_CHAR('>') PORT_CODE(KEYCODE_BACKSLASH2) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_A) PORT_CONDITION("CONFIG", 3, NOTEQUALS, 2)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CHAR('q') PORT_CHAR('Q') PORT_CODE(KEYCODE_A) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q") PORT_CHAR('q') PORT_CHAR('Q') PORT_CODE(KEYCODE_Q) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Q @") PORT_CHAR('q') PORT_CHAR('Q') PORT_CHAR('@') PORT_CODE(KEYCODE_Q) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("A") PORT_CHAR('a') PORT_CHAR('A') PORT_CODE(KEYCODE_Q) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('1') PORT_CHAR('!') PORT_CODE(KEYCODE_1) PORT_CONDITION("CONFIG", 3, NOTEQUALS, 2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('&') PORT_CHAR('1') PORT_CODE(KEYCODE_1) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) PORT_CODE(KEYCODE_LCONTROL)
+
+ PORT_START("ROW10")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F11)) PORT_CODE(KEYCODE_F11)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x08) PORT_CODE(KEYCODE_BACKSPACE)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x0d) PORT_CODE(KEYCODE_ENTER)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_SHIFT_1) PORT_CODE(KEYCODE_LSHIFT)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK)) PORT_CODE(KEYCODE_CAPSLOCK)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x09) PORT_CODE(KEYCODE_TAB)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('`') PORT_CHAR('~') PORT_CODE(KEYCODE_TILDE) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('^') PORT_CHAR(0x00b0) PORT_CODE(KEYCODE_TILDE) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(0x00b2) PORT_CODE(KEYCODE_TILDE) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(' ') PORT_CODE(KEYCODE_SPACE)
+
+ PORT_START("ROW11")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_CODE(KEYCODE_F3)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(NUMLOCK)) PORT_CODE(KEYCODE_NUMLOCK)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) PORT_CODE(KEYCODE_4_PAD)
+ PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("V") PORT_CHAR('v') PORT_CHAR('V') PORT_CODE(KEYCODE_V)
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("G") PORT_CHAR('g') PORT_CHAR('G') PORT_CODE(KEYCODE_G)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("T") PORT_CHAR('t') PORT_CHAR('T') PORT_CODE(KEYCODE_T)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('5') PORT_CHAR('%') PORT_CODE(KEYCODE_5) PORT_CONDITION("CONFIG", 3, NOTEQUALS, 2)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('(') PORT_CHAR('5') PORT_CHAR('[') PORT_CODE(KEYCODE_5) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(RALT)) PORT_CODE(KEYCODE_RALT) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Alt Gr") PORT_CHAR(UCHAR_SHIFT_2) PORT_CODE(KEYCODE_RALT) PORT_CONDITION("CONFIG", 3, NOTEQUALS, 0)
+
+ PORT_START("ROW12")
+ PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_CODE(KEYCODE_F4)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('\\') PORT_CHAR('|') PORT_CODE(KEYCODE_BACKSLASH) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) PORT_CONDITION("CONFIG", 3, NOTEQUALS, 0)
+ PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("B") PORT_CHAR('b') PORT_CHAR('B') PORT_CODE(KEYCODE_B)
+ PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_UNKNOWN) // smartcard-related
+ PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("H") PORT_CHAR('h') PORT_CHAR('H') PORT_CODE(KEYCODE_H)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Y") PORT_CHAR('y') PORT_CHAR('Y') PORT_CODE(KEYCODE_Y) PORT_CONDITION("CONFIG", 3, NOTEQUALS, 1)
+ PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("Z") PORT_CHAR('z') PORT_CHAR('Z') PORT_CODE(KEYCODE_Y) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('6') PORT_CHAR('^') PORT_CODE(KEYCODE_6) PORT_CONDITION("CONFIG", 3, EQUALS, 0)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('6') PORT_CHAR('&') PORT_CODE(KEYCODE_6) PORT_CONDITION("CONFIG", 3, EQUALS, 1)
+ PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR('-') PORT_CHAR('6') PORT_CHAR('|') PORT_CODE(KEYCODE_6) PORT_CONDITION("CONFIG", 3, EQUALS, 2)
+ PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_CHAR(UCHAR_MAMEKEY(LALT)) PORT_CODE(KEYCODE_LALT)
+INPUT_PORTS_END
+
+ioport_constructor cherry_g80_1500_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(g80_1500);
+}
+
+
+WRITE_LINE_MEMBER(cherry_g80_1500_device::data_write)
+{
+ m_mcu->set_input_line(MCS51_INT1_LINE, state ? CLEAR_LINE : ASSERT_LINE);
+}
+
+void cherry_g80_1500_device::mcu_p1_w(u8 data)
+{
+ // P1.7 is clock output to smartcard (TODO)
+ m_p1 = data;
+}
+
+u8 cherry_g80_1500_device::mcu_p3_r()
+{
+ // P3.0 (RXD) must be high to enable keycode output
+ // P3.4 (T0) is smartcard-related (TODO)
+ return m_pc_kbdc->clock_signal() ? 0xff : 0xfe;
+}
+
+void cherry_g80_1500_device::mcu_p3_w(u8 data)
+{
+ // P3.1 (TXD) is serial data output to PC
+ m_pc_kbdc->data_write_from_kb(BIT(data, 1));
+
+ // P3.2 (INT0) is clock output to PC
+ m_pc_kbdc->clock_write_from_kb(BIT(data, 2));
+
+ // P3.5 (T1) is serial data output to smartcard (TODO)
+}
+
+u8 cherry_g80_1500_device::matrix_r(offs_t offset)
+{
+ u16 strobe = u16(m_p1) << 8 | offset >> 8;
+
+ u8 data = 0xff;
+ for (int i = 0; i < 13; i++)
+ {
+ if (BIT(strobe, 14))
+ data &= m_keys[i]->read();
+
+ // Skip over P1.1
+ if (i == 4)
+ strobe <<= 2;
+ else
+ strobe <<= 1;
+ }
+
+ return ~data;
+}
+
+void cherry_g80_1500_device::outputs_w(offs_t offset, u8 data)
+{
+ // Bit 0 = Scroll Lock key LED
+ // Bit 1 = Caps Lock key LED
+ // Bit 2 = Num Lock key LED
+ for (int i = 0; i < 3; i++)
+ m_leds[i] = BIT(data, i);
+
+ // TODO: upper bits = other LEDs and smartcard-related signals
+}
+
+
+void cherry_g80_1500_device::prog_map(address_map &map)
+{
+ map(0x0000, 0x7fff).rom().region("eprom", 0);
+}
+
+void cherry_g80_1500_device::ext_map(address_map &map)
+{
+ map(0x0000, 0xffff).rw(FUNC(cherry_g80_1500_device::matrix_r), FUNC(cherry_g80_1500_device::outputs_w));
+}
+
+void cherry_g80_1500_device::device_add_mconfig(machine_config &config)
+{
+ i8032_device &mcu(I8032(config, m_mcu, 7'392'000)); // exact type and clock unknown (might actually use a more conventional 7.3728 MHz XTAL, as on G80-1000)
+ mcu.set_addrmap(AS_PROGRAM, &cherry_g80_1500_device::prog_map);
+ mcu.set_addrmap(AS_IO, &cherry_g80_1500_device::ext_map);
+ mcu.port_out_cb<1>().set(FUNC(cherry_g80_1500_device::mcu_p1_w));
+ mcu.port_in_cb<3>().set(FUNC(cherry_g80_1500_device::mcu_p3_r));
+ mcu.port_out_cb<3>().set(FUNC(cherry_g80_1500_device::mcu_p3_w));
+}
+
+ROM_START(g80_1500)
+ ROM_REGION(0x8000, "eprom", 0)
+ ROM_LOAD("nm27c256q_635-0945 index 05.bin", 0x0000, 0x8000, CRC(223714f4) SHA1(009fc939f86bf70d288523446e292095d9706ab2))
+ROM_END
+
+const tiny_rom_entry *cherry_g80_1500_device::device_rom_region() const
+{
+ return ROM_NAME(g80_1500);
+}
diff --git a/src/devices/bus/pc_kbd/cherry_mx1500.h b/src/devices/bus/pc_kbd/cherry_mx1500.h
new file mode 100644
index 00000000000..902ee7a40f8
--- /dev/null
+++ b/src/devices/bus/pc_kbd/cherry_mx1500.h
@@ -0,0 +1,44 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_BUS_PC_KBD_CHERRY_MX1500_H
+#define MAME_BUS_PC_KBD_CHERRY_MX1500_H
+
+#pragma once
+
+#include "pc_kbdc.h"
+
+class cherry_g80_1500_device : public device_t, public device_pc_kbd_interface
+{
+public:
+ cherry_g80_1500_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual DECLARE_WRITE_LINE_MEMBER(data_write) override;
+
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+private:
+ void mcu_p1_w(u8 data);
+ u8 mcu_p3_r();
+ void mcu_p3_w(u8 data);
+ u8 matrix_r(offs_t offset);
+ void outputs_w(offs_t offset, u8 data);
+
+ void prog_map(address_map &map);
+ void ext_map(address_map &map);
+
+ required_device<cpu_device> m_mcu;
+ required_ioport_array<13> m_keys;
+ output_finder<3> m_leds;
+
+ u8 m_p1;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(CHERRY_G80_1500, cherry_g80_1500_device)
+
+#endif // MAME_BUS_PC_KBD_CHERRY_MX1500_H
diff --git a/src/devices/bus/pc_kbd/keyboards.cpp b/src/devices/bus/pc_kbd/keyboards.cpp
index ff6e5a65d0a..abb8524df06 100644
--- a/src/devices/bus/pc_kbd/keyboards.cpp
+++ b/src/devices/bus/pc_kbd/keyboards.cpp
@@ -3,6 +3,7 @@
#include "emu.h"
#include "keyboards.h"
+#include "cherry_mx1500.h"
#include "ec1841.h"
#include "iskr1030.h"
#include "keytro.h"
@@ -30,6 +31,7 @@ void pc_at_keyboards(device_slot_interface &device)
device.option_add(STR_KBD_IBM_PC_AT_84, PC_KBD_IBM_PC_AT_84);
device.option_add(STR_KBD_IBM_3270PC_122, PC_KBD_IBM_3270PC_122);
device.option_add(STR_KBD_IBM_PC_AT_101, PC_KBD_IBM_PC_AT_101);
+ device.option_add(STR_KBD_CHERRY_G80_1500, CHERRY_G80_1500);
}
void ps2_mice(device_slot_interface &device)
diff --git a/src/devices/bus/pc_kbd/keyboards.h b/src/devices/bus/pc_kbd/keyboards.h
index 408a98628c4..4c87848c0a2 100644
--- a/src/devices/bus/pc_kbd/keyboards.h
+++ b/src/devices/bus/pc_kbd/keyboards.h
@@ -28,6 +28,7 @@ void pc_xt_keyboards(device_slot_interface &device);
#define STR_KBD_IBM_PC_AT_84 "pcat"
#define STR_KBD_IBM_3270PC_122 "3270pc"
#define STR_KBD_IBM_PC_AT_101 "pcat101"
+#define STR_KBD_CHERRY_G80_1500 "g80_1500"
void pc_at_keyboards(device_slot_interface &device);
diff --git a/src/emu/layout/generic.h b/src/emu/layout/generic.h
index 502e38e0765..4249c3ef68b 100644
--- a/src/emu/layout/generic.h
+++ b/src/emu/layout/generic.h
@@ -21,6 +21,9 @@
// no screens layouts
extern const internal_layout layout_noscreens; // for screenless systems
+// single screen layouts
+extern const internal_layout layout_monitors; // common monitor aspect ratios
+
// dual screen layouts
extern const internal_layout layout_dualhsxs; // dual 4:3 screens side-by-side
extern const internal_layout layout_dualhovu; // dual 4:3 screens above and below
diff --git a/src/emu/layout/monitors.lay b/src/emu/layout/monitors.lay
new file mode 100644
index 00000000000..c6391b16a12
--- /dev/null
+++ b/src/emu/layout/monitors.lay
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<!--
+license:CC0
+-->
+<mamelayout version="2">
+ <view name="4:3 Standard">
+ <screen tag="screen">
+ <bounds left="0" top="0" right="4" bottom="3" />
+ </screen>
+ </view>
+ <view name="3:4 Portrait">
+ <screen tag="screen">
+ <bounds left="0" top="0" right="3" bottom="4" />
+ </screen>
+ </view>
+ <view name="5:4 Two-Page">
+ <screen tag="screen">
+ <bounds left="0" top="0" right="5" bottom="4" />
+ </screen>
+ </view>
+ <view name="16:9 Widescreen">
+ <screen tag="screen">
+ <bounds left="0" top="0" right="16" bottom="9" />
+ </screen>
+ </view>
+ <view name="21:9 UltraWide">
+ <screen tag="screen">
+ <bounds left="0" top="0" right="21" bottom="9" />
+ </screen>
+ </view>
+ <view name="32:9 Super UltraWide">
+ <screen tag="screen">
+ <bounds left="0" top="0" right="32" bottom="9" />
+ </screen>
+ </view>
+ <view name="1:1 Air Traffic Control">
+ <screen tag="screen">
+ <bounds left="0" top="0" right="32" bottom="9" />
+ </screen>
+ </view>
+</mamelayout>
diff --git a/src/emu/rendlay.cpp b/src/emu/rendlay.cpp
index ffe680fa625..c0a9b040b50 100644
--- a/src/emu/rendlay.cpp
+++ b/src/emu/rendlay.cpp
@@ -59,6 +59,9 @@
// screenless layouts
#include "noscreens.lh"
+// single screen layouts
+#include "monitors.lh"
+
// dual screen layouts
#include "dualhsxs.lh"
#include "dualhovu.lh"
diff --git a/src/mame/drivers/mac.cpp b/src/mame/drivers/mac.cpp
index 3cdf7aaace7..e22f94a3105 100644
--- a/src/mame/drivers/mac.cpp
+++ b/src/mame/drivers/mac.cpp
@@ -14,14 +14,15 @@
#include "emu.h"
#include "includes/mac.h"
+#include "machine/macadb.h"
+
+#include "bus/nscsi/devices.h"
#include "cpu/m68000/m68000.h"
#include "cpu/m6805/m6805.h"
-#include "formats/ap_dsk35.h"
#include "machine/applepic.h"
#include "machine/iwm.h"
#include "machine/swim1.h"
#include "machine/swim2.h"
-#include "bus/nscsi/devices.h"
// NuBus and 030/040 PDS cards
#include "bus/nubus/nubus_48gc.h"
@@ -44,10 +45,12 @@
#include "bus/nubus/pds30_30hr.h"
#include "bus/nubus/pds30_mc30.h"
-#include "machine/macadb.h"
+#include "layout/generic.h"
#include "softlist_dev.h"
#include "speaker.h"
-#include "mac.lh"
+
+#include "formats/ap_dsk35.h"
+
#define C32M (31.3344_MHz_XTAL)
#define C15M (C32M/2)
@@ -928,7 +931,7 @@ void mac_state::maclc(machine_config &config, bool cpu, bool egret, asc_device::
m_screen->set_visarea(0, 640-1, 0, 480-1);
m_screen->set_screen_update(FUNC(mac_state::screen_update_macv8));
m_screen->screen_vblank().set(FUNC(mac_state::mac_rbv_vbl));
- config.set_default_layout(layout_mac);
+ config.set_default_layout(layout_monitors);
m_ram->set_default_size("2M");
m_ram->set_extra_options("4M,6M,8M,10M");
@@ -1134,7 +1137,7 @@ void mac_state::maciici(machine_config &config)
m_screen->set_visarea(0, 640-1, 0, 480-1);
m_screen->set_screen_update(FUNC(mac_state::screen_update_macrbv));
m_screen->screen_vblank().set(FUNC(mac_state::mac_rbv_vbl));
- config.set_default_layout(layout_mac);
+ config.set_default_layout(layout_monitors);
/* internal ram */
m_ram->set_default_size("2M");
@@ -1158,7 +1161,7 @@ void mac_state::maciisi(machine_config &config)
m_screen->set_visarea(0, 640-1, 0, 480-1);
m_screen->set_screen_update(FUNC(mac_state::screen_update_macrbv));
m_screen->screen_vblank().set(FUNC(mac_state::mac_rbv_vbl));
- config.set_default_layout(layout_mac);
+ config.set_default_layout(layout_monitors);
m_ram->set_default_size("2M");
m_ram->set_extra_options("4M,8M,16M,32M,48M,64M,128M");
diff --git a/src/mame/drivers/macquadra700.cpp b/src/mame/drivers/macquadra700.cpp
index d9b0ea00c91..84d2c23e2d2 100644
--- a/src/mame/drivers/macquadra700.cpp
+++ b/src/mame/drivers/macquadra700.cpp
@@ -53,6 +53,9 @@
#define C15M (C7M*2)
#define C32M (C15M*2)
+
+namespace {
+
class macquadra_state : public driver_device
{
public:
@@ -142,9 +145,9 @@ private:
int m_adb_irq_pending = 0;
DECLARE_WRITE_LINE_MEMBER(irq_539x_1_w);
- DECLARE_WRITE_LINE_MEMBER(irq_539x_2_w);
+ [[maybe_unused]] DECLARE_WRITE_LINE_MEMBER(irq_539x_2_w);
DECLARE_WRITE_LINE_MEMBER(drq_539x_1_w);
- DECLARE_WRITE_LINE_MEMBER(drq_539x_2_w);
+ [[maybe_unused]] DECLARE_WRITE_LINE_MEMBER(drq_539x_2_w);
floppy_image_device *m_cur_floppy = nullptr;
int m_hdsel = 0;
@@ -1053,4 +1056,6 @@ ROM_START( macqd700 )
ROM_LOAD( "420dbff3.rom", 0x000000, 0x100000, CRC(88ea2081) SHA1(7a8ee468d16e64f2ad10cb8d1a45e6f07cc9e212) )
ROM_END
+} // anonymous namespace
+
COMP( 1991, macqd700, 0, 0, macqd700, macadb, macquadra_state, init_macqd700, "Apple Computer", "Macintosh Quadra 700", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE)
diff --git a/src/mame/layout/mac.lay b/src/mame/layout/mac.lay
deleted file mode 100644
index 94eb2ff41d3..00000000000
--- a/src/mame/layout/mac.lay
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0"?>
-<!--
-license:CC0
--->
-<mamelayout version="2">
- <view name="Landscape (4:3)">
- <screen index="0">
- <bounds left="0" top="0" right="4" bottom="3" />
- </screen>
- </view>
- <view name="Portrait (3:4)">
- <screen index="0">
- <bounds left="0" top="0" right="3" bottom="4" />
- </screen>
- </view>
-</mamelayout>