microtan.cpp: The Microtan driver overhaul!

- Renamed driver microtan->mt65
- Added alternative monitor ROMs: TANBUG V3.1, TANBUG V.3B, TUGBUG V1.1, TANBUG V1.
- Replaced XBug with original 0.75MHz version, fixes cassette loading.
- New machine Micron, consisting of MT65 and Tanex boards only.
- Implemented the Microtan motherboard backplane and moved Tanex to slot device.
- Additional boards implemented: Bulldog Sound Generator Board, Mousepacket Designs Colour VDU Card, Tangerine Tandos Board (not working), Tangerine High Resolution Graphics Card (monochrome), Tangerine High Resolution Graphics Card (colour), Tangerine Tanram Board, TUG 64K RAM Card, TUG Programmable Graphic Module Card,  Microtanic Video 80/82 (not working), Ralph Allen 32K EPROM-RAM Card (incomplete), Ralph Allen Disc Controller Card (not working), Ralph Allen Colour VDU card
- Added Microtan 6809 System, not yet working.
- Added Space Invasion (ETI), the DIY project from Electronics Today based on the Microtan.
This commit is contained in:
Nigel Barnes 2019-07-25 17:05:31 +01:00
parent e724f4d7e6
commit 7e988f9563
33 changed files with 4305 additions and 287 deletions

View File

@ -2825,6 +2825,42 @@ if (BUSES["SMS_EXP"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/bus/tanbus/tanbus.h,BUSES["TANBUS"] = true
---------------------------------------------------
if (BUSES["TANBUS"]~=null) then
files {
MAME_DIR .. "src/devices/bus/tanbus/bullsnd.cpp",
MAME_DIR .. "src/devices/bus/tanbus/bullsnd.h",
MAME_DIR .. "src/devices/bus/tanbus/tanbus.cpp",
MAME_DIR .. "src/devices/bus/tanbus/tanbus.h",
MAME_DIR .. "src/devices/bus/tanbus/tanex.cpp",
MAME_DIR .. "src/devices/bus/tanbus/tanex.h",
MAME_DIR .. "src/devices/bus/tanbus/tandos.cpp",
MAME_DIR .. "src/devices/bus/tanbus/tandos.h",
MAME_DIR .. "src/devices/bus/tanbus/tanhrg.cpp",
MAME_DIR .. "src/devices/bus/tanbus/tanhrg.h",
MAME_DIR .. "src/devices/bus/tanbus/tanram.cpp",
MAME_DIR .. "src/devices/bus/tanbus/tanram.h",
MAME_DIR .. "src/devices/bus/tanbus/mpvdu.cpp",
MAME_DIR .. "src/devices/bus/tanbus/mpvdu.h",
MAME_DIR .. "src/devices/bus/tanbus/ra32k.cpp",
MAME_DIR .. "src/devices/bus/tanbus/ra32k.h",
MAME_DIR .. "src/devices/bus/tanbus/radisc.cpp",
MAME_DIR .. "src/devices/bus/tanbus/radisc.h",
MAME_DIR .. "src/devices/bus/tanbus/ravdu.cpp",
MAME_DIR .. "src/devices/bus/tanbus/ravdu.h",
MAME_DIR .. "src/devices/bus/tanbus/tug64k.cpp",
MAME_DIR .. "src/devices/bus/tanbus/tug64k.h",
MAME_DIR .. "src/devices/bus/tanbus/tug8082.cpp",
MAME_DIR .. "src/devices/bus/tanbus/tug8082.h",
MAME_DIR .. "src/devices/bus/tanbus/tugpgm.cpp",
MAME_DIR .. "src/devices/bus/tanbus/tugpgm.h",
}
end
---------------------------------------------------
--
--@src/devices/bus/ti8x/ti8x.h,BUSES["TI8X"] = true

View File

@ -844,6 +844,7 @@ BUSES["SUNKBD"] = true
BUSES["SUNMOUSE"] = true
BUSES["SVI_EXPANDER"] = true
BUSES["SVI_SLOT"] = true
BUSES["TANBUS"] = true
BUSES["TATUNG_PIPE"] = true
BUSES["TMC600"] = true
BUSES["TI8X"] = true

View File

@ -0,0 +1,103 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Microtan Bulldog Sound Generator Board
http://www.microtan.ukpc.net/pageProducts.html#SOUND
**********************************************************************/
#include "emu.h"
#include "bullsnd.h"
#include "speaker.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(TANBUS_BULLSND, tanbus_bullsnd_device, "tanbus_bullsnd", "Microtan Bulldog Sound Generator Board")
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void tanbus_bullsnd_device::device_add_mconfig(machine_config &config)
{
SPEAKER(config, "speaker").front_center();
AY8910(config, m_ay8910[0], DERIVED_CLOCK(1, 8)).add_route(ALL_OUTPUTS, "speaker", 0.5);
AY8910(config, m_ay8910[1], DERIVED_CLOCK(1, 8)).add_route(ALL_OUTPUTS, "speaker", 0.5);
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// tanbus_bullsnd_device - constructor
//-------------------------------------------------
tanbus_bullsnd_device::tanbus_bullsnd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TANBUS_BULLSND, tag, owner, clock)
, device_tanbus_interface(mconfig, *this)
, m_ay8910(*this, "ay8910%u", 0)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tanbus_bullsnd_device::device_start()
{
}
//-------------------------------------------------
// read - card read
//-------------------------------------------------
uint8_t tanbus_bullsnd_device::read(offs_t offset, int inhrom, int inhram, int be)
{
uint8_t data = 0xff;
switch (offset)
{
case 0xbc01:
data = m_ay8910[0]->data_r();
break;
case 0xbc03:
data = m_ay8910[1]->data_r();
break;
}
return data;
}
//-------------------------------------------------
// write - card write
//-------------------------------------------------
void tanbus_bullsnd_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
{
switch (offset)
{
case 0xbc00:
m_ay8910[0]->address_w(data);
break;
case 0xbc01:
m_ay8910[0]->data_w(data);
break;
case 0xbc02:
m_ay8910[1]->address_w(data);
break;
case 0xbc03:
m_ay8910[1]->data_w(data);
break;
}
}

View File

@ -0,0 +1,49 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Microtan Bulldog Sound Generator Board
**********************************************************************/
#ifndef MAME_BUS_TANBUS_BULLSND_H
#define MAME_BUS_TANBUS_BULLSND_H
#pragma once
#include "bus/tanbus/tanbus.h"
#include "sound/ay8910.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class tanbus_bullsnd_device :
public device_t,
public device_tanbus_interface
{
public:
// construction/destruction
tanbus_bullsnd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// device-level overrides
virtual void device_start() override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) override;
virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
private:
required_device_array<ay8910_device, 2> m_ay8910;
};
// device type definition
DECLARE_DEVICE_TYPE(TANBUS_BULLSND, tanbus_bullsnd_device)
#endif // MAME_BUS_TANBUS_BULLSND_H

View File

@ -0,0 +1,182 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Microtan Mousepacket Designs Colour VDU Card
http://www.microtan.ukpc.net/pageProducts.html#VIDEO
TODO:
- use MC6845 screen_update to implement cursor, requires interlace
**********************************************************************/
#include "emu.h"
#include "mpvdu.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(TANBUS_MPVDU, tanbus_mpvdu_device, "tanbus_mpvdu", "Mousepacket Designs Colour VDU Card")
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void tanbus_mpvdu_device::device_add_mconfig(machine_config &config)
{
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_refresh_hz(50);
m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500));
m_screen->set_size(1152, 625);
m_screen->set_visarea(0, 768 - 1, 0, 500 - 1);
//m_screen->set_screen_update("mc6845", FUNC(mc6845_device::screen_update)); // TODO: implement interlace in mc6845
m_screen->set_screen_update("saa5050", FUNC(saa5050_device::screen_update));
MC6845(config, m_crtc, DERIVED_CLOCK(1, 3));
m_crtc->set_screen(nullptr);
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(12);
m_crtc->out_vsync_callback().set(FUNC(tanbus_mpvdu_device::vsync_changed));
m_crtc->set_update_row_callback(FUNC(tanbus_mpvdu_device::crtc_update_row), this);
SAA5050(config, m_trom, DERIVED_CLOCK(1, 1));
m_trom->d_cb().set(FUNC(tanbus_mpvdu_device::videoram_r));
m_trom->set_screen_size(64, 25, 64);
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// tanbus_mpvdu_device - constructor
//-------------------------------------------------
tanbus_mpvdu_device::tanbus_mpvdu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TANBUS_MPVDU, tag, owner, clock)
, device_tanbus_interface(mconfig, *this)
, m_screen(*this, "screen")
, m_crtc(*this, "mc6845")
, m_trom(*this, "saa5050")
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tanbus_mpvdu_device::device_start()
{
m_videoram = std::make_unique<uint8_t[]>(0x800);
save_pointer(NAME(m_videoram), 0x800);
}
//-------------------------------------------------
// read - card read
//-------------------------------------------------
uint8_t tanbus_mpvdu_device::read(offs_t offset, int inhrom, int inhram, int be)
{
uint8_t data = 0xff;
if ((offset & 0xf800) == 0xa000)
{
data = m_videoram[offset & 0x7ff];
}
switch (offset & 0xfff1)
{
case 0xa7f0:
data = m_crtc->status_r();
break;
case 0xa7f1:
data = m_crtc->register_r();
break;
}
return data;
}
//-------------------------------------------------
// write - card write
//-------------------------------------------------
void tanbus_mpvdu_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
{
if ((offset & 0xf800) == 0xa000)
{
m_videoram[offset & 0x7ff] = data;
}
switch (offset & 0xfff1)
{
case 0xa7f0:
m_crtc->address_w(data);
break;
case 0xa7f1:
m_crtc->register_w(data);
break;
}
}
//-------------------------------------------------
// set_inhibit_lines
//-------------------------------------------------
void tanbus_mpvdu_device::set_inhibit_lines(offs_t offset, int &inhram, int &inhrom)
{
if ((offset & 0xf800) == 0xa000)
{
inhram = 1;
}
};
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
READ8_MEMBER(tanbus_mpvdu_device::videoram_r)
{
return m_videoram[offset];
}
MC6845_UPDATE_ROW(tanbus_mpvdu_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) & 0x7ff]);
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(tanbus_mpvdu_device::vsync_changed)
{
m_trom->dew_w(state);
}

View File

@ -0,0 +1,62 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Microtan Mousepacket Designs Colour VDU Card
**********************************************************************/
#ifndef MAME_BUS_TANBUS_MPVDU_H
#define MAME_BUS_TANBUS_MPVDU_H
#pragma once
#include "bus/tanbus/tanbus.h"
#include "video/saa5050.h"
#include "video/mc6845.h"
#include "screen.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class tanbus_mpvdu_device :
public device_t,
public device_tanbus_interface
{
public:
static constexpr feature_type imperfect_features() { return feature::GRAPHICS; }
// construction/destruction
tanbus_mpvdu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// device-level overrides
virtual void device_start() override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) override;
virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
virtual void set_inhibit_lines(offs_t offset, int &inhram, int &inhrom) override;
private:
DECLARE_READ8_MEMBER(videoram_r);
MC6845_UPDATE_ROW(crtc_update_row);
DECLARE_WRITE_LINE_MEMBER(vsync_changed);
required_device<screen_device> m_screen;
required_device<mc6845_device> m_crtc;
required_device<saa5050_device> m_trom;
std::unique_ptr<uint8_t[]> m_videoram;
};
// device type definition
DECLARE_DEVICE_TYPE(TANBUS_MPVDU, tanbus_mpvdu_device)
#endif // MAME_BUS_TANBUS_MPVDU_H

View File

@ -0,0 +1,257 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Ralph Allen 32K EPROM-RAM Card
http://www.microtan.ukpc.net/6809/32RAM.pdf
**********************************************************************/
#include "emu.h"
#include "ra32k.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(TANBUS_RA32K, tanbus_ra32k_device, "tanbus_ra32k", "Ralph Allen 32K EPROM-RAM Card")
//-------------------------------------------------
// INPUT_PORTS( ra32k )
//-------------------------------------------------
INPUT_PORTS_START( ra32k )
PORT_START("DSW1")
PORT_DIPNAME(0x01, 0x01, "2K block $0800") PORT_DIPLOCATION("SW1:1")
PORT_DIPSETTING(0x00, "Disable")
PORT_DIPSETTING(0x01, "Enable")
PORT_DIPNAME(0x02, 0x02, "2K block $1800") PORT_DIPLOCATION("SW1:2")
PORT_DIPSETTING(0x00, "Disable")
PORT_DIPSETTING(0x02, "Enable")
PORT_DIPNAME(0x04, 0x04, "2K block $2800") PORT_DIPLOCATION("SW1:3")
PORT_DIPSETTING(0x00, "Disable")
PORT_DIPSETTING(0x04, "Enable")
PORT_DIPNAME(0x08, 0x08, "2K block $3800") PORT_DIPLOCATION("SW1:4")
PORT_DIPSETTING(0x00, "Disable")
PORT_DIPSETTING(0x08, "Enable")
PORT_DIPNAME(0x10, 0x10, "2K block $4800") PORT_DIPLOCATION("SW1:5")
PORT_DIPSETTING(0x00, "Disable")
PORT_DIPSETTING(0x10, "Enable")
PORT_DIPNAME(0x20, 0x20, "2K block $5800") PORT_DIPLOCATION("SW1:6")
PORT_DIPSETTING(0x00, "Disable")
PORT_DIPSETTING(0x20, "Enable")
PORT_DIPNAME(0x40, 0x40, "2K block $6800") PORT_DIPLOCATION("SW1:7")
PORT_DIPSETTING(0x00, "Disable")
PORT_DIPSETTING(0x40, "Enable")
PORT_DIPNAME(0x80, 0x80, "2K block $7800") PORT_DIPLOCATION("SW1:8")
PORT_DIPSETTING(0x00, "Disable")
PORT_DIPSETTING(0x80, "Enable")
PORT_START("DSW2")
PORT_DIPNAME(0x01, 0x01, "2K block $0000") PORT_DIPLOCATION("SW2:1")
PORT_DIPSETTING(0x00, "Disable")
PORT_DIPSETTING(0x01, "Enable")
PORT_DIPNAME(0x02, 0x02, "2K block $1000") PORT_DIPLOCATION("SW2:2")
PORT_DIPSETTING(0x00, "Disable")
PORT_DIPSETTING(0x02, "Enable")
PORT_DIPNAME(0x04, 0x04, "2K block $2000") PORT_DIPLOCATION("SW2:3")
PORT_DIPSETTING(0x00, "Disable")
PORT_DIPSETTING(0x04, "Enable")
PORT_DIPNAME(0x08, 0x08, "2K block $3000") PORT_DIPLOCATION("SW2:4")
PORT_DIPSETTING(0x00, "Disable")
PORT_DIPSETTING(0x08, "Enable")
PORT_DIPNAME(0x10, 0x10, "2K block $4000") PORT_DIPLOCATION("SW2:5")
PORT_DIPSETTING(0x00, "Disable")
PORT_DIPSETTING(0x10, "Enable")
PORT_DIPNAME(0x20, 0x20, "2K block $5000") PORT_DIPLOCATION("SW2:6")
PORT_DIPSETTING(0x00, "Disable")
PORT_DIPSETTING(0x20, "Enable")
PORT_DIPNAME(0x40, 0x40, "2K block $6000") PORT_DIPLOCATION("SW2:7")
PORT_DIPSETTING(0x00, "Disable")
PORT_DIPSETTING(0x40, "Enable")
PORT_DIPNAME(0x80, 0x80, "2K block $7000") PORT_DIPLOCATION("SW2:8")
PORT_DIPSETTING(0x00, "Disable")
PORT_DIPSETTING(0x80, "Enable")
PORT_START("DSW3")
PORT_DIPNAME(0x0f, 0x0f, "Address Selection") PORT_DIPLOCATION("SW3:1,2,3,4")
PORT_DIPSETTING(0x0f, "$0000-$7FFF")
PORT_DIPSETTING(0x00, "$1000-$8FFF")
PORT_DIPSETTING(0x04, "$2000-$9FFF")
PORT_DIPSETTING(0x08, "$3000-$AFFF")
PORT_DIPSETTING(0x0c, "$4000-$BFFF")
PORT_DIPSETTING(0x01, "$5000-$CFFF")
PORT_DIPSETTING(0x05, "$6000-$DFFF")
PORT_DIPSETTING(0x09, "$7000-$EFFF")
PORT_DIPSETTING(0x0d, "$8000-$FFFF")
PORT_DIPSETTING(0x02, "$9000-$0FFF")
PORT_DIPSETTING(0x06, "$A000-$1FFF")
PORT_DIPSETTING(0x0a, "$B000-$2FFF")
PORT_DIPSETTING(0x0e, "$C000-$3FFF")
PORT_DIPSETTING(0x03, "$D000-$4FFF")
PORT_DIPSETTING(0x07, "$E000-$5FFF")
PORT_DIPSETTING(0x0b, "$F000-$6FFF")
PORT_START("LNK1")
PORT_CONFNAME(0x03, 0x00, "Block Enable")
PORT_CONFSETTING(0x00, "RAM (permanent)")
PORT_CONFSETTING(0x01, "RAM (page selectable)")
PORT_CONFSETTING(0x02, "EPROM (page selectable)")
INPUT_PORTS_END
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
ioport_constructor tanbus_ra32k_device::device_input_ports() const
{
return INPUT_PORTS_NAME( ra32k );
}
//-------------------------------------------------
// ROM( ra32k )
//-------------------------------------------------
ROM_START(ra32k)
ROM_REGION(0x8000, "rom", 0)
ROM_LOAD("data_v1.4.rom", 0x0000, 0x0800, CRC(de61f11d) SHA1(3e6ddc5dba47d9136f58abc9475c3e73fc8cc0c2))
ROM_LOAD("syntax_v1.4.rom", 0x0800, 0x0800, CRC(17438c4c) SHA1(46bf4e33544c19e142b380095736c5c3eb885ba0))
ROM_LOAD("ascii_v1.4.rom", 0x1000, 0x0800, CRC(93244a81) SHA1(6149eec9904438a0d23529d2c2428a594d5b1fb9))
ROM_LOAD("graph_v1.4.rom", 0x1800, 0x0800, CRC(159eb1f6) SHA1(5e49edda4b550506aca70d1f7e7de7a352f0359f))
ROM_END
const tiny_rom_entry *tanbus_ra32k_device::device_rom_region() const
{
return ROM_NAME(ra32k);
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// tanbus_ra32k_device - constructor
//-------------------------------------------------
tanbus_ra32k_device::tanbus_ra32k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TANBUS_RA32K, tag, owner, clock)
, device_tanbus_interface(mconfig, *this)
, m_rom(*this, "rom")
, m_dsw(*this, "DSW%u", 1)
, m_link(*this, "LNK1")
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tanbus_ra32k_device::device_start()
{
m_ram = std::make_unique<uint8_t[]>(0x8000);
save_pointer(NAME(m_ram), 0x8000);
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void tanbus_ra32k_device::device_reset()
{
}
//-------------------------------------------------
// read - card read
//-------------------------------------------------
uint8_t tanbus_ra32k_device::read(offs_t offset, int inhrom, int inhram, int be)
{
uint8_t data = 0xff;
switch (m_link->read() & 0x02)
{
case 0x00:
/* 32K dynamic RAM */
if (block_enabled(offset, inhrom, inhram, be))
{
//logerror("ram read %04x\n", offset);
data = m_ram[offset & 0x7fff];
}
break;
case 0x02:
/* ROM selected */
if (block_enabled(offset, inhrom, inhram, be))
{
//logerror("rom read %04x\n", offset);
data = m_rom->base()[(offset - m_addr_start) & 0x7fff];
}
break;
}
return data;
}
//-------------------------------------------------
// write - card write
//-------------------------------------------------
void tanbus_ra32k_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
{
switch (m_link->read() & 0x02)
{
case 0x00:
/* 32K dynamic RAM */
if (block_enabled(offset, inhrom, inhram, be))
{
//logerror("ram write %04x %02x\n", offset, data);
m_ram[offset & 0x7fff] = data;
}
break;
case 0x02:
/* ROM selected */
break;
}
}
bool tanbus_ra32k_device::block_enabled(offs_t offset, int inhrom, int inhram, int be)
{
m_addr_start = ((bitswap<4>(m_dsw[2]->read(), 1, 0, 3, 2) << 12) + 0x1000) & 0xffff;
m_addr_end = (m_addr_start + 0x7fff) & 0xffff;
//uint8_t block_start = (bitswap<4>(m_dsw[2]->read(), 1, 0, 3, 2) + 1) & 0x0f;
uint8_t block = offset >> 12;
//logerror("%04x start %04x current %04x\n", offset, block_start, block);
if (offset & 0x0800)
{
/* switch SW1 */
if (!BIT(m_dsw[0]->read(), block))
return false;
}
else
{
/* switch SW2 */
if (!BIT(m_dsw[1]->read(), block))
return false;
}
/* recognise INHRAM signal */
if (inhram)
return false;
/* recognise I/O signal (should be a Tanex output) */
if ((offset & 0xfc00) == 0xbc00)
return false;
/* recognise Block Enable */
if ((m_link->read() & 0x01) && !be)
return false;
return true;
}

View File

@ -0,0 +1,59 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Ralph Allen 32K Dynamic RAM Board
**********************************************************************/
#ifndef MAME_BUS_TANBUS_RA32K_H
#define MAME_BUS_TANBUS_RA32K_H
#pragma once
#include "bus/tanbus/tanbus.h"
#include "bus/tanbus/ra32k.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class tanbus_ra32k_device :
public device_t,
public device_tanbus_interface
{
public:
// construction/destruction
tanbus_ra32k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
// optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
virtual ioport_constructor device_input_ports() const override;
virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) override;
virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
private:
required_memory_region m_rom;
required_ioport_array<3> m_dsw;
required_ioport m_link;
offs_t m_addr_start;
offs_t m_addr_end;
std::unique_ptr<uint8_t[]> m_ram;
bool block_enabled(offs_t offset, int inhrom, int inhram, int be);
};
// device type definition
DECLARE_DEVICE_TYPE(TANBUS_RA32K, tanbus_ra32k_device)
#endif // MAME_BUS_TANBUS_RA32K_H

