summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/apricot
diff options
context:
space:
mode:
author Dirk Best <mail@dirk-best.de>2021-08-04 19:29:32 +0200
committer Dirk Best <mail@dirk-best.de>2021-08-04 19:30:45 +0200
commit1e7d83cc4bee4cba40853b271c06d724e25fbbcb (patch)
tree5599ed09da63c8dab83817529606eabaeb0e77ad /src/devices/bus/apricot
parent68dbd42a24f56640642423f0e57fc9951ea819b9 (diff)
apxen: Checkpoint, get something on screen
- Implement video slot and mono graphics video card - Hook up CIO, SIO, RTC, PIT, SN76489 - Add daisy chain for Z80 devices and hook it up to the PIC - Add system control ports
Diffstat (limited to 'src/devices/bus/apricot')
-rw-r--r--src/devices/bus/apricot/video/cards.cpp16
-rw-r--r--src/devices/bus/apricot/video/cards.h16
-rw-r--r--src/devices/bus/apricot/video/mono.cpp278
-rw-r--r--src/devices/bus/apricot/video/mono.h65
-rw-r--r--src/devices/bus/apricot/video/video.cpp114
-rw-r--r--src/devices/bus/apricot/video/video.h89
6 files changed, 578 insertions, 0 deletions
diff --git a/src/devices/bus/apricot/video/cards.cpp b/src/devices/bus/apricot/video/cards.cpp
new file mode 100644
index 00000000000..7611be80abc
--- /dev/null
+++ b/src/devices/bus/apricot/video/cards.cpp
@@ -0,0 +1,16 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ ACT Apricot XEN Video Expansion Slot Devices
+
+***************************************************************************/
+
+#include "emu.h"
+#include "cards.h"
+#include "mono.h"
+
+void apricot_video_cards(device_slot_interface &device)
+{
+ device.option_add("mono", APRICOT_MONO_DISPLAY);
+}
diff --git a/src/devices/bus/apricot/video/cards.h b/src/devices/bus/apricot/video/cards.h
new file mode 100644
index 00000000000..61460b37064
--- /dev/null
+++ b/src/devices/bus/apricot/video/cards.h
@@ -0,0 +1,16 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ ACT Apricot XEN Video Expansion Slot Devices
+
+***************************************************************************/
+
+#ifndef MAME_BUS_APRICOT_VIDEO_CARDS_H
+#define MAME_BUS_APRICOT_VIDEO_CARDS_H
+
+#pragma once
+
+void apricot_video_cards(device_slot_interface &device);
+
+#endif // MAME_BUS_APRICOT_VIDEO_CARDS_H
diff --git a/src/devices/bus/apricot/video/mono.cpp b/src/devices/bus/apricot/video/mono.cpp
new file mode 100644
index 00000000000..7254962193c
--- /dev/null
+++ b/src/devices/bus/apricot/video/mono.cpp
@@ -0,0 +1,278 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ ACT Apricot XEN Monochrome Display Option
+
+ TODO:
+ - Support monitor selection
+
+***************************************************************************/
+
+#include "emu.h"
+#include "mono.h"
+#include "screen.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(APRICOT_MONO_DISPLAY, apricot_mono_display_device, "apricot_mono_display", "Apricot Monochrome Display")
+
+//-------------------------------------------------
+// character viewer
+//-------------------------------------------------
+
+static const gfx_layout apricot_charlayout =
+{
+ 10, 16,
+ 1792,
+ 1,
+ { 0 },
+ { 7, 6, 5, 4, 3, 2, 1, 0, 15, 14 },
+ { STEP16(0, 16) },
+ 16*16
+};
+
+static GFXDECODE_START( gfx )
+GFXDECODE_END
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+void apricot_mono_display_device::device_add_mconfig(machine_config &config)
+{
+ screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
+ screen.set_color(rgb_t::green());
+ screen.set_size(800, 400);
+ screen.set_visarea(0, 800-1, 0, 400-1);
+ screen.set_refresh_hz(72);
+ screen.set_screen_update(FUNC(apricot_mono_display_device::screen_update));
+
+ PALETTE(config, m_palette, palette_device::MONOCHROME_HIGHLIGHT);
+
+ HD6845S(config, m_crtc, 24_MHz_XTAL / 10); // actually MB89321B (15 MHz for white monitor, 24 MHz for green)
+ m_crtc->set_screen("screen");
+ m_crtc->set_show_border_area(false);
+ m_crtc->set_char_width(10);
+ m_crtc->set_update_row_callback(FUNC(apricot_mono_display_device::crtc_update_row));
+ m_crtc->out_de_callback().set(FUNC(apricot_mono_display_device::crtc_de_w));
+ m_crtc->out_vsync_callback().set(FUNC(apricot_mono_display_device::crtc_vsync_w));
+
+ GFXDECODE(config, m_gfxdecode, m_palette, gfx);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// apricot_mono_display_device - constructor
+//-------------------------------------------------
+
+apricot_mono_display_device::apricot_mono_display_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, APRICOT_MONO_DISPLAY, tag, owner, clock),
+ device_apricot_video_interface(mconfig, *this),
+ m_crtc(*this, "crtc"),
+ m_palette(*this, "palette"),
+ m_gfxdecode(*this, "gfxdecode")
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void apricot_mono_display_device::device_start()
+{
+ // allocate 64k vram
+ m_vram = std::make_unique<uint16_t[]>(0x8000);
+
+ // init gfxdecode
+ m_gfxdecode->set_gfx(0, std::make_unique<gfx_element>(m_palette, apricot_charlayout, reinterpret_cast<uint8_t *>(m_vram.get()), 0, 1, 0));
+
+ // register for save states
+ save_pointer(NAME(m_vram), 0x8000);
+ save_item(NAME(m_portb));
+ save_item(NAME(m_portc));
+ save_item(NAME(m_portx));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void apricot_mono_display_device::device_reset()
+{
+ // a reset forces all bits to a logic high
+ m_portb = 0xff;
+ m_portc = 0xff;
+ m_portx = 0xff;
+}
+
+
+//**************************************************************************
+// IMPLEMENTATION
+//**************************************************************************
+
+bool apricot_mono_display_device::mem_r(offs_t offset, uint16_t &data, uint16_t mem_mask)
+{
+ data = m_vram[offset];
+ return true;
+}
+
+bool apricot_mono_display_device::mem_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ m_vram[offset] = data;
+ return true;
+}
+
+bool apricot_mono_display_device::io_r(offs_t offset, uint16_t &data, uint16_t mem_mask)
+{
+ offset <<= 1;
+
+ if (BIT(m_portx, 0) == 0)
+ {
+ // apricot pc/xi compatible
+ switch (offset)
+ {
+ case 0x4a: data = 0xff00 | m_portb; return true;
+ case 0x4c: data = 0xff00 | m_portc; return true;
+ case 0x6a: data = 0xff00 | m_crtc->register_r(); return true;
+ }
+ }
+ else
+ {
+ // xen mode
+ switch (offset)
+ {
+ case 0x80: data = 0xff00 | m_portb; return true;
+ case 0x82: data = 0xff00 | m_portc; return true;
+ case 0x8a: data = 0xff00 | m_crtc->register_r(); return true;
+ }
+ }
+
+ return false;
+}
+
+bool apricot_mono_display_device::io_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ offset <<= 1;
+
+ // only 8-bit writes
+ if (mem_mask != 0x00ff)
+ return false;
+
+ if (BIT(m_portx, 0) == 0)
+ {
+ // apricot pc/xi compatible
+ switch (offset)
+ {
+ case 0x4a: portb_w(data); return true;
+ case 0x68: m_crtc->address_w(data); return true;
+ case 0x6a: m_crtc->register_w(data); return true;
+ case 0x6c: portx_w(data); return true;
+ }
+ }
+ else
+ {
+ // xen mode
+ switch (offset)
+ {
+ case 0x6c: portx_w(data); return true;
+ case 0x80: portb_w(data); return true;
+ case 0x88: m_crtc->address_w(data); return true;
+ case 0x8a: m_crtc->register_w(data); return true;
+ }
+ }
+
+ return false;
+}
+
+void apricot_mono_display_device::portb_w(uint8_t data)
+{
+ logerror("portb_w: %02x\n", data);
+
+ // 765----- not used
+ // ---4---- video mode (alphanumeric/graphics)
+ // ----3--- display on
+ // -----21- not used
+ // -------0 crtc reset
+
+ m_portb = data;
+
+ if (BIT(m_portb, 0) == 0)
+ m_crtc->reset();
+}
+
+void apricot_mono_display_device::portx_w(uint8_t data)
+{
+ logerror("portx_w: %02x\n", data);
+
+ // 765432-- not used
+ // ------1- reverse video
+ // -------0 mode (compatible or xen)
+
+ m_portx = data;
+
+ // forward mode to host
+ m_slot->apvid_w(BIT(m_portx, 0));
+}
+
+uint32_t apricot_mono_display_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ m_gfxdecode->gfx(0)->mark_all_dirty();
+ m_crtc->screen_update(screen, bitmap, cliprect);
+ return 0;
+}
+
+// see drivers/apricot.cpp
+MC6845_UPDATE_ROW( apricot_mono_display_device::crtc_update_row )
+{
+ const pen_t *pen = m_palette->pens();
+
+ for (int i = 0; i < x_count; i++)
+ {
+ uint16_t code = m_vram[(0xe000 >> 1) | (ma + i)];
+ uint16_t offset = ((code & 0x7ff) << 5) | (ra << 1);
+ uint16_t data = m_vram[offset >> 1];
+
+ if (BIT(m_portb, 4))
+ {
+ int fill = 0;
+
+ if (i == cursor_x) fill = 1; // cursor?
+ if (BIT(code, 12) && BIT(data, 14)) fill = 1; // strike-through?
+ if (BIT(code, 13) && BIT(data, 15)) fill = 1; // underline?
+
+ // draw 10 pixels of the character
+ for (int x = 0; x <= 10; x++)
+ {
+ int color = fill ? 1 : BIT(data, x);
+ color ^= BIT(code, 15); // reverse?
+ bitmap.pix(y, x + i*10) = pen[color ? 1 + BIT(code, 14) : 0];
+ }
+ }
+ else
+ {
+ // draw 16 pixels of the cell
+ for (int x = 0; x <= 16; x++)
+ bitmap.pix(y, x + i*16) = pen[BIT(data, x)];
+ }
+ }
+}
+
+void apricot_mono_display_device::crtc_de_w(int state)
+{
+ m_portc &= 0xf7;
+ m_portc |= (state << 3);
+}
+
+void apricot_mono_display_device::crtc_vsync_w(int state)
+{
+ m_portc &= 0x7f;
+ m_portc |= (state << 7);
+}
diff --git a/src/devices/bus/apricot/video/mono.h b/src/devices/bus/apricot/video/mono.h
new file mode 100644
index 00000000000..36885bcb768
--- /dev/null
+++ b/src/devices/bus/apricot/video/mono.h
@@ -0,0 +1,65 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ ACT Apricot XEN Monochrome Display Option
+
+***************************************************************************/
+
+#ifndef MAME_BUS_APRICOT_VIDEO_MONO_H
+#define MAME_BUS_APRICOT_VIDEO_MONO_H
+
+#pragma once
+
+#include "video.h"
+#include "video/mc6845.h"
+#include "emupal.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> apricot_mono_display_device
+
+class apricot_mono_display_device : public device_t, public device_apricot_video_interface
+{
+public:
+ // construction/destruction
+ apricot_mono_display_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual bool mem_r(offs_t offset, uint16_t &data, uint16_t mem_mask) override;
+ virtual bool mem_w(offs_t offset, uint16_t data, uint16_t mem_mask) override;
+ virtual bool io_r(offs_t offset, uint16_t &data, uint16_t mem_mask) override;
+ virtual bool io_w(offs_t offset, uint16_t data, uint16_t mem_mask) override;
+
+private:
+ required_device<hd6845s_device> m_crtc;
+ required_device<palette_device> m_palette;
+ required_device<gfxdecode_device> m_gfxdecode;
+
+ void portb_w(uint8_t data);
+ void portx_w(uint8_t data);
+
+ uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ MC6845_UPDATE_ROW(crtc_update_row);
+ void crtc_de_w(int state);
+ void crtc_vsync_w(int state);
+
+ std::unique_ptr<uint16_t[]> m_vram;
+
+ uint8_t m_portb;
+ uint8_t m_portc;
+ uint8_t m_portx;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(APRICOT_MONO_DISPLAY, apricot_mono_display_device)
+
+#endif // MAME_BUS_APRICOT_VIDEO_MONO_H
diff --git a/src/devices/bus/apricot/video/video.cpp b/src/devices/bus/apricot/video/video.cpp
new file mode 100644
index 00000000000..fbb33ba83bf
--- /dev/null
+++ b/src/devices/bus/apricot/video/video.cpp
@@ -0,0 +1,114 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ ACT Apricot XEN Video Expansion Slot
+
+***************************************************************************/
+
+#include "emu.h"
+#include "video.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(APRICOT_VIDEO_SLOT, apricot_video_slot_device, "apricot_video", "Apricot XEN Video Slot")
+
+
+//**************************************************************************
+// SLOT DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// apricot_video_slot_device - constructor
+//-------------------------------------------------
+
+apricot_video_slot_device::apricot_video_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, APRICOT_VIDEO_SLOT, tag, owner, clock),
+ device_single_card_slot_interface<device_apricot_video_interface>(mconfig, *this),
+ m_apvid_handler(*this),
+ m_card(nullptr)
+{
+}
+
+//-------------------------------------------------
+// apricot_video_slot_device - destructor
+//-------------------------------------------------
+
+apricot_video_slot_device::~apricot_video_slot_device()
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void apricot_video_slot_device::device_start()
+{
+ // get inserted module
+ m_card = get_card_device();
+
+ // resolve callbacks
+ m_apvid_handler.resolve_safe();
+}
+
+//-------------------------------------------------
+// host to module interface
+//-------------------------------------------------
+
+bool apricot_video_slot_device::mem_r(offs_t offset, uint16_t &data, uint16_t mem_mask)
+{
+ if (m_card)
+ return m_card->mem_r(offset, data, mem_mask);
+
+ return false;
+}
+
+bool apricot_video_slot_device::mem_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if (m_card)
+ return m_card->mem_w(offset, data, mem_mask);
+
+ return false;
+}
+
+bool apricot_video_slot_device::io_r(offs_t offset, uint16_t &data, uint16_t mem_mask)
+{
+ if (m_card)
+ return m_card->io_r(offset, data, mem_mask);
+
+ return false;
+}
+
+bool apricot_video_slot_device::io_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if (m_card)
+ return m_card->io_w(offset, data, mem_mask);
+
+ return false;
+}
+
+
+//**************************************************************************
+// MODULE INTERFACE
+//**************************************************************************
+
+//-------------------------------------------------
+// device_apricot_video_interface - constructor
+//-------------------------------------------------
+
+device_apricot_video_interface::device_apricot_video_interface(const machine_config &mconfig, device_t &device) :
+ device_interface(device, "apricotvid")
+{
+ m_slot = dynamic_cast<apricot_video_slot_device *>(device.owner());
+}
+
+//-------------------------------------------------
+// ~device_apricot_video_interface - destructor
+//-------------------------------------------------
+
+device_apricot_video_interface::~device_apricot_video_interface()
+{
+}
diff --git a/src/devices/bus/apricot/video/video.h b/src/devices/bus/apricot/video/video.h
new file mode 100644
index 00000000000..5b1a8b322f8
--- /dev/null
+++ b/src/devices/bus/apricot/video/video.h
@@ -0,0 +1,89 @@
+// license: GPL-2.0+
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ ACT Apricot XEN Video Expansion Slot
+
+ Large identical to the standard Apricot PC/Xi expansion slot.
+
+***************************************************************************/
+
+#ifndef MAME_BUS_APRICOT_VIDEO_VIDEO_H
+#define MAME_BUS_APRICOT_VIDEO_VIDEO_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class device_apricot_video_interface;
+
+// ======================> apricot_video_slot_device
+
+class apricot_video_slot_device : public device_t, public device_single_card_slot_interface<device_apricot_video_interface>
+{
+public:
+ // construction/destruction
+ template <typename T>
+ apricot_video_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, const char *dflt)
+ : apricot_video_slot_device(mconfig, tag, owner, uint32_t(0))
+ {
+ option_reset();
+ opts(*this);
+ set_default_option(dflt);
+ set_fixed(false);
+ }
+
+ apricot_video_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~apricot_video_slot_device();
+
+ // callbacks
+ auto apvid_handler() { return m_apvid_handler.bind(); }
+
+ // called from cart device
+ DECLARE_WRITE_LINE_MEMBER( apvid_w ) { m_apvid_handler(state); }
+
+ // called from host
+ bool mem_r(offs_t offset, uint16_t &data, uint16_t mem_mask);
+ bool mem_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ bool io_r(offs_t offset, uint16_t &data, uint16_t mem_mask);
+ bool io_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+private:
+ devcb_write_line m_apvid_handler;
+
+ device_apricot_video_interface *m_card;
+};
+
+// ======================> device_apricot_video_interface
+
+class device_apricot_video_interface : public device_interface
+{
+public:
+ // construction/destruction
+ virtual ~device_apricot_video_interface();
+
+ virtual bool mem_r(offs_t offset, uint16_t &data, uint16_t mem_mask) { return false; }
+ virtual bool mem_w(offs_t offset, uint16_t data, uint16_t mem_mask) { return false; }
+ virtual bool io_r(offs_t offset, uint16_t &data, uint16_t mem_mask) { return false; }
+ virtual bool io_w(offs_t offset, uint16_t data, uint16_t mem_mask) { return false; }
+
+protected:
+ device_apricot_video_interface(const machine_config &mconfig, device_t &device);
+
+ apricot_video_slot_device *m_slot;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(APRICOT_VIDEO_SLOT, apricot_video_slot_device)
+
+// include here so drivers don't need to
+#include "cards.h"
+
+#endif // MAME_BUS_APRICOT_VIDEO_VIDEO_H