From 593340af38eb6488116353aafa81a87ae8ab97e3 Mon Sep 17 00:00:00 2001 From: mooglyguy Date: Fri, 13 Apr 2018 18:25:09 +0200 Subject: -vp415: Skeleton driver for Philips VP415 LV-ROM Player. Includes basic device implementation of Fujitsu MB88303 Television Display Controller. [Ryan Holtz] --- scripts/src/video.lua | 12 + src/devices/video/mb88303.cpp | 347 ++++++++++++++++++++++++ src/devices/video/mb88303.h | 136 ++++++++++ src/mame/drivers/vp415.cpp | 594 ++++++++++++++++++++++++++++++++++++++++++ src/mame/mame.lst | 3 + src/mame/mess.flt | 1 + 6 files changed, 1093 insertions(+) create mode 100644 src/devices/video/mb88303.cpp create mode 100644 src/devices/video/mb88303.h create mode 100644 src/mame/drivers/vp415.cpp diff --git a/scripts/src/video.lua b/scripts/src/video.lua index 035717a2da1..9baca568f33 100644 --- a/scripts/src/video.lua +++ b/scripts/src/video.lua @@ -508,6 +508,18 @@ if (VIDEOS["M50458"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/video/mb88303.h,MACHINES["MB88303"] = true +--------------------------------------------------- + +if (MACHINES["MB88303"]~=null) then + files { + MAME_DIR .. "src/devices/video/mb88303.cpp", + MAME_DIR .. "src/devices/video/mb88303.h", + } +end + -------------------------------------------------- -- --@src/devices/video/mb90082.h,VIDEOS["MB90082"] = true diff --git a/src/devices/video/mb88303.cpp b/src/devices/video/mb88303.cpp new file mode 100644 index 00000000000..ee4432263c8 --- /dev/null +++ b/src/devices/video/mb88303.cpp @@ -0,0 +1,347 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/*********************************************************************** + + Fujitsu MB88303 NMOS Television Display Controller (TVDC) emulation + + TOOD: + - Character-size registers. + - Proper hsync/vsync emulation. + - Blinking. + +***********************************************************************/ + +#include "emu.h" +#include "mb88303.h" + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +// device type definition +DEFINE_DEVICE_TYPE(MB88303, mb88303_device, "mb88303", "Fujitsu MB88303") + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +/*static*/ const uint8_t mb88303_device::s_character_data[0x40][7] = { + { 0x0e, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11 }, // 0x00 + { 0x1e, 0x11, 0x11, 0x1e, 0x11, 0x11, 0x1e }, + { 0x0e, 0x11, 0x10, 0x10, 0x10, 0x11, 0x0e }, + { 0x1e, 0x09, 0x09, 0x09, 0x09, 0x09, 0x1e }, + { 0x1f, 0x10, 0x10, 0x1e, 0x10, 0x10, 0x1f }, + { 0x1f, 0x10, 0x10, 0x1e, 0x10, 0x10, 0x10 }, + { 0x0f, 0x10, 0x10, 0x13, 0x11, 0x11, 0x0f }, + { 0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11 }, + { 0x0e, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0e }, + { 0x01, 0x01, 0x01, 0x01, 0x11, 0x11, 0x0e }, + { 0x11, 0x12, 0x14, 0x18, 0x14, 0x12, 0x11 }, + { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1f }, + { 0x11, 0x1b, 0x15, 0x15, 0x11, 0x11, 0x11 }, + { 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x1f }, + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, + { 0x11, 0x11, 0x19, 0x15, 0x13, 0x11, 0x11 }, // 0x10 + { 0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e }, + { 0x1e, 0x11, 0x11, 0x1e, 0x10, 0x10, 0x10 }, + { 0x0e, 0x11, 0x11, 0x11, 0x15, 0x12, 0x0d }, + { 0x1e, 0x11, 0x11, 0x1e, 0x14, 0x12, 0x11 }, + { 0x0e, 0x11, 0x10, 0x0e, 0x01, 0x11, 0x0e }, + { 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }, + { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e }, + { 0x11, 0x11, 0x11, 0x11, 0x11, 0x0a, 0x04 }, + { 0x11, 0x11, 0x11, 0x15, 0x15, 0x1b, 0x11 }, + { 0x11, 0x11, 0x0a, 0x04, 0x0a, 0x11, 0x11 }, + { 0x11, 0x11, 0x0a, 0x04, 0x04, 0x04, 0x04 }, + { 0x1f, 0x01, 0x02, 0x04, 0x08, 0x10, 0x1f }, + { 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x00 }, + { 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }, + { 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02 }, + { 0x0e, 0x11, 0x13, 0x15, 0x19, 0x11, 0x0e }, // 0x20 + { 0x04, 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04 }, + { 0x0e, 0x11, 0x01, 0x0e, 0x10, 0x10, 0x1f }, + { 0x0e, 0x11, 0x01, 0x06, 0x01, 0x11, 0x0e }, + { 0x06, 0x0a, 0x12, 0x12, 0x1f, 0x02, 0x02 }, + { 0x1f, 0x10, 0x1e, 0x01, 0x01, 0x11, 0x0e }, + { 0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x0e }, + { 0x1f, 0x11, 0x01, 0x02, 0x04, 0x04, 0x04 }, + { 0x0e, 0x11, 0x11, 0x0e, 0x11, 0x11, 0x0e }, + { 0x0e, 0x11, 0x11, 0x0f, 0x01, 0x11, 0x0e }, + { 0x0e, 0x11, 0x01, 0x06, 0x04, 0x00, 0x04 }, + { 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x04 }, + { 0x06, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08 }, + { 0x00, 0x04, 0x0a, 0x15, 0x04, 0x04, 0x00 }, // 0x30 + { 0x00, 0x04, 0x04, 0x15, 0x0a, 0x04, 0x00 }, + { 0x00, 0x04, 0x08, 0x17, 0x08, 0x04, 0x00 }, + { 0x00, 0x04, 0x02, 0x1d, 0x02, 0x04, 0x00 }, + { 0x00, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x00 }, + { 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00 }, + { 0x00, 0x04, 0x15, 0x0e, 0x15, 0x04, 0x00 }, + { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x00 }, + { 0x00, 0x00, 0x1f, 0x00, 0x1f, 0x00, 0x00 }, + { 0x0c, 0x12, 0x14, 0x08, 0x15, 0x12, 0x0d }, + { 0x10, 0x1f, 0x02, 0x0f, 0x0a, 0x1f, 0x02 }, + { 0x1f, 0x11, 0x1f, 0x11, 0x1f, 0x11, 0x11 }, + { 0x1f, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x1f }, + { 0x00, 0x00, 0x00, 0x00, 0x0c, 0x04, 0x08 }, + { 0x00, 0x00, 0x00, 0x08, 0x15, 0x02, 0x00 }, + { 0x0e, 0x11, 0x04, 0x1f, 0x1b, 0x1f, 0x11 } +}; + + +//------------------------------------------------- +// mb88303_device - constructor +//------------------------------------------------- + +mb88303_device::mb88303_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, MB88303, tag, owner, clock) + , m_write_vow(*this) + , m_write_vobn(*this) + , m_write_do(*this) + , m_horiz_display_pos(0) + , m_vert_display_pos(0) + , m_display_ctrl(0) + , m_general_out(7) + , m_address(0) + , m_addr_inc_mode(false) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void mb88303_device::device_start() +{ + // resolve callbacks + m_write_vow.resolve_safe(); + m_write_vobn.resolve_safe(); + m_write_do.resolve_safe(); + + // register for state saving + save_item(NAME(m_display_mem)); + save_item(NAME(m_horiz_display_pos)); + save_item(NAME(m_vert_display_pos)); + save_item(NAME(m_display_ctrl)); + save_item(NAME(m_general_out)); + save_item(NAME(m_address)); + save_item(NAME(m_addr_inc_mode)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void mb88303_device::device_reset() +{ + m_horiz_display_pos = 0; + m_vert_display_pos = 0; + m_display_ctrl = 0; + m_general_out = 0x07; + m_address = 0; + m_addr_inc_mode = false; + + memset(m_display_mem, 0, sizeof(uint8_t) * 180); + + m_da = 0; + m_adm = 0; + m_reset_n = 1; + m_ldi = 0; + m_hsync_n = 1; + m_vsync_n = 1; + + m_write_vow(CLEAR_LINE); + m_write_vobn(ASSERT_LINE); + m_write_do(m_general_out); +} + + +WRITE8_MEMBER( mb88303_device::da_w ) +{ + //logerror("%s: mb88303_device::da_w: %02x\n", machine().describe_context(), data); + m_da = data; +} + +WRITE_LINE_MEMBER( mb88303_device::adm_w ) +{ + //logerror("%s: mb88303_device::adm_w: %02x\n", machine().describe_context(), state); + m_adm = state; +} + +WRITE_LINE_MEMBER( mb88303_device::reset_n_w ) +{ + logerror("%s: mb88303_device::reset_n_w: %02x\n", machine().describe_context(), state); + uint8_t old = m_reset_n; + m_reset_n = state; + + if (old != m_reset_n && m_reset_n) + { + m_horiz_display_pos = 0; + m_vert_display_pos = 0; + m_display_ctrl = 0; + m_general_out = 0x07; + m_addr_inc_mode = false; + + m_write_vow(CLEAR_LINE); + m_write_vobn(ASSERT_LINE); + m_write_do(m_general_out); + } +} + +WRITE_LINE_MEMBER( mb88303_device::ldi_w ) +{ + //logerror("%s: mb88303_device::ldi_w: %02x\n", machine().describe_context(), state); + uint8_t old = m_ldi; + m_ldi = state; + + if (m_ldi != old) + { + if (!m_ldi) + { + // Direct Address Mode: At the trailing edge of LDI, a 7-bit + // data on DA6-DA0 is written into an internal control register + // or an internal display memory location that is designated by + // the address latched at the leading edge. + + // Address Increment Mode: At the trailing edge of LDI, a 7-bit + // data on DA6-DA0 is written into an internal control register + // or a display memory location that is indicated by the + // address register. + process_data(); + } + else if (!m_adm) + { + // Direct Address Mode: At the leading edge of LDI, an 8-bit + // address on DA7-DA0 is automatically latched into the + // internal address register. + //logerror("%s: mb88303_device::ldi_w: new address = %02x\n", machine().describe_context(), m_da); + m_address = m_da; + } + else + { + // Address Increment Mode: At the leading edge of LDI, the + // address register is automatically incremented. + m_address++; + //logerror("%s: mb88303_device::ldi_w: new address = %02x\n", machine().describe_context(), m_address); + } + } +} + +void mb88303_device::process_data() +{ + switch (m_address) + { + case 180: + hdpr_w(m_da); + break; + case 181: + vdpr_w(m_da); + break; + case 182: + dcr_w(m_da); + break; + case 183: + gor_w(m_da); + break; + default: + assert(m_address < 180); + m_display_mem[m_address] = m_da; + break; + } +} + +WRITE_LINE_MEMBER( mb88303_device::hsync_n_w ) +{ + m_hsync_n = state; +} + +WRITE_LINE_MEMBER( mb88303_device::vsync_n_w ) +{ + m_vsync_n = state; +} + +void mb88303_device::hdpr_w(uint8_t data) +{ + logerror("%s: mb88303_device::hdpr_w: %02x\n", machine().describe_context(), data); + m_horiz_display_pos = data & 0x3f; +} + +void mb88303_device::vdpr_w(uint8_t data) +{ + logerror("%s: mb88303_device::vdpr_w: %02x\n", machine().describe_context(), data); + m_vert_display_pos = data & 0x3f; +} + +void mb88303_device::dcr_w(uint8_t data) +{ + logerror("%s: mb88303_device::dcr_w: %02x\n", machine().describe_context(), data); + m_display_ctrl = data & 0x7f; +} + +void mb88303_device::gor_w(uint8_t data) +{ + //logerror("%s: mb88303_device::gor_w: %02x\n", machine().describe_context(), data); + uint8_t old = m_general_out; + m_general_out = data & 0x07; + if (m_general_out != old) + { + m_write_do(m_general_out); + } +} + + +bool mb88303_device::blank_display() +{ + return !BIT(m_display_ctrl, BLK_BIT); +} + +bool mb88303_device::show_background() +{ + return BIT(m_display_ctrl, BLKB_BIT); +} + +bool mb88303_device::enable_blinking() +{ + return BIT(m_display_ctrl, BLINK_BIT); +} + +void mb88303_device::update_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + if (blank_display()) + { + bitmap.fill(0, cliprect); + return; + } + + for (unsigned x = 0; x < VISIBLE_COLUMNS; x++) + { + for (unsigned y = 0; y < VISIBLE_LINES; y++) + { + uint16_t bitmap_y = y * 9; + uint16_t bitmap_x = x * 6; + const uint8_t *gfx = s_character_data[m_display_mem[y * VISIBLE_COLUMNS + x] & 0x3f]; + for (unsigned row = 0; row < 7; row++) + { + for (unsigned bit = 0; bit < 6; bit++) + { + if (gfx[row] & 0x80) + continue; + const uint32_t color = BIT(gfx[row], bit) ? 0xffffffff : 0; + if (!show_background() && !color) + continue; + bitmap.pix32(bitmap_y + row + m_vert_display_pos, bitmap_x + (6 - bit) + m_horiz_display_pos) = color; + } + } + } + } +} diff --git a/src/devices/video/mb88303.h b/src/devices/video/mb88303.h new file mode 100644 index 00000000000..058f58f212b --- /dev/null +++ b/src/devices/video/mb88303.h @@ -0,0 +1,136 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/*********************************************************************** + + Fujitsu MB88303 NMOS Television Display Controller (TVDC) emulation + +************************************************************************ + _____ _____ + /RESET 1 |* \_/ | 22 Vcc + DO0 2 | | 21 DA7 + DO1 3 | | 20 DA6 + DO2 4 | | 19 DA5 + VOW 5 | | 18 DA4 + /VOB 6 | MB88303 | 17 DA3 + /VSYNC 7 | | 16 DA2 + /HSYNC 8 | | 15 DA1 + EX 9 | | 14 DA0 + X 10 | | 13 ADM + Vss 11 |_____________| 12 LDI + +************************************************************************/ + +#ifndef MAME_VIDEO_MB88303_H +#define MAME_VIDEO_MB88303_H + +#pragma once + + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_MB88303_VOW_CALLBACK(_write) \ + devcb = &downcast(*device).set_vow_callback(DEVCB_##_write); + +#define MCFG_MB88303_VOBN_CALLBACK(_write) \ + devcb = &downcast(*device).set_vob_n_callback(DEVCB_##_write); + +#define MCFG_MB88303_DO_CALLBACK(_write) \ + devcb = &downcast(*device).set_do_callback(DEVCB_##_write); + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> mb88303_device + +class mb88303_device : public device_t +{ +public: + static constexpr unsigned VISIBLE_COLUMNS = 20; + static constexpr unsigned VISIBLE_LINES = 9; + + // construction/destruction + mb88303_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + template devcb_base &set_vow_callback(Object &&cb) { return m_write_vow.set_callback(std::forward(cb)); } + template devcb_base &set_vobn_callback(Object &&cb) { return m_write_vobn.set_callback(std::forward(cb)); } + template devcb_base &set_do_callback(Object &&cb) { return m_write_do.set_callback(std::forward(cb)); } + + DECLARE_WRITE8_MEMBER(da_w); + DECLARE_WRITE_LINE_MEMBER(adm_w); + DECLARE_WRITE_LINE_MEMBER(reset_n_w); + DECLARE_WRITE_LINE_MEMBER(ldi_w); + DECLARE_WRITE_LINE_MEMBER(hsync_n_w); + DECLARE_WRITE_LINE_MEMBER(vsync_n_w); + + void update_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + +private: + enum + { + HSZ0 = 0x01, + HSZ1 = 0x02, + VSZ0 = 0x04, + VSZ1 = 0x08, + BLK = 0x10, + BLKB = 0x20, + BLINK = 0x40, + + HSZ0_BIT = 0, + HSZ1_BIT = 1, + VSZ0_BIT = 2, + VSZ1_BIT = 3, + BLK_BIT = 4, + BLKB_BIT = 5, + BLINK_BIT = 6, + }; + + void hdpr_w(uint8_t data); // Horizontal Display Position Register + void vdpr_w(uint8_t data); // Vertical Display Position Register + void dcr_w(uint8_t data); // Display Control Register + void gor_w(uint8_t data); // General Output Register + + void process_data(); + bool blank_display(); + bool show_background(); + bool enable_blinking(); + uint8_t hsize(); + uint8_t vsize(); + + devcb_write_line m_write_vow; + devcb_write_line m_write_vobn; + devcb_write8 m_write_do; + + uint8_t m_da; + uint8_t m_adm; + uint8_t m_reset_n; + uint8_t m_ldi; + uint8_t m_hsync_n; + uint8_t m_vsync_n; + + uint8_t m_display_mem[180]; + uint8_t m_horiz_display_pos; + uint8_t m_vert_display_pos; + uint8_t m_display_ctrl; + uint8_t m_general_out; + uint8_t m_address; + + bool m_addr_inc_mode; + + static const uint8_t s_character_data[0x40][7]; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(MB88303, mb88303_device) + +#endif // MAME_VIDEO_MB88303_H diff --git a/src/mame/drivers/vp415.cpp b/src/mame/drivers/vp415.cpp new file mode 100644 index 00000000000..71b797618f7 --- /dev/null +++ b/src/mame/drivers/vp415.cpp @@ -0,0 +1,594 @@ +// license:BSD-3-Clause +// copyright-holders:Ryan Holtz +/*************************************************************************** + + Skeleton driver for Philips VP415 LV ROM Player + + List of Modules: + A - Audio Processor + B - RGB + C - Video Processor + D - Ref Source + E - Slide Drive + F - Motor+Sequence + G - Gen Lock + H - ETBC B + I - ETBC C + J - Focus + K - HF Processor + L - Video Dropout Correction + M - Radial + N - Display Keyboard + P - Front Loader + Q - RC5 Mirror + R - Drive Processor + S - Control + T - Supply + U - Analog I/O + V - Module Carrier + W - CPU Datagrabber + X - LV ROM + Y - Vid Mix + Z - Deck Electronics + + TODO: + - Module W and Module S both have a NEC D8041AHC which has not yet + been dumped. Dumps will be necessary to properly emulate the + player. + - Anyone who has information on the proper voltage with which to + dump a mask-type 8041 manufactured by NEC circa 1987, please + contact Ryan Holtz. + - Driver currently fails the initial self-test with code 025. Per + the service manual, code 25 means "no REFV pulse at system + start-up". + +***************************************************************************/ + +#include "emu.h" +#include "screen.h" + +#include "cpu/mcs51/mcs51.h" +#include "cpu/z80/z80.h" + +#include "machine/i8155.h" +#include "machine/i8255.h" +#include "video/mb88303.h" + +class vp415_state : public driver_device +{ +public: + vp415_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag) + , m_maincpu(*this, Z80CPU_TAG) + , m_drivecpu(*this, DRIVECPU_TAG) + , m_chargen(*this, CHARGEN_TAG) + , m_mainram(*this, Z80RAM_TAG) + , m_ctrlram(*this, CTRLRAM_TAG) + , m_switches(*this, SWITCHES_TAG) + { } + + void vp415(machine_config &config); + + virtual void machine_reset() override; + virtual void machine_start() override; + + uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + + DECLARE_WRITE8_MEMBER(ncr5385_w); + DECLARE_READ8_MEMBER(ncr5385_r); + DECLARE_WRITE8_MEMBER(sel34_w); + DECLARE_READ8_MEMBER(sel37_r); + DECLARE_WRITE8_MEMBER(ctrl_regs_w); + DECLARE_READ8_MEMBER(ctrl_regs_r); + + DECLARE_READ8_MEMBER(drive_i8155_pb_r); + DECLARE_READ8_MEMBER(drive_i8155_pc_r); + + DECLARE_WRITE8_MEMBER(drive_i8255_pa_w); + DECLARE_WRITE8_MEMBER(drive_i8255_pb_w); + DECLARE_READ8_MEMBER(drive_i8255_pc_r); + DECLARE_WRITE8_MEMBER(drive_cpu_port1_w); + + static const char* Z80CPU_TAG; + static const char* Z80RAM_TAG; + static const char* CTRLCPU_TAG; + static const char* CTRLRAM_TAG; + static const char* DRIVECPU_TAG; + static const char* DESCRAMBLE_ROM_TAG; + static const char* SYNC_ROM_TAG; + static const char* DRIVE_ROM_TAG; + static const char* CONTROL_ROM_TAG; + static const char* SWITCHES_TAG; + static const char* I8155_TAG; + static const char* I8255_TAG; + static const char* CHARGEN_TAG; + +protected: + enum + { + SEL34_INTR_N = 0x01, + SEL34_RES = 0x20, + SEL34_ERD = 0x40, + SEL34_ENW = 0x80, + SEL34_INTR_N_BIT = 0, + SEL34_RES_BIT = 5, + SEL34_ERD_BIT = 6, + SEL34_ENW_BIT = 7, + }; + + enum + { + SEL37_ID0 = 0x01, + SEL37_ID1 = 0x02, + SEL37_BRD = 0x10, + SEL37_MON_N = 0x20, + SEL37_SK1c = 0x40, + SEL37_SK1d = 0x40, + + SEL37_ID0_BIT = 0, + SEL37_ID1_BIT = 1, + SEL37_BRD_BIT = 4, + SEL37_MON_N_BIT = 5, + SEL37_SK1c_BIT = 6, + SEL37_SK1d_BIT = 7, + }; + + enum + { + DIAG_TURN_MISCOMPARE_INITIAL = 0x08, + DIAG_TURN_MISCOMPARE_FINAL = 0x10, + DIAG_TURN_GOOD_PARITY = 0x18, + DIAG_TURN_BAD_PARITY = 0x20, + DIAG_COMPLETE = 0x80, + + DIAG_COMPLETE_BIT = 7, + }; + + enum + { + INT_FUNC_COMPLETE = 0x01, + INT_INVALID_CMD = 0x40, + + INT_FUNC_COMPLETE_BIT = 0, + INT_INVALID_CMD_BIT = 6, + }; + + enum + { + AUX_STATUS_TC_ZERO = 0x02, + AUX_STATUS_PAUSED = 0x04, + AUX_STATUS_PARITY_ERR = 0x40, + AUX_STATUS_DATA_FULL = 0x80, + + AUX_STATUS_TC_ZERO_BIT = 1, + AUX_STATUS_PAUSED_BIT = 2, + AUX_STATUS_PARITY_ERR_BIT = 6, + AUX_STATUS_DATA_FULL_BIT = 7, + }; + + enum + { + STATE_IDLE, + STATE_DIAGNOSTIC_GOOD_PARITY, + STATE_DIAGNOSTIC_BAD_PARITY, + }; + + enum + { + CTRL_SELECT = 0x01, + CTRL_RESELECT = 0x02, + CTRL_PARITY = 0x04, + + CTRL_SELECT_BIT = 0, + CTRL_RESELECT_BIT = 1, + CTRL_PARITY_BIT = 2, + }; + + virtual void video_start() override; + + void z80_program_map(address_map &map); + void z80_io_map(address_map &map); + void set_intn_line(uint8_t line, uint8_t value); + + void ctrl_program_map(address_map &map); + void ctrl_io_map(address_map &map); + void sd_w(uint8_t data); + uint8_t sd_r(); + + void drive_program_map(address_map &map); + void drive_io_map(address_map &map); + + required_device m_maincpu; + required_device m_drivecpu; + required_device m_chargen; + required_shared_ptr m_mainram; + required_shared_ptr m_ctrlram; + required_ioport m_switches; + + uint8_t m_sel34; + uint8_t m_sel37; + + uint32_t m_state; + uint8_t m_ctrl_reg; + uint8_t m_int_reg; + uint8_t m_aux_status_reg; + uint8_t m_diag_status_reg; + uint8_t m_intn_lines[2]; +}; + +/*static*/ const char* vp415_state::Z80CPU_TAG = "z80cpu"; +/*static*/ const char* vp415_state::Z80RAM_TAG = "z80ram"; +/*static*/ const char* vp415_state::CTRLCPU_TAG = "ctrlcpu"; +/*static*/ const char* vp415_state::CTRLRAM_TAG = "ctrlram"; +/*static*/ const char* vp415_state::DRIVECPU_TAG = "drivecpu"; +/*static*/ const char* vp415_state::DESCRAMBLE_ROM_TAG = "descramblerom"; +/*static*/ const char* vp415_state::SYNC_ROM_TAG = "syncrom"; +/*static*/ const char* vp415_state::DRIVE_ROM_TAG = "driverom"; +/*static*/ const char* vp415_state::CONTROL_ROM_TAG = "controlrom"; +/*static*/ const char* vp415_state::SWITCHES_TAG = "SWITCHES"; +/*static*/ const char* vp415_state::I8155_TAG = "i8155"; +/*static*/ const char* vp415_state::I8255_TAG = "i8255"; +/*static*/ const char* vp415_state::CHARGEN_TAG = "mb88303"; + +void vp415_state::machine_reset() +{ + m_state = STATE_IDLE; + m_int_reg = 0; + m_ctrl_reg = 0; + m_aux_status_reg = AUX_STATUS_TC_ZERO; + m_diag_status_reg = DIAG_COMPLETE; + + m_sel34 = 0; + m_sel37 = SEL37_BRD | SEL37_MON_N | SEL37_SK1c | SEL37_SK1d; + m_intn_lines[0] = 1; + m_intn_lines[1] = 1; +} + +void vp415_state::machine_start() +{ +} + +// CPU Datagrabber Module (W) + +WRITE8_MEMBER(vp415_state::ncr5385_w) +{ + switch (offset) + { + case 0x0: // Data Register + switch (m_state) + { + case STATE_DIAGNOSTIC_GOOD_PARITY: + m_aux_status_reg &= ~AUX_STATUS_PARITY_ERR; + m_aux_status_reg |= AUX_STATUS_DATA_FULL; + m_int_reg = INT_FUNC_COMPLETE; + m_diag_status_reg = DIAG_COMPLETE | DIAG_TURN_GOOD_PARITY; + m_state = STATE_IDLE; + set_intn_line(1, 0); + logerror("%s: ncr5385_w: data=%02x (diagnostic w/ good parity)\n", machine().describe_context(), data); + break; + case STATE_DIAGNOSTIC_BAD_PARITY: + m_aux_status_reg |= AUX_STATUS_PARITY_ERR | AUX_STATUS_DATA_FULL; + m_int_reg = INT_FUNC_COMPLETE; + m_diag_status_reg = DIAG_COMPLETE | DIAG_TURN_BAD_PARITY; + m_state = STATE_IDLE; + set_intn_line(1, 0); + logerror("%s: ncr5385_w: data=%02x (diagnostic w/ bad parity)\n", machine().describe_context(), data); + break; + default: + logerror("%s: ncr5385_w: data=%02x\n", machine().describe_context(), data); + break; + } + break; + case 0x1: // Command Register + switch (data & 0x3f) + { + case 0x00: // Chip Reset + logerror("%s: ncr5385_w: command: reset\n", machine().describe_context()); + m_state = STATE_IDLE; + m_int_reg = 0; + m_aux_status_reg = AUX_STATUS_TC_ZERO; + m_diag_status_reg = DIAG_COMPLETE; + set_intn_line(1, 1); + break; + case 0x0b: // Diagnostic + logerror("%s: ncr5385_w: command: diagnostic (%s parity)\n", machine().describe_context(), BIT(data, 6) ? "bad" : "good"); + if (BIT(data, 6)) + m_state = STATE_DIAGNOSTIC_BAD_PARITY; + else + m_state = STATE_DIAGNOSTIC_GOOD_PARITY; + break; + default: + logerror("%s: ncr5385_w: command: %02x\n", machine().describe_context(), data); + break; + } + break; + case 0x2: // Control Register + m_ctrl_reg = data & 0x07; + logerror("%s: ncr5385_w: control: parity_en=%d, reselect_en=%d, select_en=%d\n", machine().describe_context(), BIT(data, CTRL_PARITY_BIT), BIT(data, CTRL_RESELECT_BIT), BIT(data, CTRL_SELECT_BIT)); + break; + default: + logerror("%s: ncr5385_w: %x=%02x\n", machine().describe_context(), offset, data); + break; + } +} + +READ8_MEMBER(vp415_state::ncr5385_r) +{ + switch (offset) + { + case 0x2: + logerror("%s: ncr5385_r: control (%02x)\n", machine().describe_context(), m_ctrl_reg); + return m_ctrl_reg; + case 0x4: + logerror("%s: ncr5385_r: aux status (%02x)\n", machine().describe_context(), m_aux_status_reg); + return m_aux_status_reg; + case 0x6: + logerror("%s: ncr5385_r: interrupt (%02x)\n", machine().describe_context(), m_int_reg); + set_intn_line(1, 1); + return m_int_reg; + case 0x9: + logerror("%s: ncr5385_r: diagnostic status (%02x)\n", machine().describe_context(), m_diag_status_reg); + return m_diag_status_reg; + default: + logerror("%s: ncr5385_r: %x (%02x)\n", machine().describe_context(), offset, 0); + return 0; + } +} + +WRITE8_MEMBER(vp415_state::sel34_w) +{ + logerror("%s: sel34: /INTR=%d, RES=%d, ERD=%d, ENW=%d\n", machine().describe_context(), BIT(data, SEL34_INTR_N_BIT), BIT(data, SEL34_RES_BIT), BIT(data, SEL34_ERD_BIT), BIT(data, SEL34_ENW_BIT)); + m_sel34 = data; + + if (!BIT(data, SEL34_INTR_N_BIT)) + { + m_sel37 &= ~(SEL37_ID0 | SEL37_ID1); + } +} + +READ8_MEMBER(vp415_state::sel37_r) +{ + logerror("%s: sel37: ID0=%d, ID1=%d\n", machine().describe_context(), BIT(m_sel37, SEL37_ID0_BIT), BIT(m_sel37, SEL37_ID1_BIT)); + return m_sel37; +} + +void vp415_state::set_intn_line(uint8_t line, uint8_t value) +{ + if (value == 0) + { + m_sel37 |= line ? SEL37_ID0 : SEL37_ID1; + } + + m_intn_lines[line] = value; + if (m_intn_lines[0] && m_intn_lines[1]) + { + m_maincpu->set_input_line(0, CLEAR_LINE); + } + else + { + m_maincpu->set_input_line(0, ASSERT_LINE); + } +} + +void vp415_state::z80_program_map(address_map &map) +{ + map(0x0000, 0x7fff).rom().region(Z80CPU_TAG, 0); + map(0xa000, 0xfeff).ram().share(Z80RAM_TAG); +} + +void vp415_state::z80_io_map(address_map &map) +{ + map.global_mask(0xff); + map(0x00, 0x0f).rw(this, FUNC(vp415_state::ncr5385_r), FUNC(vp415_state::ncr5385_w)); + // 0x20, 0x21: Connected to A0 + D0..D7 of SLAVE i8041 + map(0x34, 0x34).w(this, FUNC(vp415_state::sel34_w)); + map(0x37, 0x37).r(this, FUNC(vp415_state::sel37_r)); +} + + + +// Control Module (S) + +WRITE8_MEMBER(vp415_state::ctrl_regs_w) +{ + const uint8_t handler_index = (offset & 0x0c00) >> 10; + switch (handler_index) + { + case 0: // WREN + logerror("%s: ctrl_regs_w: WREN: %02x\n", machine().describe_context(), data); + sd_w(data); + break; + case 1: // WR3 + logerror("%s: ctrl_regs_w: WR3 (UPI-41, not yet dumped/implemented): %02x\n", machine().describe_context(), data); + break; + case 2: + logerror("%s: ctrl_regs_w: N.C. write %02x\n", machine().describe_context(), data); + break; + case 3: + logerror("%s: ctrl_regs_w: output buffer: VP=%d, NPL=%d, WR-CLK=%d, DB/STAT=%d, RD-STRT=%d, V/C-TXT=%d\n", machine().describe_context(), data & 0x7, BIT(data, 4), BIT(data, 3), BIT(data, 5), BIT(data, 6), BIT(data, 7)); + break; + } +} + +READ8_MEMBER(vp415_state::ctrl_regs_r) +{ + const uint8_t handler_index = (offset & 0x0c00) >> 10; + uint8_t value = 0; + switch (handler_index) + { + case 0: // RDEN + value = sd_r(); + logerror("%s: ctrl_regs_r: RDEN: %02x\n", machine().describe_context(), value); + break; + case 1: // RD3 + logerror("%s: ctrl_regs_r: RD3 (UPI-41, not yet dumped/implemented): %02x\n", machine().describe_context(), 0); + break; + case 2: // RD2 + logerror("%s: ctrl_regs_r: N.C. read\n", machine().describe_context()); + break; + case 3: + value = m_switches->read(); + logerror("%s: ctrl_regs_r: RD1 (DIP switches): %02x\n", machine().describe_context(), value); + break; + } + return value; +} + +uint8_t vp415_state::sd_r() +{ + return 0; +} + +void vp415_state::sd_w(uint8_t data) +{ +} + +void vp415_state::ctrl_program_map(address_map &map) +{ + map(0x0000, 0xffff).rom().region(CONTROL_ROM_TAG, 0); +} + +void vp415_state::ctrl_io_map(address_map &map) +{ + map(0x0000, 0x1fff).ram().share(CTRLRAM_TAG); + map(0xe000, 0xffff).rw(this, FUNC(vp415_state::ctrl_regs_r), FUNC(vp415_state::ctrl_regs_w)).mask(0x1c00); +} + +// Drive Processor Module (R) + +READ8_MEMBER(vp415_state::drive_i8155_pb_r) +{ + logerror("%s: drive_i8155_pb_r: %02x\n", machine().describe_context(), 0); + return 0; +} + +READ8_MEMBER(vp415_state::drive_i8155_pc_r) +{ + logerror("%s: drive_i8155_pc_r: %02x\n", machine().describe_context(), 0); + return 0; +} + +WRITE8_MEMBER(vp415_state::drive_i8255_pa_w) +{ + logerror("%s: drive_i8255_pa_w: %02x\n", machine().describe_context(), data); +} + +WRITE8_MEMBER(vp415_state::drive_i8255_pb_w) +{ + logerror("%s: drive_i8255_pb_w: %02x\n", machine().describe_context(), data); +} + +READ8_MEMBER(vp415_state::drive_i8255_pc_r) +{ + logerror("%s: drive_i8255_pc_r: %02x\n", machine().describe_context(), 0); + return 0; +} + +WRITE8_MEMBER(vp415_state::drive_cpu_port1_w) +{ + //logerror("%s: drive_cpu_port1_w: %02x\n", machine().describe_context(), data); + m_chargen->ldi_w(BIT(data, 2)); +} + +void vp415_state::drive_program_map(address_map &map) +{ + map(0x0000, 0x3fff).rom().region(DRIVE_ROM_TAG, 0); +} + +void vp415_state::drive_io_map(address_map &map) +{ + map(0x0000, 0x0003).mirror(0xfbfc).rw(I8255_TAG, FUNC(i8255_device::read), FUNC(i8255_device::write)); + map(0x0400, 0x04ff).mirror(0xf800).rw(I8155_TAG, FUNC(i8155_device::memory_r), FUNC(i8155_device::memory_w)); + map(0x0500, 0x0507).mirror(0xf8f8).rw(I8155_TAG, FUNC(i8155_device::io_r), FUNC(i8155_device::io_w)); +} + +void vp415_state::video_start() +{ +} + +uint32_t vp415_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + m_chargen->update_bitmap(bitmap, cliprect); + return 0; +} + +static INPUT_PORTS_START( vp415 ) + PORT_START(vp415_state::SWITCHES_TAG) + PORT_BIT( 0x03, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_DIPNAME( 0x04, 0x00, "BRA (unknown purpose)" ) + PORT_DIPSETTING( 0x04, "On" ) + PORT_DIPSETTING( 0x00, "Off" ) + PORT_DIPNAME( 0x08, 0x00, "BRB (unknown purpose)" ) + PORT_DIPSETTING( 0x08, "On" ) + PORT_DIPSETTING( 0x00, "Off" ) + PORT_DIPNAME( 0x10, 0x00, "DUMP (unknown purpose)" ) + PORT_DIPSETTING( 0x10, "On" ) + PORT_DIPSETTING( 0x00, "Off" ) + PORT_DIPNAME( 0x20, 0x00, "Remote Control IR/Euro" ) + PORT_DIPSETTING( 0x20, "IR" ) + PORT_DIPSETTING( 0x00, "Euro" ) + PORT_DIPNAME( 0x40, 0x00, "REPLAY (unknown purpose)" ) + PORT_DIPSETTING( 0x40, "On" ) + PORT_DIPSETTING( 0x00, "Off" ) + PORT_DIPNAME( 0x80, 0x00, "RESI (unknown purpose)" ) + PORT_DIPSETTING( 0x80, "On" ) + PORT_DIPSETTING( 0x00, "Off" ) +INPUT_PORTS_END + +MACHINE_CONFIG_START(vp415_state::vp415) + MCFG_CPU_ADD(Z80CPU_TAG, Z80, XTAL(8'000'000)/2) // 8MHz through a /2 flip-flop divider, per schematic + MCFG_CPU_PROGRAM_MAP(z80_program_map) + MCFG_CPU_IO_MAP(z80_io_map) + + MCFG_CPU_ADD(CTRLCPU_TAG, I8031, XTAL(11'059'200)) // 12MHz, per schematic + MCFG_CPU_PROGRAM_MAP(ctrl_program_map) + MCFG_CPU_IO_MAP(ctrl_io_map) + + MCFG_CPU_ADD(DRIVECPU_TAG, I8031, XTAL(12'000'000)) // 12MHz, per schematic + MCFG_MCS51_PORT_P1_OUT_CB(WRITE8(vp415_state, drive_cpu_port1_w)); + MCFG_CPU_PROGRAM_MAP(drive_program_map) + MCFG_CPU_IO_MAP(drive_io_map) + + MCFG_DEVICE_ADD(I8155_TAG, I8155, 0) + MCFG_I8155_OUT_PORTA_CB(DEVWRITE8(CHARGEN_TAG, mb88303_device, da_w)) + MCFG_I8155_IN_PORTB_CB(READ8(vp415_state, drive_i8155_pb_r)) + MCFG_I8155_IN_PORTC_CB(READ8(vp415_state, drive_i8155_pc_r)) + + MCFG_DEVICE_ADD(I8255_TAG, I8255, 0) + MCFG_I8255_OUT_PORTA_CB(WRITE8(vp415_state, drive_i8255_pa_w)) + MCFG_I8255_OUT_PORTB_CB(WRITE8(vp415_state, drive_i8255_pb_w)) + MCFG_I8255_IN_PORTC_CB(READ8(vp415_state, drive_i8255_pc_r)) + + MCFG_DEVICE_ADD(CHARGEN_TAG, MB88303, 0) + + MCFG_SCREEN_ADD("screen", RASTER) + MCFG_SCREEN_REFRESH_RATE(50) + MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */) + MCFG_SCREEN_UPDATE_DRIVER(vp415_state, screen_update) + MCFG_SCREEN_SIZE(320, 240) + MCFG_SCREEN_VISIBLE_AREA(0, 319, 0, 239) +MACHINE_CONFIG_END + +ROM_START(vp415) + /* Module R */ + ROM_REGION(0x4000, vp415_state::DRIVE_ROM_TAG, 0) // Version 1.7 + ROM_LOAD( "r.3104 103 6803.6_drive.ic4", 0x0000, 0x4000, CRC(02e4273e) SHA1(198f7ac8f2a880f38046c9d9075ce32f3b730bd4) ) + + /* Module S */ + ROM_REGION(0x10000, vp415_state::CONTROL_ROM_TAG, 0) // Version 1.8 + ROM_LOAD( "s.3104 103 6804.9_control.ic2", 0x0000, 0x10000, CRC(10564765) SHA1(8eb6cff7ca7cbfcb3db8b04b697cdd7e364be805) ) + + /* Module W */ + ROM_REGION(0x8000, vp415_state::Z80CPU_TAG, 0) + ROM_LOAD( "w.3104 103 6805.3_cpu", 0x0000, 0x4000, CRC(c2cf4f25) SHA1(e55e1ac917958eb42244bff17a0016b74627c8fa) ) // Version 1.3 + ROM_LOAD( "w.3104 103 6806.3_cpu", 0x4000, 0x4000, CRC(14a45ea0) SHA1(fa028d01094be91e3480c9ad35d46b5546f9ff0f) ) // Version 1.4 + + ROM_REGION(0x4000, vp415_state::DESCRAMBLE_ROM_TAG, 0) + ROM_LOAD( "w.3104 103 6807.0_cpu", 0x0000, 0x4000, CRC(19c2bc87) SHA1(152f8c645588be9fc0dbc840368ab33a13a04e62) ) // Version 1.0 + + ROM_REGION(0x4000, vp415_state::SYNC_ROM_TAG, 0) + ROM_LOAD( "w.3104 103 6808.0_cpu", 0x0000, 0x4000, CRC(bdb601e0) SHA1(4f769aa62b756b157ba9ac8d3ae8bd1228821ff9) ) // Version 1.0 +ROM_END + +CONS( 1983, vp415, 0, 0, vp415, vp415, vp415_state, 0, "Philips", "VP415", MACHINE_IS_SKELETON ) + diff --git a/src/mame/mame.lst b/src/mame/mame.lst index e18288f2d42..3a975e94d23 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -38084,6 +38084,9 @@ zoofari // (c) 2006 ICE/Play Mechanix @source:vp122.cpp vp122 // +@source:vp415.cpp +vp415 // (c) 1983 Philips + @source:vp60.cpp vp60 // diff --git a/src/mame/mess.flt b/src/mame/mess.flt index 91b1c0d2cd9..8143efea9e3 100644 --- a/src/mame/mess.flt +++ b/src/mame/mess.flt @@ -773,6 +773,7 @@ vk100.cpp votrpss.cpp votrtnt.cpp vp122.cpp +vp415.cpp vp60.cpp vsmilepro.cpp vt100.cpp -- cgit v1.2.3