View File

@ -0,0 +1,213 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Ralph Allen Disc Controller Card
http://www.microtan.ukpc.net/6809/DOS_RTC.pdf
**********************************************************************/
#include "emu.h"
#include "radisc.h"
#include "speaker.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(TANBUS_RADISC, tanbus_radisc_device, "tanbus_radisc", "Ralph Allen Disc Controller Card")
//-------------------------------------------------
// MACHINE_DRIVER( radisc )
//-------------------------------------------------
static void tandos_floppies(device_slot_interface &device)
{
device.option_add("525sssd", FLOPPY_525_SSSD);
device.option_add("525sd", FLOPPY_525_SD);
device.option_add("525qd", FLOPPY_525_QD);
}
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void tanbus_radisc_device::device_add_mconfig(machine_config &config)
{
INPUT_MERGER_ANY_HIGH(config, m_irq_line).output_handler().set(FUNC(tanbus_radisc_device::fdc_irq_w));
FD1793(config, m_fdc, 4_MHz_XTAL / 4);
m_fdc->intrq_wr_callback().set(m_irq_line, FUNC(input_merger_device::in_w<IRQ_FDC>));
m_fdc->drq_wr_callback().set(FUNC(tanbus_radisc_device::fdc_drq_w));
m_fdc->hld_wr_callback().set(FUNC(tanbus_radisc_device::fdc_hld_w));
m_fdc->set_force_ready(true);
FLOPPY_CONNECTOR(config, m_floppies[0], tandos_floppies, "525qd", floppy_image_device::default_floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, m_floppies[1], tandos_floppies, "525qd", floppy_image_device::default_floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, m_floppies[2], tandos_floppies, nullptr, floppy_image_device::default_floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, m_floppies[3], tandos_floppies, nullptr, floppy_image_device::default_floppy_formats).enable_sound(true);
MC146818(config, m_rtc, 32.768_kHz_XTAL);
m_rtc->irq().set(m_irq_line, FUNC(input_merger_device::in_w<IRQ_RTC>));
VIA6522(config, m_via, 4_MHz_XTAL / 4);
m_via->irq_handler().set(m_irq_line, FUNC(input_merger_device::in_w<IRQ_VIA>));
/* audio hardware */
SPEAKER(config, "mono").front_center();
BEEP(config, m_beeper, 1000); // TODO: unknown frequency
m_beeper->add_route(ALL_OUTPUTS, "mono", 1.0);
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// tanbus_radisc_device - constructor
//-------------------------------------------------
tanbus_radisc_device::tanbus_radisc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TANBUS_RADISC, tag, owner, clock)
, device_tanbus_interface(mconfig, *this)
, m_fdc(*this, "fdc")
, m_floppies(*this, "fdc:%u", 0)
, m_floppy(nullptr)
, m_rtc(*this, "rtc")
, m_via(*this, "via")
, m_irq_line(*this, "irq_line")
, m_beeper(*this, "beeper")
, m_beeper_state(0)
, m_drive_control(0)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tanbus_radisc_device::device_start()
{
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void tanbus_radisc_device::device_reset()
{
}
//-------------------------------------------------
// read - card read
//-------------------------------------------------
uint8_t tanbus_radisc_device::read(offs_t offset, int inhrom, int inhram, int be)
{
uint8_t data = 0xff;
switch (offset)
{
case 0xbf80: case 0xbf81: case 0xbf82: case 0xbf83: case 0xbf84: case 0xbf85: case 0xbf86: case 0xbf87: case 0xbf88: case 0xbf89: case 0xbf8a: case 0xbf8b: case 0xbf8c: case 0xbf8d: case 0xbf8e: case 0xbf8f:
data = m_via->read(offset & 0x0f);
break;
case 0xbf90: case 0xbf91: case 0xbf92: case 0xbf93:
data = m_fdc->read(offset & 0x03);
break;
case 0xbf94:
data = control_r();
break;
case 0xbf98: case 0xbf99:
data = m_rtc->read(offset & 0x01);
break;
}
return data;
}
//-------------------------------------------------
// write - card write
//-------------------------------------------------
void tanbus_radisc_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
{
switch (offset)
{
case 0xbf80: case 0xbf81: case 0xbf82: case 0xbf83: case 0xbf84: case 0xbf85: case 0xbf86: case 0xbf87: case 0xbf88: case 0xbf89: case 0xbf8a: case 0xbf8b: case 0xbf8c: case 0xbf8d: case 0xbf8e: case 0xbf8f:
m_via->write(offset & 0x0f, data);
break;
case 0xbf90: case 0xbf91: case 0xbf92: case 0xbf93:
m_fdc->write(offset & 0x03, data);
break;
case 0xbf94:
control_w(data);
break;
case 0xbf95:
m_beeper_state ^= 1;
m_beeper->set_state(m_beeper_state);
break;
case 0xbf98: case 0xbf99:
m_rtc->write(offset & 0x01, data);
break;
}
}
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
void tanbus_radisc_device::control_w(uint8_t val)
{
logerror("control_w %02x\n", val);
m_drive_control = val;
// bit 0: irq enable
m_irq_enable = BIT(val, 0);
// bit 1: data select (data stream controller)
// bit 2, 3: drive select
m_floppy = m_floppies[(val >> 2) & 0x03]->get_device();
m_fdc->set_floppy(m_floppy);
// bit 4: side select
if (m_floppy)
m_floppy->ss_w(BIT(val, 4));
// bit 5: density
m_fdc->dden_w(BIT(val, 5));
// bit 6: head load
if (m_floppy)
m_floppy->mon_w(BIT(val, 6));
// bit 7: drq enable
m_drq_enable = BIT(val, 7);
}
uint8_t tanbus_radisc_device::control_r()
{
logerror("control_r %02x\n", m_drive_control);
return m_drive_control;
}
WRITE_LINE_MEMBER(tanbus_radisc_device::fdc_drq_w)
{
m_tanbus->so_w((m_drq_enable && state) ? ASSERT_LINE : CLEAR_LINE);
}
WRITE_LINE_MEMBER(tanbus_radisc_device::fdc_irq_w)
{
m_tanbus->irq_w((m_irq_enable && state) ? ASSERT_LINE : CLEAR_LINE);
}
WRITE_LINE_MEMBER(tanbus_radisc_device::fdc_hld_w)
{
logerror("fdc_hld_w %d\n", state);
if (m_floppy)
m_floppy->mon_w(state);
}

View File

@ -0,0 +1,76 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Ralph Allen Disc Controller Card
**********************************************************************/
#ifndef MAME_BUS_TANBUS_RADISC_H
#define MAME_BUS_TANBUS_RADISC_H
#pragma once
#include "bus/tanbus/tanbus.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
#include "machine/mc146818.h"
#include "machine/6522via.h"
#include "machine/input_merger.h"
#include "sound/beep.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class tanbus_radisc_device :
public device_t,
public device_tanbus_interface
{
public:
// construction/destruction
tanbus_radisc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_FLOPPY_FORMATS(floppy_formats);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) override;
virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
private:
enum { IRQ_FDC, IRQ_VIA, IRQ_RTC };
void control_w(uint8_t val);
uint8_t control_r();
DECLARE_WRITE_LINE_MEMBER(fdc_irq_w);
DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
DECLARE_WRITE_LINE_MEMBER(fdc_hld_w);
required_device<fd1793_device> m_fdc;
required_device_array<floppy_connector, 4> m_floppies;
floppy_image_device *m_floppy;
required_device<mc146818_device> m_rtc;
required_device<via6522_device> m_via;
required_device<input_merger_device> m_irq_line;
required_device<beep_device> m_beeper;
int m_beeper_state;
uint8_t m_drive_control;
int m_irq_enable;
int m_drq_enable;
};
// device type definition
DECLARE_DEVICE_TYPE(TANBUS_RADISC, tanbus_radisc_device)
#endif // MAME_BUS_TANBUS_RADISC_H

View File

@ -0,0 +1,195 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Ralph Allen Colour VDU Card
http://www.microtan.ukpc.net/6809/Video.pdf
TODO:
- use MC6845 screen_update to implement cursor, requires interlace
- verify whether INHRAM and BE lines are used
**********************************************************************/
#include "emu.h"
#include "ravdu.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(TANBUS_RAVDU, tanbus_ravdu_device, "tanbus_ravdu", "Ralph Allen Colour VDU Card")
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void tanbus_ravdu_device::device_add_mconfig(machine_config &config)
{
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_refresh_hz(50);
m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500));
m_screen->set_size(1536, 624);
m_screen->set_visarea(0, 972 - 1, 0, 500 - 1);
//m_screen->set_screen_update("mc6845", FUNC(mc6845_device::screen_update)); // TODO: implement interlace in mc6845
m_screen->set_screen_update("saa5055", FUNC(saa5055_device::screen_update));
MC6845(config, m_crtc, DERIVED_CLOCK(1, 4));
m_crtc->set_screen(nullptr);
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(12);
m_crtc->out_vsync_callback().set(FUNC(tanbus_ravdu_device::vsync_changed));
m_crtc->set_update_row_callback(FUNC(tanbus_ravdu_device::crtc_update_row), this);
SAA5055(config, m_trom, DERIVED_CLOCK(1, 1));
m_trom->d_cb().set(FUNC(tanbus_ravdu_device::videoram_r));
m_trom->set_screen_size(81, 25, 81);
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// tanbus_ravdu_device - constructor
//-------------------------------------------------
tanbus_ravdu_device::tanbus_ravdu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TANBUS_RAVDU, tag, owner, clock)
, device_tanbus_interface(mconfig, *this)
, m_screen(*this, "screen")
, m_crtc(*this, "mc6845")
, m_trom(*this, "saa5055")
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tanbus_ravdu_device::device_start()
{
set_clock(m_tanbus->clock());
m_videoram = std::make_unique<uint8_t[]>(0x800);
memset(m_videoram.get(), 0xff, sizeof(uint8_t) * 0x800);
save_pointer(NAME(m_videoram), 0x800);
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void tanbus_ravdu_device::device_reset()
{
}
//-------------------------------------------------
// read - card read
//-------------------------------------------------
uint8_t tanbus_ravdu_device::read(offs_t offset, int inhrom, int inhram, int be)
{
uint8_t data = 0xff;
if ((offset & 0xf800) == 0xe000)
{
data = m_videoram[offset & 0x7ff];
}
switch (offset)
{
case 0xe7fe:
data = m_crtc->status_r();
break;
case 0xe7ff:
data = m_crtc->register_r();
break;
}
return data;
}
//-------------------------------------------------
// write - card write
//-------------------------------------------------
void tanbus_ravdu_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
{
if ((offset & 0xf800) == 0xe000)
{
m_videoram[offset & 0x7ff] = data;
}
switch (offset)
{
case 0xe7fe:
m_crtc->address_w(data);
break;
case 0xe7ff:
m_crtc->register_w(data);
break;
}
}
//-------------------------------------------------
// set_inhibit_lines
//-------------------------------------------------
void tanbus_ravdu_device::set_inhibit_lines(offs_t offset, int &inhram, int &inhrom)
{
if ((offset & 0xf800) == 0xe000)
{
inhram = 1;
}
};
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
READ8_MEMBER(tanbus_ravdu_device::videoram_r)
{
return m_videoram[offset & 0x7ff];
}
MC6845_UPDATE_ROW(tanbus_ravdu_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) & 0x7ff]);
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(tanbus_ravdu_device::vsync_changed)
{
m_trom->dew_w(state);
}

View File

@ -0,0 +1,63 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Ralph Allen Colour VDU Card
**********************************************************************/
#ifndef MAME_BUS_TANBUS_RAVDU_H
#define MAME_BUS_TANBUS_RAVDU_H
#pragma once
#include "bus/tanbus/tanbus.h"
#include "video/saa5050.h"
#include "video/mc6845.h"
#include "screen.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class tanbus_ravdu_device :
public device_t,
public device_tanbus_interface
{
public:
static constexpr feature_type imperfect_features() { return feature::GRAPHICS; }
// construction/destruction
tanbus_ravdu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) override;
virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
virtual void set_inhibit_lines(offs_t offset, int &inhram, int &inhrom) override;
private:
DECLARE_READ8_MEMBER(videoram_r);
MC6845_UPDATE_ROW(crtc_update_row);
DECLARE_WRITE_LINE_MEMBER(vsync_changed);
required_device<screen_device> m_screen;
required_device<mc6845_device> m_crtc;
required_device<saa5055_device> m_trom;
std::unique_ptr<uint8_t[]> m_videoram;
};
// device type definition
DECLARE_DEVICE_TYPE(TANBUS_RAVDU, tanbus_ravdu_device)
#endif // MAME_BUS_TANBUS_RAVDU_H

View File

