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