mirror of
https://github.com/holub/mame
synced 2025-04-16 21:44:32 +03:00
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
This commit is contained in:
parent
68dbd42a24
commit
1e7d83cc4b
@ -257,6 +257,23 @@ if (BUSES["APRICOT_KEYBOARD"]~=null) then
|
||||
end
|
||||
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/bus/apricot/video/video.h,BUSES["APRICOT_VIDEO"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (BUSES["APRICOT_VIDEO"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/bus/apricot/video/video.cpp",
|
||||
MAME_DIR .. "src/devices/bus/apricot/video/video.h",
|
||||
MAME_DIR .. "src/devices/bus/apricot/video/cards.cpp",
|
||||
MAME_DIR .. "src/devices/bus/apricot/video/cards.h",
|
||||
MAME_DIR .. "src/devices/bus/apricot/video/mono.cpp",
|
||||
MAME_DIR .. "src/devices/bus/apricot/video/mono.h",
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/bus/aquarius/slot.h,BUSES["AQUARIUS"] = true
|
||||
|
@ -838,6 +838,7 @@ BUSES["AMIGA_KEYBOARD"] = true
|
||||
BUSES["APF"] = true
|
||||
BUSES["APRICOT_EXPANSION"] = true
|
||||
BUSES["APRICOT_KEYBOARD"] = true
|
||||
BUSES["APRICOT_VIDEO"] = true
|
||||
BUSES["AQUARIUS"] = true
|
||||
BUSES["ARCADIA"] = true
|
||||
BUSES["ASTROCADE"] = true
|
||||
|
16
src/devices/bus/apricot/video/cards.cpp
Normal file
16
src/devices/bus/apricot/video/cards.cpp
Normal file
@ -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);
|
||||
}
|
16
src/devices/bus/apricot/video/cards.h
Normal file
16
src/devices/bus/apricot/video/cards.h
Normal file
@ -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
|
278
src/devices/bus/apricot/video/mono.cpp
Normal file
278
src/devices/bus/apricot/video/mono.cpp
Normal file
@ -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);
|
||||
}
|
65
src/devices/bus/apricot/video/mono.h
Normal file
65
src/devices/bus/apricot/video/mono.h
Normal file
@ -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
|
114
src/devices/bus/apricot/video/video.cpp
Normal file
114
src/devices/bus/apricot/video/video.cpp
Normal file
@ -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()
|
||||
{
|
||||
}
|
89
src/devices/bus/apricot/video/video.h
Normal file
89
src/devices/bus/apricot/video/video.h
Normal file
@ -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
|
@ -13,7 +13,15 @@
|
||||
- XEN WS (1 MB RAM, no drives)
|
||||
|
||||
TODO:
|
||||
- Everything
|
||||
- Boot ROM disable, wrap around mode
|
||||
- Floppy
|
||||
- DMA
|
||||
- Harddisk
|
||||
- Keyboard
|
||||
- RS232
|
||||
- Printer
|
||||
- Colour graphics board
|
||||
- Make xen_daisy_device generic?
|
||||
|
||||
Notes:
|
||||
- Two graphics cards: Mono and colour boards
|
||||
@ -22,14 +30,63 @@
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/i86/i286.h"
|
||||
#include "machine/bankdev.h"
|
||||
#include "machine/eepromser.h"
|
||||
#include "machine/mm58274c.h"
|
||||
#include "machine/pic8259.h"
|
||||
#include "machine/pit8253.h"
|
||||
#include "machine/wd_fdc.h"
|
||||
#include "machine/z80daisy.h"
|
||||
#include "machine/z80sio.h"
|
||||
#include "video/mc6845.h"
|
||||
#include "machine/z8536.h"
|
||||
#include "sound/sn76496.h"
|
||||
#include "imagedev/floppy.h"
|
||||
#include "formats/apridisk.h"
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
#include "bus/apricot/video/video.h"
|
||||
#include "speaker.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// XEN DAISY CHAIN ABSTRACTION
|
||||
//**************************************************************************
|
||||
|
||||
class xen_daisy_device : public device_t, public z80_daisy_chain_interface
|
||||
{
|
||||
public:
|
||||
xen_daisy_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
|
||||
|
||||
uint8_t acknowledge();
|
||||
IRQ_CALLBACK_MEMBER(inta_cb);
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
};
|
||||
|
||||
DEFINE_DEVICE_TYPE(XEN_DAISY, xen_daisy_device, "xen_daisy", "Apricot XEN daisy chain abstraction")
|
||||
|
||||
xen_daisy_device::xen_daisy_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, XEN_DAISY, tag, owner, clock)
|
||||
, z80_daisy_chain_interface(mconfig, *this)
|
||||
{
|
||||
}
|
||||
|
||||
void xen_daisy_device::device_start()
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t xen_daisy_device::acknowledge()
|
||||
{
|
||||
device_z80daisy_interface *intf = daisy_get_irq_device();
|
||||
if (intf != nullptr)
|
||||
return intf->z80daisy_irq_ack();
|
||||
else
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
IRQ_CALLBACK_MEMBER(xen_daisy_device::inta_cb)
|
||||
{
|
||||
return acknowledge();
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
@ -45,9 +102,15 @@ public:
|
||||
apxen_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_mem(*this, "mem"),
|
||||
m_io(*this, "io"),
|
||||
m_eeprom(*this, "eeprom"),
|
||||
m_pic(*this, "pic%u", 0U),
|
||||
m_crtc(*this, "crtc"),
|
||||
m_mono_palette(*this, "mono_palette")
|
||||
m_daisy(*this, "daisy"),
|
||||
m_pit(*this, "pit"),
|
||||
m_cio(*this, "cio"),
|
||||
m_sio(*this, "sio"),
|
||||
m_video(*this, "video")
|
||||
{ }
|
||||
|
||||
void apxen(machine_config &config);
|
||||
@ -58,17 +121,40 @@ protected:
|
||||
|
||||
private:
|
||||
required_device<i80286_cpu_device> m_maincpu;
|
||||
required_device<address_map_bank_device> m_mem;
|
||||
required_device<address_map_bank_device> m_io;
|
||||
required_device<eeprom_serial_93cxx_device> m_eeprom;
|
||||
required_device_array<pic8259_device, 2> m_pic;
|
||||
required_device<hd6845s_device> m_crtc;
|
||||
required_device<palette_device> m_mono_palette;
|
||||
required_device<xen_daisy_device> m_daisy;
|
||||
required_device<pit8253_device> m_pit;
|
||||
required_device<z8536_device> m_cio;
|
||||
required_device<z80sio_device> m_sio;
|
||||
required_device<apricot_video_slot_device> m_video;
|
||||
|
||||
void mem_map_base(address_map &map);
|
||||
void mem_map(address_map &map);
|
||||
void io_map_base(address_map &map);
|
||||
void io_map(address_map &map);
|
||||
|
||||
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
MC6845_UPDATE_ROW(crtc_update_row);
|
||||
DECLARE_WRITE_LINE_MEMBER(apvid_w);
|
||||
|
||||
uint16_t mem_r(offs_t offset, uint16_t mem_mask);
|
||||
void mem_w(offs_t offset, uint16_t data, uint16_t mem_mask);
|
||||
uint16_t io_r(offs_t offset, uint16_t mem_mask);
|
||||
void io_w(offs_t offset, uint16_t data, uint16_t mem_mask);
|
||||
|
||||
uint8_t get_slave_ack(offs_t offset);
|
||||
void leds_w(uint8_t data);
|
||||
uint8_t cpu_control_r();
|
||||
void cpu_control_w(uint8_t data);
|
||||
void cpu_reset_w(uint8_t data);
|
||||
|
||||
void cio_porta_w(uint8_t data);
|
||||
void cio_portb_w(uint8_t data);
|
||||
void cio_portc_w(uint8_t data);
|
||||
|
||||
bool m_apvid;
|
||||
uint8_t m_cpu_control;
|
||||
};
|
||||
|
||||
|
||||
@ -76,32 +162,42 @@ private:
|
||||
// ADDRESS MAPS
|
||||
//**************************************************************************
|
||||
|
||||
void apxen_state::mem_map_base(address_map &map)
|
||||
{
|
||||
map(0x000000, 0xffffff).rw(FUNC(apxen_state::mem_r), FUNC(apxen_state::mem_w));
|
||||
}
|
||||
|
||||
void apxen_state::mem_map(address_map &map)
|
||||
{
|
||||
map(0x000000, 0x07ffff).ram();
|
||||
map(0x080000, 0x0effff).noprw(); // silence memory test
|
||||
map(0x0f0000, 0x0fffff).rom().region("bios", 0);
|
||||
map(0xff0000, 0xffffff).rom().region("bios", 0);
|
||||
}
|
||||
|
||||
void apxen_state::io_map_base(address_map &map)
|
||||
{
|
||||
map(0x0000, 0xffff).rw(FUNC(apxen_state::io_r), FUNC(apxen_state::io_w));
|
||||
}
|
||||
|
||||
void apxen_state::io_map(address_map &map)
|
||||
{
|
||||
map(0x068, 0x068).w(m_crtc, FUNC(hd6845s_device::address_w));
|
||||
map(0x06a, 0x06a).rw(m_crtc, FUNC(hd6845s_device::register_r), FUNC(hd6845s_device::register_w));
|
||||
// map(0xc00, 0xc00) leds
|
||||
map.unmap_value_high();
|
||||
map(0xc00, 0xc00).w(FUNC(apxen_state::leds_w));
|
||||
// map(0xc20, 0xc20) printer
|
||||
// map(0xc30, 0xc31) SN76489
|
||||
// map(0xc40, 0xc47) CIO
|
||||
// map(0xc50, 0xc57) SIO
|
||||
// map(0xc60, 0xc6f) MM5827 RTC
|
||||
map(0xc30, 0xc30).w("sn", FUNC(sn76489_device::write));
|
||||
map(0xc40, 0xc47).rw(m_cio, FUNC(z8536_device::read), FUNC(z8536_device::write)).umask16(0x00ff);
|
||||
map(0xc50, 0xc57).rw(m_sio, FUNC(z80sio_device::ba_cd_r), FUNC(z80sio_device::ba_cd_w)).umask16(0x00ff);
|
||||
map(0xc60, 0xc7f).rw("rtc", FUNC(mm58274c_device::read), FUNC(mm58274c_device::write)).umask16(0x00ff);
|
||||
// map(0xc80, 0xc87) FDC
|
||||
// map(0xc90, 0xc93) uPD7261 HDC
|
||||
map(0xca0, 0xca3).rw(m_pic[0], FUNC(pic8259_device::read), FUNC(pic8259_device::write)).umask16(0x00ff);
|
||||
map(0xca4, 0xca7).rw(m_pic[1], FUNC(pic8259_device::read), FUNC(pic8259_device::write)).umask16(0x00ff);
|
||||
// map(0xcb0, 0xcb7) PIT
|
||||
// map(0xcc0, 0xccd) uPD71071 DMA 1
|
||||
// map(0xcd0, 0xcdd) uPD71071 DMA 2
|
||||
// map(0xce0, 0xce0) cpu control
|
||||
// map(0xcf0, 0xcf0) cpu reset
|
||||
map(0xcb0, 0xcb7).rw(m_pit, FUNC(pit8253_device::read), FUNC(pit8253_device::write)).umask16(0x00ff);
|
||||
// map(0xcc0, 0xccf) uPD71071 DMA 1
|
||||
// map(0xcd0, 0xcdf) uPD71071 DMA 2
|
||||
map(0xce0, 0xce0).rw(FUNC(apxen_state::cpu_control_r), FUNC(apxen_state::cpu_control_w));
|
||||
map(0xcf0, 0xcf0).w(FUNC(apxen_state::cpu_reset_w));
|
||||
}
|
||||
|
||||
|
||||
@ -117,13 +213,97 @@ INPUT_PORTS_END
|
||||
// VIDEO EMULATION
|
||||
//**************************************************************************
|
||||
|
||||
uint32_t apxen_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
WRITE_LINE_MEMBER( apxen_state::apvid_w )
|
||||
{
|
||||
return 0;
|
||||
m_apvid = bool(state);
|
||||
}
|
||||
|
||||
MC6845_UPDATE_ROW( apxen_state::crtc_update_row )
|
||||
|
||||
//**************************************************************************
|
||||
// MEMORY
|
||||
//**************************************************************************
|
||||
|
||||
uint16_t apxen_state::mem_r(offs_t offset, uint16_t mem_mask)
|
||||
{
|
||||
uint16_t data = 0xffff;
|
||||
|
||||
// pc/xi compatible mode vram
|
||||
if ((offset << 1) < 0x10000 && !m_apvid)
|
||||
m_video->mem_r(offset & (0xffff >> 1), data, mem_mask);
|
||||
|
||||
// pc/xi video pointer mirror
|
||||
else if ((offset << 1) >= 0xf0000 && (offset << 1) <= 0xf0fff && !m_apvid)
|
||||
m_video->mem_r((offset & (0xffff >> 1)) | (0x0e000 >> 1), data, mem_mask);
|
||||
|
||||
// xen mode vram
|
||||
else if ((offset << 1) >= 0xe0000 && (offset << 1) <= 0xeffff && m_apvid)
|
||||
m_video->mem_r(offset & (0xffff >> 1), data, mem_mask);
|
||||
|
||||
// normal access
|
||||
else
|
||||
data &= m_mem->read16(offset, mem_mask);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void apxen_state::mem_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
// pc/xi compatible mode vram
|
||||
if ((offset << 1) < 0x10000 && !m_apvid)
|
||||
m_video->mem_w(offset & (0xffff >> 1), data, mem_mask);
|
||||
|
||||
// pc/xi video pointer mirror
|
||||
else if ((offset << 1) >= 0xf0000 && (offset << 1) <= 0xf0fff && !m_apvid)
|
||||
m_video->mem_w((offset & (0xffff >> 1)) | (0x0e000 >> 1), data, mem_mask);
|
||||
|
||||
// xen mode vram
|
||||
else if ((offset << 1) >= 0xe0000 && (offset << 1) <= 0xeffff && m_apvid)
|
||||
m_video->mem_w(offset & (0xffff >> 1), data, mem_mask);
|
||||
|
||||
// normal access
|
||||
else
|
||||
m_mem->write16(offset, data, mem_mask);
|
||||
}
|
||||
|
||||
uint16_t apxen_state::io_r(offs_t offset, uint16_t mem_mask)
|
||||
{
|
||||
uint16_t data = 0xffff;
|
||||
|
||||
if (!m_video->io_r(offset, data, mem_mask))
|
||||
data &= m_io->read16(offset, mem_mask);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void apxen_state::io_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
if (!m_video->io_w(offset, data, mem_mask))
|
||||
m_io->write16(offset, data, mem_mask);
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// INTERRUPT HANDLING
|
||||
//**************************************************************************
|
||||
|
||||
static const z80_daisy_config xen_daisy_chain[] =
|
||||
{
|
||||
{ "cio" },
|
||||
{ "sio" },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
uint8_t apxen_state::get_slave_ack(offs_t offset)
|
||||
{
|
||||
// z80 daisy chain
|
||||
if (offset == 1)
|
||||
return m_daisy->acknowledge();
|
||||
|
||||
// slave pic
|
||||
if (offset == 2)
|
||||
return m_pic[1]->acknowledge();
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
|
||||
@ -137,14 +317,61 @@ void apxen_state::machine_start()
|
||||
|
||||
void apxen_state::machine_reset()
|
||||
{
|
||||
// boot rom enabled, hard reset
|
||||
m_cpu_control = 0x00;
|
||||
}
|
||||
|
||||
uint8_t apxen_state::get_slave_ack(offs_t offset)
|
||||
void apxen_state::leds_w(uint8_t data)
|
||||
{
|
||||
if (offset == 2)
|
||||
return m_pic[1]->acknowledge();
|
||||
logerror("leds_w: %02x\n", data);
|
||||
|
||||
return 0x00;
|
||||
// 76543--- not used
|
||||
// -----2-- hdd led
|
||||
// ------1- fdd led
|
||||
// -------0 voice led
|
||||
}
|
||||
|
||||
uint8_t apxen_state::cpu_control_r()
|
||||
{
|
||||
// only bits 0 and 1 can be read back
|
||||
return m_cpu_control & 0x03;
|
||||
}
|
||||
|
||||
void apxen_state::cpu_control_w(uint8_t data)
|
||||
{
|
||||
logerror("cpu_control_w: %02x\n", data);
|
||||
|
||||
// 76543--- not used
|
||||
// -----2-- full memory (virtual mode) or 1 mb wraparound (real mode)
|
||||
// ------1- hard/soft reset
|
||||
// -------0 boot rom enabled
|
||||
|
||||
m_cpu_control = data;
|
||||
}
|
||||
|
||||
void apxen_state::cpu_reset_w(uint8_t data)
|
||||
{
|
||||
logerror("cpu_reset_w: %02x\n", data);
|
||||
|
||||
// data written doesn't matter
|
||||
m_maincpu->reset();
|
||||
}
|
||||
|
||||
void apxen_state::cio_porta_w(uint8_t data)
|
||||
{
|
||||
logerror("cio_porta_w: %02x\n", data);
|
||||
}
|
||||
|
||||
void apxen_state::cio_portb_w(uint8_t data)
|
||||
{
|
||||
logerror("cio_portb_w: %02x\n", data);
|
||||
}
|
||||
|
||||
void apxen_state::cio_portc_w(uint8_t data)
|
||||
{
|
||||
logerror("cio_portc_w: %02x\n", data);
|
||||
|
||||
m_eeprom->clk_write(BIT(data, 2));
|
||||
}
|
||||
|
||||
|
||||
@ -155,10 +382,23 @@ uint8_t apxen_state::get_slave_ack(offs_t offset)
|
||||
void apxen_state::apxen(machine_config &config)
|
||||
{
|
||||
I80286(config, m_maincpu, 15_MHz_XTAL / 2);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &apxen_state::mem_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &apxen_state::io_map);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &apxen_state::mem_map_base);
|
||||
m_maincpu->set_addrmap(AS_IO, &apxen_state::io_map_base);
|
||||
m_maincpu->set_irq_acknowledge_callback(m_pic[0], FUNC(pic8259_device::inta_cb));
|
||||
|
||||
ADDRESS_MAP_BANK(config, m_mem);
|
||||
m_mem->set_addrmap(AS_PROGRAM, &apxen_state::mem_map);
|
||||
m_mem->set_data_width(16);
|
||||
m_mem->set_addr_width(24);
|
||||
|
||||
ADDRESS_MAP_BANK(config, m_io);
|
||||
m_io->set_addrmap(AS_PROGRAM, &apxen_state::io_map);
|
||||
m_io->set_data_width(16);
|
||||
m_io->set_addr_width(16);
|
||||
|
||||
EEPROM_93C06_16BIT(config, m_eeprom); // NMC9306
|
||||
m_eeprom->do_callback().set(m_sio, FUNC(z80sio_device::ctsb_w));
|
||||
|
||||
PIC8259(config, m_pic[0], 0);
|
||||
m_pic[0]->out_int_callback().set_inputline(m_maincpu, 0);
|
||||
m_pic[0]->in_sp_callback().set_constant(1);
|
||||
@ -168,21 +408,37 @@ void apxen_state::apxen(machine_config &config)
|
||||
m_pic[1]->out_int_callback().set(m_pic[0], FUNC(pic8259_device::ir2_w));
|
||||
m_pic[1]->in_sp_callback().set_constant(0);
|
||||
|
||||
XEN_DAISY(config, m_daisy);
|
||||
m_daisy->set_daisy_config(xen_daisy_chain);
|
||||
|
||||
PIT8253(config, m_pit, 0);
|
||||
m_pit->set_clk<0>(2000000);
|
||||
m_pit->out_handler<0>().set(m_sio, FUNC(z80sio_device::rxca_w));
|
||||
m_pit->set_clk<1>(2000000);
|
||||
m_pit->out_handler<1>().set(m_sio, FUNC(z80sio_device::txca_w));
|
||||
m_pit->set_clk<2>(2000000);
|
||||
m_pit->out_handler<2>().set(m_sio, FUNC(z80sio_device::rxtxcb_w));
|
||||
|
||||
Z8536(config, m_cio, 4000000);
|
||||
m_cio->irq_wr_cb().set(m_pic[0], FUNC(pic8259_device::ir1_w));
|
||||
m_cio->pa_wr_cb().set(FUNC(apxen_state::cio_porta_w));
|
||||
m_cio->pb_wr_cb().set(FUNC(apxen_state::cio_portb_w));
|
||||
m_cio->pc_wr_cb().set(FUNC(apxen_state::cio_portc_w));
|
||||
|
||||
Z80SIO(config, m_sio, 4000000);
|
||||
m_sio->out_dtrb_callback().set(m_eeprom, FUNC(eeprom_serial_93cxx_device::di_write));
|
||||
m_sio->out_rtsb_callback().set(m_eeprom, FUNC(eeprom_serial_93cxx_device::cs_write));
|
||||
// channel a rs232, b keyboard
|
||||
|
||||
MM58274C(config, "rtc", 32.768_kHz_XTAL);
|
||||
|
||||
// video hardware
|
||||
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(apxen_state::screen_update));
|
||||
APRICOT_VIDEO_SLOT(config, m_video, apricot_video_cards, "mono");
|
||||
m_video->apvid_handler().set(FUNC(apxen_state::apvid_w));
|
||||
|
||||
PALETTE(config, m_mono_palette, palette_device::MONOCHROME_HIGHLIGHT);
|
||||
|
||||
HD6845S(config, m_crtc, 24_MHz_XTAL / 20); // actually MB89321B
|
||||
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(apxen_state::crtc_update_row));
|
||||
// sound hardware
|
||||
SPEAKER(config, "mono").front_center();
|
||||
SN76489(config, "sn", 2000000).add_route(ALL_OUTPUTS, "mono", 1.0);
|
||||
}
|
||||
|
||||
|
||||
@ -211,4 +467,4 @@ ROM_END
|
||||
//**************************************************************************
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
COMP( 1985, apxen, 0, 0, apxen, apxen, apxen_state, empty_init, "ACT", "Apricot XEN", MACHINE_IS_SKELETON )
|
||||
COMP( 1985, apxen, 0, 0, apxen, apxen, apxen_state, empty_init, "ACT", "Apricot XEN", MACHINE_NOT_WORKING )
|
||||
|
Loading…
Reference in New Issue
Block a user