@ -0,0 +1,254 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Microtan Bus emulation
http://www.microtan.ukpc.net/pageProducts.html#MOTHERBOARDS
**********************************************************************/
#include "emu.h"
#include "tanbus.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(TANBUS_SLOT, tanbus_slot_device, "tanbus_slot", "Microtan Bus slot")
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// tanbus_slot_device - constructor
//-------------------------------------------------
tanbus_slot_device::tanbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TANBUS_SLOT, tag, owner, clock)
, device_slot_interface(mconfig, *this)
, m_tanbus(*this, DEVICE_SELF_OWNER)
{
}
//-------------------------------------------------
// device_validity_check - device-specific checks
//-------------------------------------------------
void tanbus_slot_device::device_validity_check(validity_checker &valid) const
{
device_t *const card(get_card_device());
if (card && !dynamic_cast<device_tanbus_interface *>(card))
osd_printf_error("tanbus_slot_device: card device %s (%s) does not implement device_tanbus_interface\n", card->tag(), card->name());
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tanbus_slot_device::device_start()
{
device_tanbus_interface *dev = dynamic_cast<device_tanbus_interface *>(get_card_device());
if (dev) m_tanbus->add_card(dev, m_bus_num);
}
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
DEFINE_DEVICE_TYPE(TANBUS, tanbus_device, "tanbus", "Microtan Bus")
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// tanbus_device - constructor
//-------------------------------------------------
tanbus_device::tanbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TANBUS, tag, owner, clock)
, m_out_irq_cb(*this)
, m_out_nmi_cb(*this)
, m_out_so_cb(*this)
, m_out_pgm_cb(*this)
{
}
void tanbus_device::add_card(device_tanbus_interface *card, int num)
{
card->m_tanbus = this;
card->m_page = num;
m_device_list.append(*card);
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tanbus_device::device_start()
{
// resolve callbacks
m_out_irq_cb.resolve_safe();
m_out_nmi_cb.resolve_safe();
m_out_so_cb.resolve_safe();
m_out_pgm_cb.resolve_safe();
save_item(NAME(m_block_register));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void tanbus_device::device_reset()
{
m_block_register = 0x00;
}
//-------------------------------------------------
// fetch - tanbus data read
//-------------------------------------------------
void tanbus_device::set_inhibit_lines(offs_t offset)
{
// prevent debugger from changing inhibit lines
if (machine().side_effects_disabled()) return;
// reset inhibit lines
m_inhram = m_inhrom = 0;
device_tanbus_interface *card = m_device_list.first();
while (card)
{
card->set_inhibit_lines(offset, m_inhram, m_inhrom);
card = card->next();
}
}
//-------------------------------------------------
// read - tanbus data read
//-------------------------------------------------
uint8_t tanbus_device::read(offs_t offset)
{
uint8_t data = 0xff;
set_inhibit_lines(offset);
device_tanbus_interface *card = m_device_list.first();
while (card)
{
// set block enable line for current card
if ((card->m_page == 0) || ((m_block_register >> 4) & 7) == card->m_page)
m_block_enable = 1;
else
m_block_enable = 0;
data &= card->read(offset, m_inhrom, m_inhram, m_block_enable);
card = card->next();
}
return data;
}
//-------------------------------------------------
// write - tanbus data write
//-------------------------------------------------
void tanbus_device::write(offs_t offset, uint8_t data)
{
if (offset == 0xffff)
{
logerror("write: Memory management control (read %d, write %d)\n", (data >> 4) & 7, data & 7);
m_block_register = data;
}
else if (offset >= 0xf800)
{
logerror("write: Unhandled write %02x to %04x\n", data, offset);
}
set_inhibit_lines(offset);
device_tanbus_interface *card = m_device_list.first();
while (card)
{
// set block enable line for current card
if ((card->m_page == 0) || (m_block_register & 7) == card->m_page)
m_block_enable = 1;
else
m_block_enable = 0;
card->write(offset, data, m_inhrom, m_inhram, m_block_enable);
card = card->next();
}
}
//**************************************************************************
// DEVICE TANBUS INTERFACE
//**************************************************************************
//-------------------------------------------------
// device_tanbus_interface - constructor
//-------------------------------------------------
device_tanbus_interface::device_tanbus_interface(const machine_config &mconfig, device_t &device)
: device_slot_card_interface(mconfig, device)
, m_tanbus(nullptr)
, m_page(0)
, m_next(nullptr)
{
}
//-------------------------------------------------
// SLOT_INTERFACE( tanbus_devices )
//-------------------------------------------------
// slot devices
#include "bullsnd.h"
#include "mpvdu.h"
#include "ra32k.h"
#include "radisc.h"
#include "ravdu.h"
#include "tanram.h"
#include "tandos.h"
#include "tanex.h"
#include "tanhrg.h"
#include "tug64k.h"
#include "tug8082.h"
#include "tugpgm.h"
void tanex_devices(device_slot_interface &device)
{
device.option_add("tanex", TANBUS_TANEX);
}
void tanbus_devices(device_slot_interface &device)
{
device.option_add("bullsnd", TANBUS_BULLSND);
device.option_add("mpvdu", TANBUS_MPVDU);
device.option_add("tanram", TANBUS_TANRAM);
device.option_add("tandos", TANBUS_TANDOS);
device.option_add("tanhrg", TANBUS_TANHRG);
device.option_add("tanhrgc", TANBUS_TANHRGC);
device.option_add("tug64k", TANBUS_TUG64K);
device.option_add("tug8082", TANBUS_TUG8082);
device.option_add("tugpgm", TANBUS_TUGPGM);
}
void tanbus6809_devices(device_slot_interface &device)
{
device.option_add("ra32k", TANBUS_RA32K);
device.option_add("radisc", TANBUS_RADISC);
device.option_add("ravdu", TANBUS_RAVDU);
device.option_add("tanram", TANBUS_TANRAM);
}

View File

@ -0,0 +1,150 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Microtan Bus emulation
**********************************************************************/
#ifndef MAME_BUS_TANBUS_TANBUS_H
#define MAME_BUS_TANBUS_TANBUS_H
#pragma once
//**************************************************************************
// FORWARD DECLARATIONS
//**************************************************************************
class tanbus_device;
class device_tanbus_interface;
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class tanbus_slot_device : public device_t, public device_slot_interface
{
public:
// construction/destruction
template <typename T>
tanbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, int num, T &&opts, const char *dflt)
: tanbus_slot_device(mconfig, tag, owner, DERIVED_CLOCK(1, 1))
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
set_tanbus_slot(tag, num);
}
tanbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// inline configuration
void set_tanbus_slot(const char *tag, int num) { m_bus_num = num; }
protected:
// device-level overrides
virtual void device_validity_check(validity_checker &valid) const override;
virtual void device_start() override;
private:
required_device<tanbus_device> m_tanbus;
int m_bus_num;
};
// device type definition
DECLARE_DEVICE_TYPE(TANBUS_SLOT, tanbus_slot_device)
// ======================> tanbus_device
class tanbus_device : public device_t
{
public:
// construction/destruction
tanbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
~tanbus_device() { m_device_list.detach_all(); }
// inline configuration
auto out_irq_callback() { return m_out_irq_cb.bind(); }
auto out_nmi_callback() { return m_out_nmi_cb.bind(); }
auto out_so_callback() { return m_out_so_cb.bind(); }
auto out_pgm_callback() { return m_out_pgm_cb.bind(); }
void add_card(device_tanbus_interface *card, int num);
uint8_t read(offs_t offset);
void write(offs_t offset, uint8_t data);
void set_inhibit_lines(offs_t offset);
DECLARE_WRITE_LINE_MEMBER(irq_w) { m_out_irq_cb(state); }
DECLARE_WRITE_LINE_MEMBER(nmi_w) { m_out_nmi_cb(state); }
DECLARE_WRITE_LINE_MEMBER(so_w) { m_out_so_cb(state); }
// pgm board has additional cable to fully decode the character generator
void pgm_w(offs_t offset, uint8_t data) { m_out_pgm_cb(offset, data); }
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
private:
// internal state
devcb_write_line m_out_irq_cb;
devcb_write_line m_out_nmi_cb;
devcb_write_line m_out_so_cb;
devcb_write8 m_out_pgm_cb;
uint8_t m_block_register;
int m_inhrom;
int m_inhram;
int m_block_enable;
simple_list<device_tanbus_interface> m_device_list;
};
// device type definition
DECLARE_DEVICE_TYPE(TANBUS, tanbus_device)
// ======================> device_tanbus_interface
class device_tanbus_interface : public device_slot_card_interface
{
friend class tanbus_device;
template <class ElementType> friend class simple_list;
public:
device_tanbus_interface *next() const { return m_next; }
// bus access
virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) { return 0xff; }
virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) { }
virtual void set_inhibit_lines(offs_t offset, int &inhram, int &inhrom) { };
protected:
device_tanbus_interface(const machine_config &mconfig, device_t &device);
tanbus_device *m_tanbus;
int m_page;
private:
device_tanbus_interface *m_next;
};
void tanex_devices(device_slot_interface &device);
void tanbus_devices(device_slot_interface &device);
void tanbus6809_devices(device_slot_interface &device);
typedef device_type_iterator<tanbus_slot_device> tanbus_slot_device_iterator;
#endif // MAME_BUS_TANBUS_TANBUS_H

View File

@ -0,0 +1,254 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Tangerine TANDOS (MT0078)
http://www.microtan.ukpc.net/pageProducts.html#DOS
**********************************************************************/
#include "emu.h"
#include "tandos.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(TANBUS_TANDOS, tanbus_tandos_device, "tanbus_tandos", "Tangerine Tandos Board")
//-------------------------------------------------
// SLOT_INTERFACE( tandos_floppies )
//-------------------------------------------------
static void tandos_floppies(device_slot_interface &device)
{
device.option_add("525sssd", FLOPPY_525_SSSD);
device.option_add("525sd", FLOPPY_525_SD);
device.option_add("525qd", FLOPPY_525_QD);
}
//-------------------------------------------------
// ROM( tandos )
//-------------------------------------------------
ROM_START(tandos)
ROM_REGION(0x1000, "dos_rom", 0)
ROM_DEFAULT_BIOS("step30")
ROM_SYSTEM_BIOS(0, "step30", "30ms Stepping Rate")
ROMX_LOAD("tandos_sr30.f2", 0x0000, 0x1000, CRC(54f55771) SHA1(5a801039fa8c05cd9227e9138469959524516c9e), ROM_BIOS(0))
ROM_SYSTEM_BIOS(1, "step6", "6ms Stepping Rate")
ROMX_LOAD("tandos_sr6.f2", 0x0000, 0x1000, CRC(10ef90fa) SHA1(b1e42cbf7197e693073d2578561803ea4c8efa8c), ROM_BIOS(1))
ROM_END
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void tanbus_tandos_device::device_add_mconfig(machine_config &config)
{
FD1793(config, m_fdc, 8_MHz_XTAL / 8);
m_fdc->intrq_wr_callback().set(FUNC(tanbus_tandos_device::fdc_irq_w));
m_fdc->drq_wr_callback().set(FUNC(tanbus_tandos_device::fdc_drq_w));
m_fdc->hld_wr_callback().set(FUNC(tanbus_tandos_device::fdc_hld_w));
m_fdc->set_force_ready(true);
FLOPPY_CONNECTOR(config, m_floppies[0], tandos_floppies, "525qd", floppy_image_device::default_floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, m_floppies[1], tandos_floppies, "525qd", floppy_image_device::default_floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, m_floppies[2], tandos_floppies, nullptr, floppy_image_device::default_floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, m_floppies[3], tandos_floppies, nullptr, floppy_image_device::default_floppy_formats).enable_sound(true);
}
const tiny_rom_entry *tanbus_tandos_device::device_rom_region() const
{
return ROM_NAME(tandos);
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// tanbus_tandos_device - constructor
//-------------------------------------------------
tanbus_tandos_device::tanbus_tandos_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TANBUS_TANDOS, tag, owner, clock)
, device_tanbus_interface(mconfig, *this)
, m_dos_rom(*this, "dos_rom")
, m_fdc(*this, "fdc")
, m_floppies(*this, "fdc:%u", 0)
, m_floppy(nullptr)
, m_drive_control(0)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tanbus_tandos_device::device_start()
{
m_ram = std::make_unique<uint8_t[]>(0x0400);
save_pointer(NAME(m_ram), 0x0400);
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void tanbus_tandos_device::device_reset()
{
// reset floppy control register
control_w(0);
}
//-------------------------------------------------
// read - card read
//-------------------------------------------------
uint8_t tanbus_tandos_device::read(offs_t offset, int inhrom, int inhram, int be)
{
uint8_t data = 0xff;
switch (offset & 0xfc00)
{
case 0xa800: case 0xac00: case 0xb000: case 0xb400:
data = m_dos_rom->base()[offset & 0x0fff];
break;
case 0xb800:
data = m_ram[offset & 0x03ff];
break;
default:
switch (offset)
{
case 0xbf90: case 0xbf91: case 0xbf92: case 0xbf93:
data = m_fdc->read(offset & 0x03);
break;
case 0xbf94: case 0xbf96:
data = status_r();
break;
case 0xbf95: case 0xbf97:
// GPIB PCB Switches
break;
case 0xbf98: case 0xbf99: case 0xbf9a: case 0xbf9b: case 0xbf9c: case 0xbf9d: case 0xbf9e: case 0xbf9f:
// GPIB (9914)
break;
}
break;
}
return data;
}
//-------------------------------------------------
// write - card write
//-------------------------------------------------
void tanbus_tandos_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
{
switch (offset & 0xfc00)
{
case 0xb800:
m_ram[offset & 0x03ff] = data;
break;
default:
switch (offset)
{
case 0xbf90: case 0xbf91: case 0xbf92: case 0xbf93:
m_fdc->write(offset & 0x03, data);
break;
case 0xbf94: case 0xbf96:
control_w(data);
break;
case 0xbf98: case 0xbf99: case 0xbf9a: case 0xbf9b: case 0xbf9c: case 0xbf9d: case 0xbf9e: case 0xbf9f:
// GPIB (9914)
break;
}
break;
}
}
//-------------------------------------------------
// set_inhibit_lines
//-------------------------------------------------
void tanbus_tandos_device::set_inhibit_lines(offs_t offset, int &inhram, int &inhrom)
{
if (offset >= 0xa800 && offset < 0xbc00)
{
inhram = 1;
inhrom = 1;
}
};
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
void tanbus_tandos_device::control_w(uint8_t data)
{
logerror("control_w %02x\n", data);
m_drive_control = data;
// bit 0: irq enable
m_irq_enable = BIT(data, 0);
// bit 1: data select (data stream controller)
// bit 2, 3: drive select
m_floppy = m_floppies[(data >> 2) & 0x03]->get_device();
m_fdc->set_floppy(m_floppy);
// bit 4: side select
if (m_floppy)
m_floppy->ss_w(BIT(data, 4));
// bit 5: density
m_fdc->dden_w(BIT(data, 5));
// bit 6: head load timing
m_fdc->hlt_w(BIT(data, 6));
if (m_floppy)
m_floppy->mon_w(!BIT(data, 6));
// bit 7: drq enable
m_drq_enable = BIT(data, 7);
}
uint8_t tanbus_tandos_device::status_r()
{
uint8_t data = 0x00;
data |= m_drive_control & 0x3c;
data |= m_fdc->intrq_r() << 0;
data |= m_fdc->hld_r() << 6;
data |= m_fdc->drq_r() << 7;
return data;
}
WRITE_LINE_MEMBER(tanbus_tandos_device::fdc_drq_w)
{
m_tanbus->so_w((m_drq_enable && state) ? ASSERT_LINE : CLEAR_LINE);
}
WRITE_LINE_MEMBER(tanbus_tandos_device::fdc_irq_w)
{
m_tanbus->irq_w((m_irq_enable && state) ? ASSERT_LINE : CLEAR_LINE);
}
WRITE_LINE_MEMBER(tanbus_tandos_device::fdc_hld_w)
{
logerror("fdc_hld_w %d\n", state);
if (m_floppy)
m_floppy->mon_w(state);
}

View File

@ -0,0 +1,72 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Tangerine TANDOS (MT0078)
**********************************************************************/
#ifndef MAME_BUS_TANBUS_TANDOS_H
#define MAME_BUS_TANBUS_TANDOS_H
#pragma once
#include "bus/tanbus/tanbus.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class tanbus_tandos_device :
public device_t,
public device_tanbus_interface
{
public:
static constexpr feature_type imperfect_features() { return feature::DISK; }
// construction/destruction
tanbus_tandos_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_FLOPPY_FORMATS(floppy_formats);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) override;
virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
virtual void set_inhibit_lines(offs_t offset, int &inhram, int &inhrom) override;
private:
void control_w(uint8_t val);
uint8_t status_r();
DECLARE_WRITE_LINE_MEMBER(fdc_irq_w);
DECLARE_WRITE_LINE_MEMBER(fdc_drq_w);
DECLARE_WRITE_LINE_MEMBER(fdc_hld_w);
required_memory_region m_dos_rom;
required_device<fd1793_device> m_fdc;
required_device_array<floppy_connector, 4> m_floppies;
floppy_image_device *m_floppy;
uint8_t m_drive_control;
int m_irq_enable;
int m_drq_enable;
std::unique_ptr<uint8_t[]> m_ram;
};
// device type definition
DECLARE_DEVICE_TYPE(TANBUS_TANDOS, tanbus_tandos_device)
#endif // MAME_BUS_TANBUS_TANDOS_H

View File

