From fc785cecbc0df66b854c9c39ba0a79c04a3b1f0b Mon Sep 17 00:00:00 2001 From: Nigel Barnes Date: Wed, 19 Aug 2020 22:58:15 +0100 Subject: bus/electron: Added the JAFA Mode 7 Display Unit. --- scripts/src/bus.lua | 2 + src/devices/bus/electron/exp.cpp | 4 +- src/devices/bus/electron/mode7.cpp | 236 +++++++++++++++++++++++++++++++++++++ src/devices/bus/electron/mode7.h | 66 +++++++++++ src/mame/machine/electron.cpp | 10 +- 5 files changed, 315 insertions(+), 3 deletions(-) create mode 100644 src/devices/bus/electron/mode7.cpp create mode 100644 src/devices/bus/electron/mode7.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 257571c1539..2b439ac3b82 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -1025,6 +1025,8 @@ if (BUSES["ELECTRON"]~=null) then MAME_DIR .. "src/devices/bus/electron/exp.h", MAME_DIR .. "src/devices/bus/electron/fbjoy.cpp", MAME_DIR .. "src/devices/bus/electron/fbjoy.h", + MAME_DIR .. "src/devices/bus/electron/mode7.cpp", + MAME_DIR .. "src/devices/bus/electron/mode7.h", MAME_DIR .. "src/devices/bus/electron/plus1.cpp", MAME_DIR .. "src/devices/bus/electron/plus1.h", MAME_DIR .. "src/devices/bus/electron/plus2.cpp", diff --git a/src/devices/bus/electron/exp.cpp b/src/devices/bus/electron/exp.cpp index 9676e02e959..93197dba97d 100644 --- a/src/devices/bus/electron/exp.cpp +++ b/src/devices/bus/electron/exp.cpp @@ -108,7 +108,7 @@ void electron_expansion_slot_device::expbus_w(offs_t offset, uint8_t data) // slot devices #include "fbjoy.h" //#include "fbprint.h" -//#include "jafamode7.h" +#include "mode7.h" //#include "lebox.h" #include "plus1.h" #include "plus2.h" @@ -125,7 +125,7 @@ void electron_expansion_devices(device_slot_interface &device) { device.option_add("fbjoy", ELECTRON_FBJOY); //device.option_add("fbprint", ELECTRON_FBPRINT); - //device.option_add("jafamode7", ELECTRON_JAFAMODE7); + device.option_add("mode7", ELECTRON_MODE7); //device.option_add("lebox", ELECTRON_LEBOX); device.option_add("plus1", ELECTRON_PLUS1); device.option_add("plus2", ELECTRON_PLUS2); diff --git a/src/devices/bus/electron/mode7.cpp b/src/devices/bus/electron/mode7.cpp new file mode 100644 index 00000000000..be2ccb453e2 --- /dev/null +++ b/src/devices/bus/electron/mode7.cpp @@ -0,0 +1,236 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + JAFA Mode 7 Display Unit + + TODO: + The SAA5050 output is currently being sent to a separate screen, it + should be output to the same screen as the Electron. + The Electron video output is 640x312 whereas the SAA5050 output is + 480x500 (doubled vertically to account for interlace). Only one + output is ever active at any time, which is selected by the MA13 + line from the HD6845. + +**********************************************************************/ + + +#include "emu.h" +#include "mode7.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(ELECTRON_MODE7, electron_mode7_device, "electron_mode7", "JAFA Mode 7 Display Unit") + + +//------------------------------------------------- +// ROM( mode7 ) +//------------------------------------------------- + +ROM_START( mode7 ) + ROM_REGION(0x2000, "exp_rom", 0) + ROM_SYSTEM_BIOS(0, "191", "Mode 7 OS v1.91") + ROMX_LOAD("mode7_1.91.rom", 0x0000, 0x2000, CRC(1863bfe6) SHA1(a18c12c8e4bcd5284aac5b0f0a33dc040176084a), ROM_BIOS(0)) + ROM_SYSTEM_BIOS(1, "15", "Mode 7 OS v1.5") + ROMX_LOAD("mode7_1.5.rom", 0x0000, 0x2000, CRC(eeea69ee) SHA1(3689a6ca8693fa9a6e53a02cf34d613303cb34d7), ROM_BIOS(1)) +ROM_END + +//------------------------------------------------- +// INPUT_PORTS( mode7 ) +//------------------------------------------------- + +static INPUT_PORTS_START( mode7 ) + PORT_START("BUTTON") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Mode 7 Break") PORT_CODE(KEYCODE_HOME) PORT_CHANGED_MEMBER(DEVICE_SELF, electron_mode7_device, break_button, 0) +INPUT_PORTS_END + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor electron_mode7_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( mode7 ); +} + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- + +void electron_mode7_device::device_add_mconfig(machine_config &config) +{ + /* video hardware */ + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_raw(16_MHz_XTAL, 768, 0, 480, 622, 0, 500); + m_screen->set_screen_update("hd6845", FUNC(hd6845s_device::screen_update)); + + HD6845S(config, m_hd6845, DERIVED_CLOCK(1, 8)); // FIXME: double clock until interlace is implemented + m_hd6845->set_screen("screen"); + m_hd6845->set_show_border_area(false); + m_hd6845->set_char_width(12); + m_hd6845->set_update_row_callback(FUNC(electron_mode7_device::crtc_update_row)); + m_hd6845->out_vsync_callback().set(FUNC(electron_mode7_device::vsync_changed)); + + SAA5050(config, m_trom, 6_MHz_XTAL); + m_trom->set_screen_size(40, 25, 40); + + /* pass-through */ + ELECTRON_EXPANSION_SLOT(config, m_exp, DERIVED_CLOCK(1, 1), electron_expansion_devices, nullptr); + m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::irq_w)); + m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(electron_expansion_slot_device::nmi_w)); +} + +const tiny_rom_entry *electron_mode7_device::device_rom_region() const +{ + return ROM_NAME( mode7 ); +} + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// electron_mode7_device - constructor +//------------------------------------------------- + +electron_mode7_device::electron_mode7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, ELECTRON_MODE7, tag, owner, clock) + , device_electron_expansion_interface(mconfig, *this) + , m_screen(*this, "screen") + , m_hd6845(*this, "hd6845") + , m_trom(*this, "saa5050") + , m_exp(*this, "exp") + , m_exp_rom(*this, "exp_rom") + , m_romsel(0) +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void electron_mode7_device::device_start() +{ + m_videoram = make_unique_clear(0x800); + + /* register for save states */ + save_pointer(NAME(m_videoram), 0x800); + save_item(NAME(m_romsel)); +} + +//------------------------------------------------- +// expbus_r - expansion data read +//------------------------------------------------- + +uint8_t electron_mode7_device::expbus_r(offs_t offset) +{ + uint8_t data = 0xff; + + if (offset >= 0x7c00 && offset < 0x8000) + { + data = m_videoram[offset & 0x3ff]; + } + else if (offset >= 0x8000 && offset < 0xc000) + { + if (m_romsel == 15) + { + data = m_exp_rom->base()[offset & 0x1fff]; + } + } + else + { + switch (offset) + { + case 0xfc1e: + data = m_hd6845->status_r(); + break; + case 0xfc1f: + data = m_hd6845->register_r(); + break; + } + } + + data &= m_exp->expbus_r(offset); + + return data; +} + +//------------------------------------------------- +// expbus_w - expansion data write +//------------------------------------------------- + +void electron_mode7_device::expbus_w(offs_t offset, uint8_t data) +{ + if (offset >= 0x7c00 && offset < 0x8000) + { + m_videoram[offset & 0x3ff] = data & 0x7f; + } + else + { + switch (offset) + { + case 0xfc1c: + m_hd6845->address_w(data); + break; + case 0xfc1d: + m_hd6845->register_w(data); + break; + + case 0xfe05: + if ((data & 0xf0) != 0xf0) + m_romsel = data & 0x0f; + break; + } + } + + m_exp->expbus_w(offset, data); +} + + +//************************************************************************** +// IMPLEMENTATION +//************************************************************************** + +MC6845_UPDATE_ROW(electron_mode7_device::crtc_update_row) +{ + uint32_t* p = &bitmap.pix32(y); + + m_trom->lose_w(1); + m_trom->lose_w(0); + + for (int column = 0; column < x_count; column++) + { + m_trom->write(m_videoram[(ma + column) & 0x3ff]); + + m_trom->f1_w(1); + m_trom->f1_w(0); + + for (int bit = 0; bit < 12; bit++) + { + m_trom->tr6_w(1); + m_trom->tr6_w(0); + + int col = m_trom->get_rgb() ^ ((column == cursor_x) ? 7 : 0); + + int r = BIT(col, 0) * 0xff; + int g = BIT(col, 1) * 0xff; + int b = BIT(col, 2) * 0xff; + + *p++ = rgb_t(r, g, b); + } + } +} + +WRITE_LINE_MEMBER(electron_mode7_device::vsync_changed) +{ + m_trom->dew_w(state); +} + + +INPUT_CHANGED_MEMBER(electron_mode7_device::break_button) +{ + m_slot->nmi_w(!newval); +} diff --git a/src/devices/bus/electron/mode7.h b/src/devices/bus/electron/mode7.h new file mode 100644 index 00000000000..b3c447ee87d --- /dev/null +++ b/src/devices/bus/electron/mode7.h @@ -0,0 +1,66 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + JAFA Mode 7 Display Unit + +**********************************************************************/ + +#ifndef MAME_BUS_ELECTRON_MODE7_H +#define MAME_BUS_ELECTRON_MODE7_H + +#include "exp.h" +#include "video/mc6845.h" +#include "video/saa5050.h" +#include "screen.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class electron_mode7_device: + public device_t, + public device_electron_expansion_interface +{ +public: + static constexpr feature_type imperfect_features() { return feature::GRAPHICS; } + + // construction/destruction + electron_mode7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + DECLARE_INPUT_CHANGED_MEMBER(break_button); + +protected: + // device-level overrides + virtual void device_start() override; + + // optional information overrides + virtual void device_add_mconfig(machine_config &config) override; + virtual const tiny_rom_entry *device_rom_region() const override; + virtual ioport_constructor device_input_ports() const override; + + virtual uint8_t expbus_r(offs_t offset) override; + virtual void expbus_w(offs_t offset, uint8_t data) override; + +private: + required_device m_screen; + required_device m_hd6845; + required_device m_trom; + required_device m_exp; + required_memory_region m_exp_rom; + + std::unique_ptr m_videoram; + + MC6845_UPDATE_ROW(crtc_update_row); + DECLARE_WRITE_LINE_MEMBER(vsync_changed); + + uint8_t m_romsel; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(ELECTRON_MODE7, electron_mode7_device) + + +#endif // MAME_BUS_ELECTRON_MODE7_H diff --git a/src/mame/machine/electron.cpp b/src/mame/machine/electron.cpp index 7846990e877..0d1924b577a 100644 --- a/src/mame/machine/electron.cpp +++ b/src/mame/machine/electron.cpp @@ -151,6 +151,10 @@ uint8_t electron_state::electron64_fetch_r(offs_t offset) uint8_t electron_state::electron_mem_r(offs_t offset) { + uint8_t data = 0xff; + + data &= m_exp->expbus_r(offset); + switch (m_mrb.read_safe(0)) { case 0x00: /* Normal */ @@ -167,11 +171,15 @@ uint8_t electron_state::electron_mem_r(offs_t offset) if (m_mrb_mapped && (offset < 0x3000 || !m_vdu_drivers)) offset += 0x8000; break; } - return m_ram->read(offset); + data &= m_ram->read(offset); + + return data; } void electron_state::electron_mem_w(offs_t offset, uint8_t data) { + m_exp->expbus_w(offset, data); + switch (m_mrb.read_safe(0)) { case 0x00: /* Normal */ -- cgit v1.2.3