1 /***************************************************************************
2 
3 IREM "M72" sound hardware
4 
5 used by:
6 
7 Game                          Year  Sound program ID string
8 ----------------------------  ----  -----------------------
9 R-Type                        1987  - (earlier version, no sample player)
10 Battle Chopper / Mr. Heli     1987  Rev 2.20
11 Vigilante                     1988  Rev 2.20
12 Ninja Spirit                  1988  Rev 2.20
13 Image Fight                   1988  Rev 2.20
14 Legend of Hero Tonma          1989  Rev 2.20
15 X Multiply                    1989  Rev 2.20
16 Dragon Breed                  1989  Rev 2.20
17 Kickle Cubicle                1988  Rev 2.21
18 Shisensho                     1989  Rev 2.21
19 R-Type II                     1989  Rev 2.21
20 Major Title                   1990  Rev 2.21
21 Air Duel                      1990  Rev 3.14 M72 (no NMI handler)
22 Daiku no Gensan               1990  Rev 3.14 M81
23 Hammerin' Harry               1990  Rev 3.15 M81
24 Ken-Go	                      1991  Rev 3.15 M81
25 Pound for Pound               1990  Rev 3.15 M83 (no NMI handler)
26 Gallop - Armed Police Unit    1991  Rev 3.15 M72 (no NMI handler)
27 Bomber Man World              1992  Rev 3.31 M81
28 Atomic Punk                   1992  Rev 3.31 M99
29 Quiz F-1 1,2finish            1992  Rev 3.33 M81
30 Risky Challenge               1993  Rev 3.34 M81
31 Shisensho II                  1993  Rev 3.34 M81
32 
33 ***************************************************************************/
34 #include "driver.h"
35 
36 
37 /*
38 
39   The sound CPU runs in interrup mode 0. IRQ is shared by two sources: the
40   YM2151 (bit 4 of the vector), and the main CPU (bit 5).
41   Since the vector can be changed from different contexts (the YM2151 timer
42   callback, the main CPU context, and the sound CPU context), it's important
43   to accurately arbitrate the changes to avoid out-of-order execution. We do
44   that by handling all vector changes in a single timer callback.
45 
46 */
47 
48 
49 enum
50 {
51 	VECTOR_INIT,
52 	YM2151_ASSERT,
53 	YM2151_CLEAR,
54 	Z80_ASSERT,
55 	Z80_CLEAR
56 };
57 
setvector_callback(int param)58 static void setvector_callback(int param)
59 {
60 	static int irqvector;
61 
62 	switch(param)
63 	{
64 		case VECTOR_INIT:
65 			irqvector = 0xff;
66 			break;
67 
68 		case YM2151_ASSERT:
69 			irqvector &= 0xef;
70 			break;
71 
72 		case YM2151_CLEAR:
73 			irqvector |= 0x10;
74 			break;
75 
76 		case Z80_ASSERT:
77 			irqvector &= 0xdf;
78 			break;
79 
80 		case Z80_CLEAR:
81 			irqvector |= 0x20;
82 			break;
83 	}
84 
85 	cpu_irq_line_vector_w(1,0,irqvector);
86 	if (irqvector == 0xff)	/* no IRQs pending */
87 		cpu_set_irq_line(1,0,CLEAR_LINE);
88 	else	/* IRQ pending */
89 		cpu_set_irq_line(1,0,ASSERT_LINE);
90 }
91 
92 static UINT8 *m72_region=NULL;
93 static int m72_region_length=0;
94 
m72_init_sound(void)95 void m72_init_sound(void)
96 {
97     m72_region=NULL;
98     m72_region_length=0;
99 	setvector_callback(VECTOR_INIT);
100 }
101 
m72_ym2151_irq_handler(int irq)102 void m72_ym2151_irq_handler(int irq)
103 {
104 	if (irq)
105 		timer_set(TIME_NOW,YM2151_ASSERT,setvector_callback);
106 	else
107 		timer_set(TIME_NOW,YM2151_CLEAR,setvector_callback);
108 }
109 
WRITE_HANDLER(m72_sound_command_w)110 WRITE_HANDLER( m72_sound_command_w )
111 {
112 	if (offset == 0)
113 	{
114 		soundlatch_w(offset,data);
115 		timer_set(TIME_NOW,Z80_ASSERT,setvector_callback);
116 	}
117 }
118 
WRITE_HANDLER(m72_sound_irq_ack_w)119 WRITE_HANDLER( m72_sound_irq_ack_w )
120 {
121 	timer_set(TIME_NOW,Z80_CLEAR,setvector_callback);
122 }
123 
124 
125 
126 static int sample_addr;
127 
m72_set_sample_start(int start)128 void m72_set_sample_start(int start)
129 {
130 	sample_addr = start;
131 }
132 
WRITE_HANDLER(vigilant_sample_addr_w)133 WRITE_HANDLER( vigilant_sample_addr_w )
134 {
135 	if (offset == 1)
136 		sample_addr = (sample_addr & 0x00ff) | ((data << 8) & 0xff00);
137 	else
138 		sample_addr = (sample_addr & 0xff00) | ((data << 0) & 0x00ff);
139 }
140 
WRITE_HANDLER(shisen_sample_addr_w)141 WRITE_HANDLER( shisen_sample_addr_w )
142 {
143 	sample_addr >>= 2;
144 
145 	if (offset == 1)
146 		sample_addr = (sample_addr & 0x00ff) | ((data << 8) & 0xff00);
147 	else
148 		sample_addr = (sample_addr & 0xff00) | ((data << 0) & 0x00ff);
149 
150 	sample_addr <<= 2;
151 }
152 
WRITE_HANDLER(rtype2_sample_addr_w)153 WRITE_HANDLER( rtype2_sample_addr_w )
154 {
155 	sample_addr >>= 5;
156 
157 	if (offset == 1)
158 		sample_addr = (sample_addr & 0x00ff) | ((data << 8) & 0xff00);
159 	else
160 		sample_addr = (sample_addr & 0xff00) | ((data << 0) & 0x00ff);
161 
162 	sample_addr <<= 5;
163 }
164 
READ_HANDLER(m72_sample_r)165 READ_HANDLER( m72_sample_r )
166 {
167     if (m72_region==NULL)
168         m72_region=memory_region(REGION_SOUND1);
169 	return m72_region[sample_addr];
170 }
171 
WRITE_HANDLER(m72_sample_w)172 WRITE_HANDLER( m72_sample_w )
173 {
174 	DAC_signed_data_w(0,data);
175 	if (m72_region_length==0)
176 	    m72_region_length=memory_region_length(REGION_SOUND1);
177 	sample_addr = (sample_addr + 1) & (m72_region_length - 1);
178 }
179