@ -0,0 +1,436 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Tangerine TANEX (MT002 Iss2)
http://www.microtan.ukpc.net/pageProducts.html#TANEX
This emulates the Tanex board with additional H2 and E2 expansion
boards. The expansion boards are pre-populated with commonly used
language and toolkit ROMs that can be selected in Machine
Configuration.
Alternatively, the expansion boards can be overridden and any
selection of ROMs can be inserted into five ROM sockets
**********************************************************************/
#include "emu.h"
#include "tanex.h"
#include "speaker.h"
//#define VERBOSE 1
#include "logmacro.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(TANBUS_TANEX, tanbus_tanex_device, "tanbus_tanex", "Tangerine Tanex Board")
//-------------------------------------------------
// INPUT_PORTS( tanex )
//-------------------------------------------------
static INPUT_PORTS_START(tanex)
PORT_START("CONFIG")
PORT_CONFNAME(0x0f, 0x00, "H2 Extension Eprom Board")
PORT_CONFSETTING(0x00, "Microsoft BASIC [GE2ED]")
PORT_CONFSETTING(0x01, "Microtanic FORTH [GC000]")
PORT_CONFSETTING(0x02, "2-Pass Assembler [GC000]")
PORT_CONFNAME(0xf0, 0x00, "E2 Extension Eprom Board")
PORT_CONFSETTING(0x00, "Toolkit")
PORT_CONFSETTING(0x10, "HRG Toolkit (TANHRG)")
PORT_CONFSETTING(0x20, "Video 80/82 Toolkit (VID8082)")
PORT_CONFSETTING(0x30, "PGM Toolkit (TUGPGM)")
PORT_START("JOY") // VIA #1 PORT A
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_BUTTON1)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_BUTTON2)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_4WAY
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_4WAY
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_4WAY
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_4WAY
INPUT_PORTS_END
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
ioport_constructor tanbus_tanex_device::device_input_ports() const
{
return INPUT_PORTS_NAME(tanex);
}
//-------------------------------------------------
// ROM( tanex )
//-------------------------------------------------
ROM_START(tanex)
ROM_REGION(0x3800, "rom_tanex", 0)
/* tanex - default configuration */
ROM_LOAD("basl.j2", 0x0000, 0x1000, CRC(3e09d384) SHA1(15a98941a672ff16242cc73f1dcf1d81fccd8910))
ROM_LOAD("basm.h2", 0x1000, 0x1000, CRC(75105113) SHA1(c6fea4d65b7c52f43aa1589cace9467349a0f290))
ROM_LOAD("bash.d3", 0x2000, 0x0800, CRC(ee6e8412) SHA1(7e1bca84bab79d94a4ab8554d23e2bc28ccd0384))
ROM_LOAD("toolkit.e2", 0x2800, 0x0800, CRC(bd87fd34) SHA1(f41895df4a733dddfaf1c89ecff5040addcab804))
ROM_LOAD("xbug.g2", 0x3000, 0x0800, CRC(4a875dda) SHA1(9f2626e09e7604ae6e8aa55c4f3a8ace3667348b))
/* eprom extension board - h2 */
ROM_REGION(0x5000, "rom_h2", 0)
ROM_LOAD("basl.j2", 0x0000, 0x1000, CRC(3e09d384) SHA1(15a98941a672ff16242cc73f1dcf1d81fccd8910))
ROM_LOAD("basm.h2", 0x1000, 0x1000, CRC(75105113) SHA1(c6fea4d65b7c52f43aa1589cace9467349a0f290))
ROM_LOAD("fforth.j2", 0x2000, 0x1000, CRC(18c8e389) SHA1(3201c90d8183e49b8ca683dcc383278b31683297))
ROM_LOAD("fforth.h2", 0x3000, 0x1000, CRC(b1869543) SHA1(b82900f40de52beb5a4ea12abb8eaaf55665cf01))
ROM_LOAD("assem12.j2", 0x4000, 0x1000, CRC(5d0cf5ec) SHA1(8832964eb647b5bf3fe954e52218ed27cf885667))
/* eprom extension board - e2 */
ROM_REGION(0x2000, "rom_e2", 0)
ROM_LOAD("toolkit.e2", 0x0000, 0x0800, CRC(bd87fd34) SHA1(f41895df4a733dddfaf1c89ecff5040addcab804))
ROM_LOAD("hrgtkt.e2", 0x0800, 0x0800, CRC(592c13de) SHA1(544c2a3d58f07dfaa90f022f059129d6b8b659d6))
ROM_LOAD("vdutkt.e2", 0x1000, 0x0800, CRC(068cbb9e) SHA1(38d99c23966b69440c8498c342a1486741f4d817))
ROM_LOAD("pgmtkt.e2", 0x1800, 0x0800, CRC(340f6ddd) SHA1(93d205ffb07a339f801b9aa9469e069de321c41c))
ROM_END
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void tanbus_tanex_device::device_add_mconfig(machine_config &config)
{
INPUT_MERGER_ANY_HIGH(config, m_irq_line).output_handler().set(FUNC(tanbus_tanex_device::bus_irq_w));
/* acia */
MOS6551(config, m_acia, 0);
m_acia->set_xtal(1.8432_MHz_XTAL);
m_acia->txd_handler().set(m_rs232, FUNC(rs232_port_device::write_txd));
m_acia->rts_handler().set(m_rs232, FUNC(rs232_port_device::write_rts));
m_acia->dtr_handler().set(m_rs232, FUNC(rs232_port_device::write_dtr));
m_acia->irq_handler().set(m_irq_line, FUNC(input_merger_device::in_w<IRQ_ACIA>));
RS232_PORT(config, m_rs232, default_rs232_devices, nullptr);
m_rs232->rxd_handler().set(m_acia, FUNC(mos6551_device::write_rxd));
m_rs232->dcd_handler().set(m_acia, FUNC(mos6551_device::write_dcd));
m_rs232->dsr_handler().set(m_acia, FUNC(mos6551_device::write_dsr));
m_rs232->cts_handler().set(m_acia, FUNC(mos6551_device::write_cts));
/* via */
VIA6522(config, m_via6522[0], DERIVED_CLOCK(1, 8));
m_via6522[0]->readpa_handler().set(FUNC(tanbus_tanex_device::via_0_in_a));
m_via6522[0]->writepa_handler().set(FUNC(tanbus_tanex_device::via_0_out_a));
m_via6522[0]->writepb_handler().set(FUNC(tanbus_tanex_device::via_0_out_b));
m_via6522[0]->ca2_handler().set(FUNC(tanbus_tanex_device::via_0_out_ca2));
m_via6522[0]->cb2_handler().set(FUNC(tanbus_tanex_device::via_0_out_cb2));
m_via6522[0]->irq_handler().set(m_irq_line, FUNC(input_merger_device::in_w<IRQ_VIA_0>));
VIA6522(config, m_via6522[1], DERIVED_CLOCK(1, 8));
m_via6522[1]->writepa_handler().set(FUNC(tanbus_tanex_device::via_1_out_a));
m_via6522[1]->writepb_handler().set(FUNC(tanbus_tanex_device::via_1_out_b));
m_via6522[1]->ca2_handler().set(FUNC(tanbus_tanex_device::via_1_out_ca2));
m_via6522[1]->cb2_handler().set(FUNC(tanbus_tanex_device::via_1_out_cb2));
m_via6522[1]->irq_handler().set(m_irq_line, FUNC(input_merger_device::in_w<IRQ_VIA_1>));
/* sound hardware */
SPEAKER(config, "speaker").front_center();
/* cassette */
CASSETTE(config, m_cassette);
m_cassette->add_route(ALL_OUTPUTS, "speaker", 0.05);
m_cassette->set_default_state(CASSETTE_STOPPED);
m_cassette->set_interface("mt65_cass");
TIMER(config, "read_cassette").configure_periodic(FUNC(tanbus_tanex_device::read_cassette), attotime::from_hz(20000));
/* 4K sockets */
GENERIC_SOCKET(config, m_rom[0], generic_linear_slot, "rom_c000", "bin,rom");
GENERIC_SOCKET(config, m_rom[1], generic_linear_slot, "rom_d000", "bin,rom");
/* 2K sockets */
GENERIC_SOCKET(config, m_rom[2], generic_linear_slot, "rom_e000", "bin,rom");
GENERIC_SOCKET(config, m_rom[3], generic_linear_slot, "rom_e800", "bin,rom");
GENERIC_SOCKET(config, m_rom[4], generic_linear_slot, "rom_f000", "bin,rom");
}
const tiny_rom_entry *tanbus_tanex_device::device_rom_region() const
{
return ROM_NAME(tanex);
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// tanbus_tanex_device - constructor
//-------------------------------------------------
tanbus_tanex_device::tanbus_tanex_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TANBUS_TANEX, tag, owner, clock)
, device_tanbus_interface(mconfig, *this)
, m_rom_tanex(*this, "rom_tanex")
, m_rom_h2(*this, "rom_h2")
, m_rom_e2(*this, "rom_e2")
, m_rom(*this, "rom%u", 0)
, m_cassette(*this, "cassette")
, m_acia(*this, "acia")
, m_rs232(*this, "rs232")
, m_via6522(*this, "via6522%u", 0)
, m_irq_line(*this, "irq_line")
, m_config(*this, "CONFIG")
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tanbus_tanex_device::device_start()
{
m_ram = std::make_unique<uint8_t[]>(0x1c00);
save_pointer(NAME(m_ram), 0x1c00);
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void tanbus_tanex_device::device_reset()
{
m_via6522[0]->write_ca1(1);
m_via6522[0]->write_ca2(1);
m_via6522[0]->write_pb(0xff);
m_via6522[0]->write_cb1(1);
m_via6522[0]->write_cb2(1);
m_via6522[1]->write_pa(0xff);
m_via6522[1]->write_ca1(1);
m_via6522[1]->write_ca2(1);
m_via6522[1]->write_pb(0xff);
m_via6522[1]->write_cb1(1);
m_via6522[1]->write_cb2(1);
}
//-------------------------------------------------
// read - card read
//-------------------------------------------------
uint8_t tanbus_tanex_device::read(offs_t offset, int inhrom, int inhram, int be)
{
uint8_t data = 0xff;
/* 7K static ram */
if ((offset >= 0x0400) && (offset < 0x2000))
{
data = m_ram[offset - 0x0400];
}
/* IO */
switch (offset & 0xfff0)
{
case 0xbfc0:
data = m_via6522[0]->read(offset & 0x0f);
break;
case 0xbfd0:
data = m_acia->read(offset & 0x03);
break;
case 0xbfe0:
data = m_via6522[1]->read(offset & 0x0f);
break;
}
/* tanex default rom 0xc000-0xf7ff */
if ((offset >= 0xc000) && (offset < 0xf800))
{
data = m_rom_tanex->base()[offset & 0x3fff];
}
/* H2 extension eprom board 0xc000-0xdfff */
if ((offset & 0xe000) == 0xc000)
{
if (m_rom[0]->exists() || m_rom[1]->exists())
{
if ((offset & 0xf000) == 0xc000)
data = m_rom[0]->read_rom(offset & 0x0fff);
else
data = m_rom[1]->read_rom(offset & 0x0fff);
}
else
{
switch (m_config->read() & 0x0f)
{
case 0x00:
data = m_rom_h2->base()[offset & 0x1fff];
break;
case 0x01:
data = m_rom_h2->base()[(offset & 0x1fff) + 0x2000];
break;
case 0x02:
data = m_rom_h2->base()[(offset & 0x0fff) + 0x4000];
break;
}
}
}
/* D3 0xe000-0e7ff */
if ((offset & 0xf800) == 0xe000)
{
if (m_rom[2]->exists())
{
data = m_rom[2]->read_rom(offset & 0x07ff);
}
}
/* E2 extension eprom board 0xe800-0efff */
if ((offset & 0xf800) == 0xe800)
{
if (m_rom[3]->exists())
{
data = m_rom[3]->read_rom(offset & 0x07ff);
}
else
{
switch (m_config->read() & 0xf0)
{
case 0x00:
data = m_rom_e2->base()[offset & 0x07ff];
break;
case 0x10:
data = m_rom_e2->base()[(offset & 0x07ff) + 0x0800];
break;
case 0x20:
data = m_rom_e2->base()[(offset & 0x07ff) + 0x1000];
break;
case 0x30:
data = m_rom_e2->base()[(offset & 0x07ff) + 0x1800];
break;
}
}
}
/* G2 0xf000-0f7ff */
if ((offset & 0xf800) == 0xf000)
{
if (m_rom[4]->exists())
{
data = m_rom[4]->read_rom(offset & 0x07ff);
}
}
return data;
}
//-------------------------------------------------
// write - card write
//-------------------------------------------------
void tanbus_tanex_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
{
/* 7K static ram */
if ((offset >= 0x0400) && (offset < 0x2000))
{
m_ram[offset - 0x0400] = data;
}
/* IO */
switch (offset & 0xfff0)
{
case 0xbfc0:
m_via6522[0]->write(offset & 0x0f, data);
break;
case 0xbfd0:
m_acia->write(offset & 0x03, data);
break;
case 0xbfe0:
m_via6522[1]->write(offset & 0x0f, data);
break;
}
}
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
TIMER_DEVICE_CALLBACK_MEMBER(tanbus_tanex_device::read_cassette)
{
double level = m_cassette->input();
LOG("read_cassette: %g\n", level);
if (level < -0.07)
m_via6522[0]->write_cb2(0);
else if (level > +0.07)
m_via6522[0]->write_cb2(1);
}
WRITE_LINE_MEMBER(tanbus_tanex_device::bus_so_w)
{
m_tanbus->so_w(state);
}
WRITE_LINE_MEMBER(tanbus_tanex_device::bus_irq_w)
{
m_tanbus->irq_w(state);
}
//**************************************************************
// VIA callback functions for VIA #0
//**************************************************************
READ8_MEMBER(tanbus_tanex_device::via_0_in_a)
{
int data = ioport("JOY")->read();
LOG("via_0_in_a %02X\n", data);
return data;
}
WRITE8_MEMBER(tanbus_tanex_device::via_0_out_a)
{
LOG("via_0_out_a %02X\n", data);
}
WRITE8_MEMBER(tanbus_tanex_device::via_0_out_b)
{
LOG("via_0_out_b %02X\n", data);
/* bit #5 is the replay cassette drive */
/* bit #6 is the record cassette drive */
/* bit #7 is the cassette output signal */
m_cassette->output(data & 0x80 ? +1.0 : -1.0);
}
WRITE_LINE_MEMBER(tanbus_tanex_device::via_0_out_ca2)
{
LOG("via_0_out_ca2 %d\n", state);
}
WRITE_LINE_MEMBER(tanbus_tanex_device::via_0_out_cb2)
{
LOG("via_0_out_cb2 %d\n", state);
}
//**************************************************************
// VIA callback functions for VIA #1
//**************************************************************
WRITE8_MEMBER(tanbus_tanex_device::via_1_out_a)
{
LOG("via_1_out_a %02X\n", data);
}
WRITE8_MEMBER(tanbus_tanex_device::via_1_out_b)
{
LOG("via_1_out_b %02X\n", data);
}
WRITE_LINE_MEMBER(tanbus_tanex_device::via_1_out_ca2)
{
LOG("via_1_out_ca2 %d\n", state);
}
WRITE_LINE_MEMBER(tanbus_tanex_device::via_1_out_cb2)
{
LOG("via_1_out_cb2 %d\n", state);
}

View File

@ -0,0 +1,86 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Tangerine TANEX (MT002 Iss2)
**********************************************************************/
#ifndef MAME_BUS_TANBUS_TANEX_H
#define MAME_BUS_TANBUS_TANEX_H
#pragma once
#include "bus/tanbus/tanbus.h"
#include "bus/generic/slot.h"
#include "bus/generic/carts.h"
#include "bus/rs232/rs232.h"
#include "machine/6522via.h"
#include "machine/mos6551.h"
#include "machine/input_merger.h"
#include "machine/timer.h"
#include "imagedev/cassette.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class tanbus_tanex_device :
public device_t,
public device_tanbus_interface
{
public:
// construction/destruction
tanbus_tanex_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() 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 read(offs_t offset, int inhrom, int inhram, int be) override;
virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
private:
enum { IRQ_VIA_0, IRQ_VIA_1, IRQ_ACIA };
DECLARE_WRITE_LINE_MEMBER(bus_irq_w);
DECLARE_WRITE_LINE_MEMBER(bus_so_w);
TIMER_DEVICE_CALLBACK_MEMBER(read_cassette);
DECLARE_READ8_MEMBER(via_0_in_a);
DECLARE_WRITE8_MEMBER(via_0_out_a);
DECLARE_WRITE8_MEMBER(via_0_out_b);
DECLARE_WRITE_LINE_MEMBER(via_0_out_ca2);
DECLARE_WRITE_LINE_MEMBER(via_0_out_cb2);
DECLARE_WRITE8_MEMBER(via_1_out_a);
DECLARE_WRITE8_MEMBER(via_1_out_b);
DECLARE_WRITE_LINE_MEMBER(via_1_out_ca2);
DECLARE_WRITE_LINE_MEMBER(via_1_out_cb2);
required_memory_region m_rom_tanex;
required_memory_region m_rom_h2;
required_memory_region m_rom_e2;
required_device_array<generic_slot_device, 5> m_rom;
required_device<cassette_image_device> m_cassette;
required_device<mos6551_device> m_acia;
required_device<rs232_port_device> m_rs232;
required_device_array<via6522_device, 2> m_via6522;
required_device<input_merger_device> m_irq_line;
required_ioport m_config;
std::unique_ptr<uint8_t[]> m_ram;
emu_timer *m_read_cassette_timer;
};
// device type definition
DECLARE_DEVICE_TYPE(TANBUS_TANEX, tanbus_tanex_device)
#endif // MAME_BUS_TANBUS_TANEX_H

View File

@ -0,0 +1,368 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Tangerine High Resolution Graphics Card (MT0055 Iss2)
http://www.microtan.ukpc.net/pageProducts.html#VIDEO
TODO:
- option to merge MT65 chunky and HRG screens
**********************************************************************/
#include "emu.h"
#include "tanhrg.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(TANBUS_TANHRG, tanbus_tanhrg_device, "tanbus_tanhrg", "Tangerine High Resolution Graphics Card (monochrome)")
DEFINE_DEVICE_TYPE(TANBUS_TANHRGC, tanbus_tanhrgc_device, "tanbus_tanhrgc", "Tangerine High Resolution Graphics Card (colour)")
//-------------------------------------------------
// INPUT_PORTS( tanhrg )
//-------------------------------------------------
INPUT_PORTS_START(tanhrg)
PORT_START("DSW")
PORT_DIPNAME(0x07, 0x04, "Address Space") PORT_DIPLOCATION("DSW:1,2,3")
PORT_DIPSETTING(0x00, "&0000-&1FFF (Invalid - Do Not Use)")
PORT_DIPSETTING(0x01, "&2000-&3FFF")
PORT_DIPSETTING(0x02, "&4000-&5FFF")
PORT_DIPSETTING(0x03, "&6000-&7FFF")
PORT_DIPSETTING(0x04, "&8000-&9FFF")
PORT_DIPSETTING(0x05, "&A000-&BFFF (Invalid - Do Not Use)")
PORT_DIPSETTING(0x06, "&C000-&DFFF")
PORT_DIPSETTING(0x07, "&E000-&FFFF")
PORT_DIPNAME(0x08, 0x00, "Video") PORT_DIPLOCATION("DSW:4")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x08, DEF_STR(On))
PORT_DIPNAME(0x10, 0x10, "Inhibit RAM (INHRAM)") PORT_DIPLOCATION("DSW:5")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x10, DEF_STR(On))
PORT_DIPNAME(0x20, 0x20, "Block Enable (BE)") PORT_DIPLOCATION("DSW:6")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x20, DEF_STR(On))
INPUT_PORTS_END
INPUT_PORTS_START(tanhrgc)
PORT_START("DSW_1")
PORT_DIPNAME(0x07, 0x02, "Address Space - Red") PORT_DIPLOCATION("DSW_R:1,2,3")
PORT_DIPSETTING(0x00, "&0000-&1FFF (Invalid - Do Not Use)")
PORT_DIPSETTING(0x01, "&2000-&3FFF")
PORT_DIPSETTING(0x02, "&4000-&5FFF")
PORT_DIPSETTING(0x03, "&6000-&7FFF")
PORT_DIPSETTING(0x04, "&8000-&9FFF")
PORT_DIPSETTING(0x05, "&A000-&BFFF (Invalid - Do Not Use)")
PORT_DIPSETTING(0x06, "&C000-&DFFF")
PORT_DIPSETTING(0x07, "&E000-&FFFF")
PORT_DIPNAME(0x08, 0x00, "Video") PORT_DIPLOCATION("DSW_R:4")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x08, DEF_STR(On))
PORT_DIPNAME(0x10, 0x10, "Inhibit RAM (INHRAM)") PORT_DIPLOCATION("DSW_R:5")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x10, DEF_STR(On))
PORT_DIPNAME(0x20, 0x20, "Block Enable (BE)") PORT_DIPLOCATION("DSW_R:6")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x20, DEF_STR(On))
PORT_START("DSW_2")
PORT_DIPNAME(0x07, 0x04, "Address Space - Green") PORT_DIPLOCATION("DSW_G:1,2,3")
PORT_DIPSETTING(0x00, "&0000-&1FFF (Invalid - Do Not Use)")
PORT_DIPSETTING(0x01, "&2000-&3FFF")
PORT_DIPSETTING(0x02, "&4000-&5FFF")
PORT_DIPSETTING(0x03, "&6000-&7FFF")
PORT_DIPSETTING(0x04, "&8000-&9FFF")
PORT_DIPSETTING(0x05, "&A000-&BFFF (Invalid - Do Not Use)")
PORT_DIPSETTING(0x06, "&C000-&DFFF")
PORT_DIPSETTING(0x07, "&E000-&FFFF")
PORT_DIPNAME(0x08, 0x00, "Video") PORT_DIPLOCATION("DSW_G:4")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x08, DEF_STR(On))
PORT_DIPNAME(0x10, 0x10, "Inhibit RAM (INHRAM)") PORT_DIPLOCATION("DSW_G:5")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x10, DEF_STR(On))
PORT_DIPNAME(0x20, 0x20, "Block Enable (BE)") PORT_DIPLOCATION("DSW_G:6")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x20, DEF_STR(On))
PORT_START("DSW_3")
PORT_DIPNAME(0x07, 0x03, "Address Space - Blue") PORT_DIPLOCATION("DSW_B:1,2,3")
PORT_DIPSETTING(0x00, "&0000-&1FFF (Invalid - Do Not Use)")
PORT_DIPSETTING(0x01, "&2000-&3FFF")
PORT_DIPSETTING(0x02, "&4000-&5FFF")
PORT_DIPSETTING(0x03, "&6000-&7FFF")
PORT_DIPSETTING(0x04, "&8000-&9FFF")
PORT_DIPSETTING(0x05, "&A000-&BFFF (Invalid - Do Not Use)")
PORT_DIPSETTING(0x06, "&C000-&DFFF")
PORT_DIPSETTING(0x07, "&E000-&FFFF")
PORT_DIPNAME(0x08, 0x00, "Video") PORT_DIPLOCATION("DSW_B:4")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x08, DEF_STR(On))
PORT_DIPNAME(0x10, 0x10, "Inhibit RAM (INHRAM)") PORT_DIPLOCATION("DSW_B:5")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x10, DEF_STR(On))
PORT_DIPNAME(0x20, 0x20, "Block Enable (BE)") PORT_DIPLOCATION("DSW_B:6")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x20, DEF_STR(On))
INPUT_PORTS_END
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
ioport_constructor tanbus_tanhrg_device::device_input_ports() const
{
return INPUT_PORTS_NAME(tanhrg);
}
ioport_constructor tanbus_tanhrgc_device::device_input_ports() const
{
return INPUT_PORTS_NAME(tanhrgc);
}
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void tanbus_tanhrg_device::device_add_mconfig(machine_config &config)
{
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(6_MHz_XTAL, 384, 0, 256, 312, 0, 256);
m_screen->set_screen_update(FUNC(tanbus_tanhrg_device::screen_update));
PALETTE(config, m_palette, palette_device::MONOCHROME);
}
void tanbus_tanhrgc_device::device_add_mconfig(machine_config &config)
{
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_raw(6_MHz_XTAL, 384, 0, 256, 312, 0, 256);
m_screen->set_screen_update(FUNC(tanbus_tanhrgc_device::screen_update));
PALETTE(config, m_palette, palette_device::RGB_3BIT);
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// tanbus_tanhrg_device - constructor
//-------------------------------------------------
tanbus_tanhrg_device::tanbus_tanhrg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TANBUS_TANHRG, tag, owner, clock)
, device_tanbus_interface(mconfig, *this)
, m_dsw(*this, "DSW")
, m_screen(*this, "screen")
, m_palette(*this, "palette")
{
}
tanbus_tanhrgc_device::tanbus_tanhrgc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TANBUS_TANHRGC, tag, owner, clock)
, device_tanbus_interface(mconfig, *this)
, m_dsw(*this, "DSW_%u", 1)
, m_screen(*this, "screen")
, m_palette(*this, "palette")
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tanbus_tanhrg_device::device_start()
{
m_videoram = std::make_unique<uint8_t[]>(0x2000);
/* randomize video memory contents */
for (uint16_t addr = 0; addr < 0x2000; addr++)
m_videoram[addr] = machine().rand() & 0xff;
save_pointer(NAME(m_videoram), 0x2000);
}
void tanbus_tanhrgc_device::device_start()
{
m_videoram = std::make_unique<uint8_t[]>(0x6000);
/* randomize video memory contents */
for (uint16_t addr = 0; addr < 0x6000; addr++)
m_videoram[addr] = machine().rand() & 0xff;
save_pointer(NAME(m_videoram), 0x6000);
}
//-------------------------------------------------
// read - card read
//-------------------------------------------------
uint8_t tanbus_tanhrg_device::read(offs_t offset, int inhrom, int inhram, int be)
{
uint8_t data = 0xff;
offs_t addr = (m_dsw->read() & 7) << 13;
if ((!BIT(m_dsw->read(), 5) || be) && (offset & 0xe000) == addr)
{
data = m_videoram[offset & 0x1fff];
}
return data;
}
uint8_t tanbus_tanhrgc_device::read(offs_t offset, int inhrom, int inhram, int be)
{
uint8_t data = 0xff;
offs_t addr_r = (m_dsw[0]->read() & 7) << 13;
offs_t addr_g = (m_dsw[1]->read() & 7) << 13;
offs_t addr_b = (m_dsw[2]->read() & 7) << 13;
if ((!BIT(m_dsw[0]->read(), 5) || be) && (offset & 0xe000) == addr_r)
{
data = m_videoram[0x0000 | (offset & 0x1fff)];
}
else if ((!BIT(m_dsw[1]->read(), 5) || be) && (offset & 0xe000) == addr_g)
{
data = m_videoram[0x2000 | (offset & 0x1fff)];
}
else if ((!BIT(m_dsw[2]->read(), 5) || be) && (offset & 0xe000) == addr_b)
{
data = m_videoram[0x4000 | (offset & 0x1fff)];
}
return data;
}
//-------------------------------------------------
// write - card write
//-------------------------------------------------
void tanbus_tanhrg_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
{
offs_t addr = (m_dsw->read() & 7) << 13;
if ((!BIT(m_dsw->read(), 5) || be) && (offset & 0xe000) == addr)
{
m_videoram[offset & 0x1fff] = data;
}
}
void tanbus_tanhrgc_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
{
offs_t addr_r = (m_dsw[0]->read() & 7) << 13;
offs_t addr_g = (m_dsw[1]->read() & 7) << 13;
offs_t addr_b = (m_dsw[2]->read() & 7) << 13;
if ((!BIT(m_dsw[0]->read(), 5) || be) && (offset & 0xe000) == addr_r)
{
m_videoram[0x0000 | (offset & 0x1fff)] = data;
}
else if ((!BIT(m_dsw[1]->read(), 5) || be) && (offset & 0xe000) == addr_g)
{
m_videoram[0x2000 | (offset & 0x1fff)] = data;
}
else if ((!BIT(m_dsw[2]->read(), 5) || be) && (offset & 0xe000) == addr_b)
{
m_videoram[0x4000 | (offset & 0x1fff)] = data;
}
}
//-------------------------------------------------
// set_inhibit_lines
//-------------------------------------------------
void tanbus_tanhrg_device::set_inhibit_lines(offs_t offset, int &inhram, int &inhrom)
{
offs_t addr = (m_dsw->read() & 7) << 13;
if (BIT(m_dsw->read(), 4) && (offset & 0xe000) == addr)
{
inhram = 1;
}
};
void tanbus_tanhrgc_device::set_inhibit_lines(offs_t offset, int &inhram, int &inhrom)
{
offs_t addr_r = (m_dsw[0]->read() & 7) << 13;
offs_t addr_g = (m_dsw[1]->read() & 7) << 13;
offs_t addr_b = (m_dsw[2]->read() & 7) << 13;
if ((BIT(m_dsw[0]->read(), 4) && (offset & 0xe000) == addr_r) || (BIT(m_dsw[1]->read(), 4) && (offset & 0xe000) == addr_g) || (BIT(m_dsw[2]->read(), 4) && (offset & 0xe000) == addr_b))
{
inhram = 1;
}
};
//-------------------------------------------------
// screen_update
//-------------------------------------------------
uint32_t tanbus_tanhrg_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
uint16_t offset;
uint32_t *p;
for (int y = 0; y < 256; y++)
{
p = &bitmap.pix32(y);
for (int x = 0; x < 256; x++)
{
offset = (y * 32) + (x / 8);
*p++ = m_palette->pen_color(BIT(m_videoram[offset], x & 7));
}
}
return 0;
}
uint32_t tanbus_tanhrgc_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
uint8_t r, g, b;
uint16_t offset;
uint32_t *p;
for (int y = 0; y < 256; y++)
{
p = &bitmap.pix32(y);
for (int x = 0; x < 256; x++)
{
offset = (y * 32) + (x / 8);
r = m_videoram[0x0000 | offset];
b = m_videoram[0x2000 | offset];
g = m_videoram[0x4000 | offset];
*p++ = m_palette->pen_color(BIT(b, x & 7) << 2 | BIT(g, x & 7) << 1 | BIT(r, x & 7));
}
}
return 0;
}

