summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/nmk112.c
blob: 5239c8987b2919b94e229bc0a3baa7ec3e7a0f34 (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
131
132
133
134
135
136
/*  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"

#define TABLESIZE   0x100
#define BANKSIZE    0x10000



const device_type NMK112 = &device_creator<nmk112_device>;

nmk112_device::nmk112_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
	: device_t(mconfig, NMK112, "NMK 112", tag, owner, clock)
{
}

//-------------------------------------------------
//  device_config_complete - perform any
//  operations now that the configuration is
//  complete
//-------------------------------------------------

void nmk112_device::device_config_complete()
{
}

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

void nmk112_device::device_start()
{
	const nmk112_interface *intf = (const nmk112_interface *)static_config();

	if (intf->rgn0 == NULL)
	{
		m_rom0 = NULL;
		m_size0 = 0;
	}
	else
	{
		m_rom0 = machine().root_device().memregion(intf->rgn0)->base();
		m_size0 = machine().root_device().memregion(intf->rgn0)->bytes() - 0x40000;
	}

	if (intf->rgn1 == NULL)
	{
		m_rom1 = NULL;
		m_size1 = 0;
	}
	else
	{
		m_rom1 = machine().root_device().memregion(intf->rgn1)->base();
		m_size1 = machine().root_device().memregion(intf->rgn1)->bytes() - 0x40000;
	}

	m_page_mask = ~intf->disable_page_mask;

	save_item(NAME(m_current_bank));
	machine().save().register_postload(save_prepost_delegate(FUNC(nmk112_device::postload_bankswitch), this));
}

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

void nmk112_device::device_reset()
{
	for (int i = 0; i < 8; i++)
	{
		m_current_bank[i] = 0;
		do_bankswitch(i, m_current_bank[i]);
	}
}


void nmk112_device::do_bankswitch( int offset, int data )
{
	int chip = (offset & 4) >> 2;
	int banknum = offset & 3;
	int paged = (m_page_mask & (1 << chip));

	UINT8 *rom = chip ? m_rom1 : m_rom0;
	int size = chip ? m_size1 : m_size0;

	m_current_bank[offset] = data;

	if (size == 0) return;

	int bankaddr = (data * BANKSIZE) % size;

	/* copy the samples */
	if ((paged) && (banknum == 0))
		memcpy(rom + 0x400, rom + 0x40000 + bankaddr + 0x400, BANKSIZE - 0x400);
	else
		memcpy(rom + banknum * BANKSIZE, rom + 0x40000 + bankaddr, BANKSIZE);

	/* also copy the sample address table, if it is paged on this chip */
	if (paged)
	{
		rom += banknum * TABLESIZE;
		memcpy(rom, rom + 0x40000 + bankaddr, TABLESIZE);
	}
}

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

WRITE8_MEMBER( nmk112_device::okibank_w )
{
	if (m_current_bank[offset] != data)
		do_bankswitch(offset, data);
}

WRITE16_MEMBER( nmk112_device::okibank_lsb_w )
{
	if (ACCESSING_BITS_0_7)
	{
		okibank_w(space, offset, data & 0xff);
	}
}

void nmk112_device::postload_bankswitch()
{
	for (int i = 0; i < 8; i++)
		do_bankswitch(i, m_current_bank[i]);
}