// 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;
}