View File

@ -0,0 +1,90 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Tangerine High Resolution Graphics Card (MT0055 Iss2)
**********************************************************************/
#ifndef MAME_BUS_TANBUS_TANHRG_H
#define MAME_BUS_TANBUS_TANHRG_H
#pragma once
#include "bus/tanbus/tanbus.h"
#include "emupal.h"
#include "screen.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class tanbus_tanhrg_device :
public device_t,
public device_tanbus_interface
{
public:
// construction/destruction
tanbus_tanhrg_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// device-level overrides
virtual void device_start() override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const override;
virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) override;
virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
virtual void set_inhibit_lines(offs_t offset, int &inhram, int &inhrom) override;
private:
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
required_ioport m_dsw;
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
std::unique_ptr<uint8_t[]> m_videoram;
};
class tanbus_tanhrgc_device :
public device_t,
public device_tanbus_interface
{
public:
// construction/destruction
tanbus_tanhrgc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// device-level overrides
virtual void device_start() override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const override;
virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) override;
virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
virtual void set_inhibit_lines(offs_t offset, int &inhram, int &inhrom) override;
private:
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
required_ioport_array<3> m_dsw;
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
std::unique_ptr<uint8_t[]> m_videoram;
};
// device type definition
DECLARE_DEVICE_TYPE(TANBUS_TANHRG, tanbus_tanhrg_device)
DECLARE_DEVICE_TYPE(TANBUS_TANHRGC, tanbus_tanhrgc_device)
#endif // MAME_BUS_TANBUS_TANHRG_H

View File

@ -0,0 +1,93 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Tangerine TANRAM (MT013 Iss2)
http://www.microtan.ukpc.net/pageProducts.html#RAM
**********************************************************************/
#include "emu.h"
#include "tanram.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(TANBUS_TANRAM, tanbus_tanram_device, "tanbus_tanram", "Tangerine Tanram Board")
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// tanbus_tanram_device - constructor
//-------------------------------------------------
tanbus_tanram_device::tanbus_tanram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TANBUS_TANRAM, tag, owner, clock)
, device_tanbus_interface(mconfig, *this)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tanbus_tanram_device::device_start()
{
m_ram = std::make_unique<uint8_t[]>(0x9c00);
save_pointer(NAME(m_ram), 0x9c00);
}
//-------------------------------------------------
// read - card read
//-------------------------------------------------
uint8_t tanbus_tanram_device::read(offs_t offset, int inhrom, int inhram, int be)
{
uint8_t data = 0xff;
if (be && !inhram)
{
/* 32K dynamic ram */
if ((offset >= 0x2000) && (offset < 0xa000))
{
data = m_ram[offset - 0x2000];
}
/* 7K static ram */
if ((offset >= 0xa000) && (offset < 0xbc00))
{
data = m_ram[offset - 0xa000];
}
}
return data;
}
//-------------------------------------------------
// write - card write
//-------------------------------------------------
void tanbus_tanram_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
{
if (be && !inhram)
{
/* 32K dynamic ram */
if ((offset >= 0x2000) && (offset < 0xa000))
{
m_ram[offset - 0x2000] = data;
}
/* 7K static ram */
if ((offset >= 0xa000) && (offset < 0xbc00))
{
m_ram[offset - 0xa000] = data;
}
}
}

View File

@ -0,0 +1,45 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Tangerine TANRAM (MT013 Iss2)
**********************************************************************/
#ifndef MAME_BUS_TANBUS_TANRAM_H
#define MAME_BUS_TANBUS_TANRAM_H
#pragma once
#include "bus/tanbus/tanbus.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class tanbus_tanram_device :
public device_t,
public device_tanbus_interface
{
public:
// construction/destruction
tanbus_tanram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// device-level overrides
virtual void device_start() override;
virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) override;
virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
private:
std::unique_ptr<uint8_t[]> m_ram;
};
// device type definition
DECLARE_DEVICE_TYPE(TANBUS_TANRAM, tanbus_tanram_device)
#endif // MAME_BUS_TANBUS_TANRAM_H

View File

@ -0,0 +1,188 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
TUG 64K Dynamic RAM Board
http://www.microtan.ukpc.net/pageProducts.html#RAM
**********************************************************************/
#include "emu.h"
#include "tug64k.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(TANBUS_TUG64K, tanbus_tug64k_device, "tanbus_tug64k", "TUG 64K Dynamic RAM Board")
//-------------------------------------------------
// INPUT_PORTS( tug64k )
//-------------------------------------------------
INPUT_PORTS_START(tug64k)
PORT_START("SW1")
PORT_DIPNAME(0x01, 0x01, "Overlay Tanex RAM") PORT_DIPLOCATION("SW1:1")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x01, DEF_STR(On))
PORT_DIPNAME(0x02, 0x02, "Recognise INHRAM Signal") PORT_DIPLOCATION("SW1:2")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x02, DEF_STR(On))
PORT_DIPNAME(0x04, 0x04, "Recognise I/O Signal") PORT_DIPLOCATION("SW1:3")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x04, DEF_STR(On))
PORT_DIPNAME(0x08, 0x08, "Recognise Block Enable") PORT_DIPLOCATION("SW1:4")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x08, DEF_STR(On))
PORT_START("SW2")
PORT_DIPNAME(0x01, 0x00, "Disable RAM &C000-&C7FF") PORT_DIPLOCATION("SW2:1")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x01, DEF_STR(On))
PORT_DIPNAME(0x02, 0x00, "Disable RAM &C800-&CFFF") PORT_DIPLOCATION("SW2:2")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x02, DEF_STR(On))
PORT_DIPNAME(0x04, 0x00, "Disable RAM &D000-&D7FF") PORT_DIPLOCATION("SW2:3")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x04, DEF_STR(On))
PORT_DIPNAME(0x08, 0x00, "Disable RAM &D800-&DFFF") PORT_DIPLOCATION("SW2:4")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x08, DEF_STR(On))
PORT_DIPNAME(0x10, 0x00, "Disable RAM &E000-&E7FF") PORT_DIPLOCATION("SW2:5")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x10, DEF_STR(On))
PORT_DIPNAME(0x20, 0x00, "Disable RAM &E800-&EFFF") PORT_DIPLOCATION("SW2:6")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x20, DEF_STR(On))
PORT_DIPNAME(0x40, 0x00, "Disable RAM &F000-&F7FF") PORT_DIPLOCATION("SW2:7")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x40, DEF_STR(On))
PORT_DIPNAME(0x80, 0x00, "Not Used") PORT_DIPLOCATION("SW2:8")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x80, DEF_STR(On))
INPUT_PORTS_END
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
ioport_constructor tanbus_tug64k_device::device_input_ports() const
{
return INPUT_PORTS_NAME(tug64k);
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// tanbus_tug64k_device - constructor
//-------------------------------------------------
tanbus_tug64k_device::tanbus_tug64k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TANBUS_TUG64K, tag, owner, clock)
, device_tanbus_interface(mconfig, *this)
, m_dsw(*this, "SW%u", 1)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tanbus_tug64k_device::device_start()
{
m_ram = std::make_unique<uint8_t[]>(0x10000);
save_pointer(NAME(m_ram), 0x10000);
}
//-------------------------------------------------
// read - card read
//-------------------------------------------------
uint8_t tanbus_tug64k_device::read(offs_t offset, int inhrom, int inhram, int be)
{
uint8_t data = 0xff;
if (ram_enabled(offset, inhrom, inhram, be))
{
data = m_ram[offset];
}
return data;
}
//-------------------------------------------------
// write - card write
//-------------------------------------------------
void tanbus_tug64k_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
{
if (ram_enabled(offset, inhrom, inhram, be))
{
m_ram[offset] = data;
}
}
bool tanbus_tug64k_device::ram_enabled(offs_t offset, int inhrom, int inhram, int be)
{
/* overlay Tanex RAM */
if (!BIT(m_dsw[0]->read(), 0) && (offset >= 0x0400) && (offset < 0x2000))
return false;
/* recognise INHRAM signal */
if (BIT(m_dsw[0]->read(), 1) && inhram)
return false;
/* recognise I/O signal (should be a Tanex output) */
if (BIT(m_dsw[0]->read(), 2) && (offset & 0xfc00) == 0xbc00)
return false;
/* recognise Block Enable */
if (BIT(m_dsw[0]->read(), 3) && !be)
return false;
/* disable RAM locations */
switch (offset & 0xf800)
{
case 0xc000:
if (BIT(m_dsw[1]->read(), 0))
return false;
break;
case 0xc800:
if (BIT(m_dsw[1]->read(), 1))
return false;
break;
case 0xd000:
if (BIT(m_dsw[1]->read(), 2))
return false;
break;
case 0xd800:
if (BIT(m_dsw[1]->read(), 3))
return false;
break;
case 0xe000:
if (BIT(m_dsw[1]->read(), 4))
return false;
break;
case 0xe800:
if (BIT(m_dsw[1]->read(), 5))
return false;
break;
case 0xf000:
if (BIT(m_dsw[1]->read(), 6))
return false;
break;
case 0xf800:
return false;
break;
}
return true;
}

View File

@ -0,0 +1,51 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
TUG 64K Dynamic RAM Board
**********************************************************************/
#ifndef MAME_BUS_TANBUS_TUG64K_H
#define MAME_BUS_TANBUS_TUG64K_H
#pragma once
#include "bus/tanbus/tanbus.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class tanbus_tug64k_device :
public device_t,
public device_tanbus_interface
{
public:
// construction/destruction
tanbus_tug64k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// device-level overrides
virtual void device_start() override;
// optional information overrides
virtual ioport_constructor device_input_ports() const override;
virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) override;
virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
private:
required_ioport_array<2> m_dsw;
std::unique_ptr<uint8_t[]> m_ram;
bool ram_enabled(offs_t offset, int inhrom, int inhram, int be);
};
// device type definition
DECLARE_DEVICE_TYPE(TANBUS_TUG64K, tanbus_tug64k_device)
#endif // MAME_BUS_TANBUS_TUG64K_H

View File

