summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Nigel Barnes <Pernod70@users.noreply.github.com>2020-08-19 22:58:15 +0100
committer Nigel Barnes <Pernod70@users.noreply.github.com>2020-08-19 22:59:51 +0100
commitfc785cecbc0df66b854c9c39ba0a79c04a3b1f0b (patch)
treeda341030a1b7c5f08bde0d4e0a7b30cbc85cf242
parentefed2ea2c21c9ac4dec8b3682efce8d731623abb (diff)
bus/electron: Added the JAFA Mode 7 Display Unit.
-rw-r--r--scripts/src/bus.lua2
-rw-r--r--src/devices/bus/electron/exp.cpp4
-rw-r--r--src/devices/bus/electron/mode7.cpp236
-rw-r--r--src/devices/bus/electron/mode7.h66
-rw-r--r--src/mame/machine/electron.cpp10
5 files changed, 315 insertions, 3 deletions
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<uint8_t[]>(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<screen_device> m_screen;
+ required_device<mc6845_device> m_hd6845;
+ required_device<saa5050_device> m_trom;
+ required_device<electron_expansion_slot_device> m_exp;
+ required_memory_region m_exp_rom;
+
+ std::unique_ptr<uint8_t[]> 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 */