summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/nmk112.cpp
blob: 7bac6435bd9635c549d3ac3613686cbefb894fb1 (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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// license:BSD-3-Clause
// copyright-holders:Alex W. Jackson
/*  NMK112 - NMK custom IC for bankswitching the sample ROMs of a pair of
    OKI6295 ADPCM chips

    The address space of each OKI6295 is divided into four banks, each one
    independently controlled. The sample table at the beginning of the
    address space may be divided in four pages as well, banked together
    with the sample data.  This allows each of the four voices on the chip
    to play a sample from a different bank at the same time. */

#include "emu.h"
#include "nmk112.h"

#include "bus/generic/slot.h"


DEFINE_DEVICE_TYPE(NMK112, nmk112_device, "nmk112", "NMK112")

nmk112_device::nmk112_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
	: device_t(mconfig, NMK112, tag, owner, clock)
	, m_samplebank{ { *this, "samplebank_0_%u", 0U }, { *this, "samplebank_1_%u", 0U } }
	, m_tablebank{ { *this, "tablebank_0_%u", 0U }, { *this, "tablebank_1_%u", 0U } }
	, m_rom(*this, { finder_base::DUMMY_TAG, finder_base::DUMMY_TAG })
	, m_page_mask(0xff)
	, m_bankmask{ 0, 0 }
{
}

void nmk112_device::device_start()
{
	for (int c = 0; c < 2; c++)
	{
		if (m_rom[c])
		{
			const auto size = m_rom[c].bytes();
			if (size & 0x0ffff)
			{
				throw emu_fatalerror(
						"%s: ROM region %s has unsupported size 0x%X (must be a multiple of 64KiB)",
						tag(),
						m_rom[c].finder_tag(),
						size);
			}

			// bank slot configurations
			m_bankmask[c] = device_generic_cart_interface::map_non_power_of_two(
					std::min<unsigned>(size / 0x10000, 0x100),
					[this, c] (unsigned entry, unsigned page)
					{
						const uint32_t pagebase = uint32_t(page) << 16;
						for (unsigned i = 0; i < 4; i++)
						{
							const uint32_t tablebase = pagebase | (i << 8);
							m_samplebank[c][i]->configure_entry(entry, &m_rom[c][pagebase]);
							if (is_paged(c))
								m_tablebank[c][i]->configure_entry(entry, &m_rom[c][tablebase]);
						}
					});

			for (unsigned i = 0; i < 4; i++)
			{
				m_samplebank[c][i]->set_entry(0);
				if (is_paged(c))
					m_tablebank[c][i]->set_entry(0);
			}
		}
	}
}

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

void nmk112_device::device_reset()
{
	for (offs_t i = 0; i < 8; i++)
		okibank_w(i, 0);
}


/*****************************************************************************
    DEVICE HANDLERS
*****************************************************************************/

void nmk112_device::okibank_w(offs_t offset, u8 data)
{
	const int chip = BIT(offset, 2);
	const int banknum = offset & 3;

	if (m_bankmask[chip])
	{
		m_samplebank[chip][banknum]->set_entry(data & m_bankmask[chip]);

		if (is_paged(chip))
			m_tablebank[chip][banknum]->set_entry(data & m_bankmask[chip]);
	}
}


/*****************************************************************************
    ADDRESS MAPS
*****************************************************************************/

void nmk112_device::oki0_map(address_map &map)
{
	oki_map(0, map);
}

void nmk112_device::oki1_map(address_map &map)
{
	oki_map(1, map);
}

void nmk112_device::oki_map(unsigned which, address_map &map)
{
	map(0x00000, 0x0ffff).bankr(m_samplebank[which][0]);
	map(0x10000, 0x1ffff).bankr(m_samplebank[which][1]);
	map(0x20000, 0x2ffff).bankr(m_samplebank[which][2]);
	map(0x30000, 0x3ffff).bankr(m_samplebank[which][3]);

	// these get installed over the top of the first bank if present
	if (is_paged(which))
	{
		map(0x00000, 0x000ff).bankr(m_tablebank[which][0]);
		map(0x00100, 0x001ff).bankr(m_tablebank[which][1]);
		map(0x00200, 0x002ff).bankr(m_tablebank[which][2]);
		map(0x00300, 0x003ff).bankr(m_tablebank[which][3]);
	}
}