@ -0,0 +1,263 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Microtanic Video 80/82 Board
http://www.microtan.ukpc.net/pageProducts.html#VIDEO
TODO:
- implement the communication between the 8212's
**********************************************************************/
#include "emu.h"
#include "tug8082.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(TANBUS_TUG8082, tanbus_tug8082_device, "tanbus_vid8082", "Microtanic Video 80/82 Board")
//-------------------------------------------------
// ADDRESS_MAP( vid8082_map )
//-------------------------------------------------
void tanbus_tug8082_device::vid8082_map(address_map &map)
{
map(0x0000, 0x07ff).ram();
map(0x4000, 0x7fff).ram().share(m_videoram);
map(0x8000, 0x8000).w(m_iop[0], FUNC(i8212_device::write));
map(0x8001, 0x8001).r(m_iop[1], FUNC(i8212_device::read));
map(0xe000, 0xffff).rom().region("rom", 0);
}
//-------------------------------------------------
// ROM( tug8082 )
//-------------------------------------------------
ROM_START(tug8082)
ROM_REGION(0x2000, "rom", 0)
ROM_LOAD("vdu80.ic28", 0x0000, 0x2000, CRC(e9df89c3) SHA1(1db8b055306067eb62940c0e9e63d97a2fab20f9))
ROM_END
//-------------------------------------------------
// INPUT_PORTS( tug8082 )
//-------------------------------------------------
INPUT_PORTS_START(tug8082)
PORT_START("DSW0")
PORT_DIPNAME(0x01, 0x01, "VDU Interrupt Request") PORT_DIPLOCATION("DSWA:1")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x01, DEF_STR(On))
PORT_DIPNAME(0x02, 0x00, "VDU Non Maskable Interrupt") PORT_DIPLOCATION("DSWA:2")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x02, DEF_STR(On))
PORT_DIPNAME(0x04, 0x00, "Not used") PORT_DIPLOCATION("DSWA:3")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x04, DEF_STR(On))
PORT_DIPNAME(0x08, 0x00, "Not used") PORT_DIPLOCATION("DSWA:4")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x08, DEF_STR(On))
PORT_DIPNAME(0xf0, 0x00, "I/O Address") PORT_DIPLOCATION("DSWA:5,6,7,8")
PORT_DIPSETTING(0x60, "$BE60 - $BE61")
PORT_DIPSETTING(0x40, "$BE40 - $BE41")
PORT_DIPSETTING(0x20, "$BE20 - $BE21")
PORT_DIPSETTING(0x00, "$BE00 - $BE01")
PORT_START("DSW1")
PORT_DIPNAME(0x01, 0x00, "Not used") PORT_DIPLOCATION("DSWB:1")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x01, DEF_STR(On))
PORT_DIPNAME(0x02, 0x00, "Not used") PORT_DIPLOCATION("DSWB:2")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x02, DEF_STR(On))
PORT_DIPNAME(0x04, 0x04, "80 Column Mode 16K Ram") PORT_DIPLOCATION("DSWB:3")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x04, DEF_STR(On))
PORT_DIPNAME(0x08, 0x00, "Not used") PORT_DIPLOCATION("DSWB:4")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x08, DEF_STR(On))
PORT_DIPNAME(0x10, 0x00, "Not used") PORT_DIPLOCATION("DSWB:5")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x10, DEF_STR(On))
PORT_DIPNAME(0x20, 0x20, "Write Protect") PORT_DIPLOCATION("DSWB:6")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x20, DEF_STR(On))
PORT_DIPNAME(0x40, 0x00, "40 Column Mode 8K Ram") PORT_DIPLOCATION("DSWB:7")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x40, DEF_STR(On))
PORT_DIPNAME(0x80, 0x80, "Video Select Disable") PORT_DIPLOCATION("DSWB:8")
PORT_DIPSETTING(0x00, DEF_STR(Off))
PORT_DIPSETTING(0x80, DEF_STR(On))
INPUT_PORTS_END
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
ioport_constructor tanbus_tug8082_device::device_input_ports() const
{
return INPUT_PORTS_NAME(tug8082);
}
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void tanbus_tug8082_device::device_add_mconfig(machine_config &config)
{
M6502(config, m_maincpu, DERIVED_CLOCK(1, 4));
m_maincpu->set_addrmap(AS_PROGRAM, &tanbus_tug8082_device::vid8082_map);
I8212(config, m_iop[0], 0);
//m_iop[0]->md_rd_callback().set(CONSTANT(0));
m_iop[0]->int_wr_callback().set(FUNC(tanbus_tug8082_device::bus_irq_w));
//m_iop->do_wr_callback().set(FUNC(tanbus_tug8082_device::write));
I8212(config, m_iop[1], 0);
//m_iop[1]->md_rd_callback().set(CONSTANT(0));
m_iop[1]->int_wr_callback().set(FUNC(tanbus_tug8082_device::vdu_irq_w));
//m_iop->di_rd_callback().set(FUNC(tanbus_tug8082_device::read));
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_refresh_hz(50);
m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500));
m_screen->set_size(512, 256);
m_screen->set_visarea(0, 512 - 1, 0, 256 - 1);
m_screen->set_screen_update(FUNC(tanbus_tug8082_device::screen_update));
PALETTE(config, "palette", palette_device::MONOCHROME);
}
//-------------------------------------------------
// rom_region - device-specific ROM region
//-------------------------------------------------
const tiny_rom_entry *tanbus_tug8082_device::device_rom_region() const
{
return ROM_NAME(tug8082);
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// tanbus_tug8082_device - constructor
//-------------------------------------------------
tanbus_tug8082_device::tanbus_tug8082_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TANBUS_TUG8082, tag, owner, clock)
, device_tanbus_interface(mconfig, *this)
, m_maincpu(*this, "maincpu")
, m_iop(*this, "iop%u", 0)
, m_dips(*this, "DSW%u", 0)
, m_rom(*this, "rom")
, m_screen(*this, "screen")
, m_palette(*this, "palette")
, m_videoram(*this, "videoram")
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tanbus_tug8082_device::device_start()
{
}
//-------------------------------------------------
// read - card read
//-------------------------------------------------
uint8_t tanbus_tug8082_device::read(offs_t offset, int inhrom, int inhram, int be)
{
uint8_t data = 0xff;
offs_t addr = 0xbe00 | (m_dips[0]->read() & 0xf0);
if (offset == addr)
{
data = m_iop[0]->read();
}
return data;
}
//-------------------------------------------------
// write - card write
//-------------------------------------------------
void tanbus_tug8082_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
{
offs_t addr = 0xbe01 | (m_dips[0]->read() & 0xf0);
if (offset == addr)
{
m_iop[1]->write(data);
}
}
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
WRITE_LINE_MEMBER(tanbus_tug8082_device::bus_irq_w)
{
/* Manual says these DIPs are not used but schematic suggests they are */
//switch (m_dips[0]->read() >> 2)
//{
//case 0x01:
m_tanbus->irq_w(state);
// break;
//case 0x02:
// m_tanbus->nmi_w(state);
// break;
//}
}
WRITE_LINE_MEMBER(tanbus_tug8082_device::vdu_irq_w)
{
switch (m_dips[0]->read() & 0x03)
{
case 0x01:
m_maincpu->set_input_line(M6502_IRQ_LINE, state);
break;
case 0x02:
m_maincpu->set_input_line(M6502_NMI_LINE, state);
break;
case 0x03:
m_maincpu->set_input_line(M6502_IRQ_LINE, state);
m_maincpu->set_input_line(M6502_NMI_LINE, state);
break;
}
}
uint32_t tanbus_tug8082_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
uint32_t *scanline;
int x, y;
uint8_t pixels;
const pen_t *pen = m_palette->pens();
for (y = 0; y < 256; y++)
{
scanline = &bitmap.pix32(y);
for (x = 0; x < 64; x++)
{
pixels = m_videoram[(y * 64) + x];
for (int i = 0; i < 8; ++i)
*scanline++ = pen[BIT(pixels, 7 - i)];
}
}
return 0;
}

View File

@ -0,0 +1,70 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
Microtanic Video 80/82 Board
**********************************************************************/
#ifndef MAME_BUS_TANBUS_TUG8082_H
#define MAME_BUS_TANBUS_TUG8082_H
#pragma once
#include "bus/tanbus/tanbus.h"
#include "cpu/m6502/m6502.h"
#include "machine/i8212.h"
#include "emupal.h"
#include "screen.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class tanbus_tug8082_device :
public device_t,
public device_tanbus_interface
{
public:
static constexpr feature_type imperfect_features() { return feature::GRAPHICS; }
// construction/destruction
tanbus_tug8082_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
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 read(offs_t offset, int inhrom, int inhram, int be) override;
virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
private:
DECLARE_WRITE_LINE_MEMBER(bus_irq_w);
DECLARE_WRITE_LINE_MEMBER(vdu_irq_w);
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
required_device<cpu_device> m_maincpu;
required_device_array<i8212_device, 2> m_iop;
required_ioport_array<2> m_dips;
required_memory_region m_rom;
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
required_shared_ptr<uint8_t> m_videoram;
void vid8082_map(address_map &map);
};
// device type definition
DECLARE_DEVICE_TYPE(TANBUS_TUG8082, tanbus_tug8082_device)
#endif // MAME_BUS_TANBUS_TUG8082_H

View File

@ -0,0 +1,113 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
TUG Programmable Graphic Module
http://www.microtan.ukpc.net/pageProducts.html#VIDEO
**********************************************************************/
#include "emu.h"
#include "tugpgm.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(TANBUS_TUGPGM, tanbus_tugpgm_device, "tanbus_tugpgm", "TUG Programmable Graphic Module")
//-------------------------------------------------
// INPUT_PORTS( tugpgm )
//-------------------------------------------------
INPUT_PORTS_START(tugpgm)
PORT_START("LINKS")
PORT_DIPNAME(0x07, 0x04, "Address Select")
PORT_DIPSETTING(0x00, "$0400 - $07FF (Not Recommended)")
PORT_DIPSETTING(0x01, "$2400 - $27FF")
PORT_DIPSETTING(0x02, "$4400 - $47FF")
PORT_DIPSETTING(0x03, "$6400 - $67FF")
PORT_DIPSETTING(0x04, "$8400 - $87FF")
PORT_DIPSETTING(0x05, "$A400 - $A7FF")
PORT_DIPSETTING(0x06, "$C400 - $C7FF")
PORT_DIPSETTING(0x07, "$E400 - $E7FF")
INPUT_PORTS_END
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
ioport_constructor tanbus_tugpgm_device::device_input_ports() const
{
return INPUT_PORTS_NAME(tugpgm);
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// tanbus_tugpgm_device - constructor
//-------------------------------------------------
tanbus_tugpgm_device::tanbus_tugpgm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TANBUS_TUGPGM, tag, owner, clock)
, device_tanbus_interface(mconfig, *this)
, m_links(*this, "LINKS")
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void tanbus_tugpgm_device::device_start()
{
m_ram = std::make_unique<uint8_t[]>(0x0400);
/* randomize video memory contents */
for (uint16_t addr = 0; addr < 0x0400; addr++)
{
m_ram[addr] = machine().rand() & 0xff;
m_tanbus->pgm_w(addr, m_ram[addr]);
}
save_pointer(NAME(m_ram), 0x0400);
}
//-------------------------------------------------
// read - card read
//-------------------------------------------------
uint8_t tanbus_tugpgm_device::read(offs_t offset, int inhrom, int inhram, int be)
{
uint8_t data = 0xff;
if ((offset & 0xfc00) == ((m_links->read() << 13) | 0x0400))
{
data = m_ram[offset & 0x3ff];
}
return data;
}
//-------------------------------------------------
// write - card write
//-------------------------------------------------
void tanbus_tugpgm_device::write(offs_t offset, uint8_t data, int inhrom, int inhram, int be)
{
if ((offset & 0xfc00) == ((m_links->read() << 13) | 0x0400))
{
m_ram[offset & 0x3ff] = data;
/* update the chargen on the CPU board */
m_tanbus->pgm_w(offset & 0x3ff, data);
}
}

View File

@ -0,0 +1,52 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
TUG Programmable Graphic Module
**********************************************************************/
#ifndef MAME_BUS_TANBUS_TUGPGM_H
#define MAME_BUS_TANBUS_TUGPGM_H
#pragma once
#include "bus/tanbus/tanbus.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class tanbus_tugpgm_device :
public device_t,
public device_tanbus_interface
{
public:
static constexpr feature_type imperfect_features() { return feature::GRAPHICS; }
// construction/destruction
tanbus_tugpgm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// device-level overrides
virtual void device_start() override;
// optional information overrides
virtual ioport_constructor device_input_ports() const override;
virtual uint8_t read(offs_t offset, int inhrom, int inhram, int be) override;
virtual void write(offs_t offset, uint8_t data, int inhrom, int inhram, int be) override;
private:
required_ioport m_links;
std::unique_ptr<uint8_t[]> m_ram;
};
// device type definition
DECLARE_DEVICE_TYPE(TANBUS_TUGPGM, tanbus_tugpgm_device)
#endif // MAME_BUS_TANBUS_TUGPGM_H

View File

