summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Patrick Mackinlay <pmackinlay@hotmail.com>2019-06-20 18:28:06 +0700
committer Patrick Mackinlay <pmackinlay@hotmail.com>2019-06-20 18:28:06 +0700
commit4c15ecdbb60f9c48dd68236f92fd77729af33fbb (patch)
treefa09f16c5c47bd333c3a83270a0cef322b30fc53
parentf84e2459b1d4ed60692e9331ffc5add88eae9ec3 (diff)
bt47x: new device (nw)
-rw-r--r--scripts/src/video.lua11
-rw-r--r--scripts/target/mame/mess.lua1
-rw-r--r--src/devices/video/bt47x.cpp236
-rw-r--r--src/devices/video/bt47x.h127
4 files changed, 375 insertions, 0 deletions
diff --git a/scripts/src/video.lua b/scripts/src/video.lua
index 87a36ce6b5a..b49bd961f95 100644
--- a/scripts/src/video.lua
+++ b/scripts/src/video.lua
@@ -1207,3 +1207,14 @@ if (VIDEOS["DECSFB"]~=null) then
}
end
+--------------------------------------------------
+--
+--@src/devices/video/bt47x.h,VIDEOS["BT47X"] = true
+--------------------------------------------------
+
+if (VIDEOS["BT47X"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/video/bt47x.cpp",
+ MAME_DIR .. "src/devices/video/bt47x.h",
+ }
+end
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 91f332ed3ee..05d675c88ea 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -298,6 +298,7 @@ VIDEOS["SEGA315_5313"] = true
--VIDEOS["BUFSPRITE"] = true
VIDEOS["BT45X"] = true
VIDEOS["BT459"] = true
+VIDEOS["BT47X"] = true
VIDEOS["CATSEYE"] = true
VIDEOS["CDP1861"] = true
VIDEOS["CDP1862"] = true
diff --git a/src/devices/video/bt47x.cpp b/src/devices/video/bt47x.cpp
new file mode 100644
index 00000000000..d5aea56a400
--- /dev/null
+++ b/src/devices/video/bt47x.cpp
@@ -0,0 +1,236 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+/*
+ * An emulation of the Brooktree Bt47x family of RAMDAC devices.
+ *
+ * Max. Input Output
+ * Part Clock Color Overlay Num. Levels Other
+ * Bt471 80MHz 8 bit 4 bit 3 6 bit
+ * Bt475 80MHz 8 bit 4 bit 3 6 bit sleep mode, compatibility mode
+ * Bt476 80Mhz 8 bit 3 6 bit
+ * Bt477 80MHz 8 bit 4 bit 3 8 bit sleep mode, compatibility mode
+ * Bt478 80MHz 8 bit 4 bit 3 8 bit
+ *
+ * Not emulated:
+ *
+ * Bt473 80MHz 24 bit 4 bit 3 8 bit true color/passthrough/bypass modes
+ * Bt474 85MHz 4x8 bit 4x4 bit 3 8 bit sleep mode, vga mode
+ * Bt479 80MHz 8 bit 4 bit 3 8 bit 16 windows, compatibility mode
+ *
+ * Sources:
+ * - http://www.bitsavers.org/components/brooktree/_dataBooks/1991_Brooktree_Product_Databook.pdf
+ *
+ * TODO:
+ * - remaining devices
+ */
+
+#include "emu.h"
+#include "bt47x.h"
+
+#define LOG_GENERAL (1U << 0)
+#define LOG_READS (1U << 1)
+
+//#define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(BT471, bt471_device, "bt471", "Brooktree Bt471 256 Color RAMDAC")
+//DEFINE_DEVICE_TYPE(BT473, bt473_device, "bt473", "Brooktree Bt473 True-Color RAMDAC")
+//DEFINE_DEVICE_TYPE(BT474, bt474_device, "bt474", "Brooktree Bt474 256 Color RAMDAC")
+DEFINE_DEVICE_TYPE(BT475, bt475_device, "bt475", "Brooktree Bt475 256 Color RAMDAC")
+DEFINE_DEVICE_TYPE(BT476, bt476_device, "bt476", "Brooktree Bt476 256 Color RAMDAC")
+DEFINE_DEVICE_TYPE(BT477, bt477_device, "bt477", "Brooktree Bt477 256 Color RAMDAC")
+DEFINE_DEVICE_TYPE(BT478, bt478_device, "bt478", "Brooktree Bt478 256 Color RAMDAC")
+//DEFINE_DEVICE_TYPE(BT479, bt479_device, "bt479", "Brooktree Bt479 1024 Color RAMDAC")
+
+void bt47x_device_base::map(address_map &map)
+{
+ map(0x00, 0x00).rw(FUNC(bt47x_device_base::address_r), FUNC(bt47x_device_base::address_w));
+ map(0x01, 0x01).rw(FUNC(bt47x_device_base::palette_r), FUNC(bt47x_device_base::palette_w));
+ map(0x02, 0x02).rw(FUNC(bt47x_device_base::mask_r), FUNC(bt47x_device_base::mask_w));
+ map(0x03, 0x03).rw(FUNC(bt47x_device_base::address_r), FUNC(bt47x_device_base::address_w));
+
+ if (m_overlay_colors)
+ {
+ map(0x04, 0x04).rw(FUNC(bt47x_device_base::address_r), FUNC(bt47x_device_base::address_w));
+ map(0x05, 0x05).rw(FUNC(bt47x_device_base::overlay_r), FUNC(bt47x_device_base::overlay_w));
+ map(0x07, 0x07).rw(FUNC(bt47x_device_base::address_r), FUNC(bt47x_device_base::address_w));
+ }
+}
+
+void bt475_device_base::map(address_map &map)
+{
+ bt47x_device_base::map(map);
+
+ map(0x06, 0x06).rw(FUNC(bt475_device_base::command_r), FUNC(bt475_device_base::command_w));
+}
+
+bt47x_device_base::bt47x_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, unsigned const palette_colors, unsigned const overlay_colors, unsigned const color_bits)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_palette_interface(mconfig, *this)
+ , m_palette_colors(palette_colors)
+ , m_overlay_colors(overlay_colors)
+ , m_color_bits(color_bits)
+{
+}
+
+bt475_device_base::bt475_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, unsigned const palette_colors, unsigned const overlay_colors, unsigned const color_bits)
+ : bt47x_device_base(mconfig, type, tag, owner, clock, palette_colors, overlay_colors, color_bits)
+{
+}
+
+bt471_device::bt471_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : bt47x_device_base(mconfig, BT471, tag, owner, clock, 256, 16, 6)
+{
+}
+
+bt475_device::bt475_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : bt475_device_base(mconfig, BT475, tag, owner, clock, 256, 16, 6)
+{
+}
+
+bt476_device::bt476_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : bt47x_device_base(mconfig, BT476, tag, owner, clock, 256, 0, 6)
+{
+}
+
+bt477_device::bt477_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : bt475_device_base(mconfig, BT477, tag, owner, clock, 256, 16, 8)
+{
+}
+
+bt478_device::bt478_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : bt47x_device_base(mconfig, BT478, tag, owner, clock, 256, 16, 8)
+{
+}
+
+void bt47x_device_base::device_start()
+{
+ save_item(NAME(m_address));
+ save_item(NAME(m_address_rgb));
+ save_item(NAME(m_read_mask));
+
+ m_color_ram = std::make_unique<std::array<u8, 3>[]>(m_palette_colors + m_overlay_colors);
+
+ save_pointer(NAME(m_color_ram), m_palette_colors + m_overlay_colors);
+}
+
+void bt475_device_base::device_start()
+{
+ bt47x_device_base::device_start();
+
+ save_item(NAME(m_command));
+}
+
+u8 bt47x_device_base::address_r()
+{
+ LOGMASKED(LOG_READS, "address_r 0x%02x\n", m_address);
+
+ if (!machine().side_effects_disabled())
+ m_address_rgb = 0;
+
+ return m_address;
+}
+
+void bt47x_device_base::address_w(u8 data)
+{
+ LOG("address_w 0x%02x\n", data);
+ m_address_rgb = 0;
+
+ m_address = data;
+}
+
+void bt47x_device_base::increment_address(bool const side_effects)
+{
+ if (!machine().side_effects_disabled() || side_effects)
+ {
+ // increment component index and address register
+ m_address_rgb = (m_address_rgb + 1) % 3;
+ if (m_address_rgb == 0)
+ m_address++;
+ }
+}
+
+u8 bt47x_device_base::palette_r()
+{
+ u8 const data = m_color_ram[m_address][m_address_rgb];
+
+ increment_address();
+
+ LOGMASKED(LOG_READS, "palette_r 0x%02x\n", data);
+
+ return data;
+}
+
+void bt47x_device_base::palette_w(u8 data)
+{
+ LOG("palette_w 0x%02x\n", data);
+
+ m_color_ram[m_address][m_address_rgb] = data;
+
+ // update the mame palette to match the device
+ if (m_address_rgb == 2)
+ set_pen_color(m_address, rgb_t(
+ m_color_ram[m_address][0] << (8 - color_bits()),
+ m_color_ram[m_address][1] << (8 - color_bits()),
+ m_color_ram[m_address][2] << (8 - color_bits())));
+
+ increment_address(true);
+}
+
+u8 bt47x_device_base::mask_r()
+{
+ LOGMASKED(LOG_READS, "mask_r 0x%02x\n", m_read_mask);
+
+ return m_read_mask;
+}
+
+void bt47x_device_base::mask_w(u8 data)
+{
+ LOG("mask_w 0x%02x\n", data);
+
+ m_read_mask = data;
+}
+
+u8 bt47x_device_base::overlay_r()
+{
+ unsigned const index = m_palette_colors + (m_address & (m_overlay_colors - 1));
+ u8 const data = m_color_ram[index][m_address_rgb];
+
+ increment_address();
+
+ LOGMASKED(LOG_READS, "overlay_r 0x%02x\n", data);
+
+ return data;
+}
+
+void bt47x_device_base::overlay_w(u8 data)
+{
+ LOG("overlay_w 0x%02x\n", data);
+
+ unsigned const index = m_palette_colors + (m_address & (m_overlay_colors - 1));
+ m_color_ram[index][m_address_rgb] = data;
+
+ // update the mame palette to match the device
+ if (m_address_rgb == 2)
+ set_pen_color(index, rgb_t(
+ m_color_ram[index][0] << (8 - color_bits()),
+ m_color_ram[index][1] << (8 - color_bits()),
+ m_color_ram[index][2] << (8 - color_bits())));
+
+ increment_address(true);
+}
+
+u8 bt475_device_base::command_r()
+{
+ LOGMASKED(LOG_READS, "command_r 0x%02x\n", m_command);
+
+ return m_command;
+}
+
+void bt475_device_base::command_w(u8 data)
+{
+ LOG("command_w 0x%02x\n", data);
+
+ m_command = data;
+}
diff --git a/src/devices/video/bt47x.h b/src/devices/video/bt47x.h
new file mode 100644
index 00000000000..cc96fed7a7b
--- /dev/null
+++ b/src/devices/video/bt47x.h
@@ -0,0 +1,127 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+#ifndef MAME_VIDEO_BT47X_H
+#define MAME_VIDEO_BT47X_H
+
+#pragma once
+
+class bt47x_device_base
+ : public device_t
+ , public device_palette_interface
+{
+public:
+ // color lookup
+ rgb_t palette_lookup(u8 index) const { return pen_color(index & m_read_mask); }
+ rgb_t overlay_lookup(u8 index) const { return pen_color(m_palette_colors + index); }
+
+ virtual void map(address_map &map);
+
+protected:
+ bt47x_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, unsigned const palette_colors, unsigned const overlay_colors, unsigned const color_bits);
+
+ // device_t overrides
+ virtual void device_start() override;
+
+ // device_palette_interface overrides
+ virtual u32 palette_entries() const override { return m_palette_colors + m_overlay_colors; }
+
+ // read/write handlers
+ u8 address_r();
+ void address_w(u8 data);
+ u8 palette_r();
+ void palette_w(u8 data);
+ u8 mask_r();
+ void mask_w(u8 data);
+ u8 overlay_r();
+ void overlay_w(u8 data);
+
+ virtual unsigned color_bits() const { return m_color_bits; }
+
+private:
+ // helpers
+ void increment_address(bool const side_effects = false);
+
+ // device state
+ u8 m_address;
+ u8 m_address_rgb;
+ u8 m_read_mask;
+
+ // internal state
+ unsigned const m_palette_colors;
+ unsigned const m_overlay_colors;
+ unsigned const m_color_bits;
+
+ std::unique_ptr<std::array<u8, 3>[]> m_color_ram;
+};
+
+class bt475_device_base : public bt47x_device_base
+{
+public:
+ virtual void map(address_map &map) override;
+
+protected:
+ bt475_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, unsigned const palette_colors, unsigned const overlay_colors, unsigned const color_bits);
+
+ // device_t overrides
+ virtual void device_start() override;
+
+ u8 command_r();
+ void command_w(u8 data);
+
+ enum command_mask : u8
+ {
+ D0 = 0x01, // sleep enable
+ D1 = 0x02, // 8-bit select (Bt477 only)
+ D2 = 0x04, // sync on red enable
+ D3 = 0x08, // sync on green enable
+ D4 = 0x10, // sync on blue enable
+ D5 = 0x20, // 7.5 IRE blank pedastal enable
+ D6 = 0x40, // reserved (logical one)
+ D7 = 0x80, // reserved (logical zero)
+ };
+ u8 m_command;
+};
+
+class bt471_device : public bt47x_device_base
+{
+public:
+ bt471_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+};
+
+class bt475_device : public bt475_device_base
+{
+public:
+ bt475_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+};
+
+class bt476_device : public bt47x_device_base
+{
+public:
+ bt476_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+};
+
+class bt477_device : public bt475_device_base
+{
+public:
+ bt477_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ virtual unsigned color_bits() const override { return (m_command & D1) ? 8 : 6; }
+};
+
+class bt478_device : public bt47x_device_base
+{
+public:
+ bt478_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+};
+
+DECLARE_DEVICE_TYPE(BT471, bt471_device)
+//DECLARE_DEVICE_TYPE(BT473, bt473_device)
+//DECLARE_DEVICE_TYPE(BT474, bt474_device)
+DECLARE_DEVICE_TYPE(BT475, bt475_device)
+DECLARE_DEVICE_TYPE(BT476, bt476_device)
+DECLARE_DEVICE_TYPE(BT477, bt477_device)
+DECLARE_DEVICE_TYPE(BT478, bt478_device)
+//DECLARE_DEVICE_TYPE(BT479, bt479_device)
+
+#endif // MAME_VIDEO_BT47X_H