summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/audio/namcoc7x.c
blob: 7be79ae6d3c82dbe22d742e21023e9ab0af297f8 (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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/*
    namcoc7x.c - sound hardware for mid-90s Namco systems

    System      MCU Synthesizer
    ------------------------------------
    NB-1        C351    C352
    NB-2        C351    C352
    System 22   C74 C352
    FL      C75 C352
    System 11   C76 C352

    All of these MCUs are Mitsubishi M377xx family (65c816 based)
    with 16k of internal BIOS ROM.  The BIOS is the same for all
    chips of the same number.  We currently use the BIOS from a
    Super System 22 game (Prop Cycle) to substitute for the
    BIOS in these chips.  This is compatible enough to play
    the sound and music, but not enough to read the inputs or
    handle coinage (the other task these MCUs have).

    These systems have 48k of shared RAM with the host.  Due to
    the MCU's work variables being moved around we cannot enable
    full sharing or else the main CPU can overwrite important
    MCU work variables and crash it.

    Emulation by R. Belmont.
    Thanks to Cync and Cap for invaluable assistance.
*/

#include "emu.h"
#include "cpu/m37710/m37710.h"
#include "deprecat.h"
#include "audio/namcoc7x.h"

static UINT16 *namcoc7x_mcuram;
static UINT16 su_82;
static UINT32 *namcoc7x_hostram;

static READ16_HANDLER( speedup_r )
{
	if ((cpu_get_pc(space->cpu) == 0xc12d) && (!(su_82 & 0xff00)))
	{
		cpu_spinuntil_int(space->cpu);
	}

	return su_82;
}

static WRITE16_HANDLER( speedup_w )
{
	COMBINE_DATA(&su_82);
}

WRITE16_HANDLER(namcoc7x_soundram16_w)
{
	COMBINE_DATA(namcoc7x_mcuram+offset);
}

READ16_HANDLER(namcoc7x_soundram16_r)
{
	return namcoc7x_mcuram[offset];
}

WRITE32_HANDLER(namcoc7x_soundram32_w)
{
	namcoc7x_soundram16_w(space, offset*2, data >> 16, mem_mask >> 16);
	namcoc7x_soundram16_w(space, offset*2+1, data, mem_mask);
}

READ32_HANDLER(namcoc7x_soundram32_r)
{
	return (namcoc7x_soundram16_r(space, offset*2, mem_mask >> 16) << 16) |
		namcoc7x_soundram16_r(space, offset*2+1, mem_mask);
}

void namcoc7x_sound_write16(UINT16 command, UINT32 offset)
{
	namcoc7x_mcuram[offset] = command;
}

void namcoc7x_on_driver_init(running_machine *machine)
{
	UINT8 *pROM = (UINT8 *)memory_region(machine, "c7x");
	const device_config *cpu;

	// clear the two 16-bits magic values at the start of the rom
	// (prevents external init routines from getting called - they assume a
	//  ROM layout for a different BIOS and crash ours)
	memset(pROM, 0, 4);

	// install speedup cheat
	for (cpu = devtag_get_device(machine, "maincpu"); cpu != NULL; cpu = cpu->typenext)
		if (cpu_get_type(cpu) == CPU_M37702)
			memory_install_readwrite16_handler(cpu_get_address_space(cpu, ADDRESS_SPACE_PROGRAM), 0x82, 0x83, 0, 0, speedup_r, speedup_w);
}

void namcoc7x_set_host_ram(UINT32 *hostram)
{
	namcoc7x_hostram = hostram;
}

// Only share the sound work area
static READ16_HANDLER( c7x_shared_r )
{
	UINT16 *share16 = (UINT16 *)namcoc7x_hostram;

	if (offset >= 0x400/2)
	{
		return namcoc7x_mcuram[offset];
	}

	return share16[BYTE_XOR_LE(offset)];
}

static WRITE16_HANDLER( c7x_shared_w )
{
	UINT16 *share16 = (UINT16 *)namcoc7x_hostram;

	if (offset >= 0x400/2)
	{
		COMBINE_DATA(&namcoc7x_mcuram[offset]);
	}
	else
	{
		COMBINE_DATA(&share16[BYTE_XOR_LE(offset)]);
	}
}

ADDRESS_MAP_START( namcoc7x_mcu_map, ADDRESS_SPACE_PROGRAM, 16 )
	AM_RANGE(0x002000, 0x002fff) AM_DEVREADWRITE("c352", c352_r, c352_w)
	AM_RANGE(0x004000, 0x00bfff) AM_RAM AM_BASE(&namcoc7x_mcuram)
	AM_RANGE(0x00c000, 0x00ffff) AM_ROM AM_REGION("c7x", 0x8c000)
	AM_RANGE(0x080000, 0x0fffff) AM_ROM AM_REGION("c7x", 0)
	AM_RANGE(0x200000, 0x27ffff) AM_ROM AM_REGION("c7x", 0)
	AM_RANGE(0x280000, 0x2fffff) AM_ROM AM_REGION("c7x", 0)
	AM_RANGE(0x301000, 0x301001) AM_NOP	// watchdog? LEDs?
	AM_RANGE(0x308000, 0x308003) AM_NOP	// volume control IC?
ADDRESS_MAP_END

ADDRESS_MAP_START( namcoc7x_mcu_share_map, ADDRESS_SPACE_PROGRAM, 16 )
	AM_RANGE(0x002000, 0x002fff) AM_DEVREADWRITE("c352", c352_r, c352_w )
	AM_RANGE(0x004000, 0x00bfff) AM_READWRITE( c7x_shared_r, c7x_shared_w ) AM_BASE(&namcoc7x_mcuram)
	AM_RANGE(0x00c000, 0x00ffff) AM_ROM AM_REGION("c7x", 0x8c000)
	AM_RANGE(0x080000, 0x0fffff) AM_ROM AM_REGION("c7x", 0)
	AM_RANGE(0x200000, 0x27ffff) AM_ROM AM_REGION("c7x", 0)
	AM_RANGE(0x280000, 0x2fffff) AM_ROM AM_REGION("c7x", 0)
	AM_RANGE(0x301000, 0x301001) AM_NOP	// watchdog? LEDs?
	AM_RANGE(0x308000, 0x308003) AM_NOP	// volume control IC?
ADDRESS_MAP_END

static int p4;

static READ8_HANDLER( mcu_port5_r )
{
	return 0xff;
}

static WRITE8_HANDLER( mcu_port4_w )
{
	p4 = data;
}

static READ8_HANDLER( mcu_port4_r )
{
	return p4;
}

static WRITE8_HANDLER( mcu_port5_w )
{
}

static READ8_HANDLER( mcu_port6_r )
{
	return 0;
}

static READ8_HANDLER( mcu_port7_r )
{
	return 0;
}

ADDRESS_MAP_START( namcoc7x_mcu_io, ADDRESS_SPACE_IO, 8 )
	AM_RANGE(M37710_PORT4, M37710_PORT4) AM_READ( mcu_port4_r ) AM_WRITE( mcu_port4_w )
	AM_RANGE(M37710_PORT5, M37710_PORT5) AM_READ( mcu_port5_r ) AM_WRITE( mcu_port5_w )
	AM_RANGE(M37710_PORT6, M37710_PORT6) AM_READ( mcu_port6_r ) AM_WRITENOP
	AM_RANGE(M37710_PORT7, M37710_PORT7) AM_READ( mcu_port7_r )
	AM_RANGE(0x10, 0x1f) AM_NOP
ADDRESS_MAP_END

INTERRUPT_GEN( namcoc7x_interrupt )
{
	if (cpu_getiloops(device) == 0)
		cpu_set_input_line(device, M37710_LINE_IRQ0, HOLD_LINE);
	else
		cpu_set_input_line(device, M37710_LINE_IRQ2, HOLD_LINE);
}