diff options
author | 2017-12-06 18:58:55 +0700 | |
---|---|---|
committer | 2017-12-06 18:58:55 +0700 | |
commit | ad9b6fe4e53fcf7037463500e42a4a458c9e670f (patch) | |
tree | 73b3954dd70b40ee334308a512fd76933bb6f9db | |
parent | 7e7bff3543662746b07b15ac53d5523c58fa8a89 (diff) |
dp8510: new device
An implementation of the National Semiconductor DP8510 BITBLT Processing Unit. This is used on the InterPro GT family graphics boards, and this implementation seems to be correct enough to enable me to progress there, hence the PR. While I'd love to have another system to test against, I'm not aware of any other systems that ever used this device other than some NatSemi reference designs, which are not (yet) in MAME.
-rw-r--r-- | scripts/src/video.lua | 12 | ||||
-rw-r--r-- | scripts/target/mame/mess.lua | 1 | ||||
-rw-r--r-- | src/devices/video/dp8510.cpp | 211 | ||||
-rw-r--r-- | src/devices/video/dp8510.h | 88 |
4 files changed, 312 insertions, 0 deletions
diff --git a/scripts/src/video.lua b/scripts/src/video.lua index 59ed7ef18f8..035717a2da1 100644 --- a/scripts/src/video.lua +++ b/scripts/src/video.lua @@ -1033,3 +1033,15 @@ if (VIDEOS["I4100"]~=null) then MAME_DIR .. "src/devices/video/imagetek_i4100.h", } end + +-------------------------------------------------- +-- +--@src/devices/video/dp8510.h,VIDEOS["DP8510"] = true +-------------------------------------------------- + +if (VIDEOS["DP8510"]~=null) then + files { + MAME_DIR .. "src/devices/video/dp8510.cpp", + MAME_DIR .. "src/devices/video/dp8510.h", + } +end diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index 3814eb5d019..65c89bc15ce 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -353,6 +353,7 @@ VIDEOS["GB_LCD"] = true VIDEOS["GBA_LCD"] = true VIDEOS["MGA2064W"] = true VIDEOS["PPU2C0X"] = true +VIDEOS["DP8510"] = true -------------------------------------------------- -- specify available machine cores diff --git a/src/devices/video/dp8510.cpp b/src/devices/video/dp8510.cpp new file mode 100644 index 00000000000..d0e64deb307 --- /dev/null +++ b/src/devices/video/dp8510.cpp @@ -0,0 +1,211 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay + +/* + * An implementation of the National Semiconductor DP8510 BITBLT Processing Unit. + * + * This device is designed to perform shifting, masking and logic operations on + * source and destination video memory data values. The device relies on + * external logic to drive the system video memory, and to control input lines + * on the device to enable it to read or write its inputs and outputs on the + * data bus. The device has a 16 bit data bus, as well as a 16 slot internal + * fifo, which enables it to work with up to 16 words containing 16 bits of + * pixel data at a time. The expected design was that a single BPU would handle + * each video bitplane, with multiple devices being used in parallel to handle + * multiple planes. + * + * This device is used in the InterPro GT family graphics, which do not make + * use of the line drawing mode, and is therefore currently unimplemented. + * + * Reference: http://bitsavers.org/components/national/_dataBooks/1988_National_Graphics_Handbook.pdf + * + * TODO + * - line drawing mode + */ + +#include "emu.h" +#include "dp8510.h" + +#define VERBOSE 0 +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(DP8510, dp8510_device, "dp8510", "National Semiconductor BITBLT Processing Unit") + +const char *const dp8510_device::BITBLT_OP[] = { + "0", "~s & ~d", "~s & d", "~s", "s & ~d", "~d", "s ^ d", "~s | ~d", + "s & d", "~s ^ ~d", "d", "~s | d", "s", "s | ~d", "s | d", "1" +}; + +dp8510_device::dp8510_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, DP8510, tag, owner, clock) + , m_line_drawing(CLEAR_LINE) + , m_barrel_input_select(CLEAR_LINE) + , m_pixel_data_input(CLEAR_LINE) + , m_data_output_select(CLEAR_LINE) + , m_left_mask(CLEAR_LINE) + , m_right_mask(CLEAR_LINE) +{ +} + +void dp8510_device::device_start() +{ + // input lines + save_item(NAME(m_line_drawing)); + save_item(NAME(m_barrel_input_select)); + save_item(NAME(m_pixel_data_input)); + save_item(NAME(m_data_output_select)); + save_item(NAME(m_left_mask)); + save_item(NAME(m_right_mask)); + + // registers and latches + save_item(NAME(m_control)); + save_item(NAME(m_barrel_input_latch)); + save_item(NAME(m_logic_output)); + save_item(NAME(m_fifo_output_latch)); + + // fifo + save_item(NAME(m_fifo[FIFO_SIZE])); + save_item(NAME(m_fifo_head)); + save_item(NAME(m_fifo_tail)); + + // helper internal state + save_item(NAME(m_f0)); + save_item(NAME(m_f1)); + save_item(NAME(m_f2)); + save_item(NAME(m_f3)); +} + +void dp8510_device::device_reset() +{ + m_fifo_head = 0; + m_fifo_tail = 0; +} + +void dp8510_device::control_w(const u16 data) +{ + LOG("control_w function select %d shift number %d left mask %d right mask %d (%s)\n", + (data & CONTROL_FS) >> 12, + (data & CONTROL_SN) >> 8, + (data & CONTROL_LM) >> 4, + (data & CONTROL_RM) >> 0, + machine().describe_context()); + + m_control = data; + + // expand function select bits to 16 bit size for convenience + m_f0 = (data & FS_0) ? ~u16(0) : 0; + m_f1 = (data & FS_1) ? ~u16(0) : 0; + m_f2 = (data & FS_2) ? ~u16(0) : 0; + m_f3 = (data & FS_3) ? ~u16(0) : 0; +} + +void dp8510_device::source_w(const u16 data, const bool fifo_write) +{ + if (fifo_write) + { + // execute barrel shift + const u8 shift_amount = (m_control & CONTROL_SN) >> 8; + const u16 shift_result = m_barrel_input_select + ? (data << shift_amount) | (m_barrel_input_latch >> (16 - shift_amount)) + : (m_barrel_input_latch << shift_amount) | (data >> (16 - shift_amount)); + + LOG("source_w 0x%04x shifted data 0x%04x written to fifo\n", data, shift_result); + + // write result to fifo + fifo_w(shift_result); + } + else + LOG("source_w barrel input latch 0x%04x\n", data); + + // save data in input latch + m_barrel_input_latch = data; +} + +u16 dp8510_device::logic_unit(const u16 src, const u16 dst) const +{ + // compute logic unit result + const u16 result = + (m_f3 & src & dst) + + (m_f2 & src & ~dst) + + (m_f1 & ~src & dst) + + (m_f0 & ~src & ~dst); + + LOG("logic_unit operation %s source 0x%04x destination 0x%04x result 0x%04x\n", + BITBLT_OP[(m_control & CONTROL_FS) >> 12], src, dst, result); + + return result; +} + +void dp8510_device::destination_w(const u16 data, const bool fifo_write) +{ + // fetch the source from the pixel data input or fifo + const u16 source = m_line_drawing ? m_pixel_data_input ? 0xffff : 0 : m_fifo_output_latch = fifo_r(); + + // compute the result + u16 result = logic_unit(source, data); + + // apply left mask + if (m_left_mask) + { + const u16 left_mask = 0xffffU >> ((m_control & CONTROL_LM) >> 4); + if (left_mask != 0xffff) + LOG("destination_w left mask 0x%04x applied\n", left_mask); + + result = (result & left_mask) | (data & ~left_mask); + } + + // apply right mask + if (m_right_mask) + { + const u16 right_mask = s16(0x8000) >> (m_control & CONTROL_RM); + if (right_mask != 0xffff) + LOG("destination_w right mask 0x%04x applied\n", right_mask); + + result = (result & right_mask) | (data & ~right_mask); + } + + // latch output + m_logic_output = result; + + // write the result back to the fifo + if (fifo_write) + { + LOG("destination_w masked data 0x%04x written to fifo\n", m_logic_output); + fifo_w(m_logic_output); + } + else + LOG("destination_w masked data 0x%04x latched\n", m_logic_output); +} + +u16 dp8510_device::output_r() const +{ + // return output from fifo or logic unit + if (m_data_output_select) + return m_fifo_output_latch; + else + return m_logic_output; +} + +u8 dp8510_device::pixel_r(const offs_t pixel_address) const +{ + return (m_logic_output >> (~pixel_address & 0xf)) & 0x1; +} + +u16 dp8510_device::fifo_r() +{ + const u16 data = m_fifo[m_fifo_head++]; + + m_fifo_head %= FIFO_SIZE; + + return data; +} + +void dp8510_device::fifo_w(const u16 data) +{ + m_fifo[m_fifo_tail++] = data; + + m_fifo_tail %= FIFO_SIZE; + + if (m_fifo_tail == m_fifo_head) + logerror("fifo_w warning fifo full (%s)\n", machine().describe_context()); +} diff --git a/src/devices/video/dp8510.h b/src/devices/video/dp8510.h new file mode 100644 index 00000000000..946dd0d8c15 --- /dev/null +++ b/src/devices/video/dp8510.h @@ -0,0 +1,88 @@ +// license:BSD-3-Clause +// copyright-holders:Patrick Mackinlay +#ifndef MAME_VIDEO_DP8510_H +#define MAME_VIDEO_DP8510_H + +#pragma once + +#include "video/dp8510.h" + +class dp8510_device : public device_t +{ +public: + dp8510_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + static const char *const BITBLT_OP[]; + static const int FIFO_SIZE = 16; + + DECLARE_WRITE_LINE_MEMBER(line_drawing) { m_line_drawing = state; } + DECLARE_WRITE_LINE_MEMBER(barrel_input_select) { m_barrel_input_select = state; } + DECLARE_WRITE_LINE_MEMBER(pixel_data_input) { m_pixel_data_input = state; } + DECLARE_WRITE_LINE_MEMBER(data_output_select) { m_data_output_select = state; } + DECLARE_WRITE_LINE_MEMBER(left_mask_enable) { m_left_mask = state; } + DECLARE_WRITE_LINE_MEMBER(right_mask_enable) { m_right_mask = state; } + + enum control_mask : u16 + { + CONTROL_RM = 0x000f, // right mask + CONTROL_LM = 0x00f0, // left mask + CONTROL_SN = 0x0f00, // shift number + CONTROL_FS = 0xf000 // function select + }; + + enum control_fs_mask : u16 + { + FS_0 = 0x1000, + FS_1 = 0x2000, + FS_2 = 0x4000, + FS_3 = 0x8000 + }; + + void control_w(const u16 data); + + void source_w(const u16 data, const bool fifo_write = true); + void destination_w(const u16 data, const bool fifo_write = false); + + u16 output_r() const; + u8 pixel_r(const offs_t pixel_address) const; + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + u16 logic_unit(const u16 src, const u16 dst) const; + + u16 fifo_r(); + void fifo_w(const u16 data); + +private: + // input lines + int m_line_drawing; + int m_barrel_input_select; + int m_pixel_data_input; + int m_data_output_select; + int m_left_mask; + int m_right_mask; + + // registers and latches + u16 m_control; + u16 m_barrel_input_latch; + u16 m_logic_output; + u16 m_fifo_output_latch; + + // fifo + u16 m_fifo[FIFO_SIZE]; + u8 m_fifo_head; + u8 m_fifo_tail; + + // helper internal state + u16 m_f0; + u16 m_f1; + u16 m_f2; + u16 m_f3; +}; + +// device type definition +DECLARE_DEVICE_TYPE(DP8510, dp8510_device) + +#endif // MAME_VIDEO_DP8510_H |