1 /***************************************************************************
2 
3   This file contains functions to emulate the sound hardware found on
4   Scramble type boards.
5 
6   There are two types, one has 2 AY8910's and the other one has one of the
7   AY8910's removed.  Interestingly, it appears that the one AY8910 version
8   came after the 2 AY8910 one.  This is supported by the fact that in the
9   one 8190 version, the filter system uses bits 6-11, while bits 0-5 are
10   left unused.
11 
12 ***************************************************************************/
13 
14 
15 #include "driver.h"
16 #include "cpu/z80/z80.h"
17 #include "machine/7474.h"
18 
19 
20 
21 /* The timer clock in Scramble which feeds the upper 4 bits of    		*/
22 /* AY-3-8910 port A is based on the same clock        					*/
23 /* feeding the sound CPU Z80.  It is a divide by      					*/
24 /* 5120, formed by a standard divide by 512,        					*/
25 /* followed by a divide by 10 using a 4 bit           					*/
26 /* bi-quinary count sequence. (See LS90 data sheet    					*/
27 /* for an example).                                   					*/
28 /*																		*/
29 /* Bit 4 comes from the output of the divide by 1024  					*/
30 /*       0, 1, 0, 1, 0, 1, 0, 1, 0, 1									*/
31 /* Bit 5 comes from the QC output of the LS90 producing a sequence of	*/
32 /* 		 0, 0, 1, 1, 0, 0, 1, 1, 1, 0									*/
33 /* Bit 6 comes from the QD output of the LS90 producing a sequence of	*/
34 /*		 0, 0, 0, 0, 1, 0, 0, 0, 0, 1									*/
35 /* Bit 7 comes from the QA output of the LS90 producing a sequence of	*/
36 /*		 0, 0, 0, 0, 0, 1, 1, 1, 1, 1			 						*/
37 
38 static int scramble_timer[10] =
39 {
40 	0x00, 0x10, 0x20, 0x30, 0x40, 0x90, 0xa0, 0xb0, 0xa0, 0xd0
41 };
42 
READ_HANDLER(scramble_portB_r)43 READ_HANDLER( scramble_portB_r )
44 {
45 	/* need to protect from totalcycles overflow */
46 	static int last_totalcycles = 0;
47 
48 	/* number of Z80 clock cycles to count */
49 	static int clock;
50 
51 	int current_totalcycles;
52 
53 	current_totalcycles = activecpu_gettotalcycles();
54 	clock = (clock + (current_totalcycles-last_totalcycles)) % 5120;
55 
56 	last_totalcycles = current_totalcycles;
57 
58 	return scramble_timer[clock/512];
59 }
60 
61 
62 
63 /* The timer clock in Frogger which feeds the upper 4 bits of    		*/
64 /* AY-3-8910 port A is based on the same clock        					*/
65 /* feeding the sound CPU Z80.  It is a divide by      					*/
66 /* 5120, formed by a standard divide by 512,        					*/
67 /* followed by a divide by 10 using a 4 bit           					*/
68 /* bi-quinary count sequence. (See LS90 data sheet    					*/
69 /* for an example).                                   					*/
70 /*																		*/
71 /* Bit 4 comes from the output of the divide by 1024  					*/
72 /*       0, 1, 0, 1, 0, 1, 0, 1, 0, 1									*/
73 /* Bit 3 comes from the QC output of the LS90 producing a sequence of	*/
74 /* 		 0, 0, 1, 1, 0, 0, 1, 1, 1, 0									*/
75 /* Bit 6 comes from the QD output of the LS90 producing a sequence of	*/
76 /*		 0, 0, 0, 0, 1, 0, 0, 0, 0, 1									*/
77 /* Bit 7 comes from the QA output of the LS90 producing a sequence of	*/
78 /*		 0, 0, 0, 0, 0, 1, 1, 1, 1, 1			 						*/
79 
80 static int frogger_timer[10] =
81 {
82 	0x00, 0x10, 0x08, 0x18, 0x40, 0x90, 0x88, 0x98, 0x88, 0xd0
83 };
84 
READ_HANDLER(frogger_portB_r)85 READ_HANDLER( frogger_portB_r )
86 {
87 	/* need to protect from totalcycles overflow */
88 	static int last_totalcycles = 0;
89 
90 	/* number of Z80 clock cycles to count */
91 	static int clock;
92 
93 	int current_totalcycles;
94 
95 	current_totalcycles = activecpu_gettotalcycles();
96 	clock = (clock + (current_totalcycles-last_totalcycles)) % 5120;
97 
98 	last_totalcycles = current_totalcycles;
99 
100 	return frogger_timer[clock/512];
101 }
102 
103 
WRITE_HANDLER(scramble_sh_irqtrigger_w)104 WRITE_HANDLER( scramble_sh_irqtrigger_w )
105 {
106 	/* the complement of bit 3 is connected to the flip-flop's clock */
107 	TTL7474_clock_w(2, ~data & 0x08);
108 	TTL7474_update(2);
109 
110 	/* bit 4 is sound disable */
111 	mixer_sound_enable_global_w(~data & 0x10);
112 }
113 
WRITE_HANDLER(sfx_sh_irqtrigger_w)114 WRITE_HANDLER( sfx_sh_irqtrigger_w )
115 {
116 	/* bit 1 is connected to the flip-flop's clock */
117 	TTL7474_clock_w(3, data & 0x01);
118 	TTL7474_update(3);
119 }
120 
WRITE_HANDLER(mrkougar_sh_irqtrigger_w)121 WRITE_HANDLER( mrkougar_sh_irqtrigger_w )
122 {
123 	/* the complement of bit 3 is connected to the flip-flop's clock */
124 	TTL7474_clock_w(2, ~data & 0x08);
125 	TTL7474_update(2);
126 }
127 
WRITE_HANDLER(froggrmc_sh_irqtrigger_w)128 WRITE_HANDLER( froggrmc_sh_irqtrigger_w )
129 {
130 	/* the complement of bit 0 is connected to the flip-flop's clock */
131 	TTL7474_clock_w(2, ~data & 0x01);
132 	TTL7474_update(2);
133 }
134 
135 
scramble_sh_irq_callback(int irqline)136 static int scramble_sh_irq_callback(int irqline)
137 {
138 	/* interrupt acknowledge clears the flip-flop --
139 	   we need to pulse the CLR line because MAME's core never clears this
140 	   line, only asserts it */
141 	TTL7474_clear_w(2, 0);
142 	TTL7474_update(2);
143 
144 	TTL7474_clear_w(2, 1);
145 	TTL7474_update(2);
146 
147 	return 0xff;
148 }
149 
sfx_sh_irq_callback(int irqline)150 static int sfx_sh_irq_callback(int irqline)
151 {
152 	/* interrupt acknowledge clears the flip-flop --
153 	   we need to pulse the CLR line because MAME's core never clears this
154 	   line, only asserts it */
155 	TTL7474_clear_w(3, 0);
156 	TTL7474_update(3);
157 
158 	TTL7474_clear_w(3, 1);
159 	TTL7474_update(3);
160 
161 	return 0xff;
162 }
163 
164 
scramble_sh_7474_callback(void)165 static void scramble_sh_7474_callback(void)
166 {
167 	/* the Q bar is connected to the Z80's INT line.  But since INT is complemented, */
168 	/* we need to complement Q bar */
169 	cpu_set_irq_line(1, 0, !TTL7474_output_comp_r(2) ? ASSERT_LINE : CLEAR_LINE);
170 }
171 
sfx_sh_7474_callback(void)172 static void sfx_sh_7474_callback(void)
173 {
174 	/* the Q bar is connected to the Z80's INT line.  But since INT is complemented, */
175 	/* we need to complement Q bar */
176 	cpu_set_irq_line(2, 0, !TTL7474_output_comp_r(3) ? ASSERT_LINE : CLEAR_LINE);
177 }
178 
WRITE_HANDLER(hotshock_sh_irqtrigger_w)179 WRITE_HANDLER( hotshock_sh_irqtrigger_w )
180 {
181 	cpu_set_irq_line(1, 0, PULSE_LINE);
182 }
183 
WRITE_HANDLER(explorer_sh_irqtrigger_w)184 WRITE_HANDLER( explorer_sh_irqtrigger_w  )
185 {
186 	cpu_set_irq_line(1, 0, PULSE_LINE);
187 	cpu_spinuntil_time(TIME_IN_USEC(100));
188 }
189 
filter_w(int chip,int channel,int data)190 static void filter_w(int chip, int channel, int data)
191 {
192 	int C;
193 
194 
195 	C = 0;
196 	if (data & 1) C += 220000;	/* 220000pF = 0.220uF */
197 	if (data & 2) C +=  47000;	/*  47000pF = 0.047uF */
198 	set_RC_filter(3*chip + channel,1000,5100,0,C);
199 }
200 
WRITE_HANDLER(scramble_filter_w)201 WRITE_HANDLER( scramble_filter_w )
202 {
203 	filter_w(1, 0, (offset >>  0) & 3);
204 	filter_w(1, 1, (offset >>  2) & 3);
205 	filter_w(1, 2, (offset >>  4) & 3);
206 	filter_w(0, 0, (offset >>  6) & 3);
207 	filter_w(0, 1, (offset >>  8) & 3);
208 	filter_w(0, 2, (offset >> 10) & 3);
209 }
210 
WRITE_HANDLER(frogger_filter_w)211 WRITE_HANDLER( frogger_filter_w )
212 {
213 	filter_w(0, 0, (offset >>  6) & 3);
214 	filter_w(0, 1, (offset >>  8) & 3);
215 	filter_w(0, 2, (offset >> 10) & 3);
216 }
217 
218 
219 static const struct TTL7474_interface scramble_sh_7474_intf =
220 {
221 	scramble_sh_7474_callback
222 };
223 
224 static const struct TTL7474_interface sfx_sh_7474_intf =
225 {
226 	sfx_sh_7474_callback
227 };
228 
229 
scramble_sh_init(void)230 void scramble_sh_init(void)
231 {
232 	cpu_set_irq_callback(1, scramble_sh_irq_callback);
233 
234 	TTL7474_config(2, &scramble_sh_7474_intf);
235 
236 	/* PR is always 0, D is always 1 */
237 	TTL7474_d_w(2, 1);
238 }
239 
sfx_sh_init(void)240 void sfx_sh_init(void)
241 {
242 	scramble_sh_init();
243 
244 	cpu_set_irq_callback(2, sfx_sh_irq_callback);
245 
246 	TTL7474_config(3, &sfx_sh_7474_intf);
247 
248 	/* PR is always 0, D is always 1 */
249 	TTL7474_d_w(3, 1);
250 }
251 
252 
253 static int latch;
254 
WRITE_HANDLER(zigzag_8910_latch_w)255 WRITE_HANDLER( zigzag_8910_latch_w )
256 {
257 	latch = offset;
258 }
259 
WRITE_HANDLER(zigzag_8910_data_trigger_w)260 WRITE_HANDLER( zigzag_8910_data_trigger_w )
261 {
262 	AY8910_write_port_0_w(0,latch);
263 }
264 
WRITE_HANDLER(zigzag_8910_control_trigger_w)265 WRITE_HANDLER( zigzag_8910_control_trigger_w )
266 {
267 	AY8910_control_port_0_w(0,latch);
268 }
269