@ -1,5 +1,5 @@
// license:GPL-2.0+
// copyright-holders:Juergen Buchmueller
// copyright-holders:Juergen Buchmueller,Nigel Barnes
/******************************************************************************
* Microtan 65
*
@ -51,46 +51,58 @@
*
*****************************************************************************/
/* Core includes */
#include "emu.h"
#include "includes/microtan.h"
/* Components */
#include "cpu/m6502/m6502.h"
#include "machine/mos6551.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
#include "softlist.h"
void microtan_state::main_map(address_map &map)
void microtan_state::mt65_map(address_map &map)
{
map(0x0000, 0xffff).rw(m_tanbus, FUNC(tanbus_device::read), FUNC(tanbus_device::write));
map(0x0000, 0x01ff).ram();
map(0x0200, 0x03ff).ram().w(FUNC(microtan_state::videoram_w)).share(m_videoram);
map(0xbc00, 0xbc00).w(m_ay8910[0], FUNC(ay8910_device::address_w));
map(0xbc01, 0xbc01).rw(m_ay8910[0], FUNC(ay8910_device::data_r), FUNC(ay8910_device::data_w));
map(0xbc02, 0xbc02).w(m_ay8910[1], FUNC(ay8910_device::address_w));
map(0xbc03, 0xbc03).rw(m_ay8910[1], FUNC(ay8910_device::data_r), FUNC(ay8910_device::data_w));
map(0xbfc0, 0xbfcf).m(m_via6522[0], FUNC(via6522_device::map));
map(0xbfd0, 0xbfd3).rw("acia", FUNC(mos6551_device::read), FUNC(mos6551_device::write));
map(0xbfe0, 0xbfef).m(m_via6522[1], FUNC(via6522_device::map));
map(0xbff0, 0xbfff).rw(FUNC(microtan_state::bffx_r), FUNC(microtan_state::bffx_w));
map(0xc000, 0xe7ff).rom();
map(0xf000, 0xffff).rom();
map(0xf800, 0xffff).rom();
}
void microtan_state::spinv_map(address_map &map)
{
map.unmap_value_high();
map(0x0000, 0x01ff).ram();
map(0x0200, 0x03ff).ram().w(FUNC(microtan_state::videoram_w)).share(m_videoram);
map(0xbc04, 0xbc04).rw(FUNC(microtan_state::sound_r), FUNC(microtan_state::sound_w));
map(0xbff0, 0xbfff).rw(FUNC(microtan_state::bffx_r), FUNC(microtan_state::bffx_w));
map(0xe800, 0xefff).rom().mirror(0x1000);
}
void mt6809_state::mt6809_map(address_map &map)
{
map(0x0000, 0xffff).rw(m_tanbus, FUNC(tanbus_device::read), FUNC(tanbus_device::write));
map(0xdc00, 0xdfff).ram();
map(0xdfd8, 0xdfd8).r(FUNC(mt6809_state::keyboard_r));
map(0xf800, 0xffff).rom();
}
INPUT_CHANGED_MEMBER(microtan_state::trigger_reset)
{
m_maincpu->set_input_line(INPUT_LINE_RESET, newval ? ASSERT_LINE : CLEAR_LINE);
if (newval)
{
machine().schedule_soft_reset();
}
}
static INPUT_PORTS_START( microtan )
PORT_START("DSW")
PORT_DIPNAME( 0x03, 0x00, "Memory size" )
PORT_DIPSETTING( 0x00, "1K" )
PORT_DIPSETTING( 0x01, "1K + 7K TANEX" )
PORT_DIPSETTING( 0x02, "1K + 7K TANEX + 40K TANRAM" )
PORT_BIT( 0xfc, 0xfc, IPT_UNUSED )
PORT_START("CONFIG")
PORT_CONFNAME(0x03, 0x00, "Input")
PORT_CONFSETTING(0x00, "ASCII Keyboard")
PORT_CONFSETTING(0x01, "Hex Keypad")
PORT_START("ROW0")
PORT_START("KBD0")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("ESC") PORT_CODE(KEYCODE_ESC)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("1 !") PORT_CODE(KEYCODE_1)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("2 \"") PORT_CODE(KEYCODE_2)
@ -100,7 +112,7 @@ static INPUT_PORTS_START( microtan )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("6 &") PORT_CODE(KEYCODE_6)
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("7 '") PORT_CODE(KEYCODE_7)
PORT_START("ROW1")
PORT_START("KBD1")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("8 *") PORT_CODE(KEYCODE_8)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("9 (") PORT_CODE(KEYCODE_9)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("0 )") PORT_CODE(KEYCODE_0)
@ -110,7 +122,7 @@ static INPUT_PORTS_START( microtan )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("BACK SPACE") PORT_CODE(KEYCODE_BACKSPACE)
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("TAB") PORT_CODE(KEYCODE_TAB)
PORT_START("ROW2")
PORT_START("KBD2")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q')
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W')
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E')
@ -120,7 +132,7 @@ static INPUT_PORTS_START( microtan )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_U) PORT_CHAR('U') PORT_CHAR('u')
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_I) PORT_CHAR('I') PORT_CHAR('i')
PORT_START("ROW3")
PORT_START("KBD3")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_O) PORT_CHAR('O') PORT_CHAR('o')
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_P) PORT_CHAR('P') PORT_CHAR('p')
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("[ {") PORT_CODE(KEYCODE_OPENBRACE)
@ -130,7 +142,7 @@ static INPUT_PORTS_START( microtan )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL)
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_NAME("CAPS LOCK") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE
PORT_START("ROW4")
PORT_START("KBD4")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_A) PORT_CHAR('A') PORT_CHAR('a')
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_S) PORT_CHAR('S') PORT_CHAR('s')
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_D) PORT_CHAR('D') PORT_CHAR('d')
@ -140,7 +152,7 @@ static INPUT_PORTS_START( microtan )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_J) PORT_CHAR('J') PORT_CHAR('j')
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_K) PORT_CHAR('K') PORT_CHAR('k')
PORT_START("ROW5")
PORT_START("KBD5")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_L) PORT_CHAR('L') PORT_CHAR('l')
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("; :") PORT_CODE(KEYCODE_COLON)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("' \"") PORT_CODE(KEYCODE_QUOTE)
@ -150,7 +162,7 @@ static INPUT_PORTS_START( microtan )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_X) PORT_CHAR('X') PORT_CHAR('x')
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_C) PORT_CHAR('C') PORT_CHAR('c')
PORT_START("ROW6")
PORT_START("KBD6")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_V) PORT_CHAR('V') PORT_CHAR('v')
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_B) PORT_CHAR('B') PORT_CHAR('b')
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_N) PORT_CHAR('N') PORT_CHAR('n')
@ -160,7 +172,7 @@ static INPUT_PORTS_START( microtan )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("/ ?") PORT_CODE(KEYCODE_SLASH)
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("SHIFT (R)") PORT_CODE(KEYCODE_RSHIFT)
PORT_START("ROW7")
PORT_START("KBD7")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("LINE FEED")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("SPACE") PORT_CODE(KEYCODE_SPACE)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("- (KP)") PORT_CODE(KEYCODE_MINUS_PAD)
@ -170,7 +182,7 @@ static INPUT_PORTS_START( microtan )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("0 (KP)") PORT_CODE(KEYCODE_0_PAD)
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("1 (KP)") PORT_CODE(KEYCODE_1_PAD)
PORT_START("ROW8")
PORT_START("KBD8")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("2 (KP)") PORT_CODE(KEYCODE_2_PAD)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("3 (KP)") PORT_CODE(KEYCODE_3_PAD)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("4 (KP)") PORT_CODE(KEYCODE_4_PAD)
@ -180,63 +192,92 @@ static INPUT_PORTS_START( microtan )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("8 (KP)") PORT_CODE(KEYCODE_8_PAD)
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("9 (KP)") PORT_CODE(KEYCODE_9_PAD)
PORT_START("JOY") // VIA #1 PORT A
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(1)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START ) PORT_PLAYER(2)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_4WAY
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_4WAY
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_4WAY
PORT_START("KPAD0")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("0") PORT_CODE(KEYCODE_0_PAD)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("4") PORT_CODE(KEYCODE_4_PAD)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("8 P") PORT_CODE(KEYCODE_8_PAD)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("C M") PORT_CODE(KEYCODE_LCONTROL)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_LSHIFT)
PORT_BIT(0xe0, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_START("KPAD1")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("1") PORT_CODE(KEYCODE_1_PAD)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("5 O") PORT_CODE(KEYCODE_5_PAD)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("9 ESC") PORT_CODE(KEYCODE_9_PAD)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("D G") PORT_CODE(KEYCODE_LCONTROL)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("LF DEL") PORT_CODE(KEYCODE_DEL_PAD)
PORT_BIT(0xe0, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_START("KPAD2")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("2") PORT_CODE(KEYCODE_2_PAD)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("6 C") PORT_CODE(KEYCODE_6_PAD)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("A") PORT_CODE(KEYCODE_LEFT)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("E S") PORT_CODE(KEYCODE_LCONTROL)
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("CR SP") PORT_CODE(KEYCODE_ENTER_PAD)
PORT_BIT(0xe0, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_START("KPAD3")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("3 '") PORT_CODE(KEYCODE_3_PAD)
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("7 R") PORT_CODE(KEYCODE_7_PAD)
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("B L") PORT_CODE(KEYCODE_LEFT)
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_KEYPAD) PORT_NAME("F N") PORT_CODE(KEYCODE_LCONTROL)
PORT_BIT(0xf0, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_START("BRK")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_NAME("RESET") PORT_CODE(KEYCODE_F12) PORT_CHAR(UCHAR_MAMEKEY(F12)) PORT_CHANGED_MEMBER(DEVICE_SELF, microtan_state, trigger_reset, 0)
INPUT_PORTS_END
static INPUT_PORTS_START( spinveti )
PORT_START("CONFIG")
PORT_CONFNAME(0x03, 0x02, "Input")
PORT_CONFSETTING(0x02, "ETI Keypad")
PORT_CONFNAME(0x60, 0x20, "Difficulty")
PORT_CONFSETTING(0x00, "Easy")
PORT_CONFSETTING(0x20, "Normal")
PORT_CONFSETTING(0x40, "Hard")
PORT_CONFSETTING(0x60, "Hardest")
PORT_START("KEYPAD")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Play") PORT_CODE(KEYCODE_P)
PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT)
PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT)
PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Fire") PORT_CODE(KEYCODE_LCONTROL)
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Hold") PORT_CODE(KEYCODE_H)
PORT_START("BRK")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_NAME("Reset") PORT_CODE(KEYCODE_R) PORT_CHANGED_MEMBER(DEVICE_SELF, microtan_state, trigger_reset, 0)
INPUT_PORTS_END
static const gfx_layout char_layout =
{
8, 16, /* 8 x 16 graphics */
128, /* 128 codes */
1, /* 1 bit per pixel */
{ 0 }, /* no bitplanes */
{ 0, 1, 2, 3, 4, 5, 6, 7 },
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8,
8*8, 9*8,10*8,11*8,12*8,13*8,14*8,15*8 },
8 * 16 /* code takes 8 times 16 bits */
};
static const gfx_layout chunky_layout =
{
8, 16, /* 8 x 16 graphics */
256, /* 256 codes */
1, /* 1 bit per pixel */
{ 0 }, /* no bitplanes */
{ 0, 1, 2, 3, 4, 5, 6, 7 },
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8,
8*8, 9*8,10*8,11*8,12*8,13*8,14*8,15*8 },
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8, 8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 },
8 * 16 /* code takes 8 times 16 bits */
};
static GFXDECODE_START( gfx_microtan )
GFXDECODE_ENTRY( "gfx1", 0, char_layout, 0, 1 )
GFXDECODE_ENTRY( "gfx2", 0, chunky_layout, 0, 1 )
GFXDECODE_ENTRY( "gfx2", 0, char_layout, 0, 1 )
GFXDECODE_END
void microtan_state::microtan(machine_config &config)
void microtan_state::mt65(machine_config &config)
{
/* basic machine hardware */
M6502(config, m_maincpu, 6_MHz_XTAL / 8); // 750 kHz
m_maincpu->set_addrmap(AS_PROGRAM, &microtan_state::main_map);
m_maincpu->set_vblank_int("screen", FUNC(microtan_state::interrupt));
/* Microtan 65 CPU board */
M6502(config, m_maincpu, 6_MHz_XTAL / 8);
m_maincpu->set_addrmap(AS_PROGRAM, &microtan_state::mt65_map);
// The 6502 IRQ line is active low and probably driven by open collector outputs (guess).
INPUT_MERGER_ANY_HIGH(config, m_irq_line).output_handler().set_inputline(m_maincpu, 0);
TIMER(config, "kbd_timer").configure_periodic(FUNC(microtan_state::kbd_scan), attotime::from_hz(45));
INPUT_MERGER_ANY_HIGH(config, m_irq_line).output_handler().set_inputline(m_maincpu, M6502_IRQ_LINE);
/* video hardware - include overscan */
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(60);
screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
screen.set_size(32*8, 16*16);
screen.set_visarea(0*8, 32*8-1, 0*16, 16*16-1);
screen.set_raw(6_MHz_XTAL, 384, 0, 32*8, 312, 0, 16*16);
screen.set_screen_update(FUNC(microtan_state::screen_update));
screen.set_palette("palette");
@ -244,10 +285,23 @@ void microtan_state::microtan(machine_config &config)
PALETTE(config, "palette", palette_device::MONOCHROME);
/* sound hardware */
SPEAKER(config, "speaker").front_center();
AY8910(config, m_ay8910[0], 1000000).add_route(ALL_OUTPUTS, "speaker", 0.5);
AY8910(config, m_ay8910[1], 1000000).add_route(ALL_OUTPUTS, "speaker", 0.5);
/* Microtan Motherboard */
TANBUS(config, m_tanbus, 6_MHz_XTAL);
m_tanbus->out_irq_callback().set(m_irq_line, FUNC(input_merger_device::in_w<IRQ_TANBUS>));
m_tanbus->out_so_callback().set_inputline(m_maincpu, M6502_SET_OVERFLOW);
m_tanbus->out_nmi_callback().set_inputline(m_maincpu, M6502_NMI_LINE);
m_tanbus->out_pgm_callback().set(FUNC(microtan_state::pgm_chargen_w));
TANBUS_SLOT(config, "tanbus:tanex", -1, tanex_devices, "tanex");
TANBUS_SLOT(config, "tanbus:0", 0, tanbus_devices, "tanram");
TANBUS_SLOT(config, "tanbus:1", 1, tanbus_devices, nullptr);
TANBUS_SLOT(config, "tanbus:2", 2, tanbus_devices, "bullsnd");
TANBUS_SLOT(config, "tanbus:3", 3, tanbus_devices, nullptr);
TANBUS_SLOT(config, "tanbus:4", 4, tanbus_devices, nullptr);
TANBUS_SLOT(config, "tanbus:5", 5, tanbus_devices, nullptr);
TANBUS_SLOT(config, "tanbus:6", 6, tanbus_devices, nullptr);
TANBUS_SLOT(config, "tanbus:7", 7, tanbus_devices, nullptr);
TANBUS_SLOT(config, "tanbus:exp", 8, tanbus_devices, nullptr);
/* snapshot/quickload */
snapshot_image_device &snapshot(SNAPSHOT(config, "snapshot", "dmp,m65"));
@ -255,52 +309,170 @@ void microtan_state::microtan(machine_config &config)
snapshot.set_interface("mt65_snap");
QUICKLOAD(config, "quickload", "hex").set_load_callback(FUNC(microtan_state::quickload_cb), this);
/* cassette */
CASSETTE(config, m_cassette);
m_cassette->add_route(ALL_OUTPUTS, "speaker", 0.05);
TIMER(config, "read_cassette").configure_periodic(FUNC(microtan_state::read_cassette), attotime::from_hz(20000)); // cass read
/* acia */
mos6551_device &acia(MOS6551(config, "acia", 0));
acia.set_xtal(1.8432_MHz_XTAL);
/* via */
VIA6522(config, m_via6522[0], 6_MHz_XTAL / 8);
m_via6522[0]->readpa_handler().set(FUNC(microtan_state::via_0_in_a));
m_via6522[0]->writepa_handler().set(FUNC(microtan_state::via_0_out_a));
m_via6522[0]->writepb_handler().set(FUNC(microtan_state::via_0_out_b));
m_via6522[0]->ca2_handler().set(FUNC(microtan_state::via_0_out_ca2));
m_via6522[0]->cb2_handler().set(FUNC(microtan_state::via_0_out_cb2));
m_via6522[0]->irq_handler().set(m_irq_line, FUNC(input_merger_device::in_w<IRQ_VIA_0>));
VIA6522(config, m_via6522[1], 6_MHz_XTAL / 8);
m_via6522[1]->writepa_handler().set(FUNC(microtan_state::via_1_out_a));
m_via6522[1]->writepb_handler().set(FUNC(microtan_state::via_1_out_b));
m_via6522[1]->ca2_handler().set(FUNC(microtan_state::via_1_out_ca2));
m_via6522[1]->cb2_handler().set(FUNC(microtan_state::via_1_out_cb2));
m_via6522[1]->irq_handler().set(m_irq_line, FUNC(input_merger_device::in_w<IRQ_VIA_1>));
/* software lists */
SOFTWARE_LIST(config, "rom_list").set_original("mt65_rom");
SOFTWARE_LIST(config, "cass_list").set_original("mt65_cass");
//SOFTWARE_LIST(config, "flop_list").set_original("mt65_flop").set_filter("6502");
SOFTWARE_LIST(config, "snap_list").set_original("mt65_snap");
}
ROM_START( microtan )
ROM_REGION( 0x10000, "maincpu", 0 )
ROM_LOAD( "tanex_j2.rom", 0xc000, 0x1000, CRC(3e09d384) SHA1(15a98941a672ff16242cc73f1dcf1d81fccd8910) )
ROM_LOAD( "tanex_h2.rom", 0xd000, 0x1000, CRC(75105113) SHA1(c6fea4d65b7c52f43aa1589cace9467349a0f290) )
ROM_LOAD( "tanex_d3.rom", 0xe000, 0x0800, CRC(ee6e8412) SHA1(7e1bca84bab79d94a4ab8554d23e2bc28ccd0384) )
ROM_LOAD( "tanex_e2.rom", 0xe800, 0x0800, CRC(bd87fd34) SHA1(f41895df4a733dddfaf1c89ecff5040addcab804) )
ROM_LOAD( "tanex_g2.rom", 0xf000, 0x0800, CRC(9fd233ee) SHA1(7b0be2d0402229ec80b062f7a0bed793686bcbf9) )
ROM_LOAD( "tanbug_2.rom", 0xf800, 0x0400, CRC(7e215313) SHA1(c8fb3d33ce2beaf624dc75ec57d34c216b086274) )
ROM_LOAD( "tanbug.rom", 0xfc00, 0x0400, CRC(c8221d9e) SHA1(c7fe4c174523aaaab30be7a8c9baf2bc08b33968) )
void microtan_state::micron(machine_config &config)
{
mt65(config);
ROM_REGION( 0x00800, "gfx1", 0 )
ROM_LOAD( "charset.rom", 0x0000, 0x0800, CRC(3b3c5360) SHA1(a3a2f74149107f8b8f35b15069c71f3aa843d12f) )
/* Microtan Mini-Motherboard connects MT65 CPU card and TANEX, no extra slots */
config.device_remove("tanbus:0");
config.device_remove("tanbus:1");
config.device_remove("tanbus:2");
config.device_remove("tanbus:3");
config.device_remove("tanbus:4");
config.device_remove("tanbus:5");
config.device_remove("tanbus:6");
config.device_remove("tanbus:7");
config.device_remove("tanbus:exp");
}
ROM_REGION( 0x01000, "gfx2", ROMREGION_ERASEFF )
// initialized in init_microtan
void microtan_state::spinveti(machine_config &config)
{
/* basic machine hardware */
M6502(config, m_maincpu, 6_MHz_XTAL / 8);
m_maincpu->set_addrmap(AS_PROGRAM, &microtan_state::spinv_map);
INPUT_MERGER_ANY_HIGH(config, m_irq_line).output_handler().set_inputline(m_maincpu, M6502_IRQ_LINE);
/* video hardware - include overscan */
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_raw(6_MHz_XTAL, 384, 0, 32*8, 312, 0, 16*16);
screen.set_screen_update(FUNC(microtan_state::screen_update));
screen.set_palette("palette");
GFXDECODE(config, m_gfxdecode, "palette", gfx_microtan);
PALETTE(config, "palette", palette_device::MONOCHROME);
/* TODO: Sound hardware */
}
static DEVICE_INPUT_DEFAULTS_START(ra32k_def_ram0000)
/* 32K RAM configured 0x0000-0x7fff */
DEVICE_INPUT_DEFAULTS("SW1", 0xff, 0xff) // all blocks enabled
DEVICE_INPUT_DEFAULTS("SW2", 0xff, 0xff) // all blocks enabled
DEVICE_INPUT_DEFAULTS("SW3", 0x0f, 0x0f) // start address $0000
DEVICE_INPUT_DEFAULTS("LNK1", 0x03, 0x01)
DEVICE_INPUT_DEFAULTS_END
static DEVICE_INPUT_DEFAULTS_START(ra32k_def_ram8000)
/* 32K RAM configured 0x8000-0xffff */
DEVICE_INPUT_DEFAULTS("SW1", 0xff, 0x7f) // disable block $F800
DEVICE_INPUT_DEFAULTS("SW2", 0xff, 0xff) // all blocks enabled
DEVICE_INPUT_DEFAULTS("SW3", 0x0f, 0x0d) // start address $8000
DEVICE_INPUT_DEFAULTS("LNK1", 0x03, 0x00)
DEVICE_INPUT_DEFAULTS_END
static DEVICE_INPUT_DEFAULTS_START(ra32k_def_rom2000)
/* 8K EPROM configured 0x2000-0x3fff */
DEVICE_INPUT_DEFAULTS("SW1", 0xff, 0xff) // all blocks enabled
DEVICE_INPUT_DEFAULTS("SW2", 0xff, 0xff) // all blocks enabled
DEVICE_INPUT_DEFAULTS("SW3", 0x0f, 0x04) // start address $2000
DEVICE_INPUT_DEFAULTS("LNK1", 0x03, 0x02)
DEVICE_INPUT_DEFAULTS_END
void mt6809_state::mt6809(machine_config &config)
{
/* Ralph Allen 6809 CPU Board */
MC6809(config, m_maincpu, 6_MHz_XTAL / 4); // TODO: verify divider
m_maincpu->set_addrmap(AS_PROGRAM, &mt6809_state::mt6809_map);
TIMER(config, "kbd_timer").configure_periodic(FUNC(microtan_state::kbd_scan), attotime::from_hz(45));
INPUT_MERGER_ANY_HIGH(config, m_irq_line).output_handler().set_inputline(m_maincpu, M6809_IRQ_LINE);
/* Microtan Motherboard */
TANBUS(config, m_tanbus, 6_MHz_XTAL);
m_tanbus->out_irq_callback().set(m_irq_line, FUNC(input_merger_device::in_w<IRQ_TANBUS>));
m_tanbus->out_nmi_callback().set_inputline(m_maincpu, M6809_FIRQ_LINE);
TANBUS_SLOT(config, "tanbus:tanex", -1, tanex_devices, nullptr);
TANBUS_SLOT(config, "tanbus:0", 0, tanbus6809_devices, "ra32k").set_option_device_input_defaults("ra32k", DEVICE_INPUT_DEFAULTS_NAME(ra32k_def_ram0000));
TANBUS_SLOT(config, "tanbus:1", 1, tanbus6809_devices, "ra32k").set_option_device_input_defaults("ra32k", DEVICE_INPUT_DEFAULTS_NAME(ra32k_def_ram8000));
TANBUS_SLOT(config, "tanbus:2", 2, tanbus6809_devices, "ravdu");
TANBUS_SLOT(config, "tanbus:3", 3, tanbus6809_devices, "radisc");
TANBUS_SLOT(config, "tanbus:4", 4, tanbus6809_devices, nullptr);
TANBUS_SLOT(config, "tanbus:5", 5, tanbus6809_devices, nullptr);
TANBUS_SLOT(config, "tanbus:6", 6, tanbus6809_devices, nullptr);
TANBUS_SLOT(config, "tanbus:7", 7, tanbus6809_devices, "ra32k").set_option_device_input_defaults("ra32k", DEVICE_INPUT_DEFAULTS_NAME(ra32k_def_rom2000));
TANBUS_SLOT(config, "tanbus:exp", 8, tanbus6809_devices, nullptr);
/* software lists */
//SOFTWARE_LIST(config, "flop_list").set_original("mt65_flop").set_filter("6809");
}
ROM_START( mt65 )
ROM_REGION(0x10000, "maincpu", 0)
ROM_DEFAULT_BIOS("tanbug23")
/* Microtan 65 (MT0016 Iss 1) */
ROM_SYSTEM_BIOS(0, "tanbug23", "TANBUG V2.3")
ROMX_LOAD("tanbug23.k3", 0xf800, 0x0800, CRC(7f29845d) SHA1(de277e942eefa11a9a6defe3d7d03071d5100b68), ROM_BIOS(0))
ROM_SYSTEM_BIOS(1, "tanbug23p", "TANBUG V2.3 (patched)")
ROMX_LOAD("tanbug_2.rom", 0xf800, 0x0400, CRC(7e215313) SHA1(c8fb3d33ce2beaf624dc75ec57d34c216b086274), ROM_BIOS(1))
ROMX_LOAD("tanbug.rom", 0xfc00, 0x0400, CRC(c8221d9e) SHA1(c7fe4c174523aaaab30be7a8c9baf2bc08b33968), ROM_BIOS(1))
ROM_SYSTEM_BIOS(2, "tanbug31", "TANBUG V3.1 (TANDOS)")
ROMX_LOAD("tanbug31.k3", 0xf800, 0x0800, CRC(5943e427) SHA1(55fe645363cd5f2015a537be6f7a00de33d1bea5), ROM_BIOS(2))
ROM_SYSTEM_BIOS(3, "tanbug3b", "TANBUG V.3B (MPVDU)")
ROMX_LOAD("tanbug3b.k3", 0xf800, 0x0800, CRC(5b49f861) SHA1(b37cddf97b6324ab0647479b5b013a9b3d47ddda), ROM_BIOS(3))
ROM_SYSTEM_BIOS(4, "tugbug11", "TUGBUG V1.1 (VID8082)")
ROMX_LOAD("tugbug11.k3", 0xf800, 0x0800, CRC(23b02439) SHA1(9e56fbd6c07b1dc5c10e7b574a5ea26405781a3d), ROM_BIOS(4))
ROM_REGION(0x1000, "gfx1", 0)
ROM_LOAD("charset.rom", 0x0000, 0x0800, CRC(3b3c5360) SHA1(a3a2f74149107f8b8f35b15069c71f3aa843d12f))
ROM_RELOAD(0x0800, 0x0800)
ROM_REGION(0x1000, "gfx2", ROMREGION_ERASEFF)
// initialized in init_gfx2
ROM_END
ROM_START( micron )
ROM_REGION(0x10000, "maincpu", 0)
ROM_DEFAULT_BIOS("tanbug1")
/* MT65 (Iss 0) */
ROM_SYSTEM_BIOS(0, "tanbug1", "TANBUG V1")
ROMX_LOAD("tanbug1.g2", 0xf800, 0x0400, CRC(6f45aaca) SHA1(c1a020d86830ee475ee75c847e98f7a02d467659), ROM_BIOS(0) | ROM_NIBBLE | ROM_SHIFT_NIBBLE_LO)
ROM_RELOAD(0xfc00, 0x0400)
ROMX_LOAD("tanbug1.h2", 0xf800, 0x0400, CRC(1ccd6b8f) SHA1(49784749599255458ba5513d8c2fc58c4df39515), ROM_BIOS(0) | ROM_NIBBLE | ROM_SHIFT_NIBBLE_HI)
ROM_RELOAD(0xfc00, 0x0400)
ROM_REGION(0x1000, "gfx1", 0)
ROM_LOAD("charset.rom", 0x0000, 0x0800, CRC(3b3c5360) SHA1(a3a2f74149107f8b8f35b15069c71f3aa843d12f))
ROM_RELOAD(0x0800, 0x0800)
ROM_REGION(0x1000, "gfx2", ROMREGION_ERASEFF)
// initialized in init_gfx2
ROM_END
ROM_START( spinveti )
ROM_REGION(0x10000, "maincpu", 0)
ROM_LOAD("spaceinv.ic20", 0xe800, 0x0800, CRC(3e235077) SHA1(ae7d2788125d01a3c5d57ab0d992bd708abd6ade))
ROM_REGION(0x1000, "gfx1", 0)
ROM_LOAD("charset.rom", 0x0000, 0x0800, CRC(3b3c5360) SHA1(a3a2f74149107f8b8f35b15069c71f3aa843d12f))
ROM_RELOAD(0x0800, 0x0800)
ROM_REGION(0x1000, "gfx2", ROMREGION_ERASEFF)
// initialized in init_gfx2
ROM_END
ROM_START( mt6809 )
/* 6809 CPU Card (Ralph Allen Engineering) */
ROM_REGION(0x10000, "maincpu", 0)
ROM_SYSTEM_BIOS(0, "ralbug14", "RALBUG V1.4")
ROMX_LOAD("ralbug14.rom", 0xf800, 0x0800, CRC(8bbc87d8) SHA1(3d53a6ffd4a8d7c8edf4f2e23946011ed29146ce), ROM_BIOS(0))
ROM_END
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
COMP( 1979, microtan, 0, 0, microtan, microtan, microtan_state, init_microtan, "Tangerine", "Microtan 65" , 0 )
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
COMP( 1979, mt65, 0, 0, mt65, microtan, microtan_state, init_microtan, "Tangerine", "Microtan 65", MACHINE_NO_SOUND_HW )
COMP( 1980, micron, mt65, 0, micron, microtan, microtan_state, init_microtan, "Tangerine", "Micron", MACHINE_NO_SOUND_HW )
COMP( 1980, spinveti, mt65, 0, spinveti, spinveti, microtan_state, init_gfx2, "Tangerine/ETI", "Space Invasion (ETI)", MACHINE_NO_SOUND )
COMP( 1984, mt6809, mt65, 0, mt6809, microtan, mt6809_state, empty_init, "Tangerine", "Microtan 6809 System", MACHINE_NO_SOUND_HW | MACHINE_NOT_WORKING )

