summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author ajrhacker <ajrhacker@users.noreply.github.com>2018-11-18 22:47:37 -0500
committer GitHub <noreply@github.com>2018-11-18 22:47:37 -0500
commit2c575fe8bc0b81ecf75671c44069ea1169987c69 (patch)
tree61ce2e407ce9574fd4b8f5017133f82e918917f0
parente567e1023709cc88d159765be7b22720a3811bce (diff)
parentf6efe2921f2a7f201d402967b1d0b849cac8ce82 (diff)
Merge pull request #4313 from hp9k/hp98550
add HP98550 high-res color graphic card
-rw-r--r--scripts/src/bus.lua2
-rw-r--r--scripts/src/video.lua12
-rw-r--r--src/devices/bus/hp_dio/hp98550.cpp234
-rw-r--r--src/devices/bus/hp_dio/hp98550.h78
-rw-r--r--src/devices/bus/hp_dio/hp_dio.cpp3
-rw-r--r--src/devices/video/catseye.cpp1224
-rw-r--r--src/devices/video/catseye.h369
-rw-r--r--src/emu/xtal.cpp1
-rw-r--r--src/mame/drivers/hp9k_3xx.cpp10
-rw-r--r--src/mame/layout/hp9k_3xx.lay56
10 files changed, 1950 insertions, 39 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua
index 198c4283c04..7fbc4448458 100644
--- a/scripts/src/bus.lua
+++ b/scripts/src/bus.lua
@@ -910,6 +910,8 @@ if (BUSES["HPDIO"]~=null) then
MAME_DIR .. "src/devices/bus/hp_dio/hp98543.h",
MAME_DIR .. "src/devices/bus/hp_dio/hp98544.cpp",
MAME_DIR .. "src/devices/bus/hp_dio/hp98544.h",
+ MAME_DIR .. "src/devices/bus/hp_dio/hp98550.cpp",
+ MAME_DIR .. "src/devices/bus/hp_dio/hp98550.h",
MAME_DIR .. "src/devices/bus/hp_dio/hp98603a.cpp",
MAME_DIR .. "src/devices/bus/hp_dio/hp98603a.h",
MAME_DIR .. "src/devices/bus/hp_dio/hp98603b.cpp",
diff --git a/scripts/src/video.lua b/scripts/src/video.lua
index fa529660ab1..6db6cd104e1 100644
--- a/scripts/src/video.lua
+++ b/scripts/src/video.lua
@@ -1106,6 +1106,18 @@ end
--------------------------------------------------
--
+--@src/devices/video/catseye.h,VIDEOS["CATSEYE"] = true
+--------------------------------------------------
+if (VIDEOS["CATSEYE"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/video/catseye.cpp",
+ MAME_DIR .. "src/devices/video/catseye.h",
+ }
+end
+
+
+--------------------------------------------------
+--
--@src/devices/video/nereid.h,VIDEOS["NEREID"] = true
--------------------------------------------------
if (VIDEOS["NEREID"]~=null) then
diff --git a/src/devices/bus/hp_dio/hp98550.cpp b/src/devices/bus/hp_dio/hp98550.cpp
new file mode 100644
index 00000000000..8ec1660d5ce
--- /dev/null
+++ b/src/devices/bus/hp_dio/hp98550.cpp
@@ -0,0 +1,234 @@
+// License:BSD-3-Clause
+// copyright-holders:Sven Schnelle
+/***************************************************************************
+
+HP98550 high-resolution color board
+
+1280x1024 @ 60Hz, 8 bpp
+
+***************************************************************************/
+
+#include "emu.h"
+#include "hp98550.h"
+#include "screen.h"
+#include "video/nereid.h"
+#include "video/catseye.h"
+#include "machine/ram.h"
+
+//#define VERBOSE 1
+#include "logmacro.h"
+
+ROM_START(hp98550)
+ ROM_REGION(0x8000, "hp98550a_rom", 0)
+ ROM_LOAD("98550a.bin", 0x000000, 0x008000, CRC(9d639233) SHA1(d6b23a34850f24525ca5fb36de3deb91196d2dc5))
+ROM_END
+
+DEFINE_DEVICE_TYPE_NS(HPDIO_98550, bus::hp_dio, dio32_98550_device, "dio98550", "HP98550 high-res color DIO video card")
+
+namespace bus { namespace hp_dio {
+
+void dio32_98550_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "hp98550_screen", SCREEN_TYPE_RASTER));
+ screen.set_screen_update(FUNC(dio32_98550_device::screen_update));
+ screen.screen_vblank().set(FUNC(dio32_98550_device::vblank_w));
+ screen.set_raw(XTAL(108'108'000), 1689, 0, m_h_pix, 1066, 0, m_v_pix);
+
+ for (int i = 0; i < CATSEYE_COUNT; i++) {
+ CATSEYE(config, m_catseye[i], XTAL(108'108'000));
+ m_catseye[i]->set_fb_width(m_fb_width);
+ m_catseye[i]->set_fb_height(m_v_pix);
+ m_catseye[i]->set_plane(i);
+ m_catseye[i]->irq_out_cb().set(FUNC(dio32_98550_device::int_w));
+ }
+
+ NEREID(config, m_nereid, 0);
+}
+
+const tiny_rom_entry *dio32_98550_device::device_rom_region() const
+{
+ return ROM_NAME(hp98550);
+}
+
+void dio32_98550_device::map(address_map& map)
+{
+ map(0, 0x3fffff).ram().share("vram_video");
+ map(0x400000, 0x7fffff).ram().share("vram_overlay");
+}
+
+device_memory_interface::space_config_vector dio32_98550_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(0, &m_space_config)
+ };
+}
+
+dio32_98550_device::dio32_98550_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ dio32_98550_device(mconfig, HPDIO_98550, tag, owner, clock)
+{
+}
+
+dio32_98550_device::dio32_98550_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_dio16_card_interface(mconfig, *this),
+ device_memory_interface(mconfig, *this),
+ m_nereid(*this, "nereid"),
+ m_catseye(*this, "catseye%d", 0),
+ m_space_config("vram", ENDIANNESS_BIG, 8, 23, 0, address_map_constructor(FUNC(dio32_98550_device::map), this)),
+ m_rom(*this, "hp98550a_rom"),
+ m_vram(*this, { "vram_video", "vram_overlay"})
+{
+}
+
+void dio32_98550_device::device_start()
+{
+ save_item(NAME(m_intreg));
+ save_item(NAME(m_ints));
+
+ dio().install_memory(
+ 0x200000, 0x3fffff,
+ read16_delegate(FUNC(dio32_98550_device::vram_r), this),
+ write16_delegate(FUNC(dio32_98550_device::vram_w), this));
+
+ dio().install_memory(
+ 0x560000, 0x56ffff,
+ read16_delegate(FUNC(dio32_98550_device::rom_r), this),
+ write16_delegate(FUNC(dio32_98550_device::rom_w), this));
+
+ dio().install_memory(
+ 0x564000, 0x5648ff,
+ read16_delegate(FUNC(dio32_98550_device::catseye_r), this),
+ write16_delegate(FUNC(dio32_98550_device::catseye_w), this));
+
+ dio().install_memory(
+ 0x566000, 0x5660ff,
+ read16_delegate(FUNC(nereid_device::ctrl_r), &(*m_nereid)),
+ write16_delegate(FUNC(nereid_device::ctrl_w), &(*m_nereid)));
+}
+
+void dio32_98550_device::device_reset()
+{
+ m_intreg = 0;
+ m_ints = 0;
+}
+
+READ16_MEMBER(dio32_98550_device::rom_r)
+{
+ LOG("%s: %04x\n", __func__, offset);
+
+ if (offset == 1)
+ return m_intreg;
+
+ return 0xff00 | m_rom[offset];
+}
+
+WRITE16_MEMBER(dio32_98550_device::rom_w)
+{
+ switch (offset) {
+ case 0:
+ reset();
+ break;
+
+ case 1:
+ m_intreg = data;
+ break;
+
+ default:
+ logerror("%s: %04x = %04x (mask %04x)\n", __func__, offset << 1, data, mem_mask);
+ break;
+ }
+}
+
+READ16_MEMBER(dio32_98550_device::catseye_r)
+{
+ uint16_t ret = 0;
+
+ for (auto &ce: m_catseye)
+ ret |= ce->ctrl_r(space, offset, mem_mask);
+ LOG("%s: %04X = %04X\n", __func__, offset << 1, ret);
+ return ret;
+}
+
+WRITE16_MEMBER(dio32_98550_device::catseye_w)
+{
+ LOG("%s: %04X = %04X\n", __func__, offset << 1, data);
+ for (auto &ce: m_catseye)
+ ce->ctrl_w(space, offset, data, mem_mask);
+}
+
+READ16_MEMBER(dio32_98550_device::vram_r)
+{
+ uint16_t ret = 0;
+
+ for (auto &ce: m_catseye)
+ ret |= ce->vram_r(space, offset, mem_mask);
+
+ return ret;
+}
+
+WRITE16_MEMBER(dio32_98550_device::vram_w)
+{
+ for (auto &ce: m_catseye)
+ ce->vram_w(space, offset, data, mem_mask);
+}
+
+WRITE_LINE_MEMBER(dio32_98550_device::vblank_w)
+{
+ for (auto &ce: m_catseye)
+ ce->vblank_w(state);
+}
+
+WRITE8_MEMBER(dio32_98550_device::int_w)
+{
+ LOG("%s: plane%d = %s\n", __func__, offset, data ? "assert" : "deassert");
+ m_ints &= ~(1 << offset);
+ m_ints |= data;
+ update_int();
+}
+
+void dio32_98550_device::update_int()
+{
+ bool state = m_ints;
+ int line = (m_intreg >> 3) & 7;
+
+ if (!(m_intreg & 0x80))
+ state = false;
+
+ irq1_out(line == 1 && state);
+ irq2_out(line == 2 && state);
+ irq3_out(line == 3 && state);
+ irq4_out(line == 4 && state);
+ irq5_out(line == 5 && state);
+ irq6_out(line == 6 && state);
+ irq7_out(line == 7 && state);
+}
+
+uint32_t dio32_98550_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ bool changed = false;
+ uint8_t mask = 0;
+
+ for (auto &ce: m_catseye)
+ changed |= ce->has_changed();
+
+ if (!changed)
+ return UPDATE_HAS_NOT_CHANGED;
+
+ for (auto &ce: m_catseye)
+ mask |= ce->plane_enabled();
+
+ for (int y = 0; y < m_v_pix; y++) {
+ uint32_t *scanline = &bitmap.pix32(y);
+
+ for (int x = 0; x < m_h_pix; x++) {
+ const int offset = y * m_fb_width +x;
+ uint8_t tmp = m_vram[0][offset] & mask;
+ uint8_t ovl = m_vram[1][offset] & mask;
+ *scanline++ = m_nereid->map_color(tmp, ovl);
+ }
+ }
+ return 0;
+}
+
+} // namespace bus::hp_dio
+} // namespace bus
diff --git a/src/devices/bus/hp_dio/hp98550.h b/src/devices/bus/hp_dio/hp98550.h
new file mode 100644
index 00000000000..47057f6da70
--- /dev/null
+++ b/src/devices/bus/hp_dio/hp98550.h
@@ -0,0 +1,78 @@
+// license:BSD-3-Clause
+// copyright-holders:Sven Schnelle
+
+#ifndef MAME_BUS_HPDIO_98550_H
+#define MAME_BUS_HPDIO_98550_H
+
+#pragma once
+
+#include "hp_dio.h"
+#include "video/catseye.h"
+#include "video/nereid.h"
+#include "machine/ram.h"
+
+namespace bus {
+ namespace hp_dio {
+class dio32_98550_device :
+ public device_t,
+ public device_dio16_card_interface,
+ public device_memory_interface
+{
+public:
+ dio32_98550_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_READ16_MEMBER(rom_r);
+ DECLARE_WRITE16_MEMBER(rom_w);
+
+ DECLARE_READ16_MEMBER(topcat_r);
+ DECLARE_WRITE16_MEMBER(topcat_w);
+ DECLARE_READ16_MEMBER(catseye_r);
+ DECLARE_WRITE16_MEMBER(catseye_w);
+
+ DECLARE_READ16_MEMBER(vram_r);
+ DECLARE_WRITE16_MEMBER(vram_w);
+
+ static constexpr int CATSEYE_COUNT = 8;
+
+
+ uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+protected:
+ required_device<nereid_device> m_nereid;
+ required_device_array<catseye_device, CATSEYE_COUNT> m_catseye;
+
+ dio32_98550_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+ virtual space_config_vector memory_space_config() const override;
+
+ DECLARE_WRITE_LINE_MEMBER(vblank_w);
+ DECLARE_WRITE8_MEMBER(int_w);
+
+ const address_space_config m_space_config;
+ void map(address_map &map);
+ void update_int();
+
+ static constexpr int m_fb_width = 2048;
+ static constexpr int m_h_pix = 1280;
+ static constexpr int m_v_pix = 1024;
+
+ required_region_ptr<uint8_t> m_rom;
+ required_shared_ptr_array<uint8_t, 2> m_vram;
+
+ uint16_t m_plane_mask;
+ uint8_t m_intreg;
+ uint8_t m_ints;
+};
+
+} // namespace bus::hp_dio
+} // namespace bus
+
+// device type definition
+DECLARE_DEVICE_TYPE_NS(HPDIO_98550, bus::hp_dio, dio32_98550_device)
+
+#endif // MAME_BUS_HPDIO_98550_H
diff --git a/src/devices/bus/hp_dio/hp_dio.cpp b/src/devices/bus/hp_dio/hp_dio.cpp
index 899b7be0c00..ed553d6ea05 100644
--- a/src/devices/bus/hp_dio/hp_dio.cpp
+++ b/src/devices/bus/hp_dio/hp_dio.cpp
@@ -11,6 +11,7 @@
#include "hp98265a.h"
#include "hp98543.h"
#include "hp98544.h"
+#include "hp98550.h"
#include "hp98603a.h"
#include "hp98603b.h"
#include "hp98620.h"
@@ -365,6 +366,8 @@ void dio16_cards(device_slot_interface & device)
void dio32_cards(device_slot_interface & device)
{
+ dio16_cards(device);
device.option_add("98265a", HPDIO_98265A);
device.option_add("98620", HPDIO_98620);
+ device.option_add("98550", HPDIO_98550);
}
diff --git a/src/devices/video/catseye.cpp b/src/devices/video/catseye.cpp
new file mode 100644
index 00000000000..c79e3b246f5
--- /dev/null
+++ b/src/devices/video/catseye.cpp
@@ -0,0 +1,1224 @@
+// license:BSD-3-Clause
+// copyright-holders:Sven Schnelle
+
+#include "emu.h"
+#include "catseye.h"
+
+#define LOG_VRAM (LOG_GENERAL << 1)
+#define LOG_REG (LOG_GENERAL << 2)
+#define LOG_WMOVE (LOG_GENERAL << 3)
+
+//#define VERBOSE (LOG_WMOVE|LOG_REG|LOG_GENERAL)
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(CATSEYE, catseye_device, "catseye", "HP Catseye ASIC")
+
+catseye_device::catseye_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, type, tag, owner, clock),
+ m_vram(*this, { "^vram_video", "^vram_overlay"}),
+ m_int_write_func(*this),
+ m_blink_timer(nullptr)
+{
+}
+
+catseye_device::catseye_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ catseye_device(mconfig, CATSEYE, tag, owner, clock)
+{
+}
+
+
+void catseye_device::device_start()
+{
+ m_int_write_func.resolve_safe();
+
+ m_blink_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(catseye_device::blink_callback), this));
+ m_blink_timer->adjust(attotime::from_hz(3));
+
+ save_item(NAME(m_changed));
+ save_item(NAME(m_blink_state));
+ save_item(NAME(m_write_enable), 2);
+ save_item(NAME(m_read_enable), 2);
+ save_item(NAME(m_fb_enable), 2);
+ save_item(NAME(m_display_enable));
+ save_item(NAME(m_blink_enable));
+ save_item(NAME(m_sync_enable));
+ save_item(NAME(m_in_vblank));
+ save_item(NAME(m_wm_int_pending));
+ save_item(NAME(m_wm_int_enable));
+ save_item(NAME(m_vblank_int_enable));
+ save_item(NAME(m_vblank_int_pending));
+ save_item(NAME(m_rugsc));
+ save_item(NAME(m_misc));
+ save_item(NAME(m_wmx));
+ save_item(NAME(m_wmwidth));
+ save_item(NAME(m_wmheight));
+ save_item(NAME(m_wmsourcex));
+ save_item(NAME(m_wmsourcey));
+ save_item(NAME(m_wmdestx));
+ save_item(NAME(m_wmdesty));
+ save_item(NAME(m_wmclipleft));
+ save_item(NAME(m_wmclipright));
+ save_item(NAME(m_wmcliptop));
+ save_item(NAME(m_wmclipbottom));
+ save_item(NAME(m_patterns));
+ save_item(NAME(m_linepath));
+ save_item(NAME(m_linetype));
+ save_item(NAME(m_prr), 2);
+ save_item(NAME(m_wrr), 2);
+ save_item(NAME(m_trr), 2);
+ save_item(NAME(m_trrctl), 2);
+ save_item(NAME(m_color), 2);
+ save_item(NAME(m_vb), 2);
+ save_item(NAME(m_acntrl));
+ save_item(NAME(m_planemode), 2);
+ save_item(NAME(m_status));
+}
+
+void catseye_device::device_reset()
+{
+ LOG("%s\n", __func__);
+
+ for(int i = 0; i < 2; i++) {
+ m_read_enable[i] = 0;
+ m_write_enable[i] = 0;
+ m_fb_enable[i] = 0;
+
+ m_prr[i] = 0;
+ m_wrr[i] = 0;
+ m_trr[i] = 0;
+ m_trrctl[i] = 0;
+ m_color[i] = 0;
+ m_vb[i] = 0;
+ m_planemode[i] = 0;
+ std::fill(m_patterns[i].begin(), m_patterns[i].end(), 0);
+ }
+ m_acntrl = 0;
+ m_blink_enable = 0;
+ m_display_enable = m_plane_mask_h;
+ m_rugsc = 0;
+ m_wmwidth = 0;
+ m_wmheight = 0;
+ m_wmsourcex = 0;
+ m_wmsourcey = 0;
+ m_wmdestx = 0;
+ m_wmdesty = 0;
+ m_wmclipleft = 0;
+ m_wmclipright = 0;
+ m_wmcliptop = 0;
+ m_wmclipbottom = 0;
+
+ m_linepath = 0;
+ m_linetype = 0;
+}
+
+void catseye_device::update_int()
+{
+ LOG("%s: pending %d, enabled %d\n", __func__, m_wm_int_pending, m_wm_int_enable);
+ if ((m_wm_int_enable && m_wm_int_pending ) ||
+ (m_vblank_int_enable && m_vblank_int_pending))
+ m_int_write_func(m_plane);
+ else
+ m_int_write_func(0);
+}
+
+TIMER_CALLBACK_MEMBER(catseye_device::blink_callback)
+{
+ m_blink_timer->adjust(attotime::from_hz(5));
+ m_blink_state ^= true;
+ m_changed = true;
+}
+
+void catseye_device::execute_rule(const bool src, const int rule, bool &dst) const
+{
+ switch (rule & 0x0f) {
+ case CATSEYE_REPLACE_RULE_CLEAR:
+ dst = false;
+ break;
+
+ case CATSEYE_REPLACE_RULE_SRC_AND_DST:
+ dst &= src;
+ break;
+
+ case CATSEYE_REPLACE_RULE_SRC_AND_NOT_DST:
+ dst = !dst & src;
+ break;
+
+ case CATSEYE_REPLACE_RULE_SRC:
+ dst = src;
+ break;
+
+ case CATSEYE_REPLACE_RULE_NOT_SRC_AND_DST:
+ dst &= !src;
+ break;
+
+ case CATSEYE_REPLACE_RULE_NOP:
+ break;
+
+ case CATSEYE_REPLACE_RULE_SRC_XOR_DST:
+ dst ^= src;
+ break;
+
+ case CATSEYE_REPLACE_RULE_SRC_OR_DST:
+ dst |= src;
+ break;
+
+ case CATSEYE_REPLACE_RULE_NOT_SRC_AND_NOT_DST:
+ dst = !dst & !src;
+ break;
+
+ case CATSEYE_REPLACE_RULE_NOT_SRC_XOR_DST:
+ dst ^= !src;
+ break;
+
+ case CATSEYE_REPLACE_RULE_NOT_DST:
+ dst ^= true;
+ break;
+
+ case CATSEYE_REPLACE_RULE_SRC_OR_NOT_DST:
+ dst = src | !dst;
+ break;
+
+ case CATSEYE_REPLACE_RULE_NOT_SRC:
+ dst = !src;
+ break;
+
+ case CATSEYE_REPLACE_RULE_NOT_SRC_OR_DST:
+ dst |= !src;
+ break;
+
+ case CATSEYE_REPLACE_RULE_NOT_SRC_OR_NOT_DST:
+ dst = !src | !dst;
+ break;
+
+ case CATSEYE_REPLACE_RULE_SET:
+ dst = true;
+ break;
+
+ }
+}
+
+template<int idx>
+void catseye_device::window_move()
+{
+
+ if (!m_fb_enable[idx])
+ return;
+
+ LOGMASKED(LOG_WMOVE, "%s%d: %3ux%3u -> %3ux%3u / %3ux%3u planemode %04x wrr %04x, trr %04x m_trrctl %04x acntr %04x\n",
+ __func__, idx, m_wmsourcex, m_wmsourcey, m_wmdestx, m_wmdesty, m_wmwidth, m_wmheight, m_planemode[idx],
+ m_wrr[idx], m_trr[idx], m_trrctl[idx], m_acntrl);
+
+ int line, endline, lineincr;
+
+ if (m_wmdesty > m_wmsourcey) {
+ /* move down */
+ line = m_wmheight-1;
+ endline = -1;
+ lineincr = -1;
+ } else {
+ /* move up */
+ line = 0;
+ endline = m_wmheight;
+ lineincr = 1;
+ }
+
+ int startcolumn, endcolumn, columnincr;
+ if (m_wmdestx > m_wmsourcex) {
+ /* move right */
+ startcolumn = m_wmwidth-1;
+ endcolumn = -1;
+ columnincr = -1;
+ } else {
+ /* move left */
+ startcolumn = 0;
+ endcolumn = m_wmwidth;
+ columnincr = 1;
+ }
+
+ for ( ; line != endline; line += lineincr) {
+ for (int column = startcolumn; column != endcolumn; column += columnincr) {
+ const int sx = m_wmsourcex + column;
+ const int sy = m_wmsourcey + line;
+ const int dx = m_wmdestx + column;
+ const int dy = m_wmdesty + line;
+
+ if ((m_misc & CATSEYE_MISC_ENABLE_CLIP) &&
+ (dy < m_wmcliptop ||
+ (dy > m_wmclipbottom) ||
+ (dx < m_wmclipleft) ||
+ (dx > m_wmclipright))) {
+ continue;
+ }
+
+ bool dst = false;
+
+ if (m_trrctl[idx] & 0x0100) {
+ bool bit = m_patterns[idx][(m_plane << 4) | (dy & 0xf)] & (1 << (dx & 0xf));
+ switch (m_trr[idx] >> 8) {
+
+ case 0xf0:
+ dst = bit;
+ break;
+
+ default:
+ logerror("%s: unknown trr %02x\n", __func__, m_trr[idx] >> 8);
+ break;
+ }
+ } else {
+ bool const src = get_vram_pixel_plane<idx>(sx, sy);
+ dst = get_vram_pixel<idx>(dx, dy);
+ execute_rule(src, m_wrr[idx] & 0x0f, dst);
+ }
+ modify_vram<idx>(dx, dy, dst);
+ }
+ }
+}
+
+
+template<int idx>
+void catseye_device::draw_pixel(int x, int y, int color)
+{
+ if ((m_misc & CATSEYE_MISC_ENABLE_CLIP) &&
+ (x < m_wmclipleft ||
+ x > m_wmclipright ||
+ y < m_wmcliptop ||
+ y > m_wmclipbottom))
+ return;
+
+ bool src = color & m_plane_mask_l;
+ bool dst = get_vram_pixel<idx>(x, y);
+ execute_rule(src, (m_prr[idx] >> 8) & 0x0f, dst);
+ modify_vram<idx>(x, y, dst);
+ m_status |= CATSEYE_STATUS_UNCLIPPED;
+}
+
+template<int idx>
+void catseye_device::draw_line()
+{
+ const int color = m_color[idx] >> 8;
+ int x1 = m_wmsourcex;
+ int y1 = m_wmsourcey;
+ int x2 = m_wmdestx;
+ int y2 = m_wmdesty;
+ int dx, dy, t, e, x, y, incy, diago, horiz;
+ bool c1;
+
+ LOGMASKED(LOG_WMOVE, "%s%d %dx%d -> %dx%d, color %d\n",
+ __func__, idx, m_wmsourcex, m_wmsourcey, m_wmdestx, m_wmdesty, color);
+
+ c1 = false;
+ incy = 1;
+
+ if (x2 > x1)
+ dx = x2 - x1;
+ else
+ dx = x1 - x2;
+
+ if (y2 > y1)
+ dy = y2 - y1;
+ else
+ dy = y1 - y2;
+
+ if (dy > dx) {
+ t = y2;
+ y2 = x2;
+ x2 = t;
+
+ t = y1;
+ y1 = x1;
+ x1 = t;
+
+ t = dx;
+ dx = dy;
+ dy = t;
+
+ c1 = true;
+ }
+
+ if (x1 > x2) {
+ t = y2;
+ y2 = y1;
+ y1 = t;
+
+ t = x1;
+ x1 = x2;
+ x2 = t;
+ }
+
+ horiz = dy << 1;
+ diago = (dy - dx) << 1;
+ e = (dy << 1) - dx;
+
+ if (y1 <= y2)
+ incy = 1;
+ else
+ incy = -1;
+
+ x = x1;
+ y = y1;
+
+ if (c1) {
+ do {
+ draw_pixel<idx>(y, x, color);
+
+ if (e > 0) {
+ y += incy;
+ e += diago;
+ } else {
+ e += horiz;
+ }
+ x++;
+ } while (x <= x2);
+ } else {
+ do {
+ draw_pixel<idx>(x, y, color);
+ if (e > 0) {
+ y += incy;
+ e += diago;
+ } else {
+ e += horiz;
+ }
+ x++;
+ } while (x <= x2);
+ }
+
+}
+
+template<int idx>
+void catseye_device::trigger_wm()
+{
+ if (!m_fb_enable[idx])
+ return;
+
+ if ((m_vb[idx] & CATSEYE_VB_VECTOR) && (m_rugsc == 0x10))
+ draw_line<idx>();
+ else if (m_rugsc == 0x90)
+ window_move<idx>();
+ else
+ logerror("%s: unsupported rugcmd: %04x vb %04x\n", __func__, m_rugsc, m_vb[idx]);
+}
+
+template<int idx>
+u16 catseye_device::vram_r_bit(offs_t offset)
+{
+ u16 ret = 0;
+
+ offset &= ~0x7;
+
+ for(int i = 0; i < 16; i++)
+ ret |= get_vram_offset_plane<idx>(offset * 2 + 15 - i) ? (1 << i) : 0;
+ return ret;
+}
+
+template<int idx>
+u16 catseye_device::vram_r_word(offs_t offset, u16 mem_mask)
+{
+ u16 ret = 0;
+
+ if (mem_mask & m_plane_mask_l)
+ ret |= get_vram_offset<idx>(offset * 2 + 1);
+
+ if (mem_mask & m_plane_mask_h)
+ ret |= get_vram_offset<idx>(offset * 2) << 8;
+
+ return ret;
+}
+
+template<int idx>
+u16 catseye_device::vram_r(offs_t offset, u16 mem_mask)
+{
+ if (m_acntrl & 0x100)
+ return vram_r_bit<idx>(offset);
+ else
+ return vram_r_word<idx>(offset, mem_mask);
+}
+
+READ16_MEMBER(catseye_device::vram_r)
+{
+ uint16_t ret = 0;
+
+ if (m_acntrl & 0x200)
+ ret = vram_r<VRAM_OVERLAY_PLANE>(offset, mem_mask);
+ else
+ ret = vram_r<VRAM_VIDEO_PLANE>(offset, mem_mask);
+
+ LOGMASKED(LOG_VRAM, "%s: %04x: %04x(%04x)\n", __func__, offset << 1, ret, mem_mask);
+ return ret;
+}
+
+template<int idx>
+void catseye_device::vram_w_bit(offs_t offset, u16 data, u16 mem_mask)
+{
+ offset &= ~0x7;
+
+ for (int i = 0; i < 16; i++) {
+
+ const int bit = (1 << i);
+
+ if (!(mem_mask & bit))
+ continue;
+
+ bool dst = get_vram_offset<idx>(offset * 2 + 15 - i);
+ execute_rule(data & bit, (m_prr[idx] >> 8) & 0x0f, dst);
+ modify_vram_offset<idx>(offset * 2 + 15 - i, dst);
+ }
+}
+
+template<int idx>
+void catseye_device::vram_w_word(offs_t offset, u16 data, u16 mem_mask)
+{
+ if (mem_mask & m_plane_mask_l) {
+ const bool src = data & m_plane_mask_l;
+ bool dst = get_vram_offset<idx>(offset * 2 + 1);
+ execute_rule(src, (m_prr[idx] >> 8) & 0x0f, dst);
+ modify_vram_offset<idx>(offset * 2 + 1, dst);
+ }
+
+ if (mem_mask & m_plane_mask_h) {
+ const bool src = data & m_plane_mask_h;
+ bool dst = get_vram_offset<idx>(offset * 2);
+ execute_rule(src, (m_prr[idx] >> 8) & 0x0f, dst);
+ modify_vram_offset<idx>(offset * 2, dst);
+ }
+}
+
+template<int idx>
+void catseye_device::vram_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ if (m_acntrl & 0x100)
+ vram_w_bit<idx>(offset, data, mem_mask);
+ else
+ vram_w_word<idx>(offset, data, mem_mask);
+}
+
+WRITE16_MEMBER(catseye_device::vram_w)
+{
+ LOGMASKED(LOG_VRAM, "%s: %04x: %04x(%04x)\n", __func__, offset << 1, data, mem_mask);
+
+ if (m_fb_enable[0])
+ vram_w<VRAM_VIDEO_PLANE>(offset, data, mem_mask);
+
+ if (m_fb_enable[1])
+ vram_w<VRAM_OVERLAY_PLANE>(offset, data, mem_mask);
+}
+
+WRITE16_MEMBER(catseye_device::ctrl_w)
+{
+ bool trigger = false;
+
+ if (m_write_enable[0] && offset >= 0x200 && offset < 0x280) {
+ COMBINE_DATA(&m_patterns[0][offset - 0x200]);
+ LOGMASKED(LOG_REG, "W PATTERNS1[%03d] = %04x\n", offset - 0x200, m_patterns[0][offset - 0x200]);
+ return;
+ }
+
+ if (m_write_enable[1] && offset >= 0x300 && offset < 0x380) {
+ COMBINE_DATA(&m_patterns[1][offset - 0x300]);
+ LOGMASKED(LOG_REG, "W PATTERNS2[%03d] = %04x\n", offset - 0x300, m_patterns[1][offset - 0x300]);
+ return;
+ }
+
+ switch(offset) {
+ case TOPCAT_REG_ENABLE_BLINK_PLANES:
+ if (mem_mask & 0xff00)
+ m_blink_enable = data & m_plane_mask_h;
+ LOGMASKED(LOG_REG, "enable blink plane: %04x\n", m_blink_enable);
+ break;
+
+ case TOPCAT_REG_DISPLAY_PLANE_ENABLE:
+ if (mem_mask & 0xff00)
+ m_display_enable = data & m_plane_mask_h;
+ LOGMASKED(LOG_REG, "display enable %04x\n", m_display_enable);
+ break;
+
+ case TOPCAT_REG_SYNC_ENABLE:
+ if (mem_mask & 0xff00)
+ m_sync_enable = data & m_plane_mask_h;
+ LOGMASKED(LOG_REG, "sync enable: %04x\n", m_sync_enable);
+ break;
+
+ case TOPCAT_REG_WMOVE_INTRQ:
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_WMOVE_INTRQ = %04x\n", data);
+ m_wm_int_pending = 0;
+ update_int();
+ break;
+
+ case TOPCAT_REG_WMOVE_IE:
+ if (mem_mask & 0xff00)
+ m_wm_int_enable = data & m_plane_mask_h;
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_WMOVE_IE = %04x\n", m_wm_int_enable);
+ update_int();
+ break;
+
+ case TOPCAT_REG_VBLANK_IE:
+ if (mem_mask & 0xff00)
+ m_vblank_int_enable = data & m_plane_mask_h;
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_WMOVE_IE = %04x\n", m_vblank_int_enable);
+ update_int();
+ break;
+
+ case CATSEYE_REG_WMX:
+ COMBINE_DATA(&m_wmx);
+ COMBINE_DATA(&m_wmsourcex);
+ COMBINE_DATA(&m_wmdestx);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_WMX = %04x\n", m_wmx);
+ break;
+
+ case CATSEYE_REG_RUG_SC:
+ COMBINE_DATA(&m_rugsc);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_RUG_SC = %04x\n", m_rugsc);
+ break;
+
+ case TOPCAT_REG_WMWIDTH:
+ case CATSEYE_REG_WMWIDTH:
+ COMBINE_DATA(&m_wmwidth);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_WMWIDTH = %04x\n", m_wmwidth);
+ break;
+
+ case TOPCAT_REG_WMHEIGHT:
+ case CATSEYE_REG_WMHEIGHT:
+ COMBINE_DATA(&m_wmheight);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_WMHEIGHT = %04x\n", m_wmheight);
+ break;
+
+ case CATSEYE_REG_LINEPATH:
+ COMBINE_DATA(&m_linepath);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_LINEPATH = %04x\n", m_linepath);
+ break;
+
+ case CATSEYE_REG_LINETYPE:
+ COMBINE_DATA(&m_linetype);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_LINETYPE = %04x\n", m_linetype);
+ break;
+
+
+ case TOPCAT_REG_WMSOURCEX:
+ case CATSEYE_REG_WMSOURCEX:
+ COMBINE_DATA(&m_wmsourcex);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_WMSOURCEX = %04x\n", m_wmsourcex);
+ break;
+
+ case TOPCAT_REG_WMSOURCEY:
+ case CATSEYE_REG_WMSOURCEY:
+ COMBINE_DATA(&m_wmsourcey);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_WMSOURCEY = %04x\n", m_wmsourcey);
+ break;
+
+ case TOPCAT_REG_WMDESTX:
+ case CATSEYE_REG_WMDESTX:
+ COMBINE_DATA(&m_wmdestx);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_WMDESTX = %04x\n", m_wmdestx);
+ break;
+
+ case TOPCAT_REG_WMDESTY:
+ case CATSEYE_REG_WMDESTY:
+ COMBINE_DATA(&m_wmdesty);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_WMDESTY = %04x\n", m_wmdesty);
+ break;
+
+ case CATSEYE_REG_WMCLIPLEFT:
+ COMBINE_DATA(&m_wmclipleft);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_WMCLIPLEFT = %04x\n", m_wmclipleft);
+ break;
+
+ case CATSEYE_REG_WMCLIPRIGHT:
+ COMBINE_DATA(&m_wmclipright);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_WMCLIPRIGHT = %04x\n", m_wmclipright);
+ break;
+
+ case CATSEYE_REG_WMCLIPTOP:
+ COMBINE_DATA(&m_wmcliptop);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_WMCLIPTOP = %04x\n", m_wmcliptop);
+ break;
+
+ case CATSEYE_REG_WMCLIPBOTTOM:
+ COMBINE_DATA(&m_wmclipbottom);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_WMCLIPBOTTOM = %04x\n", m_wmclipbottom);
+ break;
+
+ case CATSEYE_REG_TWMWIDTH:
+ COMBINE_DATA(&m_wmwidth);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_TWMWIDTH = %04x\n", m_wmwidth);
+ trigger = true;
+ break;
+
+ case CATSEYE_REG_TWMHEIGHT:
+ COMBINE_DATA(&m_wmheight);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_TWMHEIGHT = %04x\n", m_wmheight);
+ trigger = true;
+ break;
+
+ case CATSEYE_REG_TWMSOURCEX:
+ COMBINE_DATA(&m_wmsourcex);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_TWMSOURCEX = %04x\n", m_wmsourcex);
+ trigger = true;
+ break;
+
+ case CATSEYE_REG_TWMSOURCEY:
+ COMBINE_DATA(&m_wmsourcey);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_TWMSOURCEY = %04x\n", m_wmsourcey);
+ trigger = true;
+ break;
+
+ case CATSEYE_REG_TWMDESTX:
+ COMBINE_DATA(&m_wmdestx);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_TWMDESTX = %04x\n", m_wmdestx);
+ trigger = true;
+ break;
+
+ case CATSEYE_REG_TWMDESTY:
+ COMBINE_DATA(&m_wmdesty);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_TWMDESTY = %04x\n", m_wmdesty);
+ trigger = true;
+ break;
+
+ case TOPCAT_REG_START_WMOVE:
+ if (m_write_enable[0]) {
+ LOGMASKED(LOG_REG, "W TOPCAT_REG_START_WMOVE = %04x\n", data);
+ window_move<0>();
+ if (m_wm_int_enable) {
+ m_wm_int_pending = m_plane_mask_h;
+ update_int();
+ }
+ }
+ break;
+
+ case CATSEYE_REG_STATUS:
+ COMBINE_DATA(&m_status);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_STATUS = %04x\n", m_status);
+ break;
+
+ case CATSEYE_REG_STATUS+1:
+ case CATSEYE_REG_STATUS+2:
+ // unknown
+ break;
+
+
+ // TC 1 registers
+ case TOPCAT_REG_READ_ENABLE_PLANE:
+ case CATSEYE_REG_TCREN1:
+ if (mem_mask & m_plane_mask_h)
+ m_read_enable[0] = data & m_plane_mask_l;
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_READ_ENABLE1 = %04x\n", m_read_enable[0]);
+ break;
+
+ case TOPCAT_REG_WRITE_ENABLE_PLANE:
+ case CATSEYE_REG_TCWEN1:
+ if (mem_mask & m_plane_mask_h)
+ m_write_enable[0] = data & m_plane_mask_h;
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_WRITE_ENABLE1 = %04x\n", m_write_enable[0]);
+ break;
+
+ case TOPCAT_REG_FB_WRITE_ENABLE:
+ case CATSEYE_REG_FBEN1:
+ if (mem_mask & m_plane_mask_h)
+ m_fb_enable[0] = data & m_plane_mask_h;
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_FBEN1 = %04x\n", m_fb_enable[0]);
+ break;
+
+ case TOPCAT_REG_PRR:
+ case CATSEYE_REG_PRR1:
+ if (!m_write_enable[0])
+ break;
+ COMBINE_DATA(&m_prr[0]);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_PRR1 = %04x\n", m_prr[0]);
+ break;
+
+ case TOPCAT_REG_WRR:
+ case CATSEYE_REG_WRR1:
+ if (!m_write_enable[0])
+ break;
+ COMBINE_DATA(&m_wrr[0]);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_WRR1 = %04x\n", m_wrr[0]);
+ break;
+
+ case CATSEYE_REG_TRR1:
+ if (!m_write_enable[0])
+ break;
+ COMBINE_DATA(&m_trr[0]);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_TRR1 = %04x\n", m_trr[0]);
+ break;
+
+ case CATSEYE_REG_VB1:
+ if (!m_write_enable[0])
+ break;
+ COMBINE_DATA(&m_vb[0]);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_VB1 = %04x\n", m_vb[0]);
+ break;
+
+ case CATSEYE_REG_COLOR1:
+ COMBINE_DATA(&m_color[0]);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_COLOR1 = %04x\n", m_color[0]);
+ break;
+
+ case CATSEYE_REG_TRRCTL1:
+ if (!m_write_enable[0])
+ break;
+ COMBINE_DATA(&m_trrctl[0]);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_TRRCTL1 = %04x\n", m_trrctl[0]);
+ break;
+
+ case CATSEYE_REG_ACNTL1:
+ if (!m_write_enable[0])
+ break;
+ COMBINE_DATA(&m_acntrl);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_ACNTL1 = %04x\n", m_acntrl);
+ break;
+
+ case CATSEYE_REG_PLANEMODE1:
+ COMBINE_DATA(&m_planemode[0]);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_PLANEMODE1 = %04x\n", m_planemode[0]);
+ break;
+
+ // TC 2 registers
+ case CATSEYE_REG_TCREN2:
+ if (mem_mask & 0xff00)
+ m_read_enable[1] = data & m_plane_mask_h;
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_READ_ENABLE2 = %04x\n", m_read_enable[1]);
+ break;
+
+ case CATSEYE_REG_TCWEN2:
+ if (mem_mask & 0xff00)
+ m_write_enable[1] = data & m_plane_mask_h;
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_READ_ENABLE2 = %04x\n", m_write_enable[1]);
+ break;
+
+ case CATSEYE_REG_FBEN2:
+ if (mem_mask & 0xff00)
+ m_fb_enable[1] = data & m_plane_mask_h;
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_READ_ENABLE2 = %04x\n", m_fb_enable[1]);
+ break;
+
+ case CATSEYE_REG_PRR2:
+ if (!m_write_enable[1])
+ break;
+ COMBINE_DATA(&m_prr[1]);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_PRR2 = %04x\n", m_prr[1]);
+ break;
+
+ case CATSEYE_REG_WRR2:
+ if (!m_write_enable[1])
+ break;
+ COMBINE_DATA(&m_wrr[1]);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_WRR2 = %04x\n", m_wrr[1]);
+ break;
+
+ case CATSEYE_REG_TRR2:
+ if (!m_write_enable[1])
+ break;
+ COMBINE_DATA(&m_trr[1]);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_TRR2 = %04x\n", m_trr[1]);
+ break;
+
+ case CATSEYE_REG_VB2:
+ if (!m_write_enable[1])
+ break;
+
+ COMBINE_DATA(&m_vb[1]);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_VB2 = %04x\n", m_vb[1]);
+ break;
+
+ case CATSEYE_REG_COLOR2:
+ COMBINE_DATA(&m_color[1]);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_COLOR2 = %04x\n", m_color[1]);
+ break;
+
+ case CATSEYE_REG_TRRCTL2:
+ if (!m_write_enable[1])
+ break;
+
+ COMBINE_DATA(&m_trrctl[1]);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_TRRCTL2 = %04x\n", m_trrctl[1]);
+ break;
+
+ case CATSEYE_REG_ACNTL2:
+ if (!m_write_enable[1])
+ break;
+
+ COMBINE_DATA(&m_acntrl);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_ACNTL2 = %04x\n", m_acntrl);
+ break;
+
+ case CATSEYE_REG_PLANEMODE2:
+ if (!m_write_enable[1])
+ break;
+
+ COMBINE_DATA(&m_planemode[1]);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_PLANEMODE2 = %04x\n", m_planemode[1]);
+ break;
+ case CATSEYE_REG_RUG_REV:
+ COMBINE_DATA(&m_misc);
+ LOGMASKED(LOG_REG, "W CATSEYE_REG_MISC = %04x\n", m_misc);
+ break;
+ default:
+ logerror("%s: unknown: %04x = %04x (mask %04x)\n", __func__, offset << 1, data, mem_mask);
+ return;
+ }
+
+ if (m_fb_enable[0] && trigger)
+ trigger_wm<VRAM_VIDEO_PLANE>();
+
+ if (m_fb_enable[1] && trigger)
+ trigger_wm<VRAM_OVERLAY_PLANE>();
+
+}
+
+READ16_MEMBER(catseye_device::ctrl_r)
+{
+ uint16_t ret;
+
+ if (offset >= 0x200 && offset < 0x280) {
+ LOGMASKED(LOG_REG, "R PATTERNS1[%03d] = %04x\n", offset - 0x200, m_patterns[0][offset - 0x200]);
+ return m_patterns[0][offset - 0x200];
+ }
+
+ if (offset >= 0x300 && offset < 0x380) {
+ LOGMASKED(LOG_REG, "R PATTERNS2[%03d] = %04x\n", offset - 0x300, m_patterns[1][offset - 0x300]);
+ return m_patterns[1][offset - 0x300];
+ }
+
+ switch(offset) {
+ case TOPCAT_REG_ENABLE_BLINK_PLANES:
+ ret = m_blink_enable;
+ break;
+
+ case TOPCAT_REG_SYNC_ENABLE:
+ ret = m_sync_enable;
+ break;
+
+ case TOPCAT_REG_DISPLAY_PLANE_ENABLE:
+ ret = m_display_enable;
+ break;
+
+ case TOPCAT_REG_VBLANK:
+ ret = m_in_vblank;
+ LOGMASKED(LOG_REG, "R VBLANK = %04x\n", ret);
+ break;
+
+ case TOPCAT_REG_WMOVE_INTRQ:
+ ret = m_wm_int_pending;
+ LOGMASKED(LOG_REG, "R WMOVE_INTRQ = %04x\n", ret);
+ break;
+
+ case TOPCAT_REG_VBLANK_INTRQ:
+ ret = m_vblank_int_pending;
+ LOGMASKED(LOG_REG, "R VBLANK_INTRQ = %04x\n", ret);
+ break;
+
+ case TOPCAT_REG_WMOVE_IE:
+ ret = m_wm_int_enable;
+ LOGMASKED(LOG_REG, "R WMOVE_IE = %04x\n", ret);
+ break;
+
+ case TOPCAT_REG_VBLANK_IE:
+ ret = m_vblank_int_enable;
+ LOGMASKED(LOG_REG, "R VBLANK_IE = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_RUG_SC:
+ ret = m_rugsc;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_RUG_SC = %04x\n", ret);
+ break;
+
+ case TOPCAT_REG_WMWIDTH:
+ case CATSEYE_REG_WMWIDTH:
+ ret = m_wmwidth;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_WMWIDTH = %04x\n", ret);
+ break;
+
+ case TOPCAT_REG_WMHEIGHT:
+ case CATSEYE_REG_WMHEIGHT:
+ ret = m_wmheight;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_WMHEIGHT = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_LINEPATH:
+ ret = m_linepath;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_LINEPATH = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_LINETYPE:
+ ret = m_linetype;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_LINETYPE = %04x\n", ret);
+ break;
+
+ case TOPCAT_REG_WMSOURCEX:
+ case CATSEYE_REG_WMSOURCEX:
+ ret = m_wmsourcex;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_WMSOURCEX = %04x\n", ret);
+ break;
+
+ case TOPCAT_REG_WMSOURCEY:
+ case CATSEYE_REG_WMSOURCEY:
+ ret = m_wmsourcey;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_WMSOURCEY = %04x\n", ret);
+ break;
+
+ case TOPCAT_REG_WMDESTX:
+ case CATSEYE_REG_WMDESTX:
+ ret = m_wmdestx;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_WMDESTX = %04x\n", ret);
+ break;
+
+ case TOPCAT_REG_WMDESTY:
+ case CATSEYE_REG_WMDESTY:
+ ret = m_wmdesty;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_WMDESTY = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_WMCLIPLEFT:
+ ret = m_wmclipleft;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_WMCLIPLEFT = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_WMCLIPRIGHT:
+ ret = m_wmclipright;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_WMCLIPRIGHT = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_WMCLIPTOP:
+ ret = m_wmcliptop;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_WMCLIPTOP = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_WMCLIPBOTTOM:
+ ret = m_wmclipbottom;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_WMCLIPBOTTOM = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_TWMWIDTH:
+ ret = m_wmwidth;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_TWMWIDTH = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_TWMHEIGHT:
+ ret = m_wmheight;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_TWMHEIGHT = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_TWMSOURCEX:
+ ret = m_wmsourcex;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_TWMSOURCEX = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_TWMSOURCEY:
+ ret = m_wmsourcey;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_TWMSOURCEY = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_TWMDESTX:
+ ret = m_wmdestx;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_TWMDESTX = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_TWMDESTY:
+ ret = m_wmdesty;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_TWMDESTY = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_STATUS:
+ ret = CATSEYE_STATUS_READY | CATSEYE_STATUS_NO_DAUGHTERBOARD;
+ ret |= m_status & ~CATSEYE_STATUS_VBLANK;
+ if (m_in_vblank)
+ ret |= CATSEYE_STATUS_VBLANK;
+
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_STATUS = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_STATUS+1:
+ case CATSEYE_REG_STATUS+2:
+ // unknown
+ ret = 0;
+ break;
+
+ case TOPCAT_REG_START_WMOVE:
+ m_wm_int_pending = 0;
+ update_int();
+ ret = 0;
+ break;
+
+ case CATSEYE_REG_RUG_REV:
+ ret = m_misc;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_RUG_REV = %04x\n", ret);
+ break;
+
+ // TC1
+ case TOPCAT_REG_FB_WRITE_ENABLE:
+ case CATSEYE_REG_FBEN1:
+ ret = m_fb_enable[0];
+ break;
+
+ case TOPCAT_REG_READ_ENABLE_PLANE:
+ case CATSEYE_REG_TCREN1:
+ ret = m_read_enable[0];
+ break;
+
+ case TOPCAT_REG_WRITE_ENABLE_PLANE:
+ case CATSEYE_REG_TCWEN1:
+ ret = m_write_enable[0];
+ break;
+
+ case TOPCAT_REG_PRR:
+ case CATSEYE_REG_PRR1:
+ if (m_read_enable[0])
+ return 0;
+
+ ret = m_prr[0];
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_PRR1 = %04x\n", ret);
+ break;
+
+ case TOPCAT_REG_WRR:
+ case CATSEYE_REG_WRR1:
+ if (m_read_enable[0])
+ return 0;
+
+ ret = m_wrr[0];
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_WRR1 = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_TRR1:
+ if (m_read_enable[0])
+ return 0;
+
+ ret = m_trr[0];
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_TRR1 = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_COLOR1:
+ if (m_read_enable[0])
+ return 0;
+
+ ret = m_color[0];
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_COLOR1 = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_VB1:
+ if (m_read_enable[0])
+ return 0;
+
+ ret = m_vb[0];
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_VB1 = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_TRRCTL1:
+ if (m_read_enable[0])
+ return 0;
+
+ ret = m_trrctl[0];
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_TRRCTL1 = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_ACNTL1:
+ if (m_read_enable[0])
+ return 0;
+
+ ret = m_acntrl;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_ACNTL1 = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_PLANEMODE1:
+ if (m_read_enable[0])
+ return 0;
+
+ ret = m_planemode[0];
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_PLANEMODE1 = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_BARC_REV1:
+ ret = 0x0100;
+ break;
+
+ // TC2
+ case CATSEYE_REG_FBEN2:
+ ret = m_fb_enable[1];
+ break;
+
+ case CATSEYE_REG_TCREN2:
+ ret = m_read_enable[1];
+ break;
+
+ case CATSEYE_REG_TCWEN2:
+ ret = m_write_enable[1];
+ break;
+
+ case CATSEYE_REG_PRR2:
+ if (m_read_enable[1])
+ return 0;
+
+ ret = m_prr[1];
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_PRR2 = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_WRR2:
+ if (m_read_enable[1])
+ return 0;
+
+ ret = m_wrr[1];
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_WRR2 = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_TRR2:
+ if (m_read_enable[1])
+ return 0;
+
+ ret = m_trr[1];
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_TRR2 = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_COLOR2:
+ if (m_read_enable[1])
+ return 0;
+
+ ret = m_color[1];
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_COLOR2 = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_VB2:
+ if (m_read_enable[1])
+ return 0;
+
+ ret = m_vb[1];
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_VB2 = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_TRRCTL2:
+ if (m_read_enable[1])
+ return 0;
+
+ ret = m_trrctl[1];
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_TRRCTL2 = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_ACNTL2:
+ if (m_read_enable[1])
+ return 0;
+
+ ret = m_acntrl;
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_ACNTL2 = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_PLANEMODE2:
+ if (m_read_enable[1])
+ return 0;
+
+ ret = m_planemode[1];
+ LOGMASKED(LOG_REG, "R CATSEYE_REG_PLANEMODE2 = %04x\n", ret);
+ break;
+
+ case CATSEYE_REG_BARC_REV2:
+ ret = 0x0100;
+ break;
+
+ default:
+ logerror("%s: unknown: %04x (mask %04x)\n", __func__, offset << 1, mem_mask);
+ return space.unmap();
+ }
+ return ret;
+}
+
+WRITE_LINE_MEMBER(catseye_device::vblank_w)
+{
+ m_in_vblank = state ? m_plane_mask_h : 0;
+ if (state && m_vblank_int_enable)
+ m_vblank_int_pending = m_plane_mask_h;
+}
diff --git a/src/devices/video/catseye.h b/src/devices/video/catseye.h
new file mode 100644
index 00000000000..257ae13f3ee
--- /dev/null
+++ b/src/devices/video/catseye.h
@@ -0,0 +1,369 @@
+// license:BSD-3-Clause
+// copyright-holders:Sven Schnelle
+#ifndef MAME_VIDEO_CATSEYE_H
+#define MAME_VIDEO_CATSEYE_H
+
+#pragma once
+
+class catseye_device: public device_t
+{
+public:
+ catseye_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_READ16_MEMBER(vram_r);
+ DECLARE_WRITE16_MEMBER(vram_w);
+ DECLARE_READ16_MEMBER(ctrl_r);
+ DECLARE_WRITE16_MEMBER(ctrl_w);
+ DECLARE_WRITE_LINE_MEMBER(vblank_w);
+
+ void set_fb_width(int width) { m_fb_width = width; }
+ void set_fb_height(int height) { m_fb_height = height; }
+ void set_plane(const u8 plane) {
+ m_plane_mask_l = (1 << plane);
+ m_plane_mask_h = (0x100 << plane);
+ m_plane = plane;
+ }
+
+ bool has_changed() {
+ bool ret = m_changed;
+ m_changed = false;
+ return ret;
+ };
+
+ u8 plane_enabled() const {
+ if (!m_display_enable || (m_blink_enable && !m_blink_state))
+ return 0;
+ return m_plane_mask_l;
+ }
+
+ auto irq_out_cb() { return m_int_write_func.bind(); }
+
+protected:
+
+ required_shared_ptr_array<u8, 2> m_vram;
+ catseye_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ devcb_write8 m_int_write_func;
+ TIMER_CALLBACK_MEMBER(blink_callback);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ void execute_rule(const bool src, const int rule, bool &dst) const;
+ void update_int();
+
+ template<int idx> void window_move();
+ template<int idx> void draw_line();
+ template<int idx> void trigger_wm();
+ template<int idx> void draw_pixel(int x, int y, int color);
+ template<int idx> void vram_w(offs_t offset, u16 data, u16 mem_mask);
+ template<int idx> void vram_w_bit(offs_t offset, u16 data, u16 mem_mask);
+ template<int idx> void vram_w_word(offs_t offset, u16 data, u16 mem_mask);
+ template<int idx> u16 vram_r(offs_t offset, u16 mem_mask);
+ template<int idx> u16 vram_r_bit(offs_t offset);
+ template<int idx> u16 vram_r_word(offs_t offset, u16 mem_mask);
+
+ int get_plane_from_idx(const int idx) const {
+ if (idx == VRAM_VIDEO_PLANE) {
+ if (m_acntrl == 0x0200)
+ return VRAM_OVERLAY_PLANE;
+ else
+ return VRAM_VIDEO_PLANE;
+ } else {
+ if (m_acntrl == 0x0200)
+ return VRAM_VIDEO_PLANE;
+ else
+ return VRAM_OVERLAY_PLANE;
+ }
+ }
+
+ template<int idx>
+ void modify_vram(int x, int y, bool state) {
+ m_changed = true;
+ m_status |= CATSEYE_STATUS_UNCLIPPED;
+ const int offset = y * m_fb_width + x;
+ if (state)
+ m_vram[idx][offset] |= m_plane_mask_l;
+ else
+ m_vram[idx][offset] &= ~m_plane_mask_l;
+ }
+
+ template<int idx>
+ void modify_vram_offset(int offset, bool state) {
+ m_changed = true;
+ m_status |= CATSEYE_STATUS_UNCLIPPED;
+ if (state)
+ m_vram[idx][offset] |= m_plane_mask_l;
+ else
+ m_vram[idx][offset] &= ~m_plane_mask_l;
+ }
+
+ template<int idx>
+ u8 get_vram_offset_plane(int offset) const {
+ const int plane = (m_planemode[idx] >> 8) & 0x0f;
+ if (!m_planemode[idx])
+ return m_vram[idx][offset] & m_plane_mask_l;
+ else if (plane < 8)
+ return m_vram[idx][offset] & (1 << plane);
+ else
+ return m_vram[idx][offset] & (1 << (plane-8));
+ }
+
+
+ template<int idx>
+ u8 get_vram_offset(int offset) const {
+ return m_vram[idx][offset] & m_plane_mask_l;
+ }
+
+ template<int idx>
+ bool get_vram_pixel(int x, int y) const {
+ return m_vram[get_plane_from_idx(idx)][y * m_fb_width + x] & m_plane_mask_l;
+ }
+
+ template<int idx>
+ bool get_vram_pixel_plane(int x, int y) const {
+ const int plane = (m_planemode[idx] >> 8) & 0x0f;
+ const int offset = y * m_fb_width + x;
+ if (!(m_planemode[idx] & (1 << 12)))
+ return m_vram[idx][offset] & m_plane_mask_l;
+ else if (plane < 8)
+ return m_vram[0][offset] & (1 << plane);
+ else
+ return m_vram[1][offset] & (1 << (plane-8));
+ }
+
+ static constexpr int CATSEYE_REPLACE_RULE_CLEAR = 0;
+ static constexpr int CATSEYE_REPLACE_RULE_SRC_AND_DST = 1;
+ static constexpr int CATSEYE_REPLACE_RULE_SRC_AND_NOT_DST = 2;
+ static constexpr int CATSEYE_REPLACE_RULE_SRC = 3;
+ static constexpr int CATSEYE_REPLACE_RULE_NOT_SRC_AND_DST = 4;
+ static constexpr int CATSEYE_REPLACE_RULE_NOP = 5;
+ static constexpr int CATSEYE_REPLACE_RULE_SRC_XOR_DST = 6;
+ static constexpr int CATSEYE_REPLACE_RULE_SRC_OR_DST = 7;
+ static constexpr int CATSEYE_REPLACE_RULE_NOT_SRC_AND_NOT_DST = 8;
+ static constexpr int CATSEYE_REPLACE_RULE_NOT_SRC_XOR_DST = 9;
+ static constexpr int CATSEYE_REPLACE_RULE_NOT_DST = 10;
+ static constexpr int CATSEYE_REPLACE_RULE_SRC_OR_NOT_DST = 11;
+ static constexpr int CATSEYE_REPLACE_RULE_NOT_SRC = 12;
+ static constexpr int CATSEYE_REPLACE_RULE_NOT_SRC_OR_DST = 13;
+ static constexpr int CATSEYE_REPLACE_RULE_NOT_SRC_OR_NOT_DST = 14;
+ static constexpr int CATSEYE_REPLACE_RULE_SET = 15;
+
+ // registers compatible to topcat
+ static constexpr int TOPCAT_REG_VBLANK=0x20;
+ static constexpr int TOPCAT_REG_WMOVE_ACTIVE=0x22;
+ static constexpr int TOPCAT_REG_VBLANK_INTRQ=0x24;
+ static constexpr int TOPCAT_REG_WMOVE_INTRQ=0x26;
+ static constexpr int TOPCAT_REG_DISPLAY_PLANE_ENABLE=0x40;
+ static constexpr int TOPCAT_REG_SYNC_ENABLE=0x42;
+ static constexpr int TOPCAT_REG_WRITE_ENABLE_PLANE=0x44;
+ static constexpr int TOPCAT_REG_READ_ENABLE_PLANE=0x46;
+ static constexpr int TOPCAT_REG_FB_WRITE_ENABLE=0x48;
+ static constexpr int TOPCAT_REG_WMOVE_IE=0x4a;
+ static constexpr int TOPCAT_REG_VBLANK_IE=0x4c;
+ static constexpr int TOPCAT_REG_START_WMOVE=0x4e;
+ static constexpr int TOPCAT_REG_ENABLE_BLINK_PLANES=0x50;
+ static constexpr int TOPCAT_REG_ENABLE_ALT_FRAME=0x54;
+ static constexpr int TOPCAT_REG_PRR=0x75;
+ static constexpr int TOPCAT_REG_WRR=0x77;
+ static constexpr int TOPCAT_REG_WMSOURCEX=0x79;
+ static constexpr int TOPCAT_REG_WMSOURCEY=0x7b;
+ static constexpr int TOPCAT_REG_WMDESTX=0x7d;
+ static constexpr int TOPCAT_REG_WMDESTY=0x7f;
+ static constexpr int TOPCAT_REG_WMWIDTH=0x81;
+ static constexpr int TOPCAT_REG_WMHEIGHT=0x83;
+
+ // catseye specific registers
+ static constexpr int CATSEYE_REG_WMX=0x100;
+ static constexpr int CATSEYE_REG_RUG_REV=0x102;
+ static constexpr int CATSEYE_REG_RUG_SC=0x103;
+ static constexpr int CATSEYE_REG_WMWIDTH=0x104;
+ static constexpr int CATSEYE_REG_WMHEIGHT=0x105;
+ static constexpr int CATSEYE_REG_LINEPATH=0x106;
+ static constexpr int CATSEYE_REG_LINETYPE=0x107;
+ static constexpr int CATSEYE_REG_WMSOURCEX=0x108;
+ static constexpr int CATSEYE_REG_WMSOURCEY=0x109;
+ static constexpr int CATSEYE_REG_WMDESTX=0x10a;
+ static constexpr int CATSEYE_REG_WMDESTY=0x10b;
+ static constexpr int CATSEYE_REG_WMCLIPLEFT=0x10c;
+ static constexpr int CATSEYE_REG_WMCLIPRIGHT=0x10d;
+ static constexpr int CATSEYE_REG_WMCLIPTOP=0x10e;
+ static constexpr int CATSEYE_REG_WMCLIPBOTTOM=0x10f;
+ static constexpr int CATSEYE_REG_TWMWIDTH=0x184;
+ static constexpr int CATSEYE_REG_TWMHEIGHT=0x185;
+ static constexpr int CATSEYE_REG_TWMSOURCEX=0x188;
+ static constexpr int CATSEYE_REG_TWMSOURCEY=0x189;
+ static constexpr int CATSEYE_REG_TWMDESTX=0x18a;
+ static constexpr int CATSEYE_REG_TWMDESTY=0x18b;
+
+ // Window mover 1 registers
+ static constexpr int CATSEYE_REG_PATTERNS1=0x200;
+ static constexpr int CATSEYE_REG_FBEN1=0x280;
+ static constexpr int CATSEYE_REG_PRR1=0x281;
+ static constexpr int CATSEYE_REG_TCREN1=0x282;
+ static constexpr int CATSEYE_REG_WRR1=0x283;
+ static constexpr int CATSEYE_REG_TCWEN1=0x284;
+ static constexpr int CATSEYE_REG_BARC_REV1=0x285;
+ static constexpr int CATSEYE_REG_TRR1=0x286;
+ static constexpr int CATSEYE_REG_COLOR1=0x287;
+ static constexpr int CATSEYE_REG_VB1=0x288;
+ static constexpr int CATSEYE_REG_TRRCTL1=0x289;
+ static constexpr int CATSEYE_REG_ACNTL1=0x28a;
+ static constexpr int CATSEYE_REG_PLANEMODE1=0x28b;
+
+ // Window mover 2 registers
+ static constexpr int CATSEYE_REG_PATTERNS2=0x300;
+ static constexpr int CATSEYE_REG_FBEN2=0x380;
+ static constexpr int CATSEYE_REG_PRR2=0x381;
+ static constexpr int CATSEYE_REG_TCREN2=0x382;
+ static constexpr int CATSEYE_REG_WRR2=0x383;
+ static constexpr int CATSEYE_REG_TCWEN2=0x384;
+ static constexpr int CATSEYE_REG_BARC_REV2=0x385;
+ static constexpr int CATSEYE_REG_TRR2=0x386;
+ static constexpr int CATSEYE_REG_COLOR2=0x387;
+ static constexpr int CATSEYE_REG_VB2=0x388;
+ static constexpr int CATSEYE_REG_TRRCTL2=0x389;
+ static constexpr int CATSEYE_REG_ACNTL2=0x38a;
+ static constexpr int CATSEYE_REG_PLANEMODE2=0x38b;
+
+ static constexpr int CATSEYE_REG_STATUS=0x400;
+
+ static constexpr u16 CATSEYE_STATUS_READY = 0x02;
+ static constexpr u16 CATSEYE_STATUS_UNCLIPPED = 0x04;
+ static constexpr u16 CATSEYE_STATUS_NO_DAUGHTERBOARD = 0x08;
+ static constexpr u16 CATSEYE_STATUS_VBLANK = 0x10;
+
+ // bit definitions for various registers
+ static constexpr u16 CATSEYE_VB_VECTOR = 0x100;
+ static constexpr u16 CATSEYE_MISC_ENABLE_CLIP = 0x80;
+ static constexpr int VRAM_VIDEO_PLANE = 0;
+ static constexpr int VRAM_OVERLAY_PLANE = 1;
+
+ emu_timer *m_blink_timer;
+
+ // set when screen contents have changed
+ bool m_changed;
+
+ // keeps track of visibility when plane is enabled for blinking
+ bool m_blink_state;
+
+ // configuration settings
+ int m_fb_width;
+ int m_fb_height;
+ int m_plane;
+
+ // we keep the plane mask twice - once for matching the lower byte,
+ // and once for matching the higher byte.
+ u16 m_plane_mask_l;
+ u16 m_plane_mask_h;
+
+ // registers are enabled to be written by host cpu
+ u16 m_write_enable[2];
+
+ // registers are enabled to be read by host cpu
+ u16 m_read_enable[2];
+
+ // enables writing to plane from window mover
+ u16 m_fb_enable[2];
+
+ // plane is visible on screen
+ u16 m_display_enable;
+
+ // plane is blinking
+ u16 m_blink_enable;
+
+ // sync output to monitor is enabled (ignored)
+ u16 m_sync_enable;
+
+ // video output is blanked due to vert retrace
+ u16 m_in_vblank;
+
+ // interrupt status & enable
+ u16 m_wm_int_pending;
+ u16 m_vblank_int_pending;
+ u16 m_wm_int_enable;
+ u16 m_vblank_int_enable;
+
+ // RUGCMD:
+ // bit 7-6: 0 - solid vector/circle
+ // 1 - linetype vector/circle
+ // 2 - blit mode
+ // 3 - fill mode
+ // bit 5: 1 - draw circle, 0 - draw vector
+ // bit 4: 1 - RUG is allowed to write to framebuffer
+
+ u16 m_rugsc;
+
+ // unknown, bit 7 enables window mover clipping
+ u16 m_misc;
+
+ // WMX register allows to set SOURCEX and DESTX register
+ // in the window mover at the same time
+ u16 m_wmx;
+
+ // co-ordinates for window mover
+ u16 m_wmwidth;
+ u16 m_wmheight;
+ u16 m_wmsourcex;
+ u16 m_wmsourcey;
+ u16 m_wmdestx;
+ u16 m_wmdesty;
+
+ // limits for window mover
+ // (pixels outside of this range will not be drawn)
+ u16 m_wmclipleft;
+ u16 m_wmclipright;
+ u16 m_wmcliptop;
+ u16 m_wmclipbottom;
+
+ // patterns for tripple replacement rules
+ std::array<std::array<u16, 128>, 2> m_patterns;
+
+ // 16 bit pattern for lines drawn
+ u16 m_linepath;
+
+ // bit 11-8: repeat length
+ // bit 7-4: current pattern bit
+ // bit 3-0: current repeat count
+ u16 m_linetype;
+
+ // Pixel replacement rule, applied when writing to VRAM from host CPU
+ u16 m_prr[2];
+
+ // Window replacement rule, applied by window mover
+ u16 m_wrr[2];
+
+ // Tripple replacement rule, used together with the patterns register
+ u16 m_trr[2];
+
+ // bit 8: 1 - enable tripple replacement rule
+ u16 m_trrctl[2];
+
+ // color used for drawing vectors
+ u16 m_color[2];
+
+ // unknown, bit 8: 1 - vector mode, 0 - bitblt mode
+ u16 m_vb[2];
+
+ // bit 1: 1 - VRAM is accessed in bit-mode by host CPU
+ // 2 bytes are expanded to 16 bytes, with 1 bit per byte information
+ // bit 2: 1 - host CPU reads overlay plane via host interface
+ u16 m_acntrl;
+
+ // source plane for window mover operations
+ // bit 4: 1 - source plane is given in bit 3-0
+ // 0 - current plane is source for move
+ u16 m_planemode[2];
+
+ // bit 0: 1 - window mover busy
+ // bit 1: 1 - registers ready for host CPU
+ // bit 2: 1 - pixels generated by RUG
+ // bit 3: 1 - no daughter board present
+ // bit 4: 1 - in vertical blank
+ // bit 4: 1 - in horizontal sync
+ u16 m_status;
+
+};
+
+DECLARE_DEVICE_TYPE(CATSEYE, catseye_device)
+#endif // MAME_VIDEO_CATSEYE_H
diff --git a/src/emu/xtal.cpp b/src/emu/xtal.cpp
index 1310fc1b000..7b46160bb58 100644
--- a/src/emu/xtal.cpp
+++ b/src/emu/xtal.cpp
@@ -378,6 +378,7 @@ const double XTAL::known_xtals[] = {
87'183'360, /* 87.18336_MHz_XTAL AT&T 630 MTG */
100'000'000, /* 100_MHz_XTAL PSX-based Namco System 12, Vegas, Sony ZN1-2-based */
101'491'200, /* 101.4912_MHz_XTAL PSX-based Namco System 10 */
+ 108'108'000, /* 108.108_MHz_XTAL HP 98550 high-res color card */
200'000'000 /* 200_MHz_XTAL Base SH4 CPU (Naomi, Hikaru etc.) */
};
diff --git a/src/mame/drivers/hp9k_3xx.cpp b/src/mame/drivers/hp9k_3xx.cpp
index 29061c95c82..4ccf982dd4c 100644
--- a/src/mame/drivers/hp9k_3xx.cpp
+++ b/src/mame/drivers/hp9k_3xx.cpp
@@ -357,13 +357,13 @@ MACHINE_CONFIG_START(hp9k3xx_state::hp9k320)
hp9k300(config);
add_dio32_bus(config);
- DIO32_SLOT(config, "sl0", 0, "diobus", dio16_cards, "human_interface", true);
- DIO32_SLOT(config, "sl1", 0, "diobus", dio16_cards, "98543", false);
- DIO32_SLOT(config, "sl2", 0, "diobus", dio16_cards, "98603b", false);
- DIO32_SLOT(config, "sl3", 0, "diobus", dio16_cards, "98644", false);
+ DIO32_SLOT(config, "sl0", 0, "diobus", dio32_cards, "human_interface", true);
+ DIO32_SLOT(config, "sl1", 0, "diobus", dio32_cards, "98543", false);
+ DIO32_SLOT(config, "sl2", 0, "diobus", dio32_cards, "98603b", false);
+ DIO32_SLOT(config, "sl3", 0, "diobus", dio32_cards, "98644", false);
DIO32_SLOT(config, "sl4", 0, "diobus", dio32_cards, "98620", false);
DIO32_SLOT(config, "sl5", 0, "diobus", dio32_cards, "98265a", false);
- DIO32_SLOT(config, "sl6", 0, "diobus", dio16_cards, nullptr, false);
+ DIO32_SLOT(config, "sl6", 0, "diobus", dio32_cards, nullptr, false);
MACHINE_CONFIG_END
MACHINE_CONFIG_START(hp9k3xx_state::hp9k330)
diff --git a/src/mame/layout/hp9k_3xx.lay b/src/mame/layout/hp9k_3xx.lay
index 5ea470b0156..e52ea316517 100644
--- a/src/mame/layout/hp9k_3xx.lay
+++ b/src/mame/layout/hp9k_3xx.lay
@@ -15,45 +15,33 @@ Hewlett-Packard 9000/3xx Layout
<disk state="1"><color red="0.0" green="1.0" blue="0.0"/></disk>
</element>
+ <repeat count="8">
+ <param name="num" start="7" increment="-1" />
+ <element name="led_diag_~num~s"> <text string="~num~"> <color red="1.0" green="1.0" blue="1.0" /></text></element>
+ </repeat>
+ <element name="led_power_s"> <text string="Power"> <color red="1.0" green="1.0" blue="1.0" /></text></element>
- <element name="led_diag_7s"> <text string="7"> <color red="1.0" green="1.0" blue="1.0" /> </text> </element>
- <element name="led_diag_6s"> <text string="6"> <color red="1.0" green="1.0" blue="1.0" /> </text> </element>
- <element name="led_diag_5s"> <text string="5"> <color red="1.0" green="1.0" blue="1.0" /> </text> </element>
- <element name="led_diag_4s"> <text string="4"> <color red="1.0" green="1.0" blue="1.0" /> </text> </element>
- <element name="led_diag_3s"> <text string="3"> <color red="1.0" green="1.0" blue="1.0" /> </text> </element>
- <element name="led_diag_2s"> <text string="2"> <color red="1.0" green="1.0" blue="1.0" /> </text> </element>
- <element name="led_diag_1s"> <text string="1"> <color red="1.0" green="1.0" blue="1.0" /> </text> </element>
- <element name="led_diag_0s"> <text string="0"> <color red="1.0" green="1.0" blue="1.0" /> </text> </element>
-
- <element name="led_power_s"> <text string="Power"> <color red="1.0" green="1.0" blue="1.0" /> </text> </element>
+ <group name="panel">
+ <bezel element="background"><bounds x="0" y="0" width="~scr0width~" height="64"/></bezel>
+ <repeat count="8">
+ <param name="left" start="100" increment="20" />
+ <param name="right" start="116" increment="20" />
+ <param name="num" start="7" increment="-1" />
+ <bezel name="led_diag_~num~s" element="led_diag_~num~s"><bounds left="~left~" right="~right~" top="8" bottom="24"/></bezel>
+ <bezel name="led_diag_~num~" element="ledr"><bounds left="~left~" right="~right~" top="32" bottom="48"/></bezel>
+ </repeat>
+ <bezel name="led_power_s" element="led_power_s"><bounds left="20" top="8" right="56" bottom="24"/></bezel>
+ <bezel name="led_power" element="ledg"><bounds left="28" right="44" top="32" bottom="48"/></bezel>
+ </group>
<view name="HP9000/3xx">
- <bezel element="background"><bounds left="0" top="768" right="1024" bottom="832"/></bezel>
- <bezel name="led_diag_7" element="ledr"><bounds left="20" top="776" right="36" bottom="792"/></bezel>
- <bezel name="led_diag_7s" element="led_diag_7s"><bounds left="20" top="800" right="36" bottom="816"/></bezel>
- <bezel name="led_diag_6" element="ledr"><bounds left="40" top="776" right="56" bottom="792"/></bezel>
- <bezel name="led_diag_6s" element="led_diag_6s"><bounds left="40" top="800" right="56" bottom="816"/></bezel>
- <bezel name="led_diag_5" element="ledr"><bounds left="60" top="776" right="76" bottom="792"/></bezel>
- <bezel name="led_diag_5s" element="led_diag_5s"><bounds left="60" top="800" right="76" bottom="816"/></bezel>
- <bezel name="led_diag_4" element="ledr"><bounds left="80" top="776" right="96" bottom="792"/></bezel>
- <bezel name="led_diag_4s" element="led_diag_4s"><bounds left="80" top="800" right="96" bottom="816"/></bezel>
- <bezel name="led_diag_3" element="ledr"><bounds left="100" top="776" right="116" bottom="792"/></bezel>
- <bezel name="led_diag_3s" element="led_diag_3s"><bounds left="100" top="800" right="116" bottom="816"/></bezel>
- <bezel name="led_diag_2" element="ledr"><bounds left="120" top="776" right="136" bottom="792"/></bezel>
- <bezel name="led_diag_2s" element="led_diag_2s"><bounds left="120" top="800" right="136" bottom="816"/></bezel>
- <bezel name="led_diag_1" element="ledr"><bounds left="140" top="776" right="156" bottom="792"/></bezel>
- <bezel name="led_diag_1s" element="led_diag_1s"><bounds left="140" top="800" right="156" bottom="816"/></bezel>
- <bezel name="led_diag_0" element="ledr"><bounds left="160" top="776" right="176" bottom="792"/></bezel>
- <bezel name="led_diag_0s" element="led_diag_0s"><bounds left="160" top="800" right="176" bottom="816"/></bezel>
-
- <bezel name="led_power_s" element="led_power_s"><bounds left="980" top="800" right="1016" bottom="816"/></bezel>
-
- <bezel name="led_power" element="ledg"><bounds left="990" top="776" right="1006" bottom="792"/></bezel>
- <screen index="0"><bounds x="0" y="0" width="1024" height="768"/></screen>
+ <screen index="0"><bounds x="0" y="0" width="~scr0width~" height="~scr0height~"/></screen>
+ <group ref="panel"><bounds x="0" y="~scr0height~" width="~scr0width~" height="64"/></group>
</view>
- <view name="XGA Screen">
+
+ <view name="Screen">
<screen index="0">
- <bounds x="0" y="0" width="1024" height="768" />
+ <bounds x="0" y="0" width="~scr0width~" height="~scr0height~" />
</screen>
</view>
</mamelayout>