diff options
author | 2021-08-04 19:29:32 +0200 | |
---|---|---|
committer | 2021-08-04 19:30:45 +0200 | |
commit | 1e7d83cc4bee4cba40853b271c06d724e25fbbcb (patch) | |
tree | 5599ed09da63c8dab83817529606eabaeb0e77ad /src/devices/bus/apricot | |
parent | 68dbd42a24f56640642423f0e57fc9951ea819b9 (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.cpp | 16 | ||||
-rw-r--r-- | src/devices/bus/apricot/video/cards.h | 16 | ||||
-rw-r--r-- | src/devices/bus/apricot/video/mono.cpp | 278 | ||||
-rw-r--r-- | src/devices/bus/apricot/video/mono.h | 65 | ||||
-rw-r--r-- | src/devices/bus/apricot/video/video.cpp | 114 | ||||
-rw-r--r-- | src/devices/bus/apricot/video/video.h | 89 |
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 |