View File

@ -19,62 +19,60 @@
#pragma once
#include "imagedev/snapquik.h"
#include "machine/6522via.h"
#include "machine/timer.h"
#include "cpu/m6502/m6502.h"
#include "cpu/m6809/m6809.h"
#include "machine/input_merger.h"
#include "sound/ay8910.h"
#include "imagedev/cassette.h"
#include "machine/timer.h"
#include "bus/tanbus/tanbus.h"
#include "imagedev/snapquik.h"
class microtan_state : public driver_device
{
public:
microtan_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_videoram(*this, "videoram")
, m_maincpu(*this, "maincpu")
, m_irq_line(*this, "irq_line")
, m_cassette(*this, "cassette")
, m_via6522(*this, "via6522%u", 0)
, m_ay8910(*this, "ay8910%u", 0)
, m_io_keyboard(*this, "ROW%u", 0)
, m_config(*this, "CONFIG")
, m_io_keyboard(*this, "KBD%u", 0)
, m_io_keypad(*this, "KPAD%u", 0)
, m_keypad(*this, "KEYPAD")
, m_tanbus(*this, "tanbus")
, m_videoram(*this, "videoram")
, m_gfxdecode(*this, "gfxdecode")
, m_gfx1(*this, "gfx1")
, m_led(*this, "led1")
{ }
void microtan(machine_config &config);
void mt65(machine_config &config);
void micron(machine_config &config);
void spinveti(machine_config &config);
void init_gfx2();
void init_microtan();
TIMER_DEVICE_CALLBACK_MEMBER(kbd_scan);
DECLARE_READ8_MEMBER(bffx_r);
DECLARE_WRITE8_MEMBER(bffx_w);
DECLARE_INPUT_CHANGED_MEMBER(trigger_reset);
protected:
enum
{
TIMER_PULSE_NMI
};
enum { IRQ_KBD, IRQ_TANBUS };
virtual void machine_start() override;
virtual void machine_reset() override;
virtual void video_start() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
private:
enum { IRQ_VIA_0, IRQ_VIA_1, IRQ_KBD };
required_shared_ptr<uint8_t> m_videoram;
required_device<cpu_device> m_maincpu;
required_device<input_merger_device> m_irq_line;
required_device<cassette_image_device> m_cassette;
required_device_array<via6522_device, 2> m_via6522;
required_device_array<ay8910_device, 2> m_ay8910;
required_ioport_array<9> m_io_keyboard;
required_device<gfxdecode_device> m_gfxdecode;
output_finder<> m_led;
required_ioport m_config;
optional_ioport_array<9> m_io_keyboard;
optional_ioport_array<4> m_io_keypad;
optional_ioport m_keypad;
optional_device<tanbus_device> m_tanbus;
uint8_t m_chunky_graphics;
std::unique_ptr<uint8_t[]> m_chunky_buffer;
uint8_t m_keypad_column;
uint8_t m_keyboard_ascii;
emu_timer *m_read_cassette_timer;
emu_timer *m_pulse_nmi_timer;
uint8_t m_keyrows[10];
int m_lastrow;
@ -82,28 +80,27 @@ private:
int m_key;
int m_repeat;
int m_repeater;
virtual void store_key(int key);
private:
optional_shared_ptr<uint8_t> m_videoram;
optional_device<gfxdecode_device> m_gfxdecode;
optional_memory_region m_gfx1;
output_finder<> m_led;
uint8_t m_chunky_graphics;
std::unique_ptr<uint8_t[]> m_chunky_buffer;
tilemap_t *m_bg_tilemap;
DECLARE_READ8_MEMBER(sound_r);
DECLARE_WRITE8_MEMBER(sound_w);
DECLARE_READ8_MEMBER(bffx_r);
DECLARE_WRITE8_MEMBER(bffx_w);
DECLARE_WRITE8_MEMBER(videoram_w);
TILE_GET_INFO_MEMBER(get_bg_tile_info);
DECLARE_WRITE8_MEMBER(pgm_chargen_w);
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
INTERRUPT_GEN_MEMBER(interrupt);
TIMER_DEVICE_CALLBACK_MEMBER(read_cassette);
TIMER_CALLBACK_MEMBER(pulse_nmi);
DECLARE_READ8_MEMBER(via_0_in_a);
DECLARE_WRITE8_MEMBER(via_0_out_a);
DECLARE_WRITE8_MEMBER(via_0_out_b);
DECLARE_WRITE_LINE_MEMBER(via_0_out_ca2);
DECLARE_WRITE_LINE_MEMBER(via_0_out_cb2);
DECLARE_WRITE8_MEMBER(via_1_out_a);
DECLARE_WRITE8_MEMBER(via_1_out_b);
DECLARE_WRITE_LINE_MEMBER(via_1_out_ca2);
DECLARE_WRITE_LINE_MEMBER(via_1_out_cb2);
void store_key(int key);
image_verify_result verify_snapshot(uint8_t *data, int size);
image_init_result parse_intel_hex(uint8_t *snapshot_buff, char *src);
image_init_result parse_zillion_hex(uint8_t *snapshot_buff, char *src);
@ -112,7 +109,27 @@ private:
DECLARE_SNAPSHOT_LOAD_MEMBER(snapshot_cb);
DECLARE_QUICKLOAD_LOAD_MEMBER(quickload_cb);
void main_map(address_map &map);
void mt65_map(address_map &map);
void spinv_map(address_map &map);
};
class mt6809_state : public microtan_state
{
public:
using microtan_state::microtan_state;
void mt6809(machine_config &config);
protected:
virtual void video_start() override;
virtual void store_key(int key) override;
private:
DECLARE_READ8_MEMBER(keyboard_r);
void mt6809_map(address_map &map);
};
#endif // MAME_INCLUDES_MICROTAN_H

View File

@ -14,16 +14,9 @@
*
*****************************************************************************/
/* Core includes */
#include "emu.h"
#include "includes/microtan.h"
/* Components */
#include "cpu/m6502/m6502.h"
#include "machine/mos6551.h"
//#include "imagedev/snapquik.h"
//#define VERBOSE 1
#include "logmacro.h"
@ -120,86 +113,6 @@ static const char keyboard[8][9][8] = {
};
/**************************************************************
* VIA callback functions for VIA #0
**************************************************************/
READ8_MEMBER(microtan_state::via_0_in_a)
{
int data = ioport("JOY")->read();
LOG("via_0_in_a %02X\n", data);
return data;
}
WRITE8_MEMBER(microtan_state::via_0_out_a)
{
LOG("via_0_out_a %02X\n", data);
}
WRITE8_MEMBER(microtan_state::via_0_out_b)
{
LOG("via_0_out_b %02X\n", data);
/* bit #7 is the cassette output signal */
m_cassette->output(data & 0x80 ? +1.0 : -1.0);
}
WRITE_LINE_MEMBER(microtan_state::via_0_out_ca2)
{
LOG("via_0_out_ca2 %d\n", state);
}
WRITE_LINE_MEMBER(microtan_state::via_0_out_cb2)
{
LOG("via_0_out_cb2 %d\n", state);
}
/**************************************************************
* VIA callback functions for VIA #1
**************************************************************/
WRITE8_MEMBER(microtan_state::via_1_out_a)
{
LOG("via_1_out_a %02X\n", data);
}
WRITE8_MEMBER(microtan_state::via_1_out_b)
{
LOG("via_1_out_b %02X\n", data);
}
WRITE_LINE_MEMBER(microtan_state::via_1_out_ca2)
{
LOG("via_1_out_ca2 %d\n", state);
}
WRITE_LINE_MEMBER(microtan_state::via_1_out_cb2)
{
LOG("via_1_out_cb2 %d\n", state);
}
void microtan_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
switch (id)
{
case TIMER_PULSE_NMI:
pulse_nmi(ptr, param);
break;
default:
assert_always(false, "Unknown id in microtan_state::device_timer");
}
}
TIMER_DEVICE_CALLBACK_MEMBER(microtan_state::read_cassette)
{
double level = m_cassette->input();
LOG("read_cassette: %g\n", level);
if (level < -0.07)
m_via6522[0]->write_cb2(0);
else if (level > +0.07)
m_via6522[0]->write_cb2(1);
}
READ8_MEMBER(microtan_state::sound_r)
{
int data = 0xff;
@ -228,9 +141,26 @@ READ8_MEMBER(microtan_state::bffx_r)
case 2: /* BFF2: read undefined (?) */
LOG("bff2_r: -> %02x\n", data);
break;
default: /* BFF3: read keyboard ASCII value */
data = m_keyboard_ascii;
case 3: /* BFF3: read keyboard/keypad */
switch (m_config->read() & 3)
{
case 0: /* ASCII Keyboard */
data = m_keyboard_ascii;
break;
case 1: /* Hex Keypad */
data = 0x00;
for (int i = 0; i < 4; i++)
{
if (m_keypad_column & (1 << i))
data |= m_io_keypad[i]->read();
}
break;
case 2: /* ETI Keypad */
data = (m_keypad->read() & 0x1f) | (m_config->read() & 0x60);
break;
}
LOG("bff3_r: -> %02x (keyboard ASCII)\n", data);
break;
}
return data;
}
@ -256,25 +186,43 @@ WRITE8_MEMBER(microtan_state::bffx_w)
LOG("bff1_w: %d <- %02x (delayed NMI)\n", offset, data);
m_pulse_nmi_timer->adjust(m_maincpu->cycles_to_attotime(8));
break;
case 2: /* BFF2: write keypad column write (what is this meant for?) */
LOG("bff2_w: %d <- %02x (keypad column)\n", offset, data);
m_keypad_column = data;
case 2: /* BFF2: write keypad */
LOG("bff2_w: %d <- %02x (keypad column)\n", offset, data); // 1, 2, 4, 7, f
m_keypad_column = data & 0x0f;
break;
default: /* BFF3: write disable chunky graphics */
case 3: /* BFF3: write disable chunky graphics */
LOG("bff3_w: %d <- %02x (chunky graphics off)\n", offset, data);
m_chunky_graphics = 0;
break;
}
}
READ8_MEMBER(mt6809_state::keyboard_r)
{
uint8_t data = m_keyboard_ascii;
m_keyboard_ascii = 0x00;
return data;
}
void mt6809_state::store_key(int key)
{
m_keyboard_ascii = key | 0x80;
}
void microtan_state::store_key(int key)
{
LOG("microtan: store key '%c'\n", key);
m_keyboard_ascii = key | 0x80;
m_irq_line->in_w<IRQ_KBD>(1);
}
INTERRUPT_GEN_MEMBER(microtan_state::interrupt)
TIMER_DEVICE_CALLBACK_MEMBER(microtan_state::kbd_scan)
{
/* ASCII Keyboard only */
if ((m_config->read() & 3) != 0)
return;
int mod, row, col, chg, newvar;
if( m_repeat )
@ -360,7 +308,25 @@ INTERRUPT_GEN_MEMBER(microtan_state::interrupt)
}
}
void microtan_state::init_microtan()
WRITE8_MEMBER(microtan_state::pgm_chargen_w)
{
switch (offset & 0x200)
{
case 0x000:
/* update char &80-&1F */
m_gfx1->base()[offset | 0x800] = data;
m_gfxdecode->gfx(0)->mark_dirty(0x80 | (offset >> 4));
break;
case 0x200:
/* update char &E0-&FF */
m_gfx1->base()[offset | 0xc00] = data;
m_gfxdecode->gfx(0)->mark_dirty(0xc0 | (offset >> 4));
break;
}
}
void microtan_state::init_gfx2()
{
uint8_t *dst = memregion("gfx2")->base();
@ -399,24 +365,13 @@ void microtan_state::init_microtan()
}
dst += 4;
}
}
void microtan_state::init_microtan()
{
init_gfx2();
m_pulse_nmi_timer = timer_alloc(TIMER_PULSE_NMI);
m_via6522[0]->write_ca1(1);
m_via6522[0]->write_ca2(1);
m_via6522[0]->write_pb(0xff);
m_via6522[0]->write_cb1(1);
m_via6522[0]->write_cb2(1);
m_via6522[1]->write_pa(0xff);
m_via6522[1]->write_ca1(1);
m_via6522[1]->write_ca2(1);
m_via6522[1]->write_pb(0xff);
m_via6522[1]->write_cb1(1);
m_via6522[1]->write_cb2(1);
m_pulse_nmi_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(microtan_state::pulse_nmi), this));
}
void microtan_state::machine_start()
@ -435,24 +390,10 @@ void microtan_state::machine_start()
void microtan_state::machine_reset()
{
address_space &space = m_maincpu->space(AS_PROGRAM);
switch (ioport("DSW")->read() & 3)
{
case 0: // 1K only :)
space.nop_readwrite(0x0400, 0xbbff);
break;
case 1: // +7K TANEX
space.install_ram(0x0400, 0x1fff,nullptr);
space.nop_readwrite(0x2000, 0xbbff);
break;
default: // +7K TANEX + 40K TANRAM
space.install_ram(0x0400, 0xbbff, nullptr);
break;
}
for (int i = 1; i < 10; i++)
m_keyrows[i] = m_io_keyboard[i-1]->read();
{
m_keyrows[i] = m_io_keyboard[i-1].read_safe(0);
}
m_led = BIT(~m_keyrows[3], 7);
}

View File

@ -21685,7 +21685,10 @@ pentacup //
pentacup2 //
@source:microtan.cpp
microtan // 1979 Microtan 65
mt65 // 1979 Microtan 65
micron // 1980 Micron
spinveti // 1980 Space Invasion (ETI)
mt6809 // 1984 Microtan 65 (6809 CPU)
@source:microterm.cpp
mt420 //

View File

@ -60,3 +60,7 @@ uint32_t microtan_state::screen_update(screen_device &screen, bitmap_ind16 &bitm
m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
return 0;
}
void mt6809_state::video_start()
{
}