summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/z80/kc82.cpp
blob: 0dcac14e9e2ded5945a0f4b4a0d2f987969ce1de (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888 } /* Comment */
.highlight .err { color: #A61717; background-color: #E3D2D2 } /* Error */
.highlight .k { color: #080; font-weight: bold } /* Keyword */
.highlight .ch { color: #888 } /* Comment.Hashbang */
.highlight .cm { color: #888 } /* Comment.Multiline */
.highlight .cp { color: #C00; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888 } /* Comment.Single */
.highlight .cs { color: #C00; font-weight: bold; background-color: #FFF0F0 } /* Comment.Special */
.highlight .gd { color: #000; background-color: #FDD } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #A00 } /* Generic.Error */
.highlight .gh { color: #333 } /* Generic.Heading */
.highlight .gi { color: #000; background-color: #DFD } /* Generic.Inserted */
.highlight .go { color: #888 } /* Generic.Output */
.highlight .gp { color: #555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666 } /* Generic.Subheading */
.highlight .gt { color: #A00 } /* Generic.Traceback */
.highlight .kc { color: #080; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #080; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #080; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #080 } /* Keyword.Pseudo */
.highlight .kr { color: #080; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #00D; font-weight: bold } /* Literal.Number */
.highlight .s { color: #D20; background-color: #FFF0F0 } /* Literal.String */
.highlight .na { color: #369 } /* Name.Attribute */
.highlight .nb { color: #038 } /* Name.Builtin */
.highlight .nc { color: #B06; font-weight: bold } /* Name.Class */
.highlight .no { color: #036; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555 } /* Name.Decorator */
.highlight .ne { color: #B06; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #06B; font-weight: bold } /* Name.Function */
.highlight .nl { color: #369; font-style: italic } /* Name.Label */
.highlight .nn { color: #B06; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #369; font-weight: bold } /* Name.Property */
.highlight .nt { color: #B06; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #369 } /* Name.Variable */
.highlight .ow { color: #080 } /* Operator.Word */
.highlight .w { color: #BBB } /* Text.Whitespace */
.highlight .mb { color: #00D; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #00D; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #00D; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #00D; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #00D; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #D20; background-color: #FFF0F0 } /* Literal.String.Affix */
.highlight .sb { color: #D20; background-color: #FFF0F0 } /* Literal.String.Backtick */
.highlight .sc { color: #D20; background-color: #FFF0F0 } /* Literal.String.Char */
.highlight .dl { color: #D20; background-color: #FFF0F0 } /* Literal.String.Delimiter */
.highlight .sd { color: #D20; background-color: #FFF0F0 } /* Literal.String.Doc */
.highlight .s2 { color: #D20; background-color: #FFF0F0 } /* Literal.String.Double */
.highlight .se { color: #04D; background-color: #FFF0F0 } /* Literal.String.Escape */
.highlight .sh { color: #D20; background-color: #FFF0F0 } /* Literal.String.Heredoc */
.highlight .si { color: #33B; background-color: #FFF0F0 } /* Literal.String.Interpol */
.highlight .sx { color: #2B2; background-color: #F0FFF0 } /* Literal.String.Other */
.highlight .sr { color: #080; background-color: #FFF0FF } /* Literal.String.Regex */
.highlight .s1 { color: #D20; background-color: #FFF0F0 } /* Literal.String.Single */
.highlight .ss { color: #A60; background-color: #FFF0F0 } /* Literal.String.Symbol */
.highlight .bp { color: #038 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #06B; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #369 } /* Name.Variable.Class */
.highlight .vg { color: #D70 } /* Name.Variable.Global */
.highlight .vi { color: #33B } /* Name.Variable.Instance */
.highlight .vm { color: #369 } /* Name.Variable.Magic */
.highlight .il { color: #00D; font-weight: bold } /* Literal.Number.Integer.Long */
// license:BSD-3-Clause
// copyright-holders:Curt Coder
/*********************************************************************

    formats/ep64_dsk.c

    Enterprise Sixty Four disk image format

*********************************************************************/

#include <assert.h>

#include "formats/ep64_dsk.h"

ep64_format::ep64_format() : wd177x_format(formats)
{
}

const char *ep64_format::name() const
{
	return "ep64";
}

const char *ep64_format::description() const
{
	return "Enteprise Sixty Four disk image";
}

const pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888 } /* Comment */
.highlight .err { color: #A61717; background-color: #E3D2D2 } /* Error */
.highlight .k { color: #080; font-weight: bold } /* Keyword */
.highlight .ch { color: #888 } /* Comment.Hashbang */
.highlight .cm { color: #888 } /* Comment.Multiline */
.highlight .cp { color: #C00; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888 } /* Comment.Single */
.highlight .cs { color: #C00; font-weight: bold; background-color: #FFF0F0 } /* Comment.Special */
.highlight .gd { color: #000; background-color: #FDD } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #A00 } /* Generic.Error */
.highlight .gh { color: #333 } /* Generic.Heading */
.highlight .gi { color: #000; background-color: #DFD } /* Generic.Inserted */
.highlight .go { color: #888 } /* Generic.Output */
.highlight .gp { color: #555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666 } /* Generic.Subheading */
.highlight .gt { color: #A00 } /* Generic.Traceback */
.highlight .kc { color: #080; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #080; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #080; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #080 } /* Keyword.Pseudo */
.highlight .kr { color: #080; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #00D; font-weight: bold } /* Literal.Number */
.highlight .s { color: #D20; background-color: #FFF0F0 } /* Literal.String */
.highlight .na { color: #369 } /* Name.Attribute */
.highlight .nb { color: #038 } /* Name.Builtin */
.highlight .nc { color: #B06; font-weight: bold } /* Name.Class */
.highlight .no { color: #036; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555 } /* Name.Decorator */
.highlight .ne { color: #B06; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #06B; font-weight: bold } /* Name.Function */
.highlight .nl { color: #369; font-style: italic } /* Name.Label */
.highlight .nn { color: #B06; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #369; font-weight: bold } /* Name.Property */
.highlight .nt { color: #B06; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #369 } /* Name.Variable */
.highlight .ow { color: #080 } /* Operator.Word */
.highlight .w { color: #BBB } /* Text.Whitespace */
.highlight .mb { color: #00D; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #00D; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #00D; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #00D; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #00D; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #D20; background-color: #FFF0F0 } /* Literal.String.Affix */
.highlight .sb { color: #D20; background-color: #FFF0F0 } /* Literal.String.Backtick */
.highlight .sc { color: #D20; background-color: #FFF0F0 } /* Literal.String.Char */
.highlight .dl { color: #D20; background-color: #FFF0F0 } /* Literal.String.Delimiter */
.highlight .sd { color: #D20; background-color: #FFF0F0 } /* Literal.String.Doc */
.highlight .s2 { color: #D20; background-color: #FFF0F0 } /* Literal.String.Double */
.highlight .se { color: #04D; background-color: #FFF0F0 } /* Literal.String.Escape */
.highlight .sh { color: #D20; background-color: #FFF0F0 } /* Literal.String.Heredoc */
.highlight .si { color: #33B; background-color: #FFF0F0 } /* Literal.String.Interpol */
.highlight .sx { color: #2B2; background-color: #F0FFF0 } /* Literal.String.Other */
.highlight .sr { color: #080; background-color: #FFF0FF } /* Literal.String.Regex */
.highlight .s1 { color: #D20; background-color: #FFF0F0 } /* Literal.String.Single */
.highlight .ss { color: #A60; background-color: #FFF0F0 } /* Literal.String.Symbol */
.highlight .bp { color: #038 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #06B; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #369 } /* Name.Variable.Class */
.highlight .vg { color: #D70 } /* Name.Variable.Global */
.highlight .vi { color: #33B } /* Name.Variable.Instance */
.highlight .vm { color: #369 } /* Name.Variable.Magic */
.highlight .il { color: #00D; font-weight: bold } /* Literal.Number.Integer.Long */
// license:BSD-3-Clause
// copyright-holders:AJR
/***************************************************************************

    Kawasaki Steel (Kawatetsu) KC82 CPU core with MMU

***************************************************************************/

#include "emu.h"
#include "kc82.h"

#define VERBOSE 0
#include "logmacro.h"


//-------------------------------------------------
//  kc82_device - constructor
//-------------------------------------------------

kc82_device::kc82_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, const XTAL &clock, address_map_constructor mem_map, address_map_constructor io_map)
	: z80_device(mconfig, type, tag, owner, clock)
	, m_program_config("program", ENDIANNESS_LITTLE, 8, 20, 0, 16, 10, mem_map)
	, m_opcodes_config("opcodes", ENDIANNESS_LITTLE, 8, 20, 0, 16, 10, mem_map)
	, m_io_config("io", ENDIANNESS_LITTLE, 8, 16, 0, io_map)
{
	std::fill_n(&m_mmu_a[0], 4, 0);
	std::fill_n(&m_mmu_b[0], 5, 0);
	std::fill_n(&m_mmu_base[0], 0x40, 0);
}


//-------------------------------------------------
//  memory_space_config - return a vector of
//  address space configurations for this device
//-------------------------------------------------

device_memory_interface::space_config_vector kc82_device::memory_space_config() const
{
	if (has_space(AS_OPCODES))
	{
		return space_config_vector {
			std::make_pair(AS_PROGRAM, &m_program_config),
			std::make_pair(AS_IO,      &m_io_config),
			std::make_pair(AS_OPCODES, &m_opcodes_config)
		};
	}
	else
	{
		return space_config_vector {
			std::make_pair(AS_PROGRAM, &m_program_config),
			std::make_pair(AS_IO,      &m_io_config)
		};
	}
}


//-------------------------------------------------
//  device_start - device-specific startup
//-------------------------------------------------

void kc82_device::device_start()
{
	z80_device::device_start();

	for (int n = 1; n <= 4; n++)
	{
		state_add(KC82_B1 + n - 1, string_format("B%d", n).c_str(), m_mmu_b[n],
			[this, n](u8 data) { m_mmu_b[n] = data; mmu_remap_pages(); }
		).mask(0x3f);
		if (n != 4)
			state_add(KC82_A1 + n - 1, string_format("A%d", n).c_str(), m_mmu_a[n],
				[this, n](u16 data) { m_mmu_a[n] = data; mmu_remap_pages(); }
			).mask(0x3ff);
	}

	save_item(NAME(m_mmu_a));
	save_item(NAME(m_mmu_b));
}


//-------------------------------------------------
//  device_reset - device-specific reset
//-------------------------------------------------

void kc82_device::device_reset()
{
	z80_device::device_reset();

	std::fill_n(&m_mmu_a[1], 3, 0);
	std::fill_n(&m_mmu_b[1], 4, 0x3f);
	std::fill_n(&m_mmu_base[0], 0x40, 0);
}


//-------------------------------------------------
//  device_post_load - called after loading a
//  saved state
//-------------------------------------------------

void kc82_device::device_post_load()
{
	z80_device::device_post_load();

	mmu_remap_pages();
}


//**************************************************************************
//  KC82 MMU
//**************************************************************************

//-------------------------------------------------
//  mmu_remap_pages - recalculate base addresses
//  for memory pages
//-------------------------------------------------

void kc82_device::mmu_remap_pages()
{
	int n = 4;
	u32 base = 0xf0000; // A4 is fixed
	for (u8 i = 0x3f; i != 0; --i)
	{
		while (n != 0 && m_mmu_b[n] >= i)
		{
			--n;
			base = u32(m_mmu_a[n]) << 10;
		}
		if (m_mmu_base[i] != base)
		{
			u32 old_mapping = ((i << 10) + base) & 0xffc00;
			u32 new_mapping = ((i << 10) + m_mmu_base[i]) & 0xffc00;
			LOG("%s: MMU: %04X-%04XH => %05X-%05XH (was %05X-%05XH)\n",
				machine().describe_context(),
				i << 10, (i << 10) | 0x3ff,
				old_mapping, old_mapping | 0x3ff,
				new_mapping, new_mapping | 0x3ff);
		}
		m_mmu_base[i] = base;
	}
}


//-------------------------------------------------
//  mmu_r - read MMU register
//-------------------------------------------------

u8 kc82_device::mmu_r(offs_t offset)
{
	int n = (offset >> 1) + 1;
	if (BIT(offset, 0))
	{
		// read base register BRn
		return n == 4 ? 0xf0 : (m_mmu_a[n] & 0x3fc) >> 2;
	}
	else
	{
		// read boundary/base register BBRn
		return (n == 4 ? 0 : (m_mmu_a[n] & 0x003) << 6) | m_mmu_b[n];
	}
}


//-------------------------------------------------
//  mmu_w - write to MMU register
//-------------------------------------------------

void kc82_device::mmu_w(offs_t offset, u8 data)
{
	int n = (offset >> 1) + 1;
	if (BIT(offset, 0))
	{
		// write to base register BRn
		if (n != 4)
			m_mmu_a[n] = u16(data) << 2 | (m_mmu_a[n] & 0x003);
		else if (data != 0xf0)
			logerror("%s: Attempt to write %02X to upper 8 bits of A4\n", machine().describe_context(), data);
	}
	else
	{
		// write to boundary/base register BBRn
		m_mmu_b[n] = data & 0x3f;
		if (n != 4)
			m_mmu_a[n] = (m_mmu_a[n] & 0x3fc) | (data & 0xc0) >> 6;
		else if ((data & 0xc0) != 0)
			logerror("%s: Attempt to write %d to lower 2 bits of A4\n", machine().describe_context(), (data & 0xc0) >> 6);
	}
	mmu_remap_pages();
}


//-------------------------------------------------
//  memory_translate - translate from logical to
//  physical addresses
//-------------------------------------------------

bool kc82_device::memory_translate(int spacenum, int intention, offs_t &address)
{
	if (spacenum == AS_PROGRAM || spacenum == AS_OPCODES)
		address = (address + m_mmu_base[(address & 0xfc00) >> 10]) & 0xfffff;
	return true;
}


//-------------------------------------------------
//  rm - read one byte from memory
//-------------------------------------------------

u8 kc82_device::rm(u16 addr)
{
	return m_data.read_byte(addr + m_mmu_base[addr >> 10]);
}


//-------------------------------------------------
//  wm - write one byte to memory
//-------------------------------------------------

void kc82_device::wm(u16 addr, u8 value)
{
	m_data.write_byte(addr + m_mmu_base[addr >> 10], value);
}


//-------------------------------------------------
//  rop - read opcode
//-------------------------------------------------

u8 kc82_device::rop()
{
	u32 pc = m_pc.w.l + m_mmu_base[m_pc.b.h >> 2];
	m_pc.w.l++;
	// no refresh
	return m_opcodes.read_byte(pc);
}


//-------------------------------------------------
//  arg - read 8-bit argument
//-------------------------------------------------

u8 kc82_device::arg()
{
	u32 pc = m_pc.w.l + m_mmu_base[m_pc.b.h >> 2];
	m_pc.w.l++;
	return m_args.read_byte(pc);
}


//-------------------------------------------------
//  arg16 - read 16-bit argument
//-------------------------------------------------

u16 kc82_device::arg16()
{
	u16 d16 = arg();
	d16 |= u16(arg()) << 8;
